# A Note on Rotations

You probably recall from graphics class that we like to use objects called "quaternions" to represent rotations. These notes provide an engineer's-eye view of why this makes sense.

Recall: Why not euler angles? Gimbal lock.

# Starting Point: Axis + Angle

Let's start with an obvious alternative to Euler angles: storing a rotation as a pair of an unit-length axis $$u$$ (the direction to rotate around) and an angle $$\theta$$ (the angle to rotate by). Now we can have our code perform rotations as follows:

$\mathrm{rotate}((u,\theta),s) \equiv (s\cdot u)u + \cos(\theta)(s - (s\cdot u)u) + \sin(\theta)(u \times s)$

This is a perfectly fine way to rotate things, but we find ourself with a few annoying problems: composing rotations; $$\theta$$ being an angle (gotta compute trig functions every rotation; gotta throw a mod2pi into computations occasionally).

# Look Over Here For A Moment

Let's define three units -- $$\mathbf{i}$$, $$\mathbf{j}$$, and $$\mathbf{k}$$ -- and the following identity $$\mathbf{i}^2=\mathbf{j}^2=\mathbf{k}^2=\mathbf{i}\mathbf{j}\mathbf{k}=-1$$.

Consequences of the above identity (note: unit products turn out to be antisymmetric!):

$\mathbf{i}\mathbf{j} = -\mathbf{i}\mathbf{j}(\mathbf{k}^2) = -(\mathbf{i}\mathbf{j}\mathbf{k})\mathbf{k} = \mathbf{k}$ $\mathbf{j}\mathbf{i} =-\mathbf{k}^2 \mathbf{j}\mathbf{i} =-(\mathbf{k}\mathbf{i}\mathbf{j}) \mathbf{j}\mathbf{i} =-\mathbf{k}(\mathbf{i}\mathbf{j} \mathbf{j}\mathbf{i}) =-\mathbf{k}$ $\mathbf{i}\mathbf{k} =-\mathbf{j}$ $\mathbf{k}\mathbf{i} = \mathbf{j}$ $\mathbf{j}\mathbf{k} = \mathbf{i}$ $\mathbf{k}\mathbf{j} =-\mathbf{i}$

We'll call the field we get by adjoining $$\mathbb{R}$$ with these units $$\mathbb{H}$$:

$\mathbb{H} \equiv \{ x \mathbf{i} + y \mathbf{j} + z \mathbf{k} + w \;|\; x,y,z,w\in\mathbb{R} \}$

As a quick warm-up, let's look at what happens if we take two vectors in $$\mathbb{R}^3$$, map them to $$\mathbb{H}$$ in a reasonable way ($$\def\H#1{{\overrightarrow{#1}}} \H{s} \equiv s_x\mathbf{i} + s_y\mathbf{j} + s_z\mathbf{j}$$), and multiply them:

$\begin{eqnarray} \H{u}\H{v} & = & (u_x\mathbf{i} + u_y\mathbf{j} + u_z\mathbf{k}) (v_x\mathbf{i} + v_y\mathbf{j} + v_z\mathbf{k}) \\ & = & u_x\mathbf{i} (v_x\mathbf{i} + v_y\mathbf{j} + v_z\mathbf{k}) + u_y\mathbf{j} (v_x\mathbf{i} + v_y\mathbf{j} + v_z\mathbf{k}) + u_z\mathbf{k} (v_x\mathbf{i} + v_y\mathbf{j} + v_z\mathbf{k}) \\ & = & (-u_x v_x + u_x v_y\mathbf{k} - u_x v_z\mathbf{j}) + (-u_y v_x\mathbf{k} - u_y v_y + u_y v_z\mathbf{i}) + (u_z v_x\mathbf{j} - u_z v_y\mathbf{i} - u_z v_z) \\ & = & (u_y v_z - u_z v_y)\mathbf{i} + (-u_x v_z + u_z v_x)\mathbf{j} + (u_x v_y - u_y v_x)\mathbf{k} + (-u_x v_x - u_y v_y - u_z v_z) \\ & = & \H{u\times v} - u\cdot{}v \end{eqnarray}$

Woah! Notice that we've just computed the cross product minus the dot product, sort of! Actually, this ends up being sort of obvious if you squint a bit, and think about $$\mathbf{i}$$, $$\mathbf{j}$$, and $$\mathbf{k}$$ as the vectors $$(1,0,0)$$, $$(0,1,0)$$, and $$(0,0,1)$$ and the products between then as being resolved with $$\times$$.

What about multiplying two quaternions $$q,r\in\mathbb{H}$$?

$\begin{eqnarray} (\H{q_{xyz}}+q_{w})(\H{r_{xyz}}+r_{w}) & = & \H{q_{xyz}}(\H{r_{xyz}}+r_{w}) + q_{w}(\H{r_{xyz}}+r_{w}) \\ & = & \H{q_{xyz}}\H{r_{xyz}} +\H{q_{xyz}r_{w}} +\H{q_{w}r_{xyz}} +q_{w}r_{w} \\ & = & \H{q_{xyz} \times r_{xyz}} - q_{xyz} \cdot r_{xyz} +\H{q_{xyz}r_{w}} +\H{q_{w}r_{xyz}} +q_{w}r_{w} \\ & = & \H{q_{xyz} \times r_{xyz} + q_{xyz}r_{w} + q_{w}r_{xyz} } - q_{xyz} \cdot r_{xyz} +q_{w}r_{w} \end{eqnarray}$

One more multiplication exercise:

$\require{cancel} \begin{eqnarray} (\H{q}+w)\H{s}(-\H{q}+w) & = & (\H{q}+w)(-\H{s}\H{q}+\H{s}w) \\ & = & (\H{q}+w)(-\H{s\times q} + s \cdot q + \H{s}w) \\ & = & -\H{q}\H{s\times q} + \H{q}(s \cdot q) + \H{q}\H{s}w -w\H{s\times q} + w s \cdot q + w \H{s}w \\ & = & -\H{q\times(s\times q)} + \cancel{q \cdot (s \times q)} + \H{q}(s \cdot q) + w\H{q\times s} - \cancel{w(q \cdot s)} -w\H{s\times q} + \cancel{w s \cdot q} + w \H{s}w \\ & = & \H{-q\times(s\times q) + (s \cdot q)q + 2w(q\times s) + w^2 s} \end{eqnarray}$

What happens if we set $$q = \sin(\frac{\theta}{2})u$$ (for unit vector $$u$$) and $$w = \cos(\frac{\theta}{2})$$?

$\require{cancel} \begin{eqnarray} (\H{q}+w)\H{s}(-\H{q}+w) & = & \H{-q\times(s\times q) + (s \cdot q)q + 2w(q\times s) + w^2 s} \\ & = & \H{ - \sin^2\left(\frac{\theta}{2}\right)(u\times(s\times u)) + \sin^2\left(\frac{\theta}{2}\right)((s\cdot u) u) + 2\cos\left(\frac{\theta}{2}\right)\sin\left(\frac{\theta}{2}\right)(u\times s) + \cos^2\left(\frac{\theta}{2}\right)s } \\ & = & \H{ -\sin^2\left(\frac{\theta}{2}\right)(s-(s \cdot u)u) + \sin^2\left(\frac{\theta}{2}\right)((s\cdot u) u) + 2\cos\left(\frac{\theta}{2}\right)\sin\left(\frac{\theta}{2}\right)(u\times s) + \cos^2\left(\frac{\theta}{2}\right)s } \\ & = & \H{ 2\sin^2\left(\frac{\theta}{2}\right)((s\cdot u) u) + 2\cos\left(\frac{\theta}{2}\right)\sin\left(\frac{\theta}{2}\right)(u\times s) + \left(\cos^2\left(\frac{\theta}{2}\right) - \sin^2\left(\frac{\theta}{2}\right)\right)s } \\ & = & \H{ \left(-1+1-2\sin^2\left(\frac{\theta}{2}\right)\right)(-(s\cdot u) u) + \sin(\theta)(u\times s) + \cos(\theta)s } \\ & = & \H{ (-1+\cos(\theta))(-(s\cdot u) u) + \sin(\theta)(u\times s) + \cos(\theta)s } \\ & = & \H{ (s\cdot u) u + \sin(\theta)(u\times s) + \cos(\theta)(s - (s\cdot u) u) } \end{eqnarray}$

Which is exactly the formula for rotating by angle $$\theta$$ around axis $$u$$!

# Unit Quaternions as a Rotation Representation

Quaternions seem to strike a decent balance between memory and efficiency for basic operations; that is, they are the same size as axis+angle, but much cheaper to concatenate or rotate a point by; though for batch rotations, converting to mat3 is still the best strategy. They are also easy to correct for numerical drift, and very easy to interpolate (see: glm::slerp).

Memory? Same as a+a, better than mat3:

Storage
rep'nfloats
a+a4
mat39
quat4

Rotation Efficiency? Better than a+a, worse than mat3: (so if you are rotating a lot of points, use a mat3)

Rotate a Vector
a+a11182
mat3690
quat15230

Concatenation Efficiency? Better than mat3, much better than a+a: (so great for, e.g., character skeletons)

Combine Rotations