I am working on CCSDS ADM V2 (not published yet). As part of this work, I discovered that several of our implementations of CCSDS attitude modes were flawed. The new standard explains better what was intended for angular rates (which were really Euler rates in some modes) and for spin/nutation (which I would personally have called spin/precession, but this is another story).

Concerning the nutation mode, I needed to consider the rate of change of the spin axis which in CCSDS is forced to be +Z, i.e. not strictly equal to rotation rate, and which moves both with respect to inertial frame (it describes a cone) and with respect to body frame. This was tricky but fun and not that complicated. You will see that in an upcoming `PrecessionFinder`

class. However, I stumbled upon problems while validating this feature, and am now really puzzled. I think we have one flaw in `AngularCoordinates`

that has been there for at least 9 years.

The problem is the rotation acceleration vector. In `AngularCoordinates`

, we have a `Rotation`

instance for the rotation, a `Vector3D`

instance for the rotation rate and another `Vector3D`

instance for the rotation acceleration. The vectors are expressed in the transformed frame, i.e. in the body frame when the `AngularCoordinates`

represents an attitude. We can build `AngularCoordinates`

either from these components or from a `FieldRotation<Derivative>`

(either `DerivativeStructure`

, `UnivariateDerivative1`

or `UnivariateDerivative2`

) that holds a quaternion and its time derivatives.

When building from a `FieldRotation<Derivative>`

, we rebuild the rotation rate and rotation acceleration from the quaternion derivatives. The formulas are straigthforward. We start from the well-known relation expressing quaternions rates from rotation rate:

Then we invert it:

The rotation acceleration is computed by differentiating the inverted relation one more time with respect to time and simplifying (all the terms in the form \dot{q}_i\times\dot{q}_j cancel out, so only terms in the form q_i\times\ddot{q}_j remain):

What puzzles me is that in all regular cases (i.e. in all cases except when we explicitly set an arbitrary rotation acceleration or in some interpolation cases), the resulting acceleration is almost 0 (order of magnitude between 1.0e-16 and 1.0e-21).

One explanation I found is that this could be normal as the rotation rate represents the motion of the body frame and is expressed in the body frame, so it is locally fixed. Its first derivative (i.e. the acceleration) should be zero with this interpretation. Its second derivative (i.e. the jerk) would not be zero though, so the vector is not always fixed. I tried to prove this and failed, I am also not really sure about my reasoning here.

Another approach I tested was to differentiate the first expressions before inverting instead of inverting and then differentiating. After eliminating the \dot{q}_i terms I got:

In order to isolate the acceleration vector components \dot{\omega}_{x,y,z}, I used this kind of combinations:

So this leads to similar results as the other way round, but fails to prove this acceleration could be 0.

Anyway, the zero acceleration is troublesome. Either it is correct and this means that in `AngularCoordinates`

we compute a zero vector and lose some information about second derivatives, or it is incorrect and we have to fix it.

I am now considering re-implementing `AngularCoordinates`

using a `FieldRotation<UnivariateDerivative2>`

to preserve derivatives information.

What do you think about this?