12. Complex Numbers and Quaternions#
In 10. Quaternions we explored how we can make use of quaternions to perform rotation calculations. You don’t need to know exactly how the various equations are derived in order to use them in your programs, however, if you are curious their derivations are provided here.
12.1. Complex numbers#
The imaginary number \(i\) is defined as \(i = \sqrt{-1}\). A complex number is a real number plus a multiple of an imaginary number
The following arithmetic operations can be applied to complex numbers.
Operation |
Result |
---|---|
Addition |
\((a + bi) + (c + di) = a + c + (b + d)i\) |
Subtraction |
\((a + bi) - (c + di) = a - c + (b - d)i\) |
Scalar multiplication |
\(k(a + bi) = ak + bki\) |
Multiplication |
\((a + bi)(c + di) = ac - bd + (ad - bc)i\) |
For example, given the complex numbers \(z_1 = 1 + 2i\) and \(z_2 = 3 + 4i\)
12.1.1. The complex plane#
Complex numbers can be represented using a 2D graph called a complex plane (also known as an Argand diagram) where the real part is mapped to the horizontal axis and the imaginary part mapped to the vertical axis. For example, consider the complex number \(x + yi\)
12.1.2. Absolute value of a complex number#
The absolute value of a complex number \(z = x + yi\) is denoted by \(|z|\) and is the distance of the complex number from the origin of the complex plane. It is calculated using Pythagoras’ theorem
12.1.3. Complex conjugate#
The complex conjugate of a complex number \(z = x + yi\) is denoted by \(z^*\) and is the complex number with the imaginary part negated
When plotted on the complex plane the complex conjugate of \(x + yi\) is reflected about the real axis.
Multiplying a complex number by its conjugate gives
which leads to the following definition of the multiplicative inverse of a complex number
12.2. Rotation using complex numbers#
We can rotate a complex number by multiplying by \(i\). Consider the complex number \(z = 2 + i\) when multiplied recursively by \(i\)
Since \(zi^4 = z\) then this sequence will repeat every four multiples of \(i\). Plotting on the complex plane gives
So multiplying a complex number by \(i\) rotates it by 90\(^\circ\) anti-clockwise about the origin.
Given a complex number \(r = x + yi\) on the complex plane which has an absolute value of \(|r|=1\), if \(\theta\) is the angle between the real axis and the vector pointing from the origin to \(r\), then the length of an adjacent side is \(\cos(\theta)\) and the length of the opposite side is \(\sin(\theta)\).
Using the sin and cosine trigonometric ratios we can write \(r\) as
Multiplying a complex number by \(r\) rotates it by \(\theta\) anti-clockwise in the complex plane.
12.3. Quaternions#
The general form of a quaternion is
where \(w\), \(x\), \(y\) and \(z\) are real numbers and \(i\), \(j\) and \(k\) are imaginary numbers defined by
Let’s examine the relationships between \(i\), \(j\) and \(k\). Since \(ijk = -1\) then
and doing similar for the other combinations of \(i\), \(j\) and \(k\) gives
Consider the cross products between the three unit vectors pointing in the \(x\), \(y\) and \(z\) directions \(\mathbf{i}\), \(\mathbf{j}\) and \(\mathbf{k}\)
So the three imaginary numbers \(i\), \(j\) and \(k\) can be used to represent the three unit vectors pointing in the \(x\), \(y\) and \(z\) directions and multiplying the imaginary numbers is equivalent to the cross product.
12.3.1. Scalar-vector form of a quaternion#
Quaternions can be expressed more conveniently as an ordered-pair consisting of the real part \(w\) and a vector of the imaginary parts
where \(\mathbf{v} = x\mathbf{i} + y \mathbf{j} + z \mathbf{k}\). For example, the quaternion \(q = 1 + 2i + 3j + 4k\) can be represented in scalar-vector form as
12.3.2. Absolute value of a quaternion#
The absolute value of a quaternion \(q = [w, (x, y, z)]\) is denoted by \(|q|\) and calculated using
12.3.3. Unit quaternion#
A unit quaternion, denoted by \(\hat{q}\), is a quaternion that has an absolute value of 1. We can normalise a quaternion by dividing by its absolute value to give a unit quaternion
Proving that \(|\hat{q}| = 1\)
12.3.4. Pure and real quaternions#
A pure quaternion is a quaternion where the real part has a value of zero, i.e.,
A pure quaternion is equivalent to a 3-element vector.
A real quaternion is a quaternion where the vector part is the zero vector \(\mathbf{0} = 0\mathbf{i} + 0\mathbf{j} + 0\mathbf{k}\), i.e.,
A real quaternion is equivalent to a real number.
12.3.5. Quaternion dot product#
The dot product between two quaternions \(q_1 = [w_1, (x_1, y_1, z_1)]\) and \(q_2 = [w_2, (x_2, y_2, z_2)]\) is denoted by \(q_1 \cdot q_2\) and is calculated using
and the angle \(\theta\) between \(q_1\) and \(q_2\) is
12.3.6. Multiplying quaternions#
Let \(q_1 = x_1i + y_1j + z_1k + w_1\) and \(q_2 = x_2i + y_2j + z_2k + w_2\) be two quaternions then
Substituting in the pure quaternions \([0,\mathbf{i}]\), \([0,\mathbf{j}]\) and \([0,\mathbf{k}]\) as well as the real quaternion \([1,\mathbf{0}]\) then
Substituting the dot and cross products
results in
Equation (12.3) is the equation for the multiplication of two quaternions \(q_1 = [w_1, \mathbf{v}_1]\) and \(q_2 = [w_2, \mathbf{v}_2]\).
12.3.7. Quaternion conjugate#
The conjugate of a quaternion \(q\), denoted by \(q^*\), is found by negating the vector part. For example, given the quaternion \(q = [w, \mathbf{v}]\) then
12.3.8. Quaternion inverse#
The inverse of a quaternion \(q\), denoted by \(q^{-1}\), is defined by
If we multiply both sides of this equation by \(q^*\) then
If \(q\) is a unit quaternion then \(|q|=1\) and
12.4. Quaternion rotation#
In 5. Transformations we saw that we can rotate about a vector \(\mathbf{v}\) by an angle \(\theta\) using a combination of a translation and rotations about the \(x\), \(y\) and \(z\) axes. The resulting matrix shown in equation (5.3) is quite complicated and requires lots of floating point computations. Quaternions gives us a away of performing similar calculation in a way that uses fewer computations and also does not suffer from gimbal lock.
Fig. 12.1 Axis-angle rotation#
We have seen above that we can rotate a complex number by multiplying by the complex number \(z = \cos(\theta) + \sin(\theta)i\). Since quaternions are an extension of complex numbers the quaternion equivalent to this is
or in scalar-vector form
To demonstrate rotation using quaternion rotation consider the rotation of the vector \(\mathbf{p} = (2, 0, 0)\) by 45\(^\circ\) about the \(z\)-axis. The rotation quaternion for this is
and expressing \(\mathbf{p}\) as a pure quaternion we have \(p = [0, (2, 0, 0)]\). Multiplying \(p\) and \(q\) using equation (12.3) gives
Since the scalar part is zero then this is a pure quaternion and the absolute value of the rotated quaternion is
which is the same as the absolute value of \([0, (2, 0, 0)]\). This rotation is shown in shown in Fig. 12.2.
Fig. 12.2 The quaternion \(p = [0, (2, 0, 0)]\) is rotated \(45^\circ\) by multiplying by the rotation quaternion \(q = [\cos(45^\circ), \sin(45^\circ)(1, 0, 0)]\).#
In the rotation example shown above used a quaternion that was perpendicular to the vector being rotated. What happens when we rotate by a quaternion that isn’t perpendicular to the vector? Consider the rotation of the same vector \(\mathbf{p} = (2, 0, 0)\) by angle 45\(^\circ\) about the unit vector \(\hat{\mathbf{v}} = (0.707, 0, 0.707)\) which is not perpendicular to \(\mathbf{p}\). The rotation quaternion is
and multiplying by \(p = [0, (2, 0, 0)]\)
Now we no longer have a pure quaternion since the scalar part is \(-1.414\) which is non-zero. However, if we multiply \(qp\) by the quaternion conjugate \(q^*\) on the right we have
So \(qpq^*\) is a pure quaternion and its absolute value is
which is the same as \(|p|\).
Fig. 12.3 Rotating the quaternion \(p=[0, (2, 0, 0)]\) using \(qpq^*\) where \(q = [\cos(45^\circ), \sin(45^\circ) \hat{\mathbf{v}}]\)#
Plotting \(p\) and \(qpq^*\) we see that we have rotated by \(90^\circ\) instead of the desired \(45^\circ\) (Fig. 12.3). This is because we have multiplied the quaternion \(p\) by two rotation quaternions each using the angle \(45^\circ\). So to rotate a quaternion \(p\) about a vector \(\hat{\mathbf{v}}\) by angle \(\theta\) whilst ensuring that we get a pure quaternion we perform \(qpq^*\) where the rotation quaternion is
Returning to our example of rotating \(\mathbf{p} = (2, 0, 0)\) by \(45^\circ\) about the vector \(\hat{\mathbf{v}} = (0.707, 0, 0.707)\) using equation (12.4) we have a rotation quaternion of
so calculating \(qpq^*\) we have
The effect of this rotation is shown in Fig. 12.4.
Fig. 12.4 Rotating the quaternion \(p=[0, (2, 0, 0)]\) using \(qpq^*\) where \(q = [\cos(\frac{45^\circ}{2}), \sin(\frac{45^\circ}{2}) \hat{\mathbf{v}}]\).#
12.4.1. Rotation matrix#
To be able to combine quaternion rotation with other transformations we need to express the quaternion \(qpq^*\) as a \(4 \times 4\) matrix. Consider the multiplication of the axis vector quaternion \(p = [p_w, (p_x, p_y, p_z)]\) on the left by the rotation unit quaternion \(q = [w, (x, y, z)]\)
If we write the quaternion \(p\) as a 4-element vector of the form \(\mathbf{p} = (p_x, p_y, p_z, p_w)^\mathsf{T}\) (note that \(p_w\), is now at the end of the vector which is synonymous with homogeneous coordinates) then we have
and we can express the rotation \(qp\) as the matrix equation
Doing similar for multiplying \(p\) on the right by \(q^* = [w, (-x, -y, -z)]\)
Writing \(p\) the form \(\mathbf{p} = (p_x, p_y, p_z, p_w)\) as before gives
which can be expressed by the matrix equation
The two matrices for \(qp\) and \(pq^*\) from equations (12.5) and (12.6) can be combined to give a single matrix \(R\) that performs the quaternion rotation \(qpq^*\)
Recall that \(q\) is a unit quaternion so \(x^2 + y^2 + z^2 + w^2 = 1\). We can use this to simplify the main diagonal elements of \(R\), for example, consider the element in row 1 column 1 of \(R\)
Doing this for the other main diagonal elements \(R\) simplifies to
To demonstrate this lets return to our example of rotating the vector \(\mathbf{p} = (2, 0, 0)\) about the unit vector \(\hat{\mathbf{v}} = (0.707, 0, 0.707)\) by \(45^\circ\). Recall that the rotation quaternion was
From \(q\) we have \(w = 0.924\), \(x = 0.271\), \(y = 0\) and \(z = 0.271\). Substituting these into \(R\) from equation (12.7) gives
Applying the rotation to \(p = (p_x, p_y, p_z, p_w) = (2, 0, 0, 0)\)
So the rotated vector is \((1.707, 1, 0.293)\) which was shown in Fig. 12.4. We can see that the vector \(\mathbf{p}\) has now been rotated \(45^\circ\) about the vector \(\mathbf{v}\).
12.4.2. Euler angles to quaternion#
Euler angles are the rotations around the three coordinates axes \(x\), \(y\) and \(z\) so equation (12.4) can be used to give three quaternions for yaw, pitch and roll rotations
Let \(c_p = \cos(\tfrac{pitch}{2})\) and \(s_p = \sin(\tfrac{pitch}{2})\) for brevity, and do similar for the cosines and sines of \(yaw\) and \(roll\), then the single rotation quaternion that combines rotation about the three coordinates axes is
This means we can define a quaternion based on the three Euler angles and then use equation (12.7) to generate the rotation matrix. A camera only requires the \(pitch\) and \(yaw\) angles. If \(roll = 0^\circ\) then \(\cos(roll) = 1\) and \(\sin(roll) = 0\) and so the quaternion simplifies to