---
title: "Quaternions: what are they good for?"
date: 2020-11-09
tags: maths, dynamical systems
toc: false
---

* A bit of history

Quaternions come from the quest to find more numbers. A bunch of
mathematicians from the 19th century were so impressed by the
unreasonable effectiveness of complex numbers that they wondered
whether the trick could be extended to other structures, notably other
$n$-tuples of real numbers.

As it turns out, this only works for some values of $n$, namely 2, 4,
and 8. There are profound reasons for this, with connections to
various areas of mathematics.[fn:: {-} If you want to learn more about
the historical background of hypercomplex numbers and their
properties, I cannot recommend Stillwell's /Mathematics and Its
History/ enough citep:stillwell2010_mathem_its_histor.]

Here is a quick recap, in case you'd like a quick overview of all the
stuff that could reasonably be considered "numbers".

/Complex numbers/ are of the form $z = a + ib$, with $a$ and $b$ real
numbers, and $i$ (the /imaginary unit/ defined such that $i^2 =
-1$. They form a /field/, and have all the nice properties that we can
expect of well-behaved numbers, such as:
- Associativity: $(xy)z = x(yz)$
- Commutativity: $xy = yx$
for all complex numbers $x$, $y$, and $z$.

/Quaternions/ are an extension of complex numbers, but in /four/
dimensions instead of just two. They are of the form $\mathbf{q} = a +
ib + jc + kd$, where $i$, $j$, and $k$ the imaginary units. They
follow a bunch of rules, which are $i^2 = j^2 = k^2 = ijk = -1$, and
\[ ij = -ji = k,\quad jk = -kj = i,\quad \text{and } ki = -ik = j. \]

One thing we can notice straightaway: quaternions are /not
commutative!/ That is, in general, $\mathbf{q_1} \mathbf{q_2} \neq
\mathbf{q_2} \mathbf{q_1}$. However, like the complex numbers, they
are associative.

Finally, /octonions/ are the last members of the club. They can be
described with 8 real components. Their imaginary units behave
similarly to quaternions imaginary units, with more complicated
rules. And furthermore, they are neither commutative nor even
associative! (At this point, one wonders whether they deserve the
title of number at all.)

And /that's it!/ There is something really strange happening here: we
can define something looking like numbers only for dimensions 2, 4,
and 8. Not for 3, not for 6, and not for 17. Moreover, we're losing
important properties along the way. Starting from the full, complete,
/perfect/ structure of the complex numbers[fn:complex], we gradually
lose the things that make working with numbers easy and intuitive.

[fn:complex] Yes, as many authors have pointed out, complex numbers
are actually the most "complete" numbers. They have all the
interesting properties, and fill in the gaps where so-called "real"
numbers are failing. You can define any polynomial you want with
complex coefficients, they will always have the correct number of
roots in the complex numbers.


* Why are quaternions interesting?

So we can build these kinds of 4- or 8-dimensional numbers. That is
fascinating in a way, even if only to answer the more philosophical
question of what numbers are, and what their properties mean. But as
it turns out, quaternions also have direct applications, notably in
Physics.

Indeed, quaternions are extremely useful for representing /rotations/.
There are many different ways to represent rotations:
- [[https://en.wikipedia.org/wiki/Euler_angles][Euler angles]] are arguably the most intuitive: it's just three angles
  representing yaw, pitch, and roll.
- [[https://en.wikipedia.org/wiki/Rotation_matrix][Rotation matrices]] are the most natural from a mathematical point of
  view. Rotations are invertible linear transformation in 3D space,
  after all, so they should be represented by matrices in
  $\mathrm{GL}_3(\mathbb{R})$.

However, both of these representations suffer from serious
drawbacks. Euler angles are nice for intuitively understanding what's
going on, and for visualisation. However, even simple operations like
applying a rotation to a vector, or composing two rotations, quickly
lead to a lot of messy and unnatural computations. As soon as
rotations become larger that $\pi$, you get positions that are
ill-defined (and you have to implement a lot of wraparound in
$[-\pi,\pi]$ or $[0,2\pi]$).

Rotation matrices are more straightforward. Composing two rotations
and rotating a vector is matrix-matrix or matrix-vector
multiplication. However, a $3\times 3$ matrix contains 9 scalar elements, just
to represent an object that is intrinsically 3-dimensional. Because of
this, computations can become costly, or even unstable in
floating-point representations.

The quaternion is therefore an elegant compromise in space
requirements (4 elements) and ease of computations. It is moreover
easy and numerically stable to get rotation matrices from quaternions
and vice-versa.

From a numerical stability point of view, it is easier to deal with
computation errors in the case of quaternions: a renormalized
quaternion is always a valid rotation, while it is difficult to
correct a matrix that is not orthogonal any more due to rounding
errors.

* Unit quaternions and rotations

Rotations are represented by unit quaternions, i.e. quaternions of
norm 1:[fn:proofs]

\[ \mathbf{q} = \exp\left((u_x i + u_y j + u_z k) \frac{\theta}{2}\right). \]

[fn:proofs] {-} For a complete derivation of quaternion properties and
rotation representation, see
cite:sola2017_quater_kinem_error_state_kalman_filter.


This represents a rotation of angle $\theta$ around the vector
$\mathbf{u} = [u_x\; u_y\; u_z]^T$. The unit quaternion $\mathbf{q}$
can also be written as

\[ \mathbf{q} = \cos\left(\frac{\theta}{2}\right) + \mathbf{u}\sin\left(\frac{\theta}{2}\right). \]

Composition of rotations is simply the quaternion multiplication. To
orient a vector $\mathbf{x}$ by applying a rotation, we conjugate it
by our quaternion $\mathbf{q}$:

\[ \mathbf{x'} = \mathbf{q} \mathbf{x} \mathbf{q'}, \]

where all products are quaternion multiplications, and the vectors
$\mathbf{x}$ and $\mathbf{x'}$ are represented as /pure quaternions/,
i.e. quaternions whose real part is zero:

\[ \mathbf{x} = x_1 i + x_2 j + x_3 k. \]

The fact that quaternions are not commutative also corresponds
directly to the fact that rotations themselves are not commutative.

* Quaternion conventions

People are using various quaternions conventions, depending on their
choice of multiplication formula ($ij = -k$ or $ij = k$) and on their
choice of representation (real part first or real part last). The case
$ij = k$ and real part first used in this article is called the
/Hamilton convention/, whereas the convention where $ij = -k$ and the
real part is last is called the /JPL convention/.[fn:conventions]

[fn:conventions] As the name suggest, the JPL convention is used
mostly by NASA's [[https://www.jpl.nasa.gov/][Jet Propulsion Laboratory]], and by extension in
aerospace applications. The Hamilton convention in more frequent in
robotics and in the state estimation literature, such as Kalman
filtering citep:sola2017_quater_kinem_error_state_kalman_filter.


As always, it is important to clearly define ahead of time what
convention is used in your projects, especially if you're getting
inspirations from books and articles. Check if they are all using the
same conventions, or hard-to-debug issues may arise!

[[https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation#Alternative_conventions][Wikipedia]] and especially
cite:sola2017_quater_kinem_error_state_kalman_filter contain a very
useful reference of the various possible conventions, and where they
are used.

* Applications

Quaternions are often the best choice whenever rotation or attitude
representations are required. This includes robotics, aerospace
engineering, 3D graphics, video games, and so on.

They are of particular use in optimal control or state estimation
scenarios: they are often the representation of choice for the
attitude of an object in a [[https://en.wikipedia.org/wiki/Kalman_filter][Kalman filter]] for instance.[fn:kalman]

[fn:kalman] {-} For a nice introduction to Kalman filters, see [[https://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/][this
blog post]] or the introductory article by
cite:welchIntroductionKalmanFilter2006.


* Software and libraries

When working with quaternions, it may be tiresome to reimplement all
the basic functions you might need (composition, conjugation,
conversions to and from rotation matrices and [[https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles][Euler angles]], and so
on).[fn:algos] Thankfully, quaternions are a very standard part of engineers
toolboxes, so many libraries were written for a variety of scientific
programming languages.

[fn:algos] {-} For an overview of efficient floating-point algorithms
for manipulating quaternions, see
cite:joldes2020_algor_manip_quater_float_point_arith.


For [[https://julialang.org/][Julia]] (easily the best programming language for this kind of
application in my opinion):
- [[https://github.com/JuliaGeometry/Quaternions.jl][Quaternions.jl]], for basic quaternion representation and
  manipulation,
- [[https://github.com/JuliaGeometry/Rotations.jl][Rotations.jl]], for representing rotations and operating on them more
  generally,
- [[https://github.com/JuliaGeometry/CoordinateTransformations.jl][CoordinateTransformations.jl]], for a general framework not limited to
  rotations.

In Python:
- [[https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html][scipy.spatial.transform.Rotation]], which has the benefit of being
  included in SciPy directly,
- [[https://quaternion.readthedocs.io/en/latest/][numpy-quaternion]], for a more feature-complete implementation.

And if you have to work in Matlab, unfortunately the functionality is
locked away in the Robotics System Toolbox, or in the Aerospace
Toolbox. Use open source software if you can!

* The structure of the group of unit quaternions

As it turns out, quaternions are even more interesting than
expected. Not satisfied with representing rotations efficiently, they
also have the structure of a [[https://en.wikipedia.org/wiki/Lie_group][Lie group]]. A Lie group is a structure
that combines the properties of a group and of a differentiable
manifold, thus allowing to compute derivatives, and solve differential
equations, of functions taking quaternion values.[fn::{-} Rotation
matrices also have a Lie group structure.]

[fn::{-} Update: I wrote a detailed post on [[./lie-theory.html][Lie theory]]!]

This is obviously extremely interesting when studying dynamical
systems, as these are often modelled as systems of differential
equations. Having a way to define rigorously derivatives and
uncertainties on quaternions is a very significant result.

* References
