This page summarizes three different methods to convert a quaternion to a Rotation matrix. They are mathematically equivalent. Example code is provided in Python. Results are compared against those by scipy.
Let a quaternion be defined as,
w is the scalar component and [x, y, z] is the vector component.
The off-diagonals are identical to those of method 1 but the diagonal elements are different. It can be shown that the diagonal elements are identical too using the fact that quaternions representing rotations are unit quaternions:
For example the first row, first column is:
where [v×] is the skew symmetric cross product operator matrix:
Note that the transpose can be calculated by:
from scipy.spatial.transform import Rotation import numpy as np def get_rotation_matrix_1(x, y, z, w): w2 = w*w x2 = x*x y2 = y*y z2 = z*z r11 = w2 + x2 - y2 - z2 r12 = 2 * (x*y - w*z) r13 = 2 * (w*y + x*z) r21 = 2 * (x*y + w*z) r22 = w2 - x2 + y2 - z2 r23 = 2 * (y*z - w*x) r31 = 2 * (x*z - w*y) r32 = 2 * (y*z + w*x) r33 = w2 - x2 - y2 + z2 return np.array([ [r11, r12, r13], [r21, r22, r23], [r31, r32, r33] ]) def get_rotation_matrix_2(x, y, z, w): r11 = 2 * (w*w + x*x) - 1 r12 = 2 * (x*y - w*z) r13 = 2 * (x*z + w*y) r21 = 2 * (x*y + w*z) r22 = 2 * (w*w + y*y) - 1 r23 = 2 * (y*z - w*x) r31 = 2 * (x*z - w*y) r32 = 2 * (y*z + w*x) r33 = 2 * (w*w + z*z) - 1 return np.array([ [r11, r12, r13], [r21, r22, r23], [r31, r32, r33] ]) def get_rotation_matrix_3(x, y, z, w): c = np.array([ [0, -z, y], [z, 0, -x], [-y, x, 0] ]) return np.eye(3) + 2*w*c + 2*c@c # Quaternion x = 0 y = 0 z = np.sin(np.pi/4) w = np.cos(np.pi/4) print(Rotation.from_quat((x, y, z, w)).as_matrix()) print(get_rotation_matrix_1(x, y, z, w)) print(get_rotation_matrix_2(x, y, z, w)) print(get_rotation_matrix_3(x, y, z, w))
Output:
[[ 0. -1. 0.] [ 1. 0. 0.] [ 0. 0. 1.]] [[ 0. -1. 0.] [ 1. 0. 0.] [ 0. 0. 1.]] [[ 2.22044605e-16 -1.00000000e+00 0.00000000e+00] [ 1.00000000e+00 2.22044605e-16 0.00000000e+00] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]] [[-2.22044605e-16 -1.00000000e+00 0.00000000e+00] [ 1.00000000e+00 -2.22044605e-16 0.00000000e+00] [ 0.00000000e+00 0.00000000e+00 1.00000000e+00]]
It shows that the three methods are identical and match with the result of scipy.