# Quaternion

A quaternion is a four-part hypercomplex number used to describe 3D rotations and orientations.

Quaternions are used everywhere. To use this data for localization, you can capture it using a quaternion object, perform mathematical operations on it, or convert it to other rotation formats, such as Euler Angles and Rotation Matrix.

Fundamentals:

- https://docs.ros.org/en/foxy/Tutorials/Intermediate/Tf2/Quaternion-Fundamentals.html
- Watch this video when you need to by Steven M. Lavalle
- http://www.cs.cmu.edu/afs/cs/academic/class/16741-s07/www/lectures/Lecture8.pdf recommended by Raghava
- Also check out this https://eater.net/quaternions, which is an amazing intuitive video

$q=βq_{1}q_{2}q_{3}q_{4}βββR_{4}$

$β£β£qβ£β£=1$

IMPORTANT: Not sure if I completely missed this part in the VSLAM book, but $q=βq$

- important detail because I thought that the orientation was unique

## Notes from Visual SLAM book

Notes start at page 45 (chapter 2.4). A quaternion $q$ has a real part and three imaginary parts. We write the real part in the front (and there are also some books where the real part is in the last), like this:

where $i,j,k$ are three imaginary parts of the quaternion. These three imaginary parts satisfy the following relationship:

\begin{equation} \begin{cases} \begin{array}{l} {i^2} = {j^2} = {k^2} = - 1\\ ij = k, ji = - k \\ jk = i,kj = - i\\ ki = j, ik = - j \end{array} \end{cases} \end{equation}

If we look at $i,j,k$ as three axes, they look the same as complex numbers when multiplying with themselves. And look the same as the outer product when multiplying with the others.

We can also use a scalar and a vector to express quaternions: $q=[s,v]_{T},s=q_{0}βR,v=[q_{1},q_{2},q_{3}]_{T}βR_{3}$

- If the imaginary part $v$ is $0$, it is called
**real quaternion** - Conversely, if its real part $s$ is $0$, it is called
**imaginary quaternion**.

### Rotation with Quaternions

To rotate a point $p$ using Rotation Matrix, we know that is $p_{β²}=Rp$. How do we do that with a quaternion?

Let the rotation be specified by a unit quaternion $q$. First, we extend the 3D point to an imaginary quaternion: $p=[0,x,y,z]_{T}=[0,v]_{T}$

We just put the three coordinates into the imaginary part and leave the real part to be zero. Then, the rotated point $p_{β²}$ can be expressed as such a product:

**Multiplication**. Quaternion multiplication is the multiplication of each item of $q_{a}$ with each item of $q_{b}$

The scalar form is a little complicated, but the vector form is more concise:

Note that the product of two real quaternions is still real, which is also consistent with the real number multiplication. **NOTE**: quaternion multiplication is usually NOT commutative unless $v_{a}$ and $v_{b}$ at $R_{3}$ are parallel, which means the outer product term is zero.

**Length**. The length of a quaternion is defined as:

It can be verified that the length of the product is the product of the lengths. This makes the unit quaternion keep unit-length when multiplied by another unit quaternion:

**Conjugate**. The conjugate of a quaternion is to take the imaginary part as the opposite:

We get a real quaternion if the quaternion is multiplied by its conjugate. The real part is the square of its length:

**Scalar Multiplication**. Similar to vectors, quaternions can be multiplied by numbers: $kq=[ks,kv]_{T}$

### Quaternion as rotations

If you want to combine the effect of two quaternion rotations, you multiply them, not add them.

$q1βq2$

### Conversion to other Rotation Representations

The math behind this starts getting quite hefty.

#### Quaternion to Rotation Matrix

Derivation at page 65 of Visual SLAM book.

Let $q=[s,v]_{T}$. Then $R=vv_{T}+s_{2}I+2sv_{β§}+(v_{β§})_{2}$

In Eigen

`q.toRotationMatrix();`

#### Quaternion to Axis-Angle

Derivation at page 66 of Visual SLAM book.

Let $q=βq_{1}q_{2}q_{3}q_{4}βββR_{4}$. Then the conversion formula from quaternion to rotation vector can be written as

${ΞΈ=2arccosq_{0}[n_{x},n_{y},n_{z}]_{T}=[q_{1},q_{2},q_{3}]_{T}/sin2ΞΈββ$

In Eigen

```
Eigen::Vector3d axis = quaternion.axis();
double angle = quaternion.angle();
AngleAxisd rotation_vector(angle, axis);
```

#### Quaternion to Euler Angles

They donβt show it in the book. In Eigen, first convert to rotation matrix

`q.toRotationMatrix().eulerAngles(0,1,2);`

`q.eulerAngles(0,1,2)`

is not a valid function :(

No big deal though, Euler angles are rarely used apart to make it understandable for humans.

### Quaternions in Eigen

```
AngleAxisd rotation_vector(M_PI/4, Vector3d(0,0,1));
Matrix3d rotation_matrix = Matrix3d::Identity();
```

Initialize a quaternion

```
// Quaternion (3 different ways)
Quaterniond q(rotation_matrix); // using a 3x3 rotation matrix
Quaterniond q(rotation_vector); // using euler angles
Quaterniond q(w,x,y,z); // raw values, where w,x,y,z are doubles
```

Rotate a vector

```
Vector3d v(1, 0, 0);
v_rotated = q * v; // under the hood, it's qvq^{-1}
// equal to
v_rotated = q * Quaterniond(0, 1, 0, 0) β q.inverse()).coeffs().transpose()
```