Engineers widely use quaternions in unmanned aerial vehicles (UAVs) to compute the orientation in 3D space. The idea is to apply Inertial Measurement Unit (IMU) sensors (accelerometer, magnetometer, and gyroscope) for calculating the attitude of an object based on the quaternions.

This article introduces the concept of quaternions and shows how the gyroscope can help to compute the object's orientation using quaternions. I expect that you are aware of the basic principles of attitude estimation including inertial and body frame. Also, you need to have at least basic knowledge of linear algebra. So, let us get started.

## Introduction

Quaternions are numbers with three imaginary terms (** i,j,k**). At first glance, the quaternions resemble complex numbers, which is not coincidental. Complex numbers are used in 2D space, whereas quaternions are necessary for 3D space rotations. To better grasp quaternions, we will first consider complex numbers. Unlike in quaternions, we have only a single imaginary part in complex numbers:

**z = a + bi, i ^{2} = -1,**

Where ** 'i'** is an abstract notion whose square equals minus one. The true power of complex numbers comes when we represent them in a polar form. Based on the real and imaginary parts, we can define a point in 2d space, as shown in the figure below.

Using the polar form, we define two terms: magnitude (**norm**) and phase of complex numbers.

**|z| = sqrt(a ^{2} + b^{2})**

*θ = atan2(b, a)*

Using the norm and phase, we can represent a complex number differently:

**z = a + bi = |z|(cos(θ) + sin(θ)i)**

Here is the exciting point. Let us multiply two complex numbers with arbitrary magnitudes and phases:

**z _{1} * z_{2} = |z_{1}|(cos(θ_{1}) + sin(θ_{1})i) * |z_{2}|(cos(θ_{2}) + sin(θ_{2})i) = **

*= |z _{1}||z_{2}|((*

*cos(θ*

_{1})*cos(θ*

_{2}) - sin*(θ*

_{1})sin*(θ*

_{2})) + i(*cos(θ*

_{1})sin*(θ*

_{2}) + sin*(θ*

_{1})*cos(θ*

_{2})*))*

*=*

*= |z _{1}||z_{2}|(cos(*

*θ*

_{1}+*θ*

_{2}*) + sin(*

*θ*

_{1}+*θ*

_{2}*)i)*

** **

Using basic trigonometry, we can observe that multiplying complex numbers is actually multiplying magnitudes and adding phases. It means that the product of the complex numbers involves a rotation counterclockwise and multiplication of the magnitudes. If we assume that the magnitude is unity, the product of the complex numbers becomes just a rotation operation.

Using this feature of the complex numbers, we can solve our first rotation problem:

**Problem 1.** Given a point in 2D space with coordinates (2, 1). Find its position after rotating counterclockwise at 30 degrees.

**Solution**. First, we define a complex number: *2+1i*. Then, we have another complex number with a magnitude equal to one and a 30-degree phase:

**z = cos(30) + sin(30)i**

Then we multiply these complex numbers and obtain the position(**1.232, 1.866**) of the point after the rotation.

**z _{new} = (cos(30) + sin(30)i) * (2 + 1i) = 1.232 + 1.866i**

As we see, the complex numbers allow us to deal with rotations in 2D space effortlessly. The next step is to do 3D space rotations using quaternions.

### Quaternions

First, let me present some algebraic definitions of quaternions. In quaternions, like in complex numbers, there is a real and complex part. The complex part consists of three imaginary terms.

*q = s + x i +yj +zk, *

*s,x,y, and z are real numbers.*

**i**^{2} = **j**^{2} = **k**^{2} = -1

**ij **=** k, jk **=** i, ki **=** j, ji **=** -k, kj **=** -i, ik **=** -j**

It is also helpful to denote the imaginary part as a vector with three terms:

We can do elementary addition and subtraction operations. Also, we can multiply a quaternion with a scalar. **Pure quaternion** is when the real part of the quaternion equals zero:

*q _{a} = [s_{a}, a], q_{b} = [s_{b}, b]*

*q _{a }*

*+q*

_{b }= [*s*

_{a}*+*

*s*

_{b}*,*

**a + b**]*q _{a }*

*-q*

_{b }= [*s*

_{a}*+*

*s*

_{b}*,*

**a - b**]*λ**q _{a} = [*

*λ*

*s*

_{a},*λ*

**a**]**Pure quaternion**: q = [0, **v**]

For quaternions, we can also compute the norm(magnitude), the square root of the sum of squares of all terms.

*q = s + x i +yj +zk*

*|q|=sqrt(s ^{2} + x^{2} + y^{2} + z^{2})*

*Unit norm: |q| = 1*

As in complex numbers, we can have a conjugate, inversing the sign of imaginary terms. Using the conjugate, we can efficiently compute the inverse of the quaternion.

*Conjugate: q ^{*}=[s, -v]*

*Inverse q ^{-1}=*

*q*

^{*}/|q|^{2}

Lastly, we can multiply two quaternions, as shown below. We used the aforementioned algebraic definitions to deal with the product of imaginary terms.

*q _{a} = s_{a} + x_{a}i +y_{a}j +z_{a}k*

*q _{b} = s_{b} + x_{b}i +y_{b}j +z_{b}k*

*q _{a}q_{b} = (*

*s*

_{a}+ x_{a}**i**+y_{a}**j**+z_{a}

**k)(***s*

_{b}+ x_{b}**i**+y_{b}**j**+z_{b}**k**

**)**=*(s _{a}s_{b} - x_{a}x_{b} - y_{a}y_{b} - z_{a}z_{b})+(s_{a}x_{b}+x_{a}s_{b}+y_{a}z_{b}-z_{a}y_{b})i +*

*(s _{a}y_{b} - x_{a}z_{b} + y_{a}s_{b} + z_{a}x_{b})j + (s_{a}z_{b} + x_{a}y_{b} - y_{a}x_{b} + z_{a}s_{b})k*

Also, we can represent multiplication in a matrix form. There are two options: we can either keep the order of quaternions or reverse them. When holding the order, we use a matrix ** L**, whereas changing the order requires using the matrix

*R.*Finally, let me show how to do rotations in 3D space by applying the quaternions. The quaternion allows us to rotate a point in 3D space around any vector by any angle. If we have a point * p(x_{p}, y_{p}, z_{p}) *and if we decide to rotate around an arbitrary

*we follow these steps:*

**axis v(x,y,z) by Θ angle,**- We define a pure quaternion for the point:
**p = [0, x**_{p}, y_{p}, z_{p}] - We define another quaternion using the rotation axis and angle:
*q = [cos(θ/2),**sin(θ/2)**x, sin(θ/2)**y, sin(θ/2**)z]* - Finally, we will do this multiplication:
*p' = qpq*^{-1}

After this multiplication, the imaginary part of * p'* will possess the position of the point after the rotation. So, we are ready to solve our second problem when we do the rotation in 3D space.

**Problem 2. **Rotate a point (0, 1, 1) around the y-axis to 90 degrees.

**Solution. **First, we define a pure quaternion of the point to be rotated: *q = [0, 0, 1, 1].*

Second, we define another quaternion using the rotation vector and angle. In our case, the rotation axis is the y-axis (0,1,0), and the angle is 90 degrees.

*q _{rot} = [cos(45), 0*

*, sin(45)*

*, 0*

*]*

Finally, we will do these multiplications: *p' = **q _{rot}*

*pq*And we use the matrices above to handle these multiplications. We multiply the first two terms

^{-1}_{rot}.*q*

_{rot}p =**L**(*q*

_{rot}*)p =*We keep the order of the quaternions, so I use the

**a.****matrix. The result is another quaternion**

*L**, which is equal to:*

**a**

Then, we do the second part of the multiplication. We use the quaternion's conjugate to get the quaternion's inverse.* *And in this case, I decided to reverse the order using the matrix **R**: *aq ^{-1}_{rot}= R(q^{-1}_{rot}*

*)a.*

Finally, the last three terms (1,1, 0) of the result possess the position of the point after the rotation operation. We can verify it visually using the figure below.

### Multiple rotations using quaternions

If we have sequential multiple rotations, we can apply the quaternions to handle them without much difficulty.

For example, if we have a single rotation, we can use this equation to compute the position of a point after the rotation:

*q _{1}(p)q^{-1}_{1}*

If we do another rotation, we need to add another quaternion:

*q _{2}*

*q*

_{1}(p)q^{-1}_{1}*q*

^{-1}_{2}Here we can use a trick to rearrange the order of inverse quaternions: *q ^{-1}_{1}*

*q*

^{-1}_{2}= (*q*

_{2}*q*Using this trick, let's rewrite the equation of multiple rotations:

_{1})^{-1}.*q _{2}*

*q*

_{1}(p)q^{-1}_{1}*q*

^{-1}_{2}= (*q*

_{2}*q*

_{1})(p)*(*

*q*

_{2}*q*

_{1})^{-1}If we denote (*q _{2}*

*q*)

_{1}*= q*

_{final}:(q_{2}q_{1})(p)(q_{2}q_{1})^{-1} = (q_{final})(p)(q_{final})^{-1}

This equation means that instead of computing the position every time the rotations happen, we can keep track of the total rotation by multiplying the quaternions.

**Frames of reference**

At this point, we clearly understand how the quaternions can be applied to compute the position of a point after rotation around some axis with some angle in 3D space. At the same time, we can define the relationship between the inertial frame and body frame using the quaternion because, in the end, how the body frame is rotated defines its relation to the inertial frame. And the quaternions are extremely helpful in determining the rotations in 3D space.

### Quaternions and Gyroscope

Finally let me show how IMU sensors and quaternions are linked. First, I will show how to calculate quaternions using the Gyroscope. The gyroscope is a sensor that measures the angular velocity in three axes. In other words, it measures the projection of the rotation to the axes of the body frame. We can convert the gyroscope readings to a quaternion:

Gyroscope readings: *[w _{x}, w_{y}, w_{z}], converted into radians*

We compute the rotation angle(*w*) and the axes of the rotation*(x _{g}, y_{g}, z_{g}):*

*w = sqrt(w ^{2}_{x} + w^{2}_{y} + w^{2}_{z})*

*x _{g} = ω_{x}/ω, y_{g} = ω_{y}/ω, z_{g} = ω_{z}/ω*

Finally, we have a quaternion:

*q _{gyro} = [cos(w/2), x_{g}sin(w/2), y_{g}sin(w/2), z_{g}sin(w/2)]*

We can further simplify this equation by exploiting the fact that the gyroscope is sampled at a high frequency (~1kHz), so the rotation angle is tiny. Then we can employ these approximations: *cos(w/2) = 1, **sin(ω/2) = ω/2. *If we substitute these approximations*, we obtain*

*q _{gyro} = [1, x_{g}w/2, y_{g}w/2, z_{g}w/2]*

Then instead of *x _{g}, y_{g}, z_{g}*, we insert their real expressions, so

*w*is canceled:

*q _{gyro} = [1, (*

*ω*

_{x}/ω)(*w/2),*

*(*

*ω*

_{x}/ω)(*w/2)*

*,*

*(*

*ω*

_{x}/ω)(*w/2)*

*]=*

*[1, **ω _{x}*

*/2,*

*ω*

_{y}*/2,*

*ω*

_{z}*/2]*

Finally, we can extract quaternions from the gyroscope readings without much computation.

If we sample the gyroscope every 1 ms, the quaternion computed by the gyroscope readings will represent a rotation that happened in this 1 ms time frame. As I showed before, we can multiply the quaternions of the successive rotations to obtain the quaternion representing the total rotation. In the case of using the gyroscope, We can do this operation to keep the quaternion that relates the body and inertial frame up-to-date:

*q _{new} = q_{old }q_{gyro}*

And we will use the * R *matrix to do this operation:

*q _{new} = R(q_{gyro})q_{old}*

_{}_{}

Here is the final equation for updating the quaternion using the gyroscope:

_{}

_{}

_{}

If you want to get more detailed guidance about attitude estimation, please refer to my course:

### Course about attitude estimation based on IMU sensors