This function is borrowed from https://github.com/kornia/kornia Convert 3x4 rotation matrix to 4d quaternion vector This algorithm is based on algorithm described in https://github.com/KieranWynn/pyquaternion/blob/master/pyquaternion/quaternion.py#L201 Args: rotation_mat
(rotation_matrix, eps=1e-6)
| 164 | |
| 165 | |
| 166 | def rotation_matrix_to_quaternion(rotation_matrix, eps=1e-6): |
| 167 | """ |
| 168 | This function is borrowed from https://github.com/kornia/kornia |
| 169 | Convert 3x4 rotation matrix to 4d quaternion vector |
| 170 | This algorithm is based on algorithm described in |
| 171 | https://github.com/KieranWynn/pyquaternion/blob/master/pyquaternion/quaternion.py#L201 |
| 172 | Args: |
| 173 | rotation_matrix (Tensor): the rotation matrix to convert. |
| 174 | Return: |
| 175 | Tensor: the rotation in quaternion |
| 176 | Shape: |
| 177 | - Input: :math:`(N, 3, 4)` |
| 178 | - Output: :math:`(N, 4)` |
| 179 | Example: |
| 180 | >>> input = torch.rand(4, 3, 4) # Nx3x4 |
| 181 | >>> output = tgm.rotation_matrix_to_quaternion(input) # Nx4 |
| 182 | """ |
| 183 | if not torch.is_tensor(rotation_matrix): |
| 184 | raise TypeError('Input type is not a torch.Tensor. Got {}'.format( |
| 185 | type(rotation_matrix))) |
| 186 | |
| 187 | if len(rotation_matrix.shape) > 3: |
| 188 | raise ValueError( |
| 189 | 'Input size must be a three dimensional tensor. Got {}'.format( |
| 190 | rotation_matrix.shape)) |
| 191 | if not rotation_matrix.shape[-2:] == (3, 4): |
| 192 | raise ValueError( |
| 193 | 'Input size must be a N x 3 x 4 tensor. Got {}'.format( |
| 194 | rotation_matrix.shape)) |
| 195 | |
| 196 | rmat_t = torch.transpose(rotation_matrix, 1, 2) |
| 197 | |
| 198 | mask_d2 = rmat_t[:, 2, 2] < eps |
| 199 | |
| 200 | mask_d0_d1 = rmat_t[:, 0, 0] > rmat_t[:, 1, 1] |
| 201 | mask_d0_nd1 = rmat_t[:, 0, 0] < -rmat_t[:, 1, 1] |
| 202 | |
| 203 | t0 = 1 + rmat_t[:, 0, 0] - rmat_t[:, 1, 1] - rmat_t[:, 2, 2] |
| 204 | q0 = torch.stack([ |
| 205 | rmat_t[:, 1, 2] - rmat_t[:, 2, 1], t0, |
| 206 | rmat_t[:, 0, 1] + rmat_t[:, 1, 0], rmat_t[:, 2, 0] + rmat_t[:, 0, 2] |
| 207 | ], -1) |
| 208 | t0_rep = t0.repeat(4, 1).t() |
| 209 | |
| 210 | t1 = 1 - rmat_t[:, 0, 0] + rmat_t[:, 1, 1] - rmat_t[:, 2, 2] |
| 211 | q1 = torch.stack([ |
| 212 | rmat_t[:, 2, 0] - rmat_t[:, 0, 2], rmat_t[:, 0, 1] + rmat_t[:, 1, 0], |
| 213 | t1, rmat_t[:, 1, 2] + rmat_t[:, 2, 1] |
| 214 | ], -1) |
| 215 | t1_rep = t1.repeat(4, 1).t() |
| 216 | |
| 217 | t2 = 1 - rmat_t[:, 0, 0] - rmat_t[:, 1, 1] + rmat_t[:, 2, 2] |
| 218 | q2 = torch.stack([ |
| 219 | rmat_t[:, 0, 1] - rmat_t[:, 1, 0], rmat_t[:, 2, 0] + rmat_t[:, 0, 2], |
| 220 | rmat_t[:, 1, 2] + rmat_t[:, 2, 1], t2 |
| 221 | ], -1) |
| 222 | t2_rep = t2.repeat(4, 1).t() |
| 223 |
no outgoing calls
no test coverage detected