Skip to content

Quaternions

Published On:
Nov 13, 2014
Last Updated:
Oct 14, 2019

A quaternion (pronounced qwa-ter-ne-ion) is a complex-number like system which contains three imaginary components and one real component. Arguably, the most useful quaternions is a subset of all quaternions called unit quaternions (or versors), which can be used to describe a rotation in 3D space. This page focuses primarily on these unit quaternions.

Defining Equation And Identities

The basic form of a quaternion is:

q=w+xi+yj+zk\mathbf{q} = w + x\mathbf{i} + y\mathbf{j} + z\mathbf{k}

where:
w,x,y,zw, x, y, z are real numbers
i,j,k\mathbf{i, j, k} are the quaternion units
(which can be seen as similar to the complex number i\mathbf{i})

The multiplication rules for the quaternion units are:

i2=j2=k2=ijk=1\mathbf{i}^2 = \mathbf{j}^2 = \mathbf{k}^2 = \mathbf{ijk} = -1

From these rule above, you can determine some identities:

ijk=1\mathbf{ijk} = -1

Multiply both sides by i\mathbf{i}:

i2jk=i\mathbf{i}^2\mathbf{jk} = -\mathbf{i}

Using the rule that i2=1\mathbf{i}^2 = -1:

jk=i-\mathbf{jk} = -\mathbf{i}

And thus:

i=jk\mathbf{i} = \mathbf{jk}

The same process can be applied the other way around and also to j\mathbf{j} and k\mathbf{k} resulting in the following six identities:

i=jkj=ikk=iji=kjj=kik=ji\begin{align} \mathbf{i} &= \mathbf{jk} \\ \mathbf{j} &= -\mathbf{ik} \\ \mathbf{k} &= \mathbf{ij} \\ \mathbf{-i} &= \mathbf{kj} \\ \mathbf{-j} &= -\mathbf{ki} \\ \mathbf{-k} &= \mathbf{ji} \\ \end{align}

These identities are used to simplify terms when applying the product rule to quaternion multiplication.

Quaternion Conjugates

All quaternions have a conjugate. The conjugate of a quaternion represents a rotation in the opposite direction. For example, if q\mathbf{q} describes the orientation of frame B relative to frame A, then qˉ\mathbf{\bar{q}} would describe the orientation of frame A relative to frame B. The conjugate of a quaternion q\mathbf{q} is:

qˉ=wxiyjzk\mathbf{\bar{q}} = w - x\mathbf{i} - y\mathbf{j} - z\mathbf{k}

All you need to do is multiple all of the imaginary terms by 1-1. The conjugate can also be denoted by q\mathbf{q*} or qT\mathbf{q^T}. However qˉ\mathbf{\bar{q}} is the preferred choice on this site.

The conjugate of a unit quaternion is the same as it’s inverse.

Pure/Vector Quaternions

A pure quaternion is a quaternion where w=0w=0. This results in a quaternion:

q=xi+yj+zk\mathbf{q} = x\mathbf{i} + y\mathbf{j} + z\mathbf{k}

This three-valued quaternion also happens to be able to represent a vector in 3D space, and so it is also called a vector quaternion. A vector quaternion is used to represent either a vector or point in 3D space when you want to apply a quaternion rotation to it (more on this below).

Scalar/Vector Notation

You can split a quaternion into a scalar and a vector component. The ww represents the scalar part of the quaternions and the x,y,zx, y, z represents the vector part. You may see a quaternion written with an ww for the scalar part and a r\vec{r} for the vector part.

q=(w,r)\mathbf{q} = (w, \vec{r})

Unit Quaternions

Unit quaternions are quaternions in which the coefficients have been normalized as follows:

w2+x2+y2+z2=1w^2 + x^2 + y^2 + z^2 = 1

Interestingly, all rotations in 3D space (which is called the 3D rotation group, or SO(3)\mathbf{SO(3)})` can be represented by the unit quaternions (which is a sub-set of all quaternions). In fact, you will rarely ever deal with a quaternion that is not a unit quaternion!

Representation In Software/Programming

In software, quaternions are typically described with a vector/array (in the programming sense of the word) in the following form:

q=[wxyz]\mathbf{q} = \begin{bmatrix}w\\x\\y\\z\end{bmatrix}

in where the coefficients are stored in an array and the quaternion units are implied by position.

It is important to note that although it is common to represent a quaternion with vector-like syntax, it is definitely not a vector (in the mathematical sense of the word). For one, quaternion multiplication does not follow the dot or cross-product multiplication rules that vectors do.

Why Use Quaternions To Describe Rotations?

There are a number of different ways to describe rotations. These include:

  • Axis-angle representation
  • Euler angles (roll, pitch, yaw)
  • Rotation matrices
  • Quaternions

Why choose Quaternions? One reason is that Quaternions do not suffer from the gimbal lock that Euler angles do. This also is related to the fact that they are differentiable (i.e. very small changes in rotation cause very small changes in the quaternion values), which allows for smooth interpolation, important for many use cases including 3D animation. They are also more compact with only four numbers need to be stored than a 9 number rotation matrix. Quaternions are also easily converted into the angle-axis representation and back again.

Rotating A Vector

You can rotate a vector vv in 3D space to vv' with:

[0v]=q[0v]q\begin{bmatrix}0\\v'\end{bmatrix} = q \begin{bmatrix}0\\v\end{bmatrix}q'

Because the vector is squashed between the quaternion and it’s conjugate, this is sometimes referred to as the “sandwich product”. The multiplications can be done by the basic product rule, or more easily using the Hamilton product.

Lets assume we have the vector:

v=[100]v = \begin{bmatrix}1\\0\\0\end{bmatrix}

And we want to rotate it with the quaternion>

q=[0.500.50]]q = \begin{bmatrix}\sqrt{0.5} \\ 0 \\ \sqrt{0.5} \\ 0]\end{bmatrix}

This quaternion just so happens to be a rotation of 9090 around the y-axis>

We turn the vector into a vector quaternion by adding a fourth value of 0 (which is the ww):

v=[0100]v = \begin{bmatrix}0\\1\\0\\0\end{bmatrix}

Combine into:

v=[0.500.50]][0100][0.500.50]] v' = \begin{bmatrix}\sqrt{0.5} \\ 0 \\ \sqrt{0.5} \\ 0]\end{bmatrix} \begin{bmatrix}0\\1\\0\\0\end{bmatrix} \begin{bmatrix}\sqrt{0.5} \\ 0 \\ -\sqrt{0.5} \\ 0]\end{bmatrix}

To calculate the multiplication of two quaternions, you can use the Hamilton product. If you have the equation:

q3=q1q2q3 = q1*q2

where each quaternion is composed in the following manner:

q1=q1w+q1xi+q1yy+q1zzq1 = q1_w + q1_x \mathbf{i} + q1_y \mathbf{y} + q1_z \mathbf{z}

then using the Hamilton product, the values of each component in q3q3 are:

q3w=q1wq2wq1xq2xq1yq2yq1zq2zq3x=q1xq2w+q1wq2xq1zq2y+q1yq2zq3y=q1yq2w+q1zq2x+q1wq2yq1xq2zq3x=q1zq2wq1yq2x+q1xq2y+q1wq2z q3_w = q1_w q2_w - q1_x q2_x - q1_y q2_y - q1_z q2_z \\ q3_x = q1_x q2_w + q1_w q2_x - q1_z q2_y + q1_y q2_z \\ q3_y = q1_y q2_w + q1_z q2_x + q1_w q2_y - q1_x q2_z \\ q3_x = q1_z q2_w - q1_y q2_x + q1_x q2_y + q1_w q2_z

You can also rotate a vector v\vec{v} by a quaternion qq by decomposing the quaternion into it’s scalar part ww and it’s vector part r\vec{r}:

q=(w,r)\mathbf{q} = (w, \vec{r})

and then using the following formula to calculate the rotated vector vrotatedv_{rotated}:

vrotated=v+2r×(r×v+wv)v_{rotated} = \vec{v} + 2\vec{r} \times (\vec{r} \times \vec{v} + w\vec{v})

where:
×\times is the vector cross-product

Rotation Matrix

You can calculate a 3x3 rotation matrix from a quaternion. This is useful if you want to express the rotation as a matrix instead of a quaternion, but comes at the expense of having to store 9 numbers rather than 4!

Combining Rotations

Rotations can be easily combined when using quaternions.

Given two quaternion rotations that are to be applied consecutively, RAR_A and then RBR_B, the total rotation RCR_C is found with:

RC=RBRAR_C = R_B R_A

Remember that quaternion multiplication is not associative, so the ordering of RAR_A and RBR_B is important.

Some Useful Quaternions

QuaternionDescription
q=[1,0,0,0]\mathbf{q} = [1, 0, 0, 0]Identity quaternion, no rotation.
q=[0,1,0,0]\mathbf{q} = [0, 1, 0, 0]Rotation of 180 around X axis.
q=[0,0,1,0]\mathbf{q} = [0, 0, 1, 0]Rotation of 180 around Y axis.
q=[0,0,0,1]\mathbf{q} = [0, 0, 0, 1]Rotation of 180 around Z axis.
q=[0.5,0.5,0,0]\mathbf{q} = [\sqrt{0.5}, \sqrt{0.5}, 0, 0]Rotation of 90 around X axis.
q=[0.5,0,0.5,0]\mathbf{q} = [\sqrt{0.5}, 0, \sqrt{0.5}, 0]Rotation of 90 around Y axis.
q=[0.5,0,0,0.5]\mathbf{q} = [\sqrt{0.5}, 0, 0, \sqrt{0.5}]Rotation of 90 around Z axis.
q=[0.5,0.5,0,0]\mathbf{q} = [\sqrt{0.5}, -\sqrt{0.5}, 0, 0]Rotation of -90 around X axis.
q=[0.5,0,0.5,0]\mathbf{q} = [\sqrt{0.5}, 0, -\sqrt{0.5}, 0]Rotation of -90 around Y axis.
q=[0.5,0,0,0.5]\mathbf{q} = [\sqrt{0.5}, 0, 0, -\sqrt{0.5}]Rotation of -90 around Z axis.

Interpolation

SLERP

SLERP is shorthand for spherical linear interpolation. It is commonly used with quaternions to produce a smooth rotation of a 3D body from one orientation to another. Performing SLERP on two quaternions produces a smooth, continuous rotation with a constant angular velocity around a fixed rotation axis (the first quaternion describes the starting rotation, the second quaternion describes the end rotation).

SLERP does not work well when the two quaternions are too similar. In this case it is safer to just perform linear interpolation on all four values quaternion values independently (making sure to normalize the resulting quaternion before using it).

The following Python code example demonstrates the SLERP algorithm on a pair of quaternions 1:

import numpy as np
def slerp(v0, v1, t_array):
# >>> slerp([1,0,0,0],[0,0,0,1],np.arange(0,1,0.001))
t_array = np.array(t_array)
v0 = np.array(v0)
v1 = np.array(v1)
dot = np.sum(v0*v1)
if (dot < 0.0):
v1 = -v1
dot = -dot
DOT_THRESHOLD = 0.9995
if (dot > DOT_THRESHOLD):
result = v0[np.newaxis,:] + t_array[:,np.newaxis]*(v1 - v0)[np.newaxis,:]
return (result.T / np.linalg.norm(result, axis=1)).T
theta_0 = np.arccos(dot)
sin_theta_0 = np.sin(theta_0)
theta = theta_0*t_array
sin_theta = np.sin(theta)
s0 = np.cos(theta) - dot * sin_theta / sin_theta_0
s1 = sin_theta / sin_theta_0
return (s0[:,np.newaxis] * v0[np.newaxis,:]) + (s1[:,np.newaxis] * v1[np.newaxis,:])

https://en.wikipedia.org/wiki/Slerp has some code examples in Python and C++ that perform SLERP on quaternions.

Conversion From Axis-Angle Form To Quaternion

A rotation in axis-angle form:

axis=[axayaz]angle=θaxis = \begin{bmatrix}a_x\\a_y\\a_z\end{bmatrix} \quad angle = \theta

can be converted into a quaternion with:

q=[qwqxqyqz]=[cosθ2axsinθ2aysinθ2azsinθ2]\mathbf{q} = \begin{bmatrix}q_w\\q_x\\q_y\\q_z\end{bmatrix} = \begin{bmatrix} \cos{\frac{\theta}{2}} \\ a_x \sin{\frac{\theta}{2}} \\ a_y \sin{\frac{\theta}{2}} \\ a_z \sin{\frac{\theta}{2}} \\ \end{bmatrix}

Conversion From Quaternion To Rotation Matrix

If you have a quaternion in the form:

q=[qwqxqyqz]\mathbf{q} = \begin{bmatrix}q_w\\q_x\\q_y\\q_z\end{bmatrix}

Then the equivalent rotation matrix is:

R=[12qy22qz22qxqy2qzqw2qxqz+2qyqw2qxqy+2qzqw12qx22qz22qyqz2qxqw2qxqz2qyqw2qyqz+2qxqw12qx22qy2]\mathbf{R} = \begin{bmatrix} 1 - 2q_y^2 - 2q_z^2 & 2q_xq_y - 2q_zq_w & 2q_xq_z + 2q_yq_w \\ 2q_xq_y + 2q_zq_w & 1 - 2q_x^2 - 2q_z^2 & 2q_yq_z - 2q_xq_w \\ 2q_xq_z - 2q_yq_w & 2q_yq_z + 2q_xq_w & 1 - 2q_x^2 - 2q_y^2 \end{bmatrix}

Footnotes

  1. https://en.wikipedia.org/wiki/Slerp