Folded into the mixed baklava of my 2018, was a special mathematical bit of honey. With the help of some excellent YouTube videos, the light bulb finally went on for me, and I could see quaternions. Judging by online comments I’ve read, I wasn’t alone in the dark.
There does seem a conceptual stumbling block (I tripped, anyway), but once that’s cleared up, quaternions turn out to be pretty easy to use. Which is cool, because they are very useful if you want to rotate some points in 3D space (a need I’m sure many of have experienced over the years).
The stumbling block has to do with quaternions having not one, not two, but three distinct “imaginary” numbers.
The Complex Plane (it’s simple)
(If you’re reading this, I assume you have some familiarity with numbers, so I won’t get too basic.)
A complex number, c, has the form:
c = a + bi
Where c is a complex number, a and b are real numbers, and i is the infamous square root of -1.
(While i might bother some, it turns out to be necessary in basic mathematics. It’s the only way polynomials such as x2+4 can have a root.)
A complex number, with its two parts, can be treated as a two-dimensional XY coordinate:
c = [x, yi]
Which means complex numbers are inherently two-dimensional.
To actually plot a complex number, we just ignore the i part and plot the two real number parts as x and y.
What matters here is that the behavior of i creates an interesting property when it comes to multiplication of two complex numbers.
Specifically, if a complex number is considered as a vector with its tail at the origin (0,0) and the head at the coordinates, then a complex number also has an angle with respect to the axis.
Multiplying complex numbers C2 by C1 rotates C2’s angle by C1’s angle. (Assuming C1 is a unit vector — that its magnitude is one.)
So the complex plane allows easy rotation of points around the origin. Just multiply the points by some unit vector complex number with the desired angle.
Complex numbers let us do interesting things on the complex plane; quaternions let us do interesting things in three-dimensional space.
A quaternion looks like this:
q = a + bi + cj + dk
Where a, b, c, & d, are real numbers, and i, j, & k, are special “imaginary” numbers (secret sauce).
At first glance, this might make them seem like four-dimensional numbers. Which they are, strictly speaking. But another way to view them is as a real value plus a three-vector:
q = r + [xi, yj, zk]
Used like this, the complex numbers give the three-vector some special properties: the ability to rotate points in 3D space.
As with the complex numbers, when actually plotting a quaternion, we ignore i, j, & k, and plot the real numbers, x, y, & z. (Remember, the magic is in the multiplication behavior, which doesn’t ignore the complex parts.)
Complex numbers allow rotation in a plane, and three (interlocked!) rotation planes give us rotations in 3D space.
If you think about how a point in 3D space projects values onto the X, Y, & Z axes, then you can perhaps imagine how a rotation in 3-space projects rotations onto X, Y, & Z (complex) planes.
Secret “Magic Sauce”
Now, here’s where it gets a little weird, and this might be the stumbling block that challenges people about quaternions.
The quaternion complex coefficients, i, j, & k, just like the i used in the complex numbers, each have the property that their square is -1.
i2 = j2 = k2 = ijk = -1
Now, if you let that sink in, it almost doesn’t make sense. One gets — or at least I got — the impression that j and k were just placeholder names for i, that all three were the same thing.
That their squares all give -1 sure makes it seem that way.
But it’s not that way. They are completely different magic numbers that share properties with the good old i from complex numbers!
(Focus on the ijk = -1 part to see they have to be different!)
It may help to understand that these are basis vectors — orthogonal axes — on different complex planes. It’s exactly like how X, Y, & Z axes are orthogonal to each other even though they’re all represented by real numbers.
So think of i, j, & k, as three different flavors of “magic sauce” for the X, Y, & Z axes, respectively.
This complicates quaternion multiplication.
Table 1 (right) shows the multiplication table for quaternions (but there’s an easier way).
A key feature is that multiplication does not commute. (Hopefully, it does compute, though.)
To understand how it works, it’s again helpful to start with complex numbers.
To multiply two complex numbers, c3 = c1 × c2, we do:
c3 = [a, bi] × [c, di] = ac + adi + bci + bdi2 = ac + (ad + bc)i - bd = [(ac - bd), (ad + bc)i]
Where a, b, c, & d, are all real numbers.
The trick here is that the i2 resolves to -1, which provides a scalar (which is added to the scalar product). Meanwhile the two terms with i add to provide the “imaginary” part of the new complex number.
A similar situation exists when it comes to quaternions. (Only with many more terms and three complex units.)
To multiply quaternions, q3 = q1 × q2, we do:
q3 = q1 × q2 = [a1, b1i, c1j, d1k] × [a2, b2i, c2j, d2k] = a1a2 + a1b2i + a1c2j + a1d2k + b1a2i + b1b2ii + b1c2ij + b1d2ik + c1a2j + c1b2ji + c1c2jj + c1d2jk + d1a2k + d1b2ki + d1c2kj + d1d2kk
Now reduce the i, j, & k, pairs according to the multiplication rules…
q3 = a1a2 + a1b2i + a1c2j + a1d2k + b1a2i + b1b2i2 + b1c2k - b1d2j + c1a2j - c1b2k + c1c2j2 + c1d2i + d1a2k + d1b2j - d1c2i + d1d2i2
And convert any i2, j2, or k2, to -1:
q3 = a1a2 + a1b2i + a1c2j + a1d2k + b1a2i - b1b2 + b1c2k - b1d2j + c1a2j - c1b2k - c1c2 + c1d2i + d1a2k + d1b2j - d1c2i - d1d2
And, finally, collect the like terms:
q3 = (a1a2 - b1b2 - c1c2 - d1d2) + (a1b2 + b1a2 + c1d2 - d1c2)i + (a1c2 - b1d2 + c1a2 + d1b2)j + (a1d2 + b1c2 - c1b2 + d1a2)k
It looks like a mess, but only that final equation matters (I just showed how we got there). It can easily be coded in any (adequate) programming language.
Quaternion addition (or subtraction) is member-wise, so that’s simple.
q3 = q1 + q2 = [a1, b1i, c1j, d1k] + [a2, b2i, c2j, d2k] = [(a1 + b1), (a2 + b2)i, (a3 + b3)j, (a4 + b4)k]
A few other operations, and we’re ready to rotate! But first a quick detour…
Real, Complex, Quaternion, Octonion
Quaternions have all sorts of wonderful mathematical properties (that are utterly beyond me), and they apparently have a strong connection with Special Relativity in being 4D numbers.
Turns out they’re part of a progression of number types we find useful in the real world: natural numbers (ℕ), integers (ℤ), and rationals (ℚ), which got us started with analyzing stuff. Then…
- The reals (ℝ) are necessary in general science.
- The complex numbers (ℂ) are necessary in physics.
- The quaternions (ℍ) are useful in SR (I’m told).
- The octonions (𝕆) might be useful in quantum physics.
What’s fascinating is that the four items listed above are the only division algebras. Each type adds interesting properties, but each also loses something:
- The real numbers aren’t tamed by algebra (because of transcendental numbers).
- The complex numbers aren’t ordered (no sort for multi-dimensional numbers).
- The quaternions aren’t communitive (a×b ≠ b×a).
- The octonions aren’t even associative ([a×b]×c ≠ a×[b×c]).
But what interested me — and which might interest a lot of programmers — is this: How the heck do you rotate something with a quaternion?
Rotating With Quaternions
I can tell you how to make it work; I finally figured out how to cast the spells. But I have absolutely no clue (yet!) as to exactly why it works — I’m a programmer, not a mathematician. (Damn it.)
The short (unhelpful (but bear with me)) version (also the bottom line) goes like this:
P' = Q × P × Q-1
P’ is the result of rotating P, the point we want to rotate.
Note that P, in reality an [x, y, z] coordinate, is expressed as the quaternion: [0, xi, yj, zk].
Q is the rotation quaternion, and Q-1 is its inverse.
It was confusing descriptions of this process that made it hard for me to figure out what was really going on. To some extent, it was all the extra information that made it hard to absorb the key aspects.
Once I filtered out the stuff real mathematicians need to know about quaternions, it turned out to be fairly simple.
It really does boil down to sticking a [x,y,z] coordinate into a quaternion with its real part set to zero. Then multiply the rotation quaternion by the point quaternion and then by the inverse of the rotation one.
The resulting quaternion has the new [x,y,z] in its vector part. Easy Peasy.
Part of the trick is the rotation quaternion and its inverse.
First pick the rotation vector. Find the [x, y, z] that, as a vector, is the rotation axis. If necessary, normalize it so it’s a unit vector.
Then pick a rotation angle, the number of degrees to rotate whatever is being rotated.
As a simple example, assume we want to spin something like a top, about its vertical axis. And let’s say we want to rotate it five degrees (5°) each step.
The unit vector here is simple; it’s just [0,1,0].
Let’s include a second example with a non-orthogonal angle: [+10,-3,+5]. We need to take the unit vector of that: [+0.864, -0.259, +0.432].
Create a rotation quaternion like this:
Qrot = [cos(θ/2), Vxsin(θ/2), Vysin(θ/2), Vzsin(θ/2)]
Where Q is the rotation quaternion, V is the rotation vector, and θ is the rotation angle.
For the “spin like a top” example, the rotation quaternion is (notice that the x and z parts are still zero):
Qrot = [+0.999048, +0.0i, +0.043619j, +0.0k]
The second example’s rotation quaternion is:
Qrot = [+0.999048, +0.037681i, -0.011304j, +0.018841k]
We also need Qrot-1, the inverse, or reciprocal, of Qrot.
For quaternions, this is defined as: Q* ÷ |Q|2.
That is, the complex conjugate of Q (notated as Q*) divided by the squared norm (aka magnitude, notated as |Q|).
Note that we’re dividing the vector, Q*, by a scalar here, which results in a new vector. (The inverse of a quaternion is a quaternion.)
The complex conjugate of a quaternion, as with a complex number, just inverts the complex parts. For a quaternion, Q* = [a, -bi, -cj, -dk].
The bottom line is that (first example):
Qrot-1 = [+0.999048, -0.0i, -0.043619j, -0.0k]
…and (second example)…
Qrot-1 = [+0.999048, -0.037681i, +0.011304j, -0.018841k]
Now all we do is carry out the multiplication:
P' = Q × P × Q-1
Note that this moves one point one step. To rotate all the points of an object, apply the rotation quaternion to each point.
To rotate an object multiple steps (in a complete revolution, for instance), keep rotating the points. The example above steps 5°, so 72 steps makes a complete revolution.
Here’s a great video about quaternions:
And here’s a really cool quaternion explorer and tutorial:
They are well worth checking out!
Stay rotating, my friends!