Maths - Conversion Quaternion to Matrix - re: interesting method from Jay Ryness

By: thejaybird (thejaybird) - 2008-01-09 11:33
I've been using this method for many years but have never seen it published anywhere. It's not necessarily the fastest method, but is the most elegant IMO. On modern platforms with SIMD and shuffling, it's very fast. 
 
Matrix44 CreateRotation(const Quaternion& quat) 

Matrix44 m1( 
quat.w, quat.z, -quat.y, quat.x, 
-quat.z, quat.w, quat.x, quat.y, 
quat.y, -quat.x, quat.w, quat.z, 
-quat.x, -quat.y, -quat.z, quat.w ); 
 
Matrix44 m2( 
quat.w, quat.z, -quat.y, -quat.x, 
-quat.z, quat.w, quat.x, -quat.y, 
quat.y, -quat.x, quat.w, -quat.z, 
quat.x, quat.y, quat.z, quat.w ); 
 
return m1 * m2; 

 
It calculates the product of two simple matrices. The matrices have some very interesting features. Notice that they are identical and symmetric, except for the distribution of negations. The upper 3x3 is the same for both matrices, whereas the 4th row and column are transposed. I've put quite a bit of effort into finding ways to exploit that last bit of apparent symmetry/similarity, but haven't been able to simplify it any further. If anyone has any insight into this, I would be very keen to hear it. 
 
Note that it's assumed the quaternion is unit length. Otherwise, the resulting matrix will be scaled.
By: Martin Baker (martinbakerProject Admin) - 2008-01-10 01:48
This is very interesting, I don't know why this works, My first guess is that it might be related to either: 
 
* constructing a rotation from two reflections? 
* Pauli matricies? 
 
but I can't make either work at the moment, perhaps someone else can help? 
 
I would like to put this on the web page, It this alright with you? If so how would you like to be named: thejaybird? 
 
Thanks, 
 
Martin 
 
 
2 reflections 
------------- 
A single reflection in a line Px,Py,Pz is given by the symmetrical(including signs) matrix: 
 
-Px² + Pz²+ Py² - 2 * Px * Py - 2 * Px * Pz 
- 2 * Py * Px -Py² + Px² + Pz² - 2 * Py * Pz 
- 2 * Pz * Px -2 * Pz * Py -Pz² + Py² + Px² 
 
So could each of the 4x4 matricies be related to a reflection? I can't make this work. 
 
 
Pauli matricies 
--------------- 
The Pauli matricies usually represent i,j,k as: 
 
0 -i 
i 0 
 
0 1 
1 0 
 
1 0 
0 -1 
 
but we can also expand this out to a 4x4 version (I'm not sure I've got the signs correct): 
 
0 0 +1 0 | 0 0 0 1 | 0 +1 0 0 
0 0 0 -1 | 0 0 1 0 | +1 0 0 0 
-1 0 0 0 | 0 1 0 0 | 0 0 0 -1 
0 +1 0 0 | 1 0 0 0 | 0 0 -1 0 
 
We can take a linear combination of these (with the identity matrix) to give somthing like: 
 
+w x +y +z 
+x w +z -y 
-y z +w -x 
+z y -x +w 
 
So we can transform points by using the 'sandwich product' like: 
p' = [M][p][M]^t 
 
I was wondering if there is some rule we could use to reverse the order to give some variation of: 
[M][M]^t

By: thejaybird (thejaybird) - 2008-01-10 16:09
Yes, please go ahead and put it up on the website, by all means. You can use my real name, Jay Ryness. 
 
I don't have much to add, but I am reminded of some work I was doing years ago with geometric algebra. In GA, the product of two multivectors can be implemented as a 4x4 matrix multiplication, where the operands look basically like the multivector was scrambled into a 4x4 matrix not too unlike the operands in the quaternion product above, except that a multivector in GA has 8 scalar components rather than 4, and I think some of the expressions in the matrix may have been slightly more involved than a simple negation, but not much. Anyway, rotors (which are a specialized form of multivectors, where 4 of the 8 scalar components happen to be zero--I'm sure know all this stuff much better than I) are, IIRC, isomorphic to quaternions, or close enough. I haven't verified it, but I would venture to guess that if one were to write out the GA product of two rotors as a 4x4 matrix multiplication, it would simplify to something very similar if not identical to the quaternion product implementation above. 
 
It's also worth noting that rotors are logically constructed as the composition of two reflections, and all of this is tightly coupled with complex numbers, quaternions, Pauli matrices and the like. So, I think you're definitely on a good track with your approach. 
 
I should point out that I'm not a mathematician and it's been years since I delved into this stuff, and furthermore I'm shooting from the hip, so take my abstract mathematical observations for what they're worth. 
 
Anyway, thanks for taking an interest. I'll be keeping an eye out for developments. 
 
-Jay

Follow up message

Following this thread Tim Meehan has kindly sent me a message telling me that this article on Wikipedia has a section on isoclinic decomposition about how a quaternion can be converted to a 4x4 matrix by performing matrix multiplication on two simpler 4x4 matricies.

I think this sheds light on the subject and my intuition tells me this is important, I'll have to give this some thought.

Another Follow Up Message

From: Corey Powell
Date: 23/4/2009 21:03:34

I'm examining matrix math on the net and I ran across some things you
published. quaternions to matrix 'the sexy way'. I saw it mentioned that you
nor the other guy knew exactly why multiplying the 2 matrixes created by
quaternions came out as a rotation matrix. I wasn't sure if you or he had
figured it out.

Reorder the matrix so that instead of coming out X,Y,Z,W order, it comes out W,X,Y,Z order (like a quaternion is done in the documentation). It seems that was the only source of confusion. If you take the following and break it down into two matrixes, one where Q1 is broken down into colums, the other where Q2 is broken down, they're the same as the matrixes you posted in your 'the sexy way' article that I saw. The only difference is that matrixes are popularly ordered like 3x3 with 4th elements on the side and bottom, and quaternions are W oriented. I think the 2nd matrix was the 1/Q matrix.

(Q1*Q2).w=( +w1w2 -x1x2 -y1y2 -z1z2 )
(Q1*Q2).x=( +w1x2 +x1w2 +y1z2 -z1y2 )
(Q1*Q2).y=( +w1y2 -x1z2 +y1w2 +z1x2 )
(Q1*Q2).z=( +w1z2 +x1y2 -y1x2 +z1w2 )

Q1*Q2 (plug in Q2)

W2

X2

Y2

Z2

+W1 -X1 -Y1 -Z1

W3

+X1 +W1 -Z1 +Y1

X3

+Y1 +Z1 +W1 -X1

Y3

+Z1 -Y1 +X1 +W1

Z3

Q1*Q2 (plug in Q1)

W1

X1

Y1

Z1

+W2 -X2 -Y2 -Z2

W3

+X2 +W2 +Z2 -Y2

X3

+Y2 -Z2 +W2 +X2

Y3

+Z2 +Y2 -X2 +W2

Z3

Here are the 2 matrixes from the original post converted to W,X,Y,Z order

Q

+W -X -Y -Z
+X +W -Z +Y
+Y +Z +W -X
+Z -Y +X +W

Inverted Conj (Q)

+W +X +Y +Z
-X +W -Z +Y
-Y +Z +W -X
-Z -Y +X +W

Your post shows the matrixes as:

q.w q.z -q.y q.x -q.z q.w q.x q.y q.y -q.x q.w q.z -q.x -q.y -q.z q.w

q.w q.z -q.y -q.x -q.z q.w q.x -q.y q.y -q.x q.w -q.z q.x q.y q.z q.w
In a traditional rotation matrix, a value in the y/x slot represents
data subtracted from the x axis and added into the y axis. The mere presence
of a number though in a matrix row or column represents a presence between
axises. Negative numbers still have presence, just in the opposite
direction; they're still a gain. Your quaternion matrix posted above, which
you could consider as a 'quaternion matrix', denotes an absence of
relationship to an axis. In other words, a value like qz above in the y/x
field indicates that the relationship to x and y is actually lost from the z
axis. Quaternions work in a "don't ask don't tell" relationship, where
instead of axises we're dealing with imaginary dimensions. The presence of w
denotes real presence, but the other variables sort of imply a lack of
presence.

Another thing to try to imagine here is that the q.z field in your matrix is
a rotation on the z axis. Of course a rotation on the z axis creates a
relationship between x and y. So you will see q.z present in the x and y row
and column. The only reason q.z appears in the z row or column is when it's
paired with w and z, because you can move rotation from w to z and it
doesn't change the z axis. That is the opposite of what I was saying in the
previous paragraph, but it still implies that transparency between
dimensions that I'm trying to relate here.

Martin I think your site is excellent. I've been to it a few times through
the years.

By: thejaybird (thejaybird) - 2010-08-08 21:51:47 UTC

Here's my derivation of the 2-matrix product quaternion-to-matrix conversion. Sorry for the delay, I've been meaning to post this for a long time.

Remember the standard formula for vector rotation by a quaternion:

q v ~q

The trick is to represent each product above as a matrix transform and then concatenate the results.

I'll represent the quaternion as a rotor in geometric algebra since that is more comfortable for me, but you can get exactly the same result using the standard formula for quaternion product.

Our rotor 'q' in expressed in a bivector basis: q1 e2e3 + q2 e3e1 + q3 e1e2 + q4

(e2e3, e3e1, and e1e2 may correspond to the yz, zx, and xy planes)

We want to calculate q v ~q so first we will find a matrix to represent multiplication by a rotor on the left.

let I = e1e2e3

(q1 e2e3 + q2 e3e1 + q3 e1e2 + q4) e1      q1 I  +  q2 e3 + -q3 e2 + q4 e1
                                   e2  =  -q1 e3 +  q2 I  +  q3 e1 + q4 e2
                                   e3      q1 e2 + -q2 e1 +  q3 I  + q4 e3
                                   I      -q1 e1 + -q2 e2 + -q3 e3 + q4 I

which is the matrix

| q4 -q3  q2  q1|
| q3  q4 -q1  q2|
|-q2  q1  q4  q3|
|-q1 -q2 -q3  q4|

Now if we follow exactly the same process for right-multiplication by the rotor's inverse (-q1 e2e3 + -q2 e3e1 + -q3 e1e2 + q4) we will get the matrix:

e1 (-q1 e2e3 + -q2 e3e1 + -q3 e1e2 + q4)     -q1 I  +  q2 e3 + -q3 e2 + q4 e1
e2                                        =  -q1 e3 + -q2 I  +  q3 e1 + q4 e2
e3                                            q1 e2 + -q2 e1 + -q3 I  + q4 e3 
I                                             q1 e1 +  q2 e2 +  q3 e3 + q4 I

which is obviously

| q4 -q3  q2 -q1|  
| q3  q4 -q1 -q2|
|-q2  q1  q4 -q3|
| q1  q2  q3  q4|

Now we have a matrix for left multiplication (q v) and for right multiplication by the conjugate (v ~q) which we wish to apply sequentially, so we just concatenate them

                            | q4 -q3  q2  q1|   | q4 -q3  q2 -q1|
q v ~q =   | v1 v2 v3 0 | * | q3  q4 -q1  q2| * | q3  q4 -q1 -q2|
                            |-q2  q1  q4  q3|   |-q2  q1  q4 -q3|
                            |-q1 -q2 -q3  q4|   | q1  q2  q3  q4|

I notice that it isn't identical to the original factorization, but it does produce the same result.

-Jay


metadata block
see also:

 

Correspondence about this page

Book Shop - Further reading.

Where I can, I have put links to Amazon for books that are relevant to the subject, click on the appropriate country flag to get more details of the book or to buy it from them.

cover us uk de jp fr ca Matrix Computations

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2014 Martin John Baker - All rights reserved - privacy policy.