Helios++
Helios software for LiDAR simulations
Rotation Class Reference

#include <Rotation.h>

Public Member Functions

 Rotation (double q0, double q1, double q2, double q3, bool needsNormalization)
 
 Rotation (glm::dvec3 axis, double angle)
 
 Rotation (glm::dvec3 u, glm::dvec3 v)
 
 Rotation (RotationOrder order, double alpha1, double alpha2, double alpha3)
 
double getQ0 () const
 Get the scalar coordinate of the quaternion. More...
 
void setQ0 (double q0)
 
double getQ1 () const
 Get the first coordinate of the vectorial part of the quaternion. More...
 
void setQ1 (double q1)
 
double getQ2 () const
 Get the second coordinate of the vectorial part of the quaternion. More...
 
void setQ2 (double q2)
 
double getQ3 () const
 Get the third coordinate of the vectorial part of the quaternion. More...
 
void setQ3 (double q3)
 
Rotation revert ()
 
glm::dvec3 getAxis ()
 
double getAngle ()
 
double ** getMatrix ()
 
glm::dvec3 applyTo (glm::dvec3 u)
 
void applyTo (double *in, double *out)
 
glm::dvec3 applyInverseTo (glm::dvec3 u)
 
void applyInverseTo (double *in, double *out)
 
Rotation applyTo (Rotation r)
 
Rotation applyInverseTo (Rotation r)
 
glm::dvec3 operator* (glm::dvec3 u)
 
Rotation operator* (Rotation r)
 
void getAngles (RotationOrder const *order, double &roll, double &pitch, double &yaw)
 Get the roll, pitch and yaw for the Rotation. More...
 
PythonDVec3getAxisPython ()
 

Private Member Functions

template<class Archive >
void serialize (Archive &ar, const unsigned int version)
 

Private Attributes

double q0
 
double q1
 
double q2
 
double q3
 

Friends

class boost::serialization::access
 
std::ostream & operator<< (std::ostream &out, Rotation &r)
 

Detailed Description

This class implements rotations in a three-dimensional space.

Rotations can be represented by several different mathematical entities (matrices, axe and angle, Cardan or Euler angles, quaternions). This class presents an higher level abstraction, more user-oriented and hiding this implementation details. Well, for the curious, we use quaternions for the internal representation. The user can build a rotation from any of these representations, and any of these representations can be retrieved from a Rotation instance (see the various constructors and getters). In addition, a rotation can also be built implicitly from a set of vectors and their image.

This implies that this class can be used to convert from one representation to another one. For example, converting a rotation matrix into a set of Cardan angles from can be done using the following single line of code:

double[] angles = new Rotation(matrix, 1.0e-10).getAngles(RotationOrder.XYZ);

Focus is oriented on what a rotation do rather than on its underlying representation. Once it has been built, and regardless of its internal representation, a rotation is an operator which basically transforms three dimensional vectors into other three dimensional vectors. Depending on the application, the meaning of these vectors may vary and the semantics of the rotation also.

For example in an spacecraft attitude simulation tool, users will often consider the vectors are fixed (say the Earth direction for example) and the frames change. The rotation transforms the coordinates of the vector in inertial frame into the coordinates of the same vector in satellite frame. In this case, the rotation implicitly defines the relation between the two frames.

Another example could be a telescope control application, where the rotation would transform the sighting direction at rest into the desired observing direction when the telescope is pointed towards an object of interest. In this case the rotation transforms the direction at rest in a topocentric frame into the sighting direction in the same topocentric frame. This implies in this case the frame is fixed and the vector moves.

In many case, both approaches will be combined. In our telescope example, we will probably also need to transform the observing direction in the topocentric frame into the observing direction in inertial frame taking into account the observatory location and the Earth rotation, which would essentially be an application of the first approach.

These examples show that a rotation is what the user wants it to be. This class does not push the user towards one specific definition and hence does not provide methods like projectVectorIntoDestinationFrame or computeTransformedDirection. It provides simpler and more generic methods: applyTo(Vector3D) and {applyInverseTo(Vector3D)}.

Since a rotation is basically a vectorial operator, several rotations can be composed together and the composite operation r = r1 o r2 (which means that for each vector u, r(u) = r1(r2(u))) is also a rotation. Hence we can consider that in addition to vectors, a rotation can be applied to other rotations as well (or to itself). With our previous notations, we would say we can apply r1 to r2 and the result we get is r = r1 o r2. For this purpose, the class provides the methods: applyTo(Rotation) and applyInverseTo(Rotation).

Rotations are guaranteed to be immutable objects.

See also
Vector3D
RotationOrder
Since
1.2

Constructor & Destructor Documentation

◆ Rotation() [1/4]

Rotation::Rotation ( double  q0,
double  q1,
double  q2,
double  q3,
bool  needsNormalization 
)

Build a rotation from the quaternion coordinates.

A rotation can be built from a normalized quaternion, i.e. a quaternion for which q02 + q12 + q22 + q32 = 1. If the quaternion is not normalized, the constructor can normalize it in a preprocessing step.

Note that some conventions put the scalar part of the quaternion as the 4th component and the vector part as the first three components. This is not our convention. We put the scalar part as the first component.

Parameters
q0scalar part of the quaternion
q1first coordinate of the vectorial part of the quaternion
q2second coordinate of the vectorial part of the quaternion
q3third coordinate of the vectorial part of the quaternion
needsNormalizationif true, the coordinates are considered not to be normalized, a normalization preprocessing step is performed before using them

◆ Rotation() [2/4]

Rotation::Rotation ( glm::dvec3  axis,
double  angle 
)

Build a rotation from an axis and an angle.

We use the convention that angles are oriented according to the effect of the rotation on vectors around the axis. That means that if (i, j, k) is a direct frame and if we first provide +k as the axis and π/2 as the angle to this constructor, and then apply the instance to +i, we will get +j.

Another way to represent our convention is to say that a rotation of angle θ about the unit vector (x, y, z) is the same as the rotation build from quaternion components { cos(-θ/2), x * sin(-θ/2), y * sin(-θ/2), z * sin(-θ/2) }. Note the minus sign on the angle!

On the one hand this convention is consistent with a vectorial perspective (moving vectors in fixed frames), on the other hand it is different from conventions with a frame perspective (fixed vectors viewed from different frames) like the ones used for example in spacecraft attitude community or in the graphics community.

Parameters
axisaxis around which to rotate
anglerotation angle.
Exceptions
MathIllegalArgumentExceptionif the axis norm is zero

◆ Rotation() [3/4]

Rotation::Rotation ( glm::dvec3  u,
glm::dvec3  v 
)

Build one of the rotations that transform one vector into another one.

Except for a possible scale factor, if the instance were applied to the vector u it will produce the vector v. There is an infinite number of such rotations, this constructor choose the one with the smallest associated angle (i.e. the one whose axis is orthogonal to the (u, v) plane). If u and v are colinear, an arbitrary rotation axis is chosen.

Parameters
uoriginWaypoint vector
vdesired image of u by the rotation
Exceptions
MathArithmeticExceptionif the norm of one of the vectors is zero

◆ Rotation() [4/4]

Rotation::Rotation ( RotationOrder  order,
double  alpha1,
double  alpha2,
double  alpha3 
)

Build a rotation from three Cardan or Euler elementary rotations.

Cardan rotations are three successive rotations around the canonical axes X, Y and Z, each axis being used once. There are 6 such sets of rotations (XYZ, XZY, YXZ, YZX, ZXY and ZYX). Euler rotations are three successive rotations around the canonical axes X, Y and Z, the first and last rotations being around the same axis. There are 6 such sets of rotations (XYX, XZX, YXY, YZY, ZXZ and ZYZ), the most popular one being ZXZ.

Beware that many people routinely use the term Euler angles even for what really are Cardan angles (this confusion is especially widespread in the aerospace business where Roll, Pitch and Yaw angles are often wrongly tagged as Euler angles).

Parameters
orderorder of rotations to use
alpha1angle of the first elementary rotation
alpha2angle of the second elementary rotation
alpha3angle of the third elementary rotation

Member Function Documentation

◆ applyInverseTo() [1/3]

void Rotation::applyInverseTo ( double *  in,
double *  out 
)

Apply the inverse of the rotation to a vector stored in an array.

Parameters
inan array with three items which stores vector to rotate
outan array with three items to put result to (it can be the same array as in)

◆ applyInverseTo() [2/3]

glm::dvec3 Rotation::applyInverseTo ( glm::dvec3  u)

Apply the inverse of the rotation to a vector.

Parameters
uvector to apply the inverse of the rotation to
Returns
a new vector which such that u is its image by the rotation

◆ applyInverseTo() [3/3]

Rotation Rotation::applyInverseTo ( Rotation  r)

Apply the inverse of the instance to another rotation. Applying the inverse of the instance to a rotation is computing the composition in an order compliant with the following rule : let u be any vector and v its image by r (i.e. r.applyTo(u) = v), let w be the inverse image of v by the instance (i.e. applyInverseTo(v) = w), then w = comp.applyTo(u), where comp = applyInverseTo(r).

Parameters
rrotation to apply the rotation to
Returns
a new rotation which is the composition of r by the inverse of the instance

◆ applyTo() [1/3]

void Rotation::applyTo ( double *  in,
double *  out 
)

Apply the rotation to a vector stored in an array.

Parameters
inan array with three items which stores vector to rotate
outan array with three items to put result to (it can be the same array as in)

◆ applyTo() [2/3]

glm::dvec3 Rotation::applyTo ( glm::dvec3  u)

Apply the rotation to a vector.

Parameters
uvector to apply the rotation to
Returns
a new vector which is the image of u by the rotation

◆ applyTo() [3/3]

Rotation Rotation::applyTo ( Rotation  r)

Apply the instance to another rotation. Applying the instance to a rotation is computing the composition in an order compliant with the following rule : let u be any vector and v its image by r (i.e. r.applyTo(u) = v), let w be the image of v by the instance (i.e. applyTo(v) = w), then w = comp.applyTo(u), where comp = applyTo(r).

Parameters
rrotation to apply the rotation to
Returns
a new rotation which is the composition of r by the instance

◆ getAngle()

double Rotation::getAngle ( )

Get the angle of the rotation.

Returns
angle of the rotation (between 0 and π)
See also
#Rotation(Vector3D, double)

◆ getAngles()

void Rotation::getAngles ( RotationOrder const *  order,
double &  roll,
double &  pitch,
double &  yaw 
)

Get the roll, pitch and yaw for the Rotation.

Parameters
orderRotation order to use
[out]rollRoll angle (standard roll for XYZ order)
[out]pitchPitch angle (standard pitch for XYZ order)
[out]yawYaw angle (standard yaw for XYZ order)

◆ getAxis()

glm::dvec3 Rotation::getAxis ( )

Get the normalized axis of the rotation.

Returns
normalized axis of the rotation
See also
#Rotation(Vector3D, double)

◆ getMatrix()

double ** Rotation::getMatrix ( )

Get the 3X3 matrix corresponding to the instance

Returns
the matrix corresponding to the instance

◆ getQ0()

double Rotation::getQ0 ( ) const
inline

Get the scalar coordinate of the quaternion.

Identity rotation.

Returns
scalar coordinate of the quaternion

◆ getQ1()

double Rotation::getQ1 ( ) const
inline

Get the first coordinate of the vectorial part of the quaternion.

Returns
first coordinate of the vectorial part of the quaternion

◆ getQ2()

double Rotation::getQ2 ( ) const
inline

Get the second coordinate of the vectorial part of the quaternion.

Returns
second coordinate of the vectorial part of the quaternion

◆ getQ3()

double Rotation::getQ3 ( ) const
inline

Get the third coordinate of the vectorial part of the quaternion.

Returns
third coordinate of the vectorial part of the quaternion

◆ revert()

Rotation Rotation::revert ( )

Revert a rotation. Build a rotation which reverse the effect of another rotation. This means that if r(u) = v, then r.revert(v) = u. The instance is not changed.

Returns
a new rotation whose effect is the reverse of the effect of the instance

Friends And Related Function Documentation

◆ operator<<

std::ostream& operator<< ( std::ostream &  out,
Rotation r 
)
friend

Perfect orthogonality on a 3X3 matrix.

Parameters
minitial matrix (not exactly orthogonal)
thresholdconvergence threshold for the iterative orthogonality correction (convergence is reached when the difference between two steps of the Frobenius norm of the correction is below this threshold)
Returns
an orthogonal matrix close to m
Exceptions
NotARotationMatrixExceptionif the matrix cannot be orthogonalized with the given threshold after 10 iterations Compute the distance between two rotations.

The distance is intended here as a way to check if two rotations are almost similar (i.e. they transform vectors the same way) or very different. It is mathematically defined as the angle of the rotation r that prepended to one of the rotations gives the other one:

       r1(r) = r2

This distance is an angle between 0 and π. Its value is the smallest possible upper bound of the angle in radians between r1(v) and r2(v) for all possible vectors v. This upper bound is reached for some v. The distance is equal to 0 if and only if the two rotations are identical.

Comparing two rotations should always be done using this value rather than for example comparing the components of the quaternions. It is much more stable, and has a geometric meaning. Also comparing quaternions components is error prone since for example quaternions (0.36, 0.48, -0.48, -0.64) and (-0.36, -0.48, 0.48, 0.64) represent exactly the same rotation despite their components are different (they are exact opposites).

Parameters
r1first rotation
r2second rotation
Returns
distance between r1 and r2

Member Data Documentation

◆ q0

double Rotation::q0
private

Scalar coordinate of the quaternion.


The documentation for this class was generated from the following files: