Unit Quaternions in Rotation
Most people know about rotation matrices, and unit vectors, but it's rare to run across someone who knows what a unit quaternion is, or why it might be useful.
Turns out that unit quaternions are very good computationally for representing and manipulating orientation. They can be converted either to a conventional rotation matrix when needed to interface with components based on those techniques.
A quaternion q is a 4-tuple of values, similar to a vector with 4 components.
q = [a, b, c, d]
Additionally, unit quaternions have a 2-norm equal to 1:
||q|| = √ ( a2 + b2 + c2 + d2 ) = 1
It turns out that there are fairly simple rules to combine take a vector and combine it with a quaternion so that the net effect is the vector underwent a specific rotation. We can then associate the rotation with the quaternion. There is a simple way to reverse the rotation, which equates to inverting the quaternion.
It's also simple to combine quaternions to represent a sequence of transformations. To do so, requires 16 multiplies, and 4 divides to renormalize, while rotation matrices require 27 multiplies and 9 divides to renormalize.
To combine rotations, quaternion product is used:
q1 q2 = [
a1a2 - b1b2 - c1c2 - d1d2,
a1b2 + b1a2 + c1d2 - d1c2,
a1c2 - b1d2 + c1a2 + d1b2,
a1d2 + b1c2 - c1b2 + d1a2 ]
and the inverse rotation is applied using the quaternion conjugate q*, defined such that for all q1 and q2
q1* (q1 q2) = q2
For unit quaternions the conjugate simplifies to:
q* = [a, -b, -c, -d]
To rotate a local vector v = (x, y, z) into global coordinates v' = (x', y', z') use the vector part of normal quaternions:
[0, x', y', z'] = q [0, x, y, z] q*
The inverse rotation is
[0, x, y, z] = q* [0, x', y', z'] q
This forumlation completely avoids singularities like gimbal lock when using euler angles. However for any particular orientation, there are always two unit quaternion values that can both be used to represent it. In practice, it is the transformations that are important, and this ambiguity doesn't get in the way.
I used this as the basis for my geometry engine and implemented very lightweight real-time physical simulation of connected mechanical linkages shown in the applets below.