MCPcopy Create free account
hub / github.com/MotrixLab/AiOS / rotation_matrix_to_quaternion

Function rotation_matrix_to_quaternion

detrsmpl/utils/geometry.py:166–244  ·  view source on GitHub ↗

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)

Source from the content-addressed store, hash-verified

164
165
166def 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

Callers 1

Calls

no outgoing calls

Tested by

no test coverage detected