When I calculate a rotation matrix from a quaternion, it seems to be in the opposite direction. For instance:
For a rotation of +45 degrees about the Y-axis, I would expect to get the following matrix:
# Pesudo Code
m1 = Matrix()
m1.RotateEulerY(45)
m1 =
| 0.71 0.00 0.71 0.00 |
| 0.00 1.00 0.00 0.00 |
| -0.71 0.00 0.71 0.00 |
| 0.00 0.00 0.00 1.00 |
However the rotation matrix calculated from a quaternion with the same rotation is
# Pesudo Code
axis_angle = AxisAngle((0,1,0), 45)
quat = Quaternion(axis_angle)
quat = { 0.0,0.375,0.0,0.927 }
rotate_matrix = quat.ToRotationMatrix()
rotate_matrix =
| 0.72 0.00 -0.69 0.00 |
| 0.00 1.00 0.00 0.00 |
| 0.69 0.00 0.72 0.00 |
| 0.00 0.00 0.00 1.00 |
Which happens to be a rotation of -45 about the Y-axis. I have tried to get the rotation matrix from the angle axis and it the same as the expected result.
Is this the expected behaviour or have I made a mistake/assumption somewhere? (Yes, the answers are not exactly the same; for now I am assuming it is a rounding error since the answers are so close).
Background info: I am using column major matrix, i.e. OpenGL style. The algorithms used to calculate the rotation matrix from the quaternion comes from http://www.j3d.org/matrix_faq/matrfaq_latest.html, Q54.
UPDATE #1
As teodron suggested, , I have tried to do a Quaternion(q) to Rotation Matrix(M) and back to Quaternion combination (i.e. q->M->q'). I also did a M->q->M' conversion for sanity check.
While q == q' and M == M', the conversion between q and M is wrong!
The rotation used in the example is the same as before, a rotation of +45 around the Y-axis. The matrix is right hand orientated, using column major vector, a.k.a openGL conformance. Matrix and Quaternion format is shown below:
# | 0 4 8 12 |
# M = | 1 5 9 13 |
# | 2 6 10 14 |
# | 3 7 11 15 |
#
# q = {i,j,k,w}
First convert M to q then back to q.
#M->q->M'
# I am confident M is the correct representation for the rotation.
M =
| 0.71 0.00 0.71 0.00 |
| 0.00 1.00 0.00 0.00 |
| -0.71 0.00 0.71 0.00 |
| 0.00 0.00 0.00 1.00 |
# Here I would expect the quaternion to be all positive, but the
# j component is negative!
q =
{ 0.00, -0.38,0.00, 0.92}
# M' == M
M' =
| 0.71 0.00 0.71 0.00 |
| -0.00 1.00 0.00 0.00 |
| -0.71 -0.00 0.71 0.00 |
| 0.00 0.00 0.00 1.00 |
second part: from q to M to q'
#q->M->q'
# I have created the quaternion from both an axis angle and euler angle
# and both approaches give me the same answer
q =
{ 0.00, 0.37,0.00, 0.93}
# Here M is different from the Matrix in the first part
M =
| 0.72 0.00 -0.69 0.00 |
| 0.00 1.00 0.00 0.00 |
| 0.69 0.00 0.72 0.00 |
| 0.00 0.00 0.00 1.00 |
# but q' == q!
q' =
{ 0.00, 0.37,0.00, 0.93}
Since the q<->M is consistently wrong, I thought I would focus on q->M for now.
I had check the formula to convert a quaternion to matrix across different sources and they are all consistent with one another. Basically the normal maths style, row-major matrix is as follows: (taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm)
| 1 - 2(kk + jj) 2(ij - kw) 2(jw + ik) |
| 2(ij + kw) 1 - 2(ii + kk) 2(jk - iw) |
| 2(ik - jw) 2(jk + iw) 1- 2(jj + ii) |
Hence the openGL column major matrix equivalent should be
| 1 - 2(kk + jj) 2(ij + kw) 2(ik - jw) |
| 2(ij - kw) 1 - 2(ii + kk) 2(jk + iw) |
| 2(jw + ik) 2(jk - iw) 1- 2(jj + ii) |
Comparing this with the column major rotation matrix as generated via a rotation of angle A around Y axis.
| cos(A) 0 sinA |
| 0 1 0 |
| -sinA 0 cosA |
Now the problem is more obvious to me: Looking at M[2] for both matrices, the quaternion matrix ,(2(jw + ik)), will produce a positive while the rotation matrix, -sinA, will produce a negative value!
I am at a loss here; I cannot think of a reason why these two matrices differ and I don't know what should I investigate next.Any ideas?
UPDATE #2
This is an update to explain the solution to the problem. Basically it boils down to how I ordered the elements in the matrices. For my case I did not need to transpose the original quaternion to matrix formula; some websites do perform the transpose because they have ordered it differently.