Skip to content

Latest commit

 

History

History
1288 lines (682 loc) · 87.4 KB

7_Geometry_Transformation.md

File metadata and controls

1288 lines (682 loc) · 87.4 KB

Chapter 7 Geometry Transformation

1. Euler Angles

1.1. Introduction

The Euler angles are three angles to describe the orientation of a rigid body with respect to a fixed coordinate system.

The rotations may be about the axes XYZ of the original coordinate system, which is assumed to remain motionless (extrinsic), or rotations about the axes of the rotating coordinate system XYZ (intrinsic), solidary with the moving body, which changes its orientation with respect to the extrinsic frame after each elemental rotation.

1.2. Roll, Pitch, and Yaw

Euler angles are typically denoted as:

  • represents a rotation around the x axis.
  • represents a rotation around the y axis,
  • represents a rotation around the z axis,

1.3. Proper Euler angles and Tait-Bryan angles

There exist twelve possible sequences of rotation axes, which can be divided into two categories:

  1. Proper Euler angles, where one axis of rotation is repeated (x-z-x, x-y-x, y-x-y, y-z-y, z-y-z, z-x-z),
  2. Tait-Bryan angles, which rotate around all axes (x-z-y, x-y-z, y-x-z, y-z-x, z-y-x, z-x-y).

Sometimes, both kinds of sequences are called "Euler angles". In that case, the sequences of the first group are called proper or classic Euler angles.

There are six possibilities of choosing the rotation axes for Tait–Bryan angles. The six possible sequences are:

  • x-y′-z″ (intrinsic rotations) or z-y-x (extrinsic rotations)
  • y-z′-x″ (intrinsic rotations) or x-z-y (extrinsic rotations)
  • z-x′-y″ (intrinsic rotations) or y-x-z (extrinsic rotations)
  • x-z′-y″ (intrinsic rotations) or y-z-x (extrinsic rotations)
  • z-y′-x″ (intrinsic rotations) or x-y-z (extrinsic rotations): the intrinsic rotations are known as: yaw, pitch and roll
  • y-x′-z″ (intrinsic rotations) or z-x-y (extrinsic rotations)

1.4. Rotation matrix









It is important to note that performs the roll first, then the pitch, and finally the yaw.



1.5. Determining Yaw, Pitch, And Roll From a Rotation Matrix









and



There is a choice of four quadrants for the inverse tangent functions. Each quadrant should be chosen by using the signs of the numerator and denominator of the argument. The numerator sign selects whether the direction will be above or below the x-axis , and the denominator selects whether the direction will be to the left or right of the y-axis . the function atan2 can calculate this for us:

Note that this method assumes and .

1.6. Signs and ranges

  • for and , the range is defined modulo radians. For instance, a valid range could be .
  • for , the range covers radians (but can't be said to be modulo ). For example, it could be or .

1.7. Tait–Bryan Angles







1.8. Equivalent Proper Euler Angles





Click here for interactive demo

1.9. Oder of Rotation and Translation in Transformation

to apply a transformation, first we apply the rotation around the axis of the frame the we pre-multiplied and then we translate again on the axis of the frame that we pre-multiplied











1.10. Gimbal Lock

The angles are uniquely determined except for the singular case. If



This will result in:

This will result in:

This means that there are infinitely many sets of (roll,yaw) angles for a given rotation matrix at with https://latex.codecogs.com/svg.image?\beta=\pm \pi/2

Visit the link for interactive Gimbal visualization.

Absolutely, let's illustrate the gimbal lock issue using a numerical example and then explain how the problem manifests in the Euler angle representation but not with quaternions.

Numerical Example:

Consider a 3D object that we wish to rotate using the roll-pitch-yaw sequence (often used in aerospace). For the sake of simplicity, let's work with degrees:

  1. Initial orientation: No rotation applied. Euler angles are (roll, pitch, yaw) = (0°, 0°, 0°).

  2. Rotation: We apply a pitch of +90°. Now, our Euler angles are (0°, 90°, 0°).

At this point, the object's 'nose' is pointing straight up. Here's the problem:

If we now try to apply a roll of, say, +45°, the actual effect in 3D space will be identical to applying a yaw of +45°. We cannot distinguish between roll and yaw anymore; they have become degenerate. This is gimbal lock.

Numerical Values:

Euler Angles: After the +90° pitch, our Euler angles become: Roll: (or +45° if we attempt a roll after pitching) Pitch: 90° Yaw: (or +45° if we attempt a yaw after pitching)

This is problematic because after the pitch of +90°, the roll and yaw rotations are indistinguishable in effect.

Quaternion Representation: The rotation for a +90° pitch around the Y-axis can be represented as: q = \cos\left(\frac{\theta}{2}\right) + \sin\left(\frac{\theta}{2}\right)\mathbf{j}
= q = \cos(45) + \sin(45)\mathbf{j}

= q = 0.707 + 0.707\mathbf{j}

Now, if we wanted to apply a roll of +45° after this pitch using quaternions, we would multiply the above quaternion by the quaternion representation of a +45° roll around the X-axis, resulting in a distinct and unique quaternion value that smoothly combines both rotations without ambiguity.

Why Euler Angles Have This Problem:

The core of the gimbal lock problem with Euler angles lies in the sequential nature of the rotations. When the pitch angle is ±90°, the axes for roll and yaw become aligned. Hence, rotating around one of these axes is indistinguishable from rotating around the other. This overlap or "lock" is what causes the loss of a degree of freedom.

Why Quaternions Don't Have This Problem:

Quaternions represent rotations as a single, unified operation rather than a sequence. This means there's no inherent order or sequence to worry about. A quaternion rotation of +90° pitch followed by a +45° roll will result in a unique orientation distinct from any other combination of rotations.

Furthermore, quaternions interpolate smoothly between orientations using "slerp" (spherical linear interpolation), ensuring a consistent and continuous rotation without the jumps or singularities associated with Euler angles.

In summary, the non-sequential nature of quaternions, combined with their ability to uniquely represent every possible orientation in 3D space, makes them immune to the gimbal lock problem that plagues Euler angles.

quaternions.online.png

Click here for interactive demo

1.10. Uniqueness of 3D Rotation Matrix

Refs: 1

2. Global References and Local Tangent Plane Coordinates

There are several axes conventions in practice for choosing the mobile and fixed axes and these conventions determine the signs of the angles.

Tait–Bryan angles are often used to describe a vehicle's attitude with respect to a chosen reference frame. The positive x-axis in vehicles points always in the direction of movement. For positive y- and z-axis, we have to face two different conventions:

2.1. East, North, Up (ENU)

East, North, Up (ENU), used in geography (z is up and x is in the direction of move, y is pointing left)

2.2 North, East, Down (NED)

  • North, East, Down (NED), used specially in aerospace (z is down and x is in the direction of move, y is pointing right)

In case of land vehicles like cars, tanks ENU-system (East-North-Up) as external reference (World frame), the vehicle's (body's) positive y- or pitch axis always points to its left, and the positive z- or yaw axis always points up.

In case of air and sea vehicles like submarines, ships, airplanes etc., which use the NED-system (North-East-Down) as external reference (World frame), the vehicle's (body's) positive y- or pitch axis always points to its right, and its positive z- or yaw axis always points down.

https://latex.codecogs.com/svg.latex?\begin{array}{rcl}
\mathbf{g} &=&
\left\{
\begin{array}{ll}
\begin{bmatrix}0 & 0 & -1\end{bmatrix}^T & \mathrm{if}\; \mathrm{NED} \\
\begin{bmatrix}0 & 0 & 1\end{bmatrix}^T & \mathrm{if}\; \mathrm{ENU}
\end{array}
\right.\\ && \\
\mathbf{r} &=&
\left\{
\begin{array}{ll}
\frac{1}{\sqrt{\cos^2\theta+\sin^2\theta}}\begin{bmatrix}\cos\theta & 0 & \sin\theta\end{bmatrix}^T & \mathrm{if}\; \mathrm{NED} \\
\frac{1}{\sqrt{\cos^2\theta+\sin^2\theta}}\begin{bmatrix}0 & \cos\theta & -\sin\theta\end{bmatrix}^T & \mathrm{if}\; \mathrm{ENU}
\end{array}
\right.
\end{array}

3. Axis-angle Representation

Axis-angle representation of a rotation in a three-dimensional Euclidean space by two quantities:

  1. A unit vector indicating the direction of an axis of rotation,
  2. An angle



The above example can be represented as:

Rodrigues' Rotation Formula

If is a vector in and is a unit vector describing an axis of rotation by an angle



to get the rotation matrix:

where is written in the matrix form.


Exponential Coordinates For Rotation

Any orientation can be achieved from initial orientation by rotating about some unit axis (angular velocity) by a particular angle . If we multiply these two we will get which is a three parameter representation of parameter. We call these three parameters Exponential Coordinates representing the orientation of one frame relative to another.





The answer to this vector differential equation is matrix exponential which can be expressed with series expansion.





Taylor Series

{\displaystyle f(a)+{\frac {f'(a)}{1!}}(x-a)+{\frac {f''(a)}{2!}}(x-a)^{2}+{\frac {f'''(a)}{3!}}(x-a)^{3}+\cdots ,}

if we write it for around point zero:



https://latex.codecogs.com/svg.latex?{\displaystyle f(0)+{\frac {f'(0)}{1!}}(x-0)+{\frac {f''(0)}{2!}}(x-0)^{2}+{\frac {f'''(0)}{3!}}(x-0)^{3}+\cdots ,}



https://latex.codecogs.com/svg.latex?{\displaystyle 1+{\frac a{1!}}x+{\frac {a^2}{2!}}x^{2}+{\frac {a^3}{3!}}x^{3}+\cdots ,}



if





and if





when the matrix skew-symmetric the expansion has closed form solution:









Exponential Coordinates For Rigid-Body Motions



The final transformation of the frame:



where if then:



and if



4. Quaternions

quaternion number system extends the complex numbers which introduced by William Rowan Hamilton. Hamilton defined a quaternion as the quotient of two vectors (two lines in a three-dimensional space). Quaternions are generally represented in the form:

where a, b, c, and d are real numbers; and i, j, and k are the basic quaternions ( symbols that can be interpreted as unit-vectors pointing along the three spatial axes).

a quaternion , as consisting of a scalar part and a vector part. The quaternion is called the vector part (sometimes imaginary part) of q, and is the scalar part (sometimes real part) of q.

4.1. Basis

The set of quaternions is made a 4-dimensional vector space over the real numbers, with as a basis, by the componentwise addition

vector definition of a quaternion:

https://latex.codecogs.com/svg.latex?\mathbf{q}\triangleq 
\begin{bmatrix}q_w \\ \mathbf{q}_v\end{bmatrix} =
\begin{bmatrix}q_w \\ q_x \\ q_y \\ q_z\end{bmatrix}





4.1.1. Quaternion Conventions: Hamilton and JPL

Refs: 1

4.2. Inverse of Quaternions

Conjugate

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

https://latex.codecogs.com/svg.image?\begin{equation}
\mathbf{q}_a ^ * = s_a - x_ai - y_aj - z_ak = [s_a, - \mathbf{v}_a] ^T.
\end{equation}

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

https://latex.codecogs.com/svg.image?\begin{equation}     \mathbf{q}^* \mathbf{q} = \mathbf{q} \mathbf{q}^* = [s^2+\mathbf{v}^T \mathbf{v}, \mathbf{0} ]^T.     \end{equation}



length

The length of a quaternion is defined as

https://latex.codecogs.com/svg.image?\begin{equation}     \| \mathbf{q}_a \| = \sqrt{ s_a^2 + x_a^2 + y_a^2 + z_a^2 }.\end{equation}

It can be verified that the length of the product is the product of the lengths.

https://latex.codecogs.com/svg.image?\begin{equation}     \| \mathbf{q}_a \mathbf{q}_b \| = \|\mathbf{q}_a \| \| \mathbf{q}_b \|.     \end{equation}



The inverse of a quaternion is:

https://latex.codecogs.com/svg.image?\begin{equation}     \label{eq:quaternionInverse}     \mathbf{q} ^ { - 1 } = \mathbf{q} ^ * / \| \mathbf{q} \| ^ 2.    \end{equation}

4.3. Quaternions Multiplication (Hamilton product)


For two elements and , their product, called the Hamilton product and is determined by distributive law:







https://latex.codecogs.com/svg.latex?\mathbf{pq} =
\begin{bmatrix}
p_w q_w - p_x q_x - p_y q_y - p_z q_z \\
p_w q_x + p_x q_w + p_y q_z - p_z q_y \\
p_w q_y - p_x q_z + p_y q_w + p_z q_x \\
p_w q_z + p_x q_y - p_y q_x + p_z q_w
\end{bmatrix}



4.4. Quaternion as Orientation

Any orientation in a three-dimensional euclidean space of a frame https://latex.codecogs.com/svg.latex?B with respect to a frame https://latex.codecogs.com/svg.latex?S can be represented by a unit quaternion (a.k.a. versor), https://latex.codecogs.com/svg.latex?\mathbf{q}\in\mathbb{H}^4 , in Hamiltonian space defined as:

https://latex.codecogs.com/svg.latex?^S_B\mathbf{q} = \begin{bmatrix}q_w\\q_x\\q_y\\q_z\end{bmatrix} =
\begin{bmatrix}
\cos\frac{\alpha}{2}\\e_x\sin\frac{\alpha}{2}\\e_y\sin\frac{\alpha}{2}\\e_z\sin\frac{\alpha}{2}
\end{bmatrix}

where https://latex.codecogs.com/svg.latex?\alpha is the rotation angle and e is the unit vector representing the rotation axis.

The orientation of frame https://latex.codecogs.com/svg.latex?S relative to frame https://latex.codecogs.com/svg.latex?B is the conjugate quaternion:

https://latex.codecogs.com/svg.latex?^S_B\mathbf{q}^* = \,^B_S\mathbf{q} = \begin{bmatrix}q_w\\-q_x\\-q_y\\-q_z\end{bmatrix}

the sequence of rotations follows the subscript cancellation rule:

https://latex.codecogs.com/svg.latex?^C_A\mathbf{q} = \,^C_B\mathbf{q} \, ^B_A\mathbf{q}



4.5 Changing Frame of Reference with Unit Quaternion

If you have a vector that has been expressed in frame A:
https://latex.codecogs.com/svg.latex?^A\mathbf{v}=\begin{bmatrix}v_x \\ v_y \\ v_z\end{bmatrix}


If you want to express it in frame B, First express it as :

https://latex.codecogs.com/svg.latex?^A\mathbf{v}_q=\begin{bmatrix}0\\v_x \\ v_y \\ v_z\end{bmatrix}


https://latex.codecogs.com/svg.latex?^B\mathbf{v}_q = \, ^B_A\mathbf{q} \, ^A\mathbf{v}_q \, ^B_A\mathbf{q}^*

The inverse rotation:

https://latex.codecogs.com/svg.latex?^A\mathbf{v}_q = \, ^B_A\mathbf{q}^* \, ^B\mathbf{v}_q \, ^B_A\mathbf{q} = \, ^A_B\mathbf{q} \, ^B\mathbf{v}_q \, ^A_B\mathbf{q}^*

These rotations can also be expressed Direction Cosine Matrix:

https://latex.codecogs.com/svg.latex?\mathbf{R}(^B_A\mathbf{q}) =
\begin{bmatrix} q_w^2+q_x^2-q_y^2-q_z^2 & 2(q_xq_y - q_wq_z) & 2(q_xq_z + q_wq_y) \\ 2(q_xq_y + q_wq_z) & q_w^2-q_x^2+q_y^2-q_z^2 & 2(q_yq_z - q_wq_x) \\ 2(q_xq_z - q_wq_y) & 2(q_wq_x + q_yq_z) & q_w^2-q_x^2-q_y^2+q_z^2 \end{bmatrix}



4.6 Quaternions Inverse Pose

If you have the pose of frame A expressed in the world frame as [x, y, z, q1, q2, q3, q4] where [x, y, z] is the position and [q1, q2, q3, q4] is the quaternion representing the orientation, then you want to find the pose of the world frame with respect to frame A.

Given:

  • Position of frame A in world frame: [x, y, z]
  • Orientation of frame A in world frame (as quaternion): [q1, q2, q3, q4]

To compute the pose of the world in frame A, we'll need to find the inverse transformation.

  1. Inverse Position: The position of the world origin in frame A coordinates is given by the negation of the original position: [x', y', z'] = [-x, -y, -z]

  2. Inverse Orientation: The orientation of the world frame with respect to frame A can be obtained by taking the conjugate of the given quaternion. The conjugate of a quaternion [q1, q2, q3, q4] is given by: [q1', q2', q3', q4'] = [q1, -q2, -q3, -q4]

However, simply inverting the translation is not enough. The correct pose of the world in frame A would require us to rotate the negated translation vector using the inverse orientation.

To do this, you'll express the negated position vector as a quaternion with zero scalar part:  q_{\text{pos}} = [0, -x, -y, -z] .

Then, you'll multiply this by the inverse orientation quaternion:  q_{\text{result}} = q_{\text{inv}} \times q_{\text{pos}} \times q where q is the original orientation quaternion, and q_{\text{inv}} is its conjugate.

The resulting quaternion q_{\text{result}} will have its vector part (last three components) as the desired transformed position of the world in frame A. The scalar part of q_{\text{result}} should be 0.

Finally:

  • The position of the world in frame A is the vector part of q_{\text{result}}.
  • The orientation of the world in frame A is the conjugate of the given orientation: [q1', q2', q3', q4'].


4.7 Quaternions Relative Pose

If Pose C express in Frame B and pose of B expressed in A using quaternions, equation for finding the pose C expressed in A using quaternions

  1. Rotations: Let's define the following quaternions for the rotations:
  • Q^{A}_{B} is the quaternion representing the rotation of frame B with respect to frame A (B's rotation expressed in frame A).
  • Q^{B}_{C} is the quaternion representing the rotation of frame C with respect to frame B (C's rotation expressed in frame B).

The combined rotation of frame C with respect to frame A, Q^{A}_{C} , is given by: Q^{A}_{C} = Q^{A}_{B} \otimes Q^{B}_{C}

  1. Translations (positions): If you have the positions:
  • P^{A}_{B} is the position of point B (or frame B's origin) expressed in frame A.
  • P^{B}_{C} is the position of point C (or frame C's origin) expressed in frame B.

The position of point C (or frame C's origin) expressed in frame A, P^{A}_{C}, when considering rotations, is:  P^{A}_{C} = P^{A}_{B} + Q^{A}_{B} \otimes P^{B}_{C} \otimes (Q^{A}_{B})^{-1}

Where (Q^{A}_{B})^{-1} denotes the conjugate (or inverse) of the quaternion \( Q^{A}_{B} \).



4.8. Conversion between quaternions and Euler angles

A unit quaternion can be described as:

where

To get the rotation matrix:

To get the roll pitch, yaw:

A very good article to read about quaternions



4.9. Quaternion Representing the Rotation From One Vector to Another

Refs: 1



4.10. Quaternions and Axis-Angle Representation

Quaternions can encode axis-angle representation in four numbers and can be used to apply the corresponding rotation to a position vector https://latex.codecogs.com/svg.image?(x,y,z), representing a point relative to the origin in https://latex.codecogs.com/svg.image?\mathbb{R}^3.

Euclidean vectors such as https://latex.codecogs.com/svg.image?(2,3,4) or https://latex.codecogs.com/svg.image?(a_x,a_y,a_z) can be rewritten as https://latex.codecogs.com/svg.image?2i+3j+4k or https://latex.codecogs.com/svg.image?(a_xi,a_yj,a_zk) , where i, j, k are unit vectors representing the three Cartesian axes (traditionally x, y, z), and also obey the multiplication rules of the fundamental quaternion units.

Therefore, a rotation of angle https://latex.codecogs.com/svg.image?\theta around the axis defined by the unit vector https://latex.codecogs.com/svg.image?{\vec {u}}=(u_{x},u_{y},u_{z})=u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k}

can be represented by a quaternion using an extension of Euler's formula:

https://latex.codecogs.com/svg.image?\mathbf {q} =e^{{\frac {\theta }{2}}{(u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k} )}}=\cos {\frac {\theta }{2}}+(u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k} )\sin {\frac {\theta }{2}}

The desired rotation can be applied to an ordinary vector

https://latex.codecogs.com/svg.image?\mathbf {p} =(p_{x},p_{y},p_{z})=p_{x}\mathbf {i} +p_{y}\mathbf {j} +p_{z}\mathbf {k} in 3-dimensional space, considered as a quaternion with a real coordinate equal to zero, by the followings:

https://latex.codecogs.com/svg.image?\mathbf {p'} =\mathbf {q} \mathbf {p} \mathbf {q} ^{-1}

In this instance, q is a unit quaternion and

https://latex.codecogs.com/svg.image?\mathbf {q} ^{-1}=e^{-{\frac {\theta }{2}}{(u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k} )}}=\cos {\frac {\theta }{2}}-(u_{x}\mathbf {i} +u_{y}\mathbf {j} +u_{z}\mathbf {k} )\sin {\frac {\theta }{2}}.

Example: rotate the point vector (1,0,0) around y axis (0,1,0) 90 degrees.

// P  = [0, p1, p2, p3]  <-- point vector
// alpha = angle to rotate
//[x, y, z] = axis to rotate around (unit vector)
// R = [cos(alpha/2), sin(alpha/2)*x, sin(alpha/2)*y, sin(alpha/2)*z] <-- rotation
// R' = [w, -x, -y, -z]
// P' = RPR'
// P' = H(H(R, P), R')

Eigen::Vector3d p(1, 0, 0);

Quaternion P;
P.w = 0;
P.x = p(0);
P.y = p(1);
P.z = p(2);

// rotation of 90 degrees about the y-axis
double alpha = M_PI / 2;
Quaternion R;
Eigen::Vector3d r(0, 1, 0);
r = r.normalized();


R.w = cos(alpha / 2);
R.x = sin(alpha / 2) * r(0);
R.y = sin(alpha / 2) * r(1);
R.z = sin(alpha / 2) * r(2);

std::cout << R.w << "," << R.x << "," << R.y << "," << R.z << std::endl;

Quaternion R_prime = quaternionInversion(R);
Quaternion P_prime = quaternionMultiplication(quaternionMultiplication(R, P), R_prime);

/*rotation of 90 degrees about the y-axis for the point (1, 0, 0). The result
is (0, 0, -1). (Note that the first element of P' will always be 0 and can
therefore be discarded.)
*/

Refs: 1

let's demonstrate the rotation of a vector using both the quaternion and the axis-angle methods, using the same angle \theta and a unit axis vector \mathbf{u} .

Consider:

  • Vector \mathbf{v} = [a_x, b_y, c_z]
  • Rotation axis \mathbf{u} = [u_x, u_y, u_z] (assuming \mathbf{u} is a unit vector)
  • Rotation angle \theta

4.11. Fully Represent a Frame With Quaternions

To represent a position in 3D space use a combination of a quaternion for orientation and a vector for the position.

  • For the position, you can use a Vector3d, which is a vector of three doubles.
  • For the orientation, use a Quaterniond, which is a quaternion that uses double precision.

** Define Position and Orientation **

Eigen::Vector3d position(1.0, 2.0, 3.0); // Example position (x, y, z)
Eigen::Quaterniond orientation; // Quaternion for orientation

Initialize the Quaternion:

  • You can initialize the quaternion in several ways, such as from an axis-angle representation, from a rotation matrix, or directly setting its components.
// Example: initializing the quaternion from an axis and an angle
Eigen::Vector3d axis(0, 1, 0); // Rotation around the y-axis
double angle = M_PI / 4; // Rotate 45 degrees
orientation = Eigen::AngleAxisd(angle, axis.normalized());

Using the Position and Orientation:

  • Once you have the position and the quaternion, you can use them to transform points, calculate rotations, etc.
// Example: rotating a point using the quaternion
Eigen::Vector3d point(1, 0, 0);
Eigen::Vector3d rotatedPoint = orientation * point;

Combining Position and Orientation:

  • If you want to create a transformation matrix that includes both the position and orientation, you can do so using an affine transformation.
Eigen::Affine3d transform = Eigen::Translation3d(position) * orientation;

4.12. Multiplication of Frames Expressed with Quaternions

Here's a complete example putting it all together:

double x1 = 1.0, y1 = 0.0, z1 = 0.0;
double q_w1 = 1.0, q_x1 = 0.0, q_y1 = 0.0, q_z1 = 0.0;
double x2 = 1.0, y2 = 0.0, z2 = 0.0;
double q_w2 = 1.0, q_x2 = 0.0, q_y2 = 0.0, q_z2 = 0.0;

Eigen::Affine3d pose1 = Eigen::Translation3d(x1, y1, z1) * Eigen::Quaterniond(q_w1, q_x1, q_y1, q_z1);
Eigen::Affine3d pose2 = Eigen::Translation3d(x2, y2, z2) * Eigen::Quaterniond(q_w2, q_x2, q_y2, q_z2);

Eigen::Affine3d result = pose1 * pose2;

Eigen::Vector3d res_translation = result.translation();
Eigen::Quaterniond res_quaternion(result.rotation());

std::cout << "Resulting Pose Translation: " << res_translation.transpose() << std::endl;
std::cout << "Resulting Pose Quaternion: " 
      << res_quaternion.w() << " " 
      << res_quaternion.x() << " " 
      << res_quaternion.y() << " " 
      << res_quaternion.z() << std::endl;

Rotating using Quaternion:

First, convert the axis-angle representation to a quaternion:

q = \cos\left(\frac{\theta}{2}\right) + \sin\left(\frac{\theta}{2}\right)(u_x\mathbf{i} + u_y\mathbf{j} + u_z\mathbf{k})

Now, to rotate the vector: \mathbf{v'} = q \times \mathbf{v} \times q^* Where: \mathbf{v} = 0 + a_x\mathbf{i} + b_y\mathbf{j} + c_z\mathbf{k}

And q^* is the conjugate of q.

Rotating using Axis-Angle:

\mathbf{v'} = \mathbf{v} \cos(\theta) + (\mathbf{u} \times \mathbf{v}) \sin(\theta) + \mathbf{u} (\mathbf{u} \cdot \mathbf{v}) (1 - \cos(\theta))

Example:

Let's rotate the vector \mathbf{v} = [1, 0, 0] by \theta = \frac{\pi}{2} (90 degrees) around the unit axis \mathbf{u} = [0, 0, 1]:

Using the Quaternion method:

  1. Convert to quaternion: q = \cos(45^\circ) + 0\mathbf{i} + 0\mathbf{j} + \sin(45^\circ)\mathbf{k}
  2. Rotate: \mathbf{v'} = q \times [0, 1, 0, 0] \times q^* Result:

Using the Axis-Angle method:

  1. Calculate: \mathbf{v'} = [1, 0, 0] \cos(90^\circ) + [0, 1, 0] \sin(90^\circ) + [0, 0, 1] ([0, 0, 1] \cdot [1, 0, 0]) (1 - \cos(90^\circ))

Result: \mathbf{v'} = [0, 1, 0]

In both methods, the result is \mathbf{v'} = [0, 1, 0], which is a 90-degree rotation of the original vector around the z-axis.

4.12.1. Rotating a vector using a quaternion

how to rotate a vector \mathbf{v} by a quaternion q:

  1. Represent the Vector as a Quaternion: If your vector is \mathbf{v} = [v_x, v_y, v_z], represent it as a quaternion:

\mathbf{v} = 0 + v_x\mathbf{i} + v_y\mathbf{j} + v_z\mathbf{k}

  1. Quaternion Rotation: To rotate the vector by quaternion https://latex.codecogs.com/svg.latex?q, use the following formula:

\mathbf{v}_{\text{rot}} = q \times \mathbf{v} \times q^*

where

q^*

is the conjugate of

https://latex.codecogs.com/svg.latex?q

.
  1. Extract the Rotated Vector: After the multiplication, your rotated vector is the imaginary part of the resulting quaternion.

Example: Let's say you have a vector \mathbf{v} = [1, 0, 0] and you want to rotate it by 90 degrees around the z-axis. The corresponding quaternion for this rotation is: q = \cos(\theta/2) + \sin(\theta/2) \times \mathbf{axis} = \cos(45^\circ) + \sin(45^\circ)k = \sqrt{2}/2 + \sqrt{2}/2k

To rotate the vector:

  1. Represent the vector as a quaternion: \mathbf{v} = 0 + 1\mathbf{i} + 0\mathbf{j} + 0\mathbf{k}
  2. Multiply:

\mathbf{v}_{\text{rot}} = q \times \mathbf{v} \times q^*

  1. The imaginary part of \mathbf{v}_{\text{rot}} is your rotated vector.

Using the above method, the vector [1, 0, 0] would be rotated to approximately [0, 1, 0] (assuming unit quaternions).

It's worth noting that using quaternions to represent and perform rotations can help avoid issues like gimbal lock, which can occur with Euler angles. Quaternions provide a compact and efficient way to represent 3D orientations and perform rotations.

4.12.2. Transform a full representation of position (orientation and translation ) with quaternions

When you have a full representation of position using both orientation (rotation) and translation, and you want to transform it using quaternions, you'll need to consider both the rotational and translational components.

Let's denote:

  • The source frame as:

    • Orientation (rotation) quaternion: q_s
    • Translation vector: t_s
  • The transformation frame as:

    • Orientation (rotation) quaternion: q_t
    • Translation vector: t_t

To transform the source frame by the transformation frame:

  1. Rotate the orientation of the source frame using the orientation of the transformation frame.
  2. Rotate the translation of the source frame by the orientation of the transformation frame, then add the translation of the transformation frame.

a source frame represented by the orientation q_s and translation t_s using a transformation frame with orientation q_t and translation t_t, here's the mathematical breakdown:

  1. Compound the Rotations: The resulting orientation q_{combined} of the transformed source frame is found by quaternion multiplication: q_{combined} = q_t \times q_s

  2. Rotate the Source Translation and Add Transformation Translation:

    First, convert the translation vector t_s of the source frame into a quaternion t_{s\_quat} with a zero scalar part:

t_{s\_quat} = 0 + t_{s_x}\mathbf{i} + t_{s_y}\mathbf{j} + t_{s_z}\mathbf{k}

Then, rotate this quaternion using the orientation q_t of the transformation frame: t_{s\_rotated\_quat} = q_t \times t_{s\_quat} \times q_t^* where q_t^* is the conjugate of q_t.

The rotated translation vector t_{s\_rotated} is then the imaginary part (vector part) of t_{s\_rotated\_quat}.

Finally, add the translation vector t_t of the transformation frame to get the combined translation: t_{combined} = t_{s\_rotated} + t_t

So, the final transformed source frame in the new reference frame is represented by orientation q_{combined} and translation t_{combined}.

Here's a Python code example using the numpy and numpy-quaternion libraries:

import numpy as np
import quaternion

# Define quaternions and translations
# For the sake of the example, let's assume the following:
# A rotation of 45 degrees around the z-axis for both frames
# And a translation of (1,0,0) for both frames

angle = np.pi / 4
axis = np.array([0, 0, 1])

q_s = quaternion.from_rotation_vector(angle * axis)
t_s = np.array([1, 0, 0])

q_t = quaternion.from_rotation_vector(angle * axis)
t_t = np.array([1, 0, 0])

# 1. Compound the rotations
q_combined = q_t * q_s

# 2. Rotate the source translation and then translate
# Convert translation to quaternion
t_s_quat = np.quaternion(0, t_s[0], t_s[1], t_s[2])

# Rotate translation
t_s_rotated_quat = q_t * t_s_quat * q_t.inverse()

# Extract the vector part and add the transformation translation
t_combined = np.array([t_s_rotated_quat.x, t_s_rotated_quat.y, t_s_rotated_quat.z]) + t_t

print(f"Combined Orientation (Quaternion): {q_combined}")
print(f"Combined Translation: {t_combined}")

4.12.3. Inverse of Full Pose (position and orientation ) expressed in Quaternions

If you have the pose of frame A expressed in the world frame as [x, y, z, q1, q2, q3, q4] where [x, y, z] is the position and [q1, q2, q3, q4] is the quaternion representing the orientation, then you want to find the pose of the world frame with respect to frame A.

Given:

  • Position of frame A in world frame: [x, y, z]
  • Orientation of frame A in world frame (as quaternion): [q1, q2, q3, q4]

To compute the pose of the world in frame A, we'll need to find the inverse transformation.

  1. Inverse Position: The position of the world origin in frame A coordinates is given by the negation of the original position: [x', y', z'] = [-x, -y, -z]

  2. Inverse Orientation: The orientation of the world frame with respect to frame A can be obtained by taking the conjugate of the given quaternion. The conjugate of a quaternion [q1, q2, q3, q4] is given by: [q1', q2', q3', q4'] = [q1, -q2, -q3, -q4]

However, simply inverting the translation is not enough. The correct pose of the world in frame A would require us to rotate the negated translation vector using the inverse orientation.

To do this, you'll express the negated position vector as a quaternion with zero scalar part:  q_{\text{pos}} = [0, -x, -y, -z] .

Then, you'll multiply this by the inverse orientation quaternion:  q_{\text{result}} = q_{\text{inv}} \times q_{\text{pos}} \times q where q is the original orientation quaternion, and q_{\text{inv}} is its conjugate.

The resulting quaternion q_{\text{result}} will have its vector part (last three components) as the desired transformed position of the world in frame A. The scalar part of q_{\text{result}} should be 0.

Finally:

  • The position of the world in frame A is the vector part of q_{\text{result}}.
  • The orientation of the world in frame A is the conjugate of the given orientation: [q1', q2', q3', q4'].

4.12.4. Example of relative pose of two camera and IMU

if the given transformations are the positions of the IMU expressed in the camera frames, then we need to slightly modify our approach.

Given:

  • q_{C0-IMU}: Quaternion of IMU with respect to Camera0
  • q_{C1-IMU}: Quaternion of IMU with respect to Camera1
  • t_{C0-IMU}: Translation of IMU with respect to Camera0
  • t_{C1-IMU}: Translation of IMU with respect to Camera1

We want to find:

  • q_{C0-C1}: Quaternion of Camera1 with respect to Camera0
  • t_{C0-C1}: Translation of Camera1 with respect to Camera0

The formulae are:

  • q_{C0-C1} = q_{C0-IMU} \otimes q_{C1-IMU}^{-1}
  • t_{C0-C1} = q_{C0-IMU} \otimes (t_{C1-IMU} - t_{C0-IMU}) \otimes q_{C0-IMU}^{-1}

Let's implement this in Python:

import numpy as np
from pyquaternion import Quaternion

def relative_pose(q_C0_IMU, t_C0_IMU, q_C1_IMU, t_C1_IMU):
    # Calculate relative quaternion
    q_C0_C1 = q_C0_IMU * q_C1_IMU.inverse

    # Calculate relative translation
    t_diff = np.array(t_C1_IMU) - np.array(t_C0_IMU)
    t_C0_C1 = q_C0_IMU.rotate(t_diff)

    return q_C0_C1, t_C0_C1.tolist()

# Define quaternions and translations for IMU w.r.t Camera0 and Camera1
q_C0_IMU = Quaternion(w=0.6328142, x=0.3155095, y=-0.3155095, z=0.6328142)
t_C0_IMU = [0.234508, 0.028785, 0.039920]

q_C1_IMU = Quaternion(w=0.3155095, x=-0.6328142, y=-0.6328142, z=-0.3155095)
t_C1_IMU = [0.234508, 0.028785, -0.012908]

q_C0_C1, t_C0_C1 = relative_pose(q_C0_IMU, t_C0_IMU, q_C1_IMU, t_C1_IMU)
print("Quaternion of Camera1 w.r.t Camera0:", q_C0_C1)
print("Translation of Camera1 w.r.t Camera0:", t_C0_C1)

This Python code should give you the pose of Camera1 with respect to Camera0.

4.12.5. Expressing Relative Pose using Quaternions (subscript cancellation)

If Pose C express in Frame B and pose of B expressed in A using quaternions, equation for finding the pose C expressed in A using quaternions

  1. Rotations: Let's define the following quaternions for the rotations:
  • Q^{A}_{B} is the quaternion representing the rotation of frame B with respect to frame A (B's rotation expressed in frame A).
  • Q^{B}_{C} is the quaternion representing the rotation of frame C with respect to frame B (C's rotation expressed in frame B).

The combined rotation of frame C with respect to frame A, Q^{A}_{C} , is given by: Q^{A}_{C} = Q^{A}_{B} \otimes Q^{B}_{C}

  1. Translations (positions): If you have the following positions:
  • P^{A}_{B} is the position of point B (or frame B's origin) expressed in frame A.
  • P^{B}_{C} is the position of point C (or frame C's origin) expressed in frame B.

The position of point C (or frame C's origin) expressed in frame A, P^{A}_{C}, when considering rotations, is:  P^{A}_{C} = P^{A}_{B} + Q^{A}_{B} \otimes P^{B}_{C} \otimes (Q^{A}_{B})^{-1}

Where (Q^{A}_{B})^{-1} denotes the conjugate (or inverse) of the quaternion \( Q^{A}_{B} \).

4.13. Quaternions Interpolation Slerp

5. Conversion between different representations

Full list of conversion here

Conversion of Quaternions to Other Rotation Representations

Refs: 1

<< Previous Home Next >>