2d rotation
A 2d rotation has only one parameter $\theta$, when the basis vectors $\unit{i} = [1, 0]$ and $\unit{j} = [0, 1]$ are rotated by an angle $\theta$
$$
\mbold{p} = \cos{\theta} \unit{i} + \sin{\theta} \unit{j} \\
\mbold{q} = -\sin{\theta} \unit{i} + \cos{\theta} \unit{j}
$$
Which builds the rotation matrix
$$
\mbold{R}(\theta) = \begin{bmatrix}
\textbf{p} \\
\textbf{q}
\end{bmatrix} = \begin{bmatrix}
\cos{\theta} & \sin{\theta} \\
-\sin{\theta} & \cos{\theta}
\end{bmatrix}
$$
When a vector $\mbold{v}$ is transformed by this matrix we know that the vector will be a linear combination of the basis which are $\mbold{p}$ and $\mbold{q}$
$$
\begin{align*}
\mbold{v'} = \mbold{vR}(\theta) &= v_x \mbold{p} + v_y \mbold{q} \\
&= v_x \begin{bmatrix}\cos{\theta} & \sin{\theta}\end{bmatrix} + v_y \begin{bmatrix}-\sin{\theta} & \cos{\theta}\end{bmatrix} \\
&= \begin{bmatrix}
v_x \cos{\theta} - v_y \sin{\theta} \\
v_x \sin{\theta} + v_y \cos{\theta}
\end{bmatrix}^T
\end{align*}
$$
Using a matrix to encode this operation
$$
\begin{align*}
\mbold{v'} = \mbold{vR}(\theta) &= \begin{bmatrix}v_x & v_y\end{bmatrix} \begin{bmatrix}
\cos{\theta} & \sin{\theta} \\
-\sin{\theta} & \cos{\theta}
\end{bmatrix} \\
&= \begin{bmatrix}
v_x \cos{\theta} - v_y \sin{\theta} \\
v_x \sin{\theta} + v_y \cos{\theta}
\end{bmatrix}^T
\end{align*}
$$
See also complex numbers
3d rotation
About cardinal axes
$$
\mathbf{R_x}(\alpha) = \begin{bmatrix}
1 & 0 & 0 \\
0 & \cos{\alpha} & -\sin{\alpha} \\
0 & \sin{\alpha} & \cos{\alpha}
\end{bmatrix}
$$
$$
\mathbf{R_y}(\beta) = \begin{bmatrix}
\cos{\beta} & 0 & \sin{\beta} \\
0 & 1 & 0 \\
-\sin{\beta} & 0 & \cos{\beta}
\end{bmatrix}
$$
$$
\mathbf{R_z}(\gamma) = \begin{bmatrix}
\cos{\gamma} & -\sin{\gamma} & 0 \\
\sin{\gamma} & \cos{\gamma} & 0 \\
0 & 0 & 1
\end{bmatrix}
$$
See also
About an arbitrary axis
Given an axis $\unit{n}$ and an amount of rotation around it $\theta$ our goal is to find a rotation matrix that rotates about $\unit{n}$ by th angle $\theta$
$$
\mathbf{v'} = \mathbf{R}(\unit{n}, \theta)\mathbf{v}
$$
The basic idea is to solve this problem in a plane perpendicular to $\unit{n}$ which becomes a 2d problem
Separate $\mbold{v}$ in two vectors, a vector parallel to $\unit{v}$ called $\mbold{v_{\parallel}}$ and a vector perpendicular to $\unit{v}$ called $\mbold{v_{\perp}}$ such that $\mbold{v_{\parallel}} + \mbold{v_{\perp}} = \mbold{v}$
$$
\begin{align*}
\mbold{v_{\parallel}} &= (\mbold{v} \cdot \unit{n}) \unit{n} \\
\mbold{v_{\perp}} &= \mbold{v} - \mbold{v_{\parallel}}
\end{align*}
$$
After the rotation it’s obvious that the $\mbold{v_{\parallel}}$ component will be the same and only the vector $\mbold{v_{\perp}}$ will be rotated
A plane can be defined with two vectors that lie on it, since we have $\mbold{v_{\perp}}$ and we also know the normal of the plane (which is $\unit{n}$) any vector perpendicular to both vectors will also lie in the plane, we can use the cross product to find this vector
$$
\mbold{w} = \unit{n} \times \mbold{v_{\perp}}
$$
The length of $\mbold{w}$ is
$$
\begin{align*}
\left \| \mbold{w} \right \| &= \left \| \unit{n} \right \| \left \| \mbold{v_{\perp}}\right \| \sin{\deg{90}} \\
&= \left \| \mbold{v_{\perp}}\right \|
\end{align*}
$$
Which means that $\mbold{w}$ has the same length as $\mbold{v_{\perp}}$, note that even though they have the same length they don’t necessarily have unit length
$\mbold{w}$ and $\mbold{v_{\perp}}$ form now a 2d coordinate space where the $x$-axis is $\mbold{v_{\perp}}$ and the $y$-axis is $\mbold{v_{\perp}}$
Let $\mbold{v_{\perp}’}$ be a vector that is the result of rotating $\mbold{v_{\perp}}$ by an angle $\theta$, we can find the projection of it onto the $x$-axis and the $y$-axis as follows
$$
\begin{align*}
\mbold{v_{\perp,x}'} &= (\magnitude{ \mbold{v_{\perp}} } \cos{\theta}) \unit{v_{\perp}} = \cos{\theta} \mbold{v_{\perp}}\\
\mbold{v_{\perp,y}'} &= (\magnitude{ \mbold{v_{\perp}} } \sin{\theta}) \unit{w} = \sin{\theta} \mbold{w}
\end{align*}
$$
- Expressing $\mbold{v_{\perp}’}$ as a linear combination of the basis
$$
\mbold{v_{\perp}'} = \cos{\theta} \mbold{v_{\perp}} + \sin{\theta} \mbold{w}
$$
Reconstructing the solution from the observations above
$$
\begin{align*}
\mbold{v_{\parallel}} &= (\mbold{v} \cdot \unit{n}) \unit{n} \\
\mbold{v_{\perp}} &= \mbold{v} - \mbold{v_{\parallel}} \\
&= \mbold{v} - (\mbold{v} \cdot \unit{n}) \unit{n} \\
\mbold{w} &= \unit{n} \times \mbold{v_{\perp}} \\
&= \unit{n} \times (\mbold{v} - \mbold{v_{\parallel}}) \\
&= \unit{n} \times \mbold{v} - \unit{n} \times \mbold{v_{\parallel}} \\
&= \unit{n} \times \mbold{v}
\end{align*}
$$
Finally
$$
\begin{align}
\mbold{v'} &= \mbold{v_{\perp}'} + \mbold{v_{\parallel}'} \nonumber \\
&= \cos{\theta} \mbold{v_{\perp}} + \sin{\theta} \mbold{w} + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\
&= \cos{\theta} (\mbold{v - (\mbold{v} \cdot \unit{n}) \unit{n}}) + \sin{\theta} (\unit{n} \times \mbold{v}) + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\
&= \cos{\theta} \mbold{v} - \cost (\mathbf{v} \cdot \unit{n}) \unit{n} + \sin{\theta} (\unit{n} \times \mbold{v}) + (\mbold{v} \cdot \unit{n}) \unit{n} \nonumber \\
&= \cos{\theta} \mbold{v} + \sin{\theta} (\unit{n} \times \mbold{v}) + (1 - \cost)(\mathbf{v} \cdot \unit{n}) \unit{n} \label{3d-rotation}
\end{align}
$$
Now we can compute what the basis vectors are after the transformation above (by using each of the basis vectors as $\mbold{v}$ on \eqref{3d-rotation}) to construct a rotation matrix
$$
\begin{align*}
\mbold{p} &= \begin{bmatrix}1 \\ 0 \\ 0\end{bmatrix} \quad \quad \quad \quad \mbold{p'} = \begin{bmatrix}
n_x^2(1 - \cost) + \cost \\
n_xn_y(1 - \cost) + n_z \sint \\
n_xn_z(1 - \cost) - n_z \sint
\end{bmatrix}\\
\\
\mbold{q} &= \begin{bmatrix}0 \\ 1 \\ 0\end{bmatrix} \quad \quad \quad \quad \mbold{q'} = \begin{bmatrix}
n_yn_x(1 - \cost) - n_z \sint \\
n_y^2(1 - \cost) + \cost \\
n_yn_z(1 - \cost) + n_x \sint
\end{bmatrix}\\
\\
\mbold{r} &= \begin{bmatrix}0 \\ 0 \\ 1\end{bmatrix} \quad \quad \quad \quad \mbold{r'} = \begin{bmatrix}
n_zn_x(1 - \cost) + n_y \sint \\
n_zn_y(1 - \cost) - n_x \sint \\
n_z^2(1 - \cost) + \cost
\end{bmatrix}\\
\end{align*}
$$
Constructing the matrix from these vectors
$$
\mathbf{R}(\unit{n}, \theta) =
\begin{bmatrix}
\mbold{p'} & \mbold{q'} & \mbold{r'}
\end{bmatrix}
$$
3d rotations using quaternions
A complex rotor is a unit norm complex number which rotates another complex number by the angle $\theta$ and has the form
$$
e^{i\theta} = \cost + i \sint
$$
Hamilton had hoped that a unit-norm quaternion $q$ could be used to rotate a vector which is stored as a pure quaternion $p$, the unit norm quaternion is given by
$$
\begin{align}
q &= [s, \lambda \unit{n}] \quad s,\lambda \in \mathbb{R}, \unit{n} \in \mathbb{R}^3 \label{unit-norm-quaternion}\\
\left | \unit{n} \right | &= 1 \nonumber \\
s^2 + \lambda^2 &= 1 \nonumber
\end{align}
$$
$$
p = [0, \mbold{v}] \quad \mbold{v} \in \mathbb{R}^3
$$
Let’s compute the product $p’ = qp$
$$
\begin{align}
p' &= qp \nonumber \\
&= [s, \lambda \unit{n}][0, \mathbf{v}] \nonumber \\
&= [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}] \label{p-prime}
\end{align}
$$
Special case
What if $\unit{n}$ is perpendicular to $\mathbf{v}$? Then the scalar quantity of \eqref{p-prime} is zero and we are left with the pure quaternion
$$
\begin{equation} \label{p-prime-perpendicular}
p' = [0, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}] \quad\quad \text{given that $\unit{n}$ is perpendicular to $\mathbf{n}$}
\end{equation}
$$
Let’s analyze the vector part of $\eqref{p-prime-perpendicular}$ (which is now a 3d entity because it’s a pure quaternion), since $\unit{n}$ is perpendicular to $\mathbf{v}$ then the vector $\unit{n} \times \mathbf{v}$ will have a norm equal to $\magnitude{ \unit{n} \times \mathbf{v} } = \magnitude{ \unit{n} } \magnitude { \mathbf{v} } \sin{\deg{90}}$ and also since $\unit{n}$ is a unit vector then $\magnitude{\unit{n} \times \mathbf{v}} = \magnitude{\mathbf{v}}$ which means that we have two orthogonal vectors with the same length
To rotate the vector $\mathbf{v}$ about $\unit{n}$ let’s transform $\mathbf{v}$ to the 2d space whose basis vectors are $\mathbf{v}$ and $\unit{n} \times \mathbf{v}$ and perform the rotation there which is trivially $[\cost, \sint]$, therefore all we have to do in \eqref{p-prime-perpendicular} is make the scalar quantities multiplying each vector equal the projection of the rotated vector over the basis
$$
p' = [0, \cost \mathbf{v} + \sint \unit{n} \times \mathbf{v}]
$$
Which makes the quaternion $\mathbf{q}$ have the form
$$
\begin{align}
q &= [\cost, \sint \unit{n}] \label{perp-rotor}
\end{align}
$$
And it acts as a rotor only when $\unit{n}$ is perpendicular to $\mathbf{v}$
Important notes/facts about orthogonal quaternions
- If $q$ is a rotor about the unit vector $\unit{n}$ by an angle $\theta$ whose vector term is perpendicular to the pure quaternion $p$
- $qp$ and $pq^{-1}$ rotate $p$ by an angle $\theta$ about $\unit{n}$
- $pq$ and $q^{-1}p$ rotate $p$ by an angle $-\theta$ about $\unit{n}$
- Each of these products leave $p’$ unscaled (because $q$ is a unit norm quaternion)
General case
Let’s use \eqref{unit-norm-quaternion} as the starting point, note that this time its vector part it’s not necessarily perpendicular to the pure quaternion $p$, the product $qp$ yields
$$
\begin{align*}
qp &= [s, \lambda \unit{n}][0, \mathbf{v}] \\
&= [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}]
\end{align*}
$$
Note that the term $-\lambda \unit{n} \cdot \mathbf{v}$ does not vanish since for the general case $\unit{n}$ and $\mathbf{v}$ are no longer perpendicular, what’s more important is that the product $qp$ is no longer a pure quaternion, multiplying a vector by a non-orthogonal quaternion has converted some of the vector information into the quaternion’s scalar component
What happens if we post-multiply $qp$ by $q^{-1}$, could it reverse the operation? (Note that since $q$ is a norm quaternion $q^{-1} = q^*$)
$$
qpq^{-1} = [-\lambda \unit{n} \cdot \mathbf{v}, s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}][s, -\lambda \unit{n}]
$$
Let’s first check if doing this multiplication makes the scalar component vanish
$$
\begin{align*}
qpq^{-1} &= [-\lambda s \unit{n} \cdot \mathbf{v} - (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) \cdot (-\lambda \unit{n}), \ldots] \\
&= [-\lambda s \unit{n} \cdot \mathbf{v} + (s \mathbf{v}) \cdot (\lambda \unit{n}) + (\lambda \unit{n} \times \mathbf{v}) \cdot (\lambda \unit{n}), \ldots] \\
&= [-\lambda s \unit{n} \cdot \mathbf{v} + (s \mathbf{v}) \cdot (\lambda \unit{n}) + 0, \ldots] \quad \text {since $\unit{n}$ is perpendicular to $\unit{n} \times \mathbf{v}$ }\\
&= [-\lambda s \unit{n} \cdot \mathbf{v} + \lambda s \mathbf{v} \cdot \unit{n}), \ldots] \\
&= [0, \ldots]
\end{align*}
$$
Indeed it magically made the scalar component vanish! Now let’s look at the vector component of $qpq^{-1}$
$$
\begin{align*}
qpq^{-1} &= [0, s (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) + (-\lambda \unit{n} \cdot \mathbf{v})(-\lambda \unit{n}) + (s \mathbf{v} + \lambda \unit{n} \times \mathbf{v}) \times (-\lambda \unit{n})] \\
&= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 (\unit{n} \times \mathbf{v} \times \unit{n})]
\end{align*}
$$
Let’s expand the cross product
$$
(\unit{n} \times \mathbf{v}) \times \unit{n} = (\unit{n} \cdot \unit{n}) \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n} = \mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n}
$$
Therefore
$$
\begin{align*}
qpq^{-1} &= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 (\mathbf{v} - (\mathbf{v} \cdot \unit{n}) \unit{n})] \\
&= [0, s^2 \mathbf{v} + s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - s \lambda (\mathbf{v} \times \unit{n}) - \lambda^2 \mathbf{v} + \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n})] \\
&= [0, s^2 \mathbf{v} + 2 s \lambda (\unit{n} \times \mathbf{v}) + \lambda^2 (\unit{n} \cdot \mathbf{v})\unit{n} - \lambda^2 \mathbf{v} + \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n})] \\
&= [0, (s^2 - \lambda^2) \mathbf{v} + 2 s \lambda (\unit{n} \times \mathbf{v}) + 2 \lambda^2 (\mathbf{v} \cdot \unit{n}) \unit{n}] \\
\end{align*}
$$
Let’s make $s = \cost$ and $\lambda = \sint$ just like in \eqref{perp-rotor} (it worked as a rotor when it was orthogonal to $p$, it might work with the general case too)
$$
qpq^{-1} = [0, (\cos^2{\theta} - \sin^2{\theta}) \mathbf{v} + 2 \cost \sint (\unit{n} \times \mathbf{v}) + 2 \sin^2{\theta} (\mathbf{v} \cdot \unit{n}) \unit{n}]
$$
Which involves double-angle terms, replacing these terms with double angle-identities
$$
qpq^{-1} = [0, \cos{2\theta} \mathbf{v} + \sin{2\theta} (\unit{n} \times \mathbf{v}) + (1 - \cos{2\theta}) (\mathbf{v} \cdot \unit{n}) \unit{n}]
$$
The product created a pure quaternion equal to $\mathbf{v}$ rotated by an angle $2\theta$, if we want to rotate $\mathbf{v}$ by an angle $\theta$ we must build a half angle $\theta$ quaternion $q$ (note above that $q$ was equal to \eqref{perp-rotor})
$$
\begin{equation} \label{rotor}
q = [\cos{\frac{1}{2}\theta}, \sin{\frac{1}{2}\theta}\unit{n}]
\end{equation}
$$
Using \eqref{rotor} the product is
$$
qpq^{-1} = [0, \cos{\theta} \mathbf{v} + \sin{\theta} (\unit{n} \times \mathbf{v}) + (1 - \cos{\theta}) (\mathbf{v} \cdot \unit{n}) \unit{n}]
$$
Note that the vector part of $qpq^{-1}$ is identical to \eqref{3d-rotation}
Quaternion difference and dot product
Let $a$ and $b’$ be two unit norm quaternions (rotors that have the same form as \eqref{rotor}), the quaternion to rotate from $a$ to $b$ is given by $da = b$ and is known as quaternion difference, finding the value of $d$ given that we know $a$ and $b$
$$
\begin{align*}
da &= b \\
d(aa^*) &= ba^* \quad \quad \text{since $a$ is a unit norm quaternion its inverse is equal to its conjugate} \\
d &= ba^*
\end{align*}
$$
Expanding the product
$$
\begin{align*}
d &= [s_b, \mathbf{b}][s_a, -\mathbf{a}] \\
&= [s_bs_a + \mathbf{b} \cdot \mathbf{a}, -s_b\mathbf{a} + s_a\mathbf{b} - \mathbf{b} \times \mathbf{a}]
\end{align*}
$$
Note that the scalar part of this quaternion is equal to the inner product (a generalization of the dot product to abstract vector spaces) between two quaternions
$$
d = [\left \langle a, b \right \rangle, -s_b\mathbf{a} + s_a\mathbf{b} - \mathbf{b} \times \mathbf{a}]
$$
Remembering that a rotor is given by \eqref{rotor} we can relate the inner product between rotor quaternions with the scalar quantity of \eqref{rotor} and interpret it geometrically just like the dot product between two vectors in 3d/2d space but this time noticing that the dot product gives the cosine of half the angle between the quaternions
$$
a \cdot b = \cos{\frac{\theta}{2}}
$$
This means that the angle between $a$ and $b$ is equal to
$$
\theta = 2 \arccos{(a \cdot b)}
$$
Or using the half angle formulas
$$
\begin{align*}
\cos^2{\frac{\theta}{2}} &= \frac{1}{2}(1 + \cos{\theta}) \\
(a \cdot b)^2 &= \frac{1}{2}(1 + \cos{\theta}) \\
\cost &= 2 (a \cdot b)^2 - 1 \\
\theta &= \arccos(2(a \cdot b)^2 - 1)
\end{align*}
$$
The second formula works for all the cases as noted here (the first one doesn’t work when $a \cdot b < 0$)
References
- Dunn, F. and Parberry, I. (2002). 3D math primer for graphics and game development. Plano, Tex.: Wordware Pub.
- Vince, J. (2011). Quaternions for computer graphics. London: Springer.
- Shoemake, K. (2016). Quaternions [online] Cs.ucr.edu. Available at: http://www.cs.ucr.edu/~vbz/resources/quatut.pdf [Accessed 7 Mar. 2016].