Multiply quaternion(s) q with quaternion(s) r. Expects two equally-sized tensors of shape (*, 4), where * denotes any number of dimensions. Returns q*r as a tensor of shape (*, 4).
(q, r)
| 31 | |
| 32 | |
| 33 | def qmul(q, r): |
| 34 | """ |
| 35 | Multiply quaternion(s) q with quaternion(s) r. |
| 36 | Expects two equally-sized tensors of shape (*, 4), where * denotes any number of dimensions. |
| 37 | Returns q*r as a tensor of shape (*, 4). |
| 38 | """ |
| 39 | assert q.shape[-1] == 4 |
| 40 | assert r.shape[-1] == 4 |
| 41 | |
| 42 | original_shape = q.shape |
| 43 | |
| 44 | # Compute outer product |
| 45 | terms = torch.bmm(r.view(-1, 4, 1), q.view(-1, 1, 4)) |
| 46 | |
| 47 | w = terms[:, 0, 0] - terms[:, 1, 1] - terms[:, 2, 2] - terms[:, 3, 3] |
| 48 | x = terms[:, 0, 1] + terms[:, 1, 0] - terms[:, 2, 3] + terms[:, 3, 2] |
| 49 | y = terms[:, 0, 2] + terms[:, 1, 3] + terms[:, 2, 0] - terms[:, 3, 1] |
| 50 | z = terms[:, 0, 3] - terms[:, 1, 2] + terms[:, 2, 1] + terms[:, 3, 0] |
| 51 | return torch.stack((w, x, y, z), dim=1).view(original_shape) |
| 52 | |
| 53 | |
| 54 | def qrot(q, v): |
no outgoing calls
no test coverage detected