Class QuaternionRotation

  • All Implemented Interfaces:
    java.util.function.Function<Vector3D,​Vector3D>, java.util.function.UnaryOperator<Vector3D>, Transform<Vector3D>, EuclideanTransform<Vector3D>, Rotation3D

    public final class QuaternionRotation
    extends java.lang.Object
    implements Rotation3D
    Class using a unit-length quaternion to represent rotations in 3-dimensional Euclidean space. The underlying quaternion is in positive polar form: It is normalized and has a non-negative scalar component (w).
    See Also:
    Quaternion
    • Field Detail

      • ANTIPARALLEL_DOT_THRESHOLD

        private static final double ANTIPARALLEL_DOT_THRESHOLD
        Threshold value for the dot product of antiparallel vectors. If the dot product of two vectors is less than this value, (adjusted for the lengths of the vectors), then the vectors are considered to be antiparallel (ie, negations of each other).
        See Also:
        Constant Field Values
      • AXIS_ANGLE_SINGULARITY_THRESHOLD

        private static final double AXIS_ANGLE_SINGULARITY_THRESHOLD
        Threshold value used to identify singularities when converting from quaternions to axis angle sequences.
        See Also:
        Constant Field Values
      • IDENTITY_INSTANCE

        private static final QuaternionRotation IDENTITY_INSTANCE
        Instance used to represent the identity rotation, ie a rotation with an angle of zero.
      • quat

        private final org.apache.commons.numbers.quaternion.Quaternion quat
        Unit-length quaternion instance in positive polar form.
    • Constructor Detail

      • QuaternionRotation

        private QuaternionRotation​(org.apache.commons.numbers.quaternion.Quaternion quat)
        Simple constructor. The given quaternion is converted to positive polar form.
        Parameters:
        quat - quaternion instance
        Throws:
        java.lang.IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
    • Method Detail

      • getQuaternion

        public org.apache.commons.numbers.quaternion.Quaternion getQuaternion()
        Get the underlying quaternion instance.
        Returns:
        the quaternion instance
      • getAxis

        public Vector3D getAxis()
        Get the axis of rotation as a normalized Vector3D. The rotation axis is not well defined when the rotation is the identity rotation, ie it has a rotation angle of zero. In this case, the vector representing the positive x-axis is returned.
        Specified by:
        getAxis in interface Rotation3D
        Returns:
        the axis of rotation
        See Also:
        Rotation3D.getAngle()
      • getAngle

        public double getAngle()
        Get the angle of rotation in radians. The returned value is in the range 0 through pi.
        Specified by:
        getAngle in interface Rotation3D
        Returns:
        The rotation angle in the range [0, pi].
        See Also:
        Rotation3D.getAxis()
      • inverse

        public QuaternionRotation inverse()
        Get the inverse of this rotation. The returned rotation has the same rotation angle but the opposite rotation axis. If r.apply(u) is equal to v, then r.negate().apply(v) is equal to u.
        Specified by:
        inverse in interface Rotation3D
        Specified by:
        inverse in interface Transform<Vector3D>
        Returns:
        the negation (inverse) of the rotation
      • apply

        public Vector3D apply​(Vector3D v)
        Apply this rotation to the given vector.
        Specified by:
        apply in interface java.util.function.Function<Vector3D,​Vector3D>
        Specified by:
        apply in interface Rotation3D
        Parameters:
        v - vector to rotate
        Returns:
        the rotated vector
      • applyVector

        public Vector3D applyVector​(Vector3D vec)
        Apply this transform to the given vector, ignoring translations.

        This method can be used to transform vector instances representing displacements between points. For example, if v represents the difference between points p1 and p2, then transform.applyVector(v) will represent the difference between p1 and p2 after transform is applied.

        This method simply calls apply(vec) since rotations treat points and vectors similarly.

        Specified by:
        applyVector in interface EuclideanTransform<Vector3D>
        Parameters:
        vec - the vector to transform
        Returns:
        the new, transformed vector
      • preservesOrientation

        public boolean preservesOrientation()
        Return true if the transform preserves the orientation of the space. For example, in Euclidean 2D space, this will be true for translations, rotations, and scalings but will be false for reflections.

        This method simply returns true since rotations always preserve the orientation of the space.

        Specified by:
        preservesOrientation in interface Transform<Vector3D>
        Returns:
        true if the transform preserves the orientation of the space
        See Also:
        Orientation
      • multiply

        public QuaternionRotation multiply​(QuaternionRotation q)
        Multiply this instance by the given argument, returning the result as a new instance. This is equivalent to the expression t * q where q is the argument and t is this instance.

        Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if q1 and q2 are unit quaternions, then the quaternion qr = q1*q2 will give the effect of applying the rotation in q2 followed by the rotation in q1. In other words, the rightmost element in the multiplication is applied first.

        Parameters:
        q - quaternion to multiply with the current instance
        Returns:
        the result of multiplying this quaternion by the argument
      • premultiply

        public QuaternionRotation premultiply​(QuaternionRotation q)
        Multiply the argument by this instance, returning the result as a new instance. This is equivalent to the expression q * t where q is the argument and t is this instance.

        Multiplication of quaternions behaves similarly to transformation matrices in regard to the order that operations are performed. For example, if q1 and q2 are unit quaternions, then the quaternion qr = q1*q2 will give the effect of applying the rotation in q2 followed by the rotation in q1. In other words, the rightmost element in the multiplication is applied first.

        Parameters:
        q - quaternion to multiply by the current instance
        Returns:
        the result of multiplying the argument by the current instance
      • slerp

        public java.util.function.DoubleFunction<QuaternionRotation> slerp​(QuaternionRotation end)
        Creates a function that performs a spherical linear interpolation between this instance and the argument.

        The argument to the function returned by this method is the interpolation parameter t. If t = 0, the rotation is equal to this instance. If t = 1, the rotation is equal to the end instance. All other values are interpolated (or extrapolated if t is outside of the [0, 1] range).

        Parameters:
        end - end value of the interpolation
        Returns:
        a function that interpolates between this instance and the argument.
        See Also:
        Slerp
      • toAxisAngleSequence

        public AxisAngleSequence toAxisAngleSequence​(AxisReferenceFrame frame,
                                                     AxisSequence axes)
        Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance.

        In most cases, the returned rotation sequence will be unique. However, at points of singularity (second angle equal to 0 or -pi for Euler angles and +pi/2 or -pi/2 for Tait-Bryan angles), there are an infinite number of possible sequences that produce the same result. In these cases, the result is returned that leaves the last rotation equal to 0 (in the case of a relative reference frame) or the first rotation equal to 0 (in the case of an absolute reference frame).

        Parameters:
        frame - the reference frame used to interpret the positions of the rotation axes
        axes - the sequence of rotation axes
        Returns:
        a sequence of axis-angle rotations equivalent to this rotation
      • toRelativeAxisAngleSequence

        public AxisAngleSequence toRelativeAxisAngleSequence​(AxisSequence axes)
        Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance. Each rotation axis is interpreted relative to the rotated coordinate frame (ie, intrinsic rotation).
        Parameters:
        axes - the sequence of rotation axes
        Returns:
        a sequence of relative axis-angle rotations equivalent to this rotation
        See Also:
        toAxisAngleSequence(AxisReferenceFrame, AxisSequence)
      • toAbsoluteAxisAngleSequence

        public AxisAngleSequence toAbsoluteAxisAngleSequence​(AxisSequence axes)
        Get a sequence of axis-angle rotations that produce an overall rotation equivalent to this instance. Each rotation axis is interpreted as part of an absolute, unmoving coordinate frame (ie, extrinsic rotation).
        Parameters:
        axes - the sequence of rotation axes
        Returns:
        a sequence of absolute axis-angle rotations equivalent to this rotation
        See Also:
        toAxisAngleSequence(AxisReferenceFrame, AxisSequence)
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class java.lang.Object
      • equals

        public boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • getAngles

        private double[] getAngles​(AxisReferenceFrame frame,
                                   AxisSequence axes)
        Get a sequence of angles around the given axes that produce a rotation equivalent to this instance.
        Parameters:
        frame - the reference frame used to define the positions of the axes
        axes - the axis sequence
        Returns:
        a sequence of angles around the given axes that produce a rotation equivalent to this instance
      • getRelativeTaitBryanAngles

        private double[] getRelativeTaitBryanAngles​(Vector3D axis1,
                                                    Vector3D axis2,
                                                    Vector3D axis3)
        Get a sequence of angles around the given Tait-Bryan axes that produce a rotation equivalent to this instance. The axes are interpreted as being relative to the rotated coordinate frame.
        Parameters:
        axis1 - first Tait-Bryan axis
        axis2 - second Tait-Bryan axis
        axis3 - third Tait-Bryan axis
        Returns:
        a sequence of rotation angles around the relative input axes that produce a rotation equivalent to this instance
      • getAbsoluteTaitBryanAngles

        private double[] getAbsoluteTaitBryanAngles​(Vector3D axis1,
                                                    Vector3D axis2,
                                                    Vector3D axis3)
        Get a sequence of angles around the given Tait-Bryan axes that produce a rotation equivalent to this instance. The axes are interpreted as being part of an absolute (unmoving) coordinate frame.
        Parameters:
        axis1 - first Tait-Bryan axis
        axis2 - second Tait-Bryan axis
        axis3 - third Tait-Bryan axis
        Returns:
        a sequence of rotation angles around the absolute input axes that produce a rotation equivalent to this instance
      • getRelativeEulerAngles

        private double[] getRelativeEulerAngles​(Vector3D axis1,
                                                Vector3D axis2)
        Get a sequence of angles around the given Euler axes that produce a rotation equivalent to this instance. The axes are interpreted as being relative to the rotated coordinate frame. Only the first two axes are needed since, by definition, the first Euler angle axis is repeated as the third axis.
        Parameters:
        axis1 - first Euler axis
        axis2 - second Euler axis
        Returns:
        a sequence of rotation angles around the relative input axes that produce a rotation equivalent to this instance
      • getAbsoluteEulerAngles

        private double[] getAbsoluteEulerAngles​(Vector3D axis1,
                                                Vector3D axis2)
        Get a sequence of angles around the given Euler axes that produce a rotation equivalent to this instance. The axes are interpreted as being part of an absolute (unmoving) coordinate frame. Only the first two axes are needed since, by definition, the first Euler angle axis is repeated as the third axis.
        Parameters:
        axis1 - first Euler axis
        axis2 - second Euler axis
        Returns:
        a sequence of rotation angles around the absolute input axes that produce a rotation equivalent to this instance
      • of

        public static QuaternionRotation of​(org.apache.commons.numbers.quaternion.Quaternion quat)
        Create a new instance from the given quaternion. The quaternion is normalized and converted to positive polar form (ie, with w >= 0).
        Parameters:
        quat - the quaternion to use for the rotation
        Returns:
        a new instance built from the given quaternion.
        Throws:
        java.lang.IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
        See Also:
        Quaternion.normalize(), Quaternion.positivePolarForm()
      • of

        public static QuaternionRotation of​(double w,
                                            double x,
                                            double y,
                                            double z)
        Create a new instance from the given quaternion values. The inputs are normalized and converted to positive polar form (ie, with w >= 0).
        Parameters:
        w - quaternion scalar component
        x - first quaternion vectorial component
        y - second quaternion vectorial component
        z - third quaternion vectorial component
        Returns:
        a new instance containing the normalized quaterion components
        Throws:
        java.lang.IllegalStateException - if the the norm of the given components is zero, NaN, or infinite
        See Also:
        Quaternion.normalize(), Quaternion.positivePolarForm()
      • identity

        public static QuaternionRotation identity()
        Return an instance representing a rotation of zero.
        Returns:
        instance representing a rotation of zero.
      • fromAxisAngle

        public static QuaternionRotation fromAxisAngle​(Vector3D axis,
                                                       double angle)
        Create a new instance representing a rotation of angle radians around axis.

        Rotation direction follows the right-hand rule, meaning that if one places their right hand such that the thumb points in the direction of the vector, the curl of the fingers indicates the direction of rotation.

        Note that the returned quaternion will represent the defined rotation but the values returned by getAxis() and getAngle() may not match the ones given here. This is because the axis and angle are normalized such that the axis has unit length, and the angle lies in the range [0, pi]. Depending on the inputs, the axis may need to be inverted in order for the angle to lie in this range.

        Parameters:
        axis - the axis of rotation
        angle - angle of rotation in radians
        Returns:
        a new instance representing the defined rotation
        Throws:
        java.lang.IllegalArgumentException - if the given axis cannot be normalized or the angle is NaN or infinite
      • createVectorRotation

        public static QuaternionRotation createVectorRotation​(Vector3D u,
                                                              Vector3D v)
        Return an instance that rotates the first vector to the second.

        Except for a possible scale factor, if the returned instance is applied to vector u, it will produce the vector v. There are an infinite number of such rotations; this method chooses the one with the smallest associated angle, meaning 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 - target vector
        Returns:
        a new instance that rotates u to point in the direction of v
        Throws:
        java.lang.IllegalArgumentException - if either vector has a norm of zero, NaN, or infinity
      • createBasisRotation

        public static QuaternionRotation createBasisRotation​(Vector3D u1,
                                                             Vector3D u2,
                                                             Vector3D v1,
                                                             Vector3D v2)
        Return an instance that rotates the basis defined by the first two vectors into the basis defined by the second two.

        The given basis vectors do not have to be directly orthogonal. A right-handed orthonormal basis is created from each pair by normalizing the first vector, making the second vector orthogonal to the first, and then taking the cross product. A rotation is then calculated that rotates the first to the second.

        Parameters:
        u1 - first vector of the source basis
        u2 - second vector of the source basis
        v1 - first vector of the target basis
        v2 - second vector of the target basis
        Returns:
        an instance that rotates the source basis to the target basis
        Throws:
        java.lang.IllegalArgumentException - if any of the input vectors cannot be normalized or the vectors defining either basis are collinear
      • fromAxisAngleSequence

        public static QuaternionRotation fromAxisAngleSequence​(AxisAngleSequence sequence)
        Create a new instance equivalent to the given sequence of axis-angle rotations.
        Parameters:
        sequence - the axis-angle rotation sequence to convert to a quaternion rotation
        Returns:
        instance representing a rotation equivalent to the given axis-angle sequence
      • orthogonalRotationMatrixToQuaternion

        private static QuaternionRotation orthogonalRotationMatrixToQuaternion​(double m00,
                                                                               double m01,
                                                                               double m02,
                                                                               double m10,
                                                                               double m11,
                                                                               double m12,
                                                                               double m20,
                                                                               double m21,
                                                                               double m22)
        Create an instance from an orthogonal rotation matrix.
        Parameters:
        m00 - matrix entry m0,0
        m01 - matrix entry m0,1
        m02 - matrix entry m0,2
        m10 - matrix entry m1,0
        m11 - matrix entry m1,1
        m12 - matrix entry m1,2
        m20 - matrix entry m2,0
        m21 - matrix entry m2,1
        m22 - matrix entry m2,2
        Returns:
        an instance representing the same 3D rotation as the given matrix
      • reverseArray

        private static double[] reverseArray​(double[] arr)
        Reverse the elements in arr. The array is returned.
        Parameters:
        arr - the array to reverse
        Returns:
        the input array with the elements reversed