Non-normalized angles in transformed element sets

The example here shows, in Out [19], an inclination that exceeds \pi radians. I am able to reproduce this result. In addition, the RAAN is not normalized, i.e., either 0 \leq \Omega < \pi or -\pi \leq \Omega < \pi. Is there a way to create orbital element sets with these angles normalized?

Or am I confused, are these degrees?

No, I think the output is in degrees, as it is the result of a print. Orekit uses SI units in its API, but for some input/outputs (including orbits), it does units conversions.

You have to normalize by yourself. This is in fact intentional. The rationale is that for angles that could potentially evolve throughout the unit circle, and this includes RAAN, perigee argument or anomalies, then forcing normalization induces many problems:

  • it complicates computing mean values or smoothing around the 2π jump
  • it complicates evaluating finite differences
  • it complicates finding roots
  • it introduces numerical noise

It is also often not really needed, as the sin/cos/tan methods are perfectly able to be called on angles far above 2π. In fact, contrary to popular belief, normalizing an angle manually before computing its sin/cos/tan should not be done: it is a waste of time because another normalization will be done internally, and it reduces accuracy because the internal normalization is far better than what you would do manually. One of my favorite examples for the loss of accuracy is the following C code:

#include <math.h>
#include <stdio.h>

int main(int argc, char** argv) {
    double a       = 0x1.39188885EC6D3p20;
    double cos1 = cos(a);
    double cos2 = cos(remainder(a, 2 * M_PI)); // same result with fmod
    printf("%.12f %10.6e %10.6e %6.3f\n", a, cos1, cos2, cos1 / cos2);
    return 0;
}

We would expect this program to display cos1 and cos2 with close values, and cos1/cos2 to be close to 1.0. In fact, the output of this program on a computer using IEEE754 arithmetic is:

1282440.532696177019 -4.334283e-11  6.648965e-12 -6.519

So the error factor is huge, we end up with 0 significant digits, even the sign is wrong! The shocking truth is that in fact the correct value is cos1, i.e. the value that is computed without applying manually argument reduction. All the error comes from the call remainder(a, 2 * M_PI).

So our advice is the following: if you intend to reuse an angle computed at some place further (for smoothing, differentiating, root finding, or even simply evaluting its sin/cos/tan), just keep the angle as is, even if it corresponds to several billions radians. If on the other hand your really need to normalize it because for example it is an end result in a file with limited format, then you will need to perform the normalization by yourself. For this, you can use MathUtils.normalizeAngle(a, FastMath.PI) if you want a [0; 2π] range or MathUtils.normalizeAngle(a,0) if you want a [-π ; +π] range.

I did not realize that the print output is in different units, as I’m used to dealing with the API.

Thank you for the very detailed explanation on why normalization is not usually a good idea; I’m used to not normalizing with time elements (true, mean anomaly) because then multiple orbit information is lost. I had not considered there are issues with other angles as well.