Monday, August 27, 2018

Quaternions are just a weird encoding of a rotation around a vector

Whenever the topic of Quaternions comes up, programmers I talk to are always annoyed by them. Quaternions seem useful, but tutorials that give nice intuitive pictures are very hard to find. Just look at the Wikipedia page and you'll see what I mean.

Let's fix that :)

The takeaway here is this: a single Quaternion is equivalent to an axis (3D unit vector) and a rotation θ degrees around that axis. Quaternions are just a weird encoding of these 4 values that make some computations nice.

How do we get the angle axis representation? Given a quaternion $Q=(q_x,q_y,q_z,q_w)$, our axis of rotation $V=(v_x, v_y, v_z)$ is:

$v_x = q_x / \sqrt{1-q_w*q_w}$
$v_y = q_y / \sqrt{1-q_w*q_w}$
$v_z = q_z / \sqrt{1-q_w*q_w}$

and our rotation angle $\theta_V$

$\theta_V = 2 * acos(q_w)$

You can just call this $\theta$, I just use this notation to make it clear that this is the axis $V$'s angle and not some other axis $W=(w_x, w_y, w_z)$'s angle (which would be $\theta_W$).

Cool so that's nice. Intuitively, rotating objects with these is nice: we stick the axis $V$ pointing out from the center of that object, then rotate the object $\theta_V$ around it. But how do we represent this in code? If you have a library (such as Unity) that has quaternions, just use their code. If not, see my follow up blog post.

The important takeaway here is that every time you use a quaternion, just imagine it as an angle axis in your head.

For example, given two quaternions Q_V and Q_U that by using the formula above map to angle axes $V=(v_x, v_y, v_z), \theta_V$ and $U=(u_x, u_y, u_z), \theta_U$, if you do $Q_V*Q_U$ that is equivalent to a new angle axis that rotates by V and U.

What order do these happen in? Well, rotations are weird in that they are associative (you can swap parenthesis, so $(Q_V*Q_U)Q_W=Q_V*(Q_U*Q_W)$), but they aren't communicative so $Q_V*Q_W$ isn't always equal to $Q_W*Q_V$. So if want to rotate some $M$,

$M*Q_V*Q_U$

means: rotate M by V, and then by U

while

$Q_V*Q_U*M$

means: rotate M by U, and then by V.

The main reason we use quaternions (as far as I know) is that to rotate positions and vectors using angle-axis, you end up using some sins, cos, dot products, etc. With quaternions you can rotate positions and vectors via linear functions that you can just represent as a 4x4 matrix.