Package org.apache.commons.math3.geometry.euclidean.threed

# Class FieldRotation<T extends RealFieldElement<T>>

java.lang.Object
org.apache.commons.math3.geometry.euclidean.threed.FieldRotation<T>

Type Parameters:
  `T` - the type of the field elements

All Implemented Interfaces:
  `Serializable`

public class FieldRotation<T extends RealFieldElement<T>> extends Object implements Serializable
This class is a re-implementation of `Rotation` using `RealFieldElement`.

Instance of this class are guaranteed to be immutable.

Since:
  3.2
See Also:
  - `FieldVector3D`
  - `RotationOrder`
  - Serialized Form

## Constructor Summary

Constructors
Constructor
Description
`FieldRotation(FieldVector3D<T> u, FieldVector3D<T> v)`
Build one of the rotations that transform one vector into another one.
`FieldRotation(FieldVector3D<T> u1, FieldVector3D<T> u2, FieldVector3D<T> v1, FieldVector3D<T> v2)`
Build the rotation that transforms a pair of vectors into another pair.
`FieldRotation(FieldVector3D<T> axis, T angle)`
Deprecated.
as of 3.6, replaced with `FieldRotation(FieldVector3D, RealFieldElement, RotationConvention)`
`FieldRotation(FieldVector3D<T> axis, T angle, RotationConvention convention)`
Build a rotation from an axis and an angle.
`FieldRotation(RotationOrder order, RotationConvention convention, T alpha1, T alpha2, T alpha3)`
Build a rotation from three Cardan or Euler elementary rotations.
`FieldRotation(RotationOrder order, T alpha1, T alpha2, T alpha3)`
Deprecated.
as of 3.6, replaced with `FieldRotation(RotationOrder, RotationConvention, RealFieldElement, RealFieldElement, RealFieldElement)`
`FieldRotation(T[][] m, double threshold)`
Build a rotation from a 3X3 matrix.
`FieldRotation(T q0, T q1, T q2, T q3, boolean needsNormalization)`
Build a rotation from the quaternion coordinates.

## Method Summary

Modifier and Type
Method
Description
`void`
`applyInverseTo(double[] in, T[] out)`
Apply the inverse of the rotation to a vector stored in an array.
`FieldRotation<T>`
`applyInverseTo(FieldRotation<T> r)`
Apply the inverse of the instance to another rotation.
`FieldVector3D<T>`
`applyInverseTo(FieldVector3D<T> u)`
Apply the inverse of the rotation to a vector.
`FieldRotation<T>`
`applyInverseTo(Rotation r)`
Apply the inverse of the instance to another rotation.
`static <T extends RealFieldElement<T>>
FieldRotation<T>`
`applyInverseTo(Rotation rOuter, FieldRotation<T> rInner)`
Apply the inverse of a rotation to another rotation.
`static <T extends RealFieldElement<T>>
FieldVector3D<T>`
`applyInverseTo(Rotation r, FieldVector3D<T> u)`
Apply the inverse of a rotation to a vector.
`FieldVector3D<T>`
`applyInverseTo(Vector3D u)`
Apply the inverse of the rotation to a vector.
`void`
`applyInverseTo(T[] in, T[] out)`
Apply the inverse of the rotation to a vector stored in an array.
`void`
`applyTo(double[] in, T[] out)`
Apply the rotation to a vector stored in an array.
`FieldRotation<T>`
`applyTo(FieldRotation<T> r)`
Apply the instance to another rotation.
`FieldVector3D<T>`
`applyTo(FieldVector3D<T> u)`
Apply the rotation to a vector.
`FieldRotation<T>`
`applyTo(Rotation r)`
Apply the instance to another rotation.
`static <T extends RealFieldElement<T>>
FieldRotation<T>`
`applyTo(Rotation r1, FieldRotation<T> rInner)`
Apply a rotation to another rotation.
`static <T extends RealFieldElement<T>>
FieldVector3D<T>`
`applyTo(Rotation r, FieldVector3D<T> u)`
Apply a rotation to a vector.
`FieldVector3D<T>`
`applyTo(Vector3D u)`
Apply the rotation to a vector.
`void`
`applyTo(T[] in, T[] out)`
Apply the rotation to a vector stored in an array.
`FieldRotation<T>`
`compose(FieldRotation<T> r, RotationConvention convention)`
Compose the instance with another rotation.
`FieldRotation<T>`
`compose(Rotation r, RotationConvention convention)`
Compose the instance with another rotation.
`FieldRotation<T>`
`composeInverse(FieldRotation<T> r, RotationConvention convention)`
Compose the inverse of the instance with another rotation.
`FieldRotation<T>`
`composeInverse(Rotation r, RotationConvention convention)`
Compose the inverse of the instance with another rotation.
`static <T extends RealFieldElement<T>>
T`
`distance(FieldRotation<T> r1, FieldRotation<T> r2)`
Compute the distance between two rotations.
`T`
`getAngle()`
Get the angle of the rotation.
`T[]`
`getAngles(RotationOrder order)`
Deprecated.
as of 3.6, replaced with `getAngles(RotationOrder, RotationConvention)`
`T[]`
`getAngles(RotationOrder order, RotationConvention convention)`
Get the Cardan or Euler angles corresponding to the instance.
`FieldVector3D<T>`
`getAxis()`
Deprecated.
as of 3.6, replaced with `getAxis(RotationConvention)`
`FieldVector3D<T>`
`getAxis(RotationConvention convention)`
Get the normalized axis of the rotation.
`T[][]`
`getMatrix()`
Get the 3X3 matrix corresponding to the instance
`T`
`getQ0()`
Get the scalar coordinate of the quaternion.
`T`
`getQ1()`
Get the first coordinate of the vectorial part of the quaternion.
`T`
`getQ2()`
Get the second coordinate of the vectorial part of the quaternion.
`T`
`getQ3()`
Get the third coordinate of the vectorial part of the quaternion.
`FieldRotation<T>`
`revert()`
Revert a rotation.
`Rotation`
`toRotation()`
Convert to a constant vector without derivatives.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Constructor Details

### FieldRotation

public FieldRotation(T q0, T q1, T q2, T q3, boolean 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:
  `q0` - scalar part of the quaternion
  `q1` - first coordinate of the vectorial part of the quaternion
  `q2` - second coordinate of the vectorial part of the quaternion
  `q3` - third coordinate of the vectorial part of the quaternion
  `needsNormalization` - if true, the coordinates are considered not to be normalized, a normalization preprocessing step is performed before using them

### FieldRotation

@Deprecated public FieldRotation(FieldVector3D<T> axis, T angle) throws MathIllegalArgumentException
Deprecated.
as of 3.6, replaced with `FieldRotation(FieldVector3D, RealFieldElement, RotationConvention)`
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:
  `axis` - axis around which to rotate
  `angle` - rotation angle.
Throws:
  `MathIllegalArgumentException` - if the axis norm is zero

### FieldRotation

public FieldRotation(FieldVector3D<T> axis, T angle, RotationConvention convention) throws MathIllegalArgumentException
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:
  `axis` - axis around which to rotate
  `angle` - rotation angle.
  `convention` - convention to use for the semantics of the angle
Throws:
  `MathIllegalArgumentException` - if the axis norm is zero
Since:
  3.6

### FieldRotation

public FieldRotation(T[][] m, double threshold) throws NotARotationMatrixException
Build a rotation from a 3X3 matrix.

Rotation matrices are orthogonal matrices, i.e. unit matrices (which are matrices for which m.mT = I) with real coefficients. The module of the determinant of unit matrices is 1, among the orthogonal 3X3 matrices, only the ones having a positive determinant (+1) are rotation matrices.

When a rotation is defined by a matrix with truncated values (typically when it is extracted from a technical sheet where only four to five significant digits are available), the matrix is not orthogonal anymore. This constructor handles this case transparently by using a copy of the given matrix and applying a correction to the copy in order to perfect its orthogonality. If the Frobenius norm of the correction needed is above the given threshold, then the matrix is considered to be too far from a true rotation matrix and an exception is thrown.

Parameters:
  `m` - rotation matrix
  `threshold` - convergence 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)
Throws:
  `NotARotationMatrixException` - if the matrix is not a 3X3 matrix, or if it cannot be transformed into an orthogonal matrix with the given threshold, or if the determinant of the resulting orthogonal matrix is negative

### FieldRotation

public FieldRotation(FieldVector3D<T> u1, FieldVector3D<T> u2, FieldVector3D<T> v1, FieldVector3D<T> v2) throws MathArithmeticException
Build the rotation that transforms a pair of vectors into another pair.

Except for possible scale factors, if the instance were applied to the pair (u1, u2) it will produce the pair (v1, v2).

If the angular separation between u1 and u2 is not the same as the angular separation between v1 and v2, then a corrected v'2 will be used rather than v2, the corrected vector will be in the (±v1, +v2) half-plane.

Parameters:
  `u1` - first vector of the origin pair
  `u2` - second vector of the origin pair
  `v1` - desired image of u1 by the rotation
  `v2` - desired image of u2 by the rotation
Throws:
  `MathArithmeticException` - if the norm of one of the vectors is zero, or if one of the pair is degenerated (i.e. the vectors of the pair are collinear)

### FieldRotation

public FieldRotation(FieldVector3D<T> u, FieldVector3D<T> v) throws MathArithmeticException
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 collinear, an arbitrary rotation axis is chosen.

Parameters:
  `u` - origin vector
  `v` - desired image of u by the rotation
Throws:
  `MathArithmeticException` - if the norm of one of the vectors is zero

### FieldRotation

@Deprecated public FieldRotation(RotationOrder order, T alpha1, T alpha2, T alpha3)
Deprecated.
as of 3.6, replaced with `FieldRotation(RotationOrder, RotationConvention, RealFieldElement, RealFieldElement, RealFieldElement)`
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:
  `order` - order of rotations to use
  `alpha1` - angle of the first elementary rotation
  `alpha2` - angle of the second elementary rotation
  `alpha3` - angle of the third elementary rotation

### FieldRotation

public FieldRotation(RotationOrder order, RotationConvention convention, T alpha1, T alpha2, T 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:
  `order` - order of rotations to compose, from left to right (i.e. we will use `r1.compose(r2.compose(r3, convention), convention)`)
  `convention` - convention to use for the semantics of the angle
  `alpha1` - angle of the first elementary rotation
  `alpha2` - angle of the second elementary rotation
  `alpha3` - angle of the third elementary rotation
Since:
  3.6

## Method Details

### revert

public FieldRotation<T> 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

### getQ0

public T getQ0()
Get the scalar coordinate of the quaternion.

Returns:
  scalar coordinate of the quaternion

### getQ1

public T getQ1()
Get the first coordinate of the vectorial part of the quaternion.

Returns:
  first coordinate of the vectorial part of the quaternion

### getQ2

public T getQ2()
Get the second coordinate of the vectorial part of the quaternion.

Returns:
  second coordinate of the vectorial part of the quaternion

### getQ3

public T getQ3()
Get the third coordinate of the vectorial part of the quaternion.

Returns:
  third coordinate of the vectorial part of the quaternion

### getAxis

@Deprecated public FieldVector3D<T> getAxis()
Deprecated.
as of 3.6, replaced with `getAxis(RotationConvention)`
Get the normalized axis of the rotation.

Returns:
  normalized axis of the rotation
See Also:
  - `FieldRotation(FieldVector3D, RealFieldElement)`

### getAxis

public FieldVector3D<T> getAxis(RotationConvention convention)
Get the normalized axis of the rotation.

Note that as `getAngle()` always returns an angle between 0 and π, changing the convention changes the direction of the axis, not the sign of the angle.

Parameters:
  `convention` - convention to use for the semantics of the angle
Returns:
  normalized axis of the rotation
Since:
  3.6
See Also:
  - `FieldRotation(FieldVector3D, RealFieldElement)`

### getAngle

public T getAngle()
Get the angle of the rotation.

Returns:
  angle of the rotation (between 0 and π)
See Also:
  - `FieldRotation(FieldVector3D, RealFieldElement)`

### getAngles

@Deprecated public T[] getAngles(RotationOrder order) throws CardanEulerSingularityException
Deprecated.
as of 3.6, replaced with `getAngles(RotationOrder, RotationConvention)`
Get the Cardan or Euler angles corresponding to the instance.

The equations show that each rotation can be defined by two different values of the Cardan or Euler angles set. For example if Cardan angles are used, the rotation defined by the angles a1, a2 and a3 is the same as the rotation defined by the angles π + a1, π - a2 and π + a3. This method implements the following arbitrary choices:

- for Cardan angles, the chosen set is the one for which the second angle is between -π/2 and π/2 (i.e its cosine is positive),
- for Euler angles, the chosen set is the one for which the second angle is between 0 and π (i.e its sine is positive).

Cardan and Euler angle have a very disappointing drawback: all of them have singularities. This means that if the instance is too close to the singularities corresponding to the given rotation order, it will be impossible to retrieve the angles. For Cardan angles, this is often called gimbal lock. There is nothing to do to prevent this, it is an intrinsic problem with Cardan and Euler representation (but not a problem with the rotation itself, which is perfectly well defined). For Cardan angles, singularities occur when the second angle is close to -π/2 or +π/2, for Euler angle singularities occur when the second angle is close to 0 or π, this implies that the identity rotation is always singular for Euler angles!

Parameters:
  `order` - rotation order to use
Returns:
  an array of three angles, in the order specified by the set
Throws:
  `CardanEulerSingularityException` - if the rotation is singular with respect to the angles set specified

### getAngles

public T[] getAngles(RotationOrder order, RotationConvention convention) throws CardanEulerSingularityException
Get the Cardan or Euler angles corresponding to the instance.

The equations show that each rotation can be defined by two different values of the Cardan or Euler angles set. For example if Cardan angles are used, the rotation defined by the angles a1, a2 and a3 is the same as the rotation defined by the angles π + a1, π - a2 and π + a3. This method implements the following arbitrary choices:

- for Cardan angles, the chosen set is the one for which the second angle is between -π/2 and π/2 (i.e its cosine is positive),
- for Euler angles, the chosen set is the one for which the second angle is between 0 and π (i.e its sine is positive).

Cardan and Euler angle have a very disappointing drawback: all of them have singularities. This means that if the instance is too close to the singularities corresponding to the given rotation order, it will be impossible to retrieve the angles. For Cardan angles, this is often called gimbal lock. There is nothing to do to prevent this, it is an intrinsic problem with Cardan and Euler representation (but not a problem with the rotation itself, which is perfectly well defined). For Cardan angles, singularities occur when the second angle is close to -π/2 or +π/2, for Euler angle singularities occur when the second angle is close to 0 or π, this implies that the identity rotation is always singular for Euler angles!

Parameters:
  `order` - rotation order to use
  `convention` - convention to use for the semantics of the angle
Returns:
  an array of three angles, in the order specified by the set
Throws:
  `CardanEulerSingularityException` - if the rotation is singular with respect to the angles set specified
Since:
  3.6

### getMatrix

public T[][] getMatrix()
Get the 3X3 matrix corresponding to the instance

Returns:
  the matrix corresponding to the instance

### toRotation

public Rotation toRotation()
Convert to a constant vector without derivatives.

Returns:
  a constant vector

### applyTo

public FieldVector3D<T> applyTo(FieldVector3D<T> u)
Apply the rotation to a vector.

Parameters:
  `u` - vector to apply the rotation to
Returns:
  a new vector which is the image of u by the rotation

### applyTo

public FieldVector3D<T> applyTo(Vector3D u)
Apply the rotation to a vector.

Parameters:
  `u` - vector to apply the rotation to
Returns:
  a new vector which is the image of u by the rotation

### applyTo

public void applyTo(T[] in, T[] out)
Apply the rotation to a vector stored in an array.

Parameters:
  `in` - an array with three items which stores vector to rotate
  `out` - an array with three items to put result to (it can be the same array as in)

### applyTo

public void applyTo(double[] in, T[] out)
Apply the rotation to a vector stored in an array.

Parameters:
  `in` - an array with three items which stores vector to rotate
  `out` - an array with three items to put result to

### applyTo

public static <T extends RealFieldElement<T>> FieldVector3D<T> applyTo(Rotation r, FieldVector3D<T> u)
Apply a rotation to a vector.

Type Parameters:
  `T` - the type of the field elements
Parameters:
  `r` - rotation to apply
  `u` - vector to apply the rotation to
Returns:
  a new vector which is the image of u by the rotation

### applyInverseTo

public FieldVector3D<T> applyInverseTo(FieldVector3D<T> u)
Apply the inverse of the rotation to a vector.

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

### applyInverseTo

public FieldVector3D<T> applyInverseTo(Vector3D u)
Apply the inverse of the rotation to a vector.

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

### applyInverseTo

public void applyInverseTo(T[] in, T[] out)
Apply the inverse of the rotation to a vector stored in an array.

Parameters:
  `in` - an array with three items which stores vector to rotate
  `out` - an array with three items to put result to (it can be the same array as in)

### applyInverseTo

public void applyInverseTo(double[] in, T[] out)
Apply the inverse of the rotation to a vector stored in an array.

Parameters:
  `in` - an array with three items which stores vector to rotate
  `out` - an array with three items to put result to

### applyInverseTo

public static <T extends RealFieldElement<T>> FieldVector3D<T> applyInverseTo(Rotation r, FieldVector3D<T> u)
Apply the inverse of a rotation to a vector.

Type Parameters:
  `T` - the type of the field elements
Parameters:
  `r` - rotation to apply
  `u` - vector to apply the inverse of the rotation to
Returns:
  a new vector which such that u is its image by the rotation

### applyTo

public FieldRotation<T> applyTo(FieldRotation<T> r)
Apply the instance to another rotation.

Calling this method is equivalent to call `compose(r, RotationConvention.VECTOR_OPERATOR)`.

Parameters:
  `r` - rotation to apply the rotation to
Returns:
  a new rotation which is the composition of r by the instance

### compose

public FieldRotation<T> compose(FieldRotation<T> r, RotationConvention convention)
Compose the instance with another rotation.

If the semantics of the rotations composition corresponds to a `vector operator` convention, 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 `r1` (i.e. `r1.applyTo(u) = v`). Let `w` be the image of `v` by rotation `r2` (i.e. `r2.applyTo(v) = w`). Then `w = comp.applyTo(u)`, where `comp = r2.compose(r1, RotationConvention.VECTOR_OPERATOR)`.

If the semantics of the rotations composition corresponds to a `frame transform` convention, the application order will be reversed. So keeping the exact same meaning of all `r1`, `r2`, `u`, `v`, `w` and `comp` as above, `comp` could also be computed as `comp = r1.compose(r2, RotationConvention.FRAME_TRANSFORM)`.

Parameters:
  `r` - rotation to apply the rotation to
  `convention` - convention to use for the semantics of the angle
Returns:
  a new rotation which is the composition of r by the instance

### applyTo

public FieldRotation<T> applyTo(Rotation r)
Apply the instance to another rotation.

Calling this method is equivalent to call `compose(r, RotationConvention.VECTOR_OPERATOR)`.

Parameters:
  `r` - rotation to apply the rotation to
Returns:
  a new rotation which is the composition of r by the instance

### compose

public FieldRotation<T> compose(Rotation r, RotationConvention convention)
Compose the instance with another rotation.

If the semantics of the rotations composition corresponds to a `vector operator` convention, 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 `r1` (i.e. `r1.applyTo(u) = v`). Let `w` be the image of `v` by rotation `r2` (i.e. `r2.applyTo(v) = w`). Then `w = comp.applyTo(u)`, where `comp = r2.compose(r1, RotationConvention.VECTOR_OPERATOR)`.

If the semantics of the rotations composition corresponds to a `frame transform` convention, the application order will be reversed. So keeping the exact same meaning of all `r1`, `r2`, `u`, `v`, `w` and `comp` as above, `comp` could also be computed as `comp = r1.compose(r2, RotationConvention.FRAME_TRANSFORM)`.

Parameters:
  `r` - rotation to apply the rotation to
  `convention` - convention to use for the semantics of the angle
Returns:
  a new rotation which is the composition of r by the instance

### applyTo

public static <T extends RealFieldElement<T>> FieldRotation<T> applyTo(Rotation r1, FieldRotation<T> rInner)
Apply a rotation to another rotation. Applying a rotation to another rotation is computing the composition in an order compliant with the following rule : let u be any vector and v its image by rInner (i.e. rInner.applyTo(u) = v), let w be the image of v by rOuter (i.e. rOuter.applyTo(v) = w), then w = comp.applyTo(u), where comp = applyTo(rOuter, rInner).

Type Parameters:
  `T` - the type of the field elements
Parameters:
  `r1` - rotation to apply
  `rInner` - rotation to apply the rotation to
Returns:
  a new rotation which is the composition of r by the instance

### applyInverseTo

public FieldRotation<T> applyInverseTo(FieldRotation<T> r)
Apply the inverse of the instance to another rotation.

Calling this method is equivalent to call `composeInverse(r, RotationConvention.VECTOR_OPERATOR)`.

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

### composeInverse

public FieldRotation<T> composeInverse(FieldRotation<T> r, RotationConvention convention)
Compose the inverse of the instance with another rotation.

If the semantics of the rotations composition corresponds to a `vector operator` convention, 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 `r1` (i.e. `r1.applyTo(u) = v`). Let `w` be the inverse image of `v` by `r2` (i.e. `r2.applyInverseTo(v) = w`). Then `w = comp.applyTo(u)`, where `comp = r2.composeInverse(r1)`.

If the semantics of the rotations composition corresponds to a `frame transform` convention, the application order will be reversed, which means it is the innermost rotation that will be reversed. So keeping the exact same meaning of all `r1`, `r2`, `u`, `v`, `w` and `comp` as above, `comp` could also be computed as `comp = r1.revert().composeInverse(r2.revert(), RotationConvention.FRAME_TRANSFORM)`.

Parameters:
  `r` - rotation to apply the rotation to
  `convention` - convention to use for the semantics of the angle
Returns:
  a new rotation which is the composition of r by the inverse of the instance

### applyInverseTo

public FieldRotation<T> applyInverseTo(Rotation r)
Apply the inverse of the instance to another rotation.

Calling this method is equivalent to call `composeInverse(r, RotationConvention.VECTOR_OPERATOR)`.

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

### composeInverse

public FieldRotation<T> composeInverse(Rotation r, RotationConvention convention)
Compose the inverse of the instance with another rotation.

If the semantics of the rotations composition corresponds to a `vector operator` convention, 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 `r1` (i.e. `r1.applyTo(u) = v`). Let `w` be the inverse image of `v` by `r2` (i.e. `r2.applyInverseTo(v) = w`). Then `w = comp.applyTo(u)`, where `comp = r2.composeInverse(r1)`.

If the semantics of the rotations composition corresponds to a `frame transform` convention, the application order will be reversed, which means it is the innermost rotation that will be reversed. So keeping the exact same meaning of all `r1`, `r2`, `u`, `v`, `w` and `comp` as above, `comp` could also be computed as `comp = r1.revert().composeInverse(r2.revert(), RotationConvention.FRAME_TRANSFORM)`.

Parameters:
  `r` - rotation to apply the rotation to
  `convention` - convention to use for the semantics of the angle
Returns:
  a new rotation which is the composition of r by the inverse of the instance

### applyInverseTo

public static <T extends RealFieldElement<T>> FieldRotation<T> applyInverseTo(Rotation rOuter, FieldRotation<T> rInner)
Apply the inverse of a rotation to another rotation. Applying the inverse of a rotation to another rotation is computing the composition in an order compliant with the following rule : let u be any vector and v its image by rInner (i.e. rInner.applyTo(u) = v), let w be the inverse image of v by rOuter (i.e. rOuter.applyInverseTo(v) = w), then w = comp.applyTo(u), where comp = applyInverseTo(rOuter, rInner).

Type Parameters:
  `T` - the type of the field elements
Parameters:
  `rOuter` - rotation to apply the rotation to
  `rInner` - rotation to apply the rotation to
Returns:
  a new rotation which is the composition of r by the inverse of the instance

### distance

public static <T extends RealFieldElement<T>> T distance(FieldRotation<T> r1, FieldRotation<T> r2)
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).

Type Parameters:
  `T` - the type of the field elements
Parameters:
  `r1` - first rotation
  `r2` - second rotation
Returns:
  distance between r1 and r2