This function is borrowed from https://github.com/kornia/kornia Convert quaternion vector to angle axis of rotation. Adapted from ceres C++ library: ceres-solver/include/ceres/rotation.h Args: quaternion (torch.Tensor): tensor with quaternions. Return: torch.Tens
(quaternion: torch.Tensor)
| 117 | |
| 118 | |
| 119 | def quaternion_to_angle_axis(quaternion: torch.Tensor) -> torch.Tensor: |
| 120 | """ |
| 121 | This function is borrowed from https://github.com/kornia/kornia |
| 122 | Convert quaternion vector to angle axis of rotation. |
| 123 | Adapted from ceres C++ library: ceres-solver/include/ceres/rotation.h |
| 124 | Args: |
| 125 | quaternion (torch.Tensor): tensor with quaternions. |
| 126 | Return: |
| 127 | torch.Tensor: tensor with angle axis of rotation. |
| 128 | Shape: |
| 129 | - Input: :math:`(*, 4)` where `*` means, any number of dimensions |
| 130 | - Output: :math:`(*, 3)` |
| 131 | Example: |
| 132 | >>> quaternion = torch.rand(2, 4) # Nx4 |
| 133 | >>> angle_axis = tgm.quaternion_to_angle_axis(quaternion) # Nx3 |
| 134 | """ |
| 135 | if not torch.is_tensor(quaternion): |
| 136 | raise TypeError('Input type is not a torch.Tensor. Got {}'.format( |
| 137 | type(quaternion))) |
| 138 | |
| 139 | if not quaternion.shape[-1] == 4: |
| 140 | raise ValueError( |
| 141 | 'Input must be a tensor of shape Nx4 or 4. Got {}'.format( |
| 142 | quaternion.shape)) |
| 143 | # unpack input and compute conversion |
| 144 | q1: torch.Tensor = quaternion[..., 1] |
| 145 | q2: torch.Tensor = quaternion[..., 2] |
| 146 | q3: torch.Tensor = quaternion[..., 3] |
| 147 | sin_squared_theta: torch.Tensor = q1 * q1 + q2 * q2 + q3 * q3 |
| 148 | |
| 149 | sin_theta: torch.Tensor = torch.sqrt(sin_squared_theta) |
| 150 | cos_theta: torch.Tensor = quaternion[..., 0] |
| 151 | two_theta: torch.Tensor = 2.0 * torch.where( |
| 152 | cos_theta < 0.0, torch.atan2(-sin_theta, -cos_theta), |
| 153 | torch.atan2(sin_theta, cos_theta)) |
| 154 | |
| 155 | k_pos: torch.Tensor = two_theta / sin_theta |
| 156 | k_neg: torch.Tensor = 2.0 * torch.ones_like(sin_theta) |
| 157 | k: torch.Tensor = torch.where(sin_squared_theta > 0.0, k_pos, k_neg) |
| 158 | |
| 159 | angle_axis: torch.Tensor = torch.zeros_like(quaternion)[..., :3] |
| 160 | angle_axis[..., 0] += q1 * k |
| 161 | angle_axis[..., 1] += q2 * k |
| 162 | angle_axis[..., 2] += q3 * k |
| 163 | return angle_axis |
| 164 | |
| 165 | |
| 166 | def rotation_matrix_to_quaternion(rotation_matrix, eps=1e-6): |
no outgoing calls
no test coverage detected