On the use of TEME

Hi everyone,

First, a disclaimer: I know that TEME is not a recommended frame (lack of common definition, pointed out by CCSDS for example and well traced in Orekit’s documentation) and should be avoided, but unfortunately some data e.g. 18SDS’s SP ephemerides do come in that frame.

I have made a simple test which is the following (code follows):

  1. I create an instance of EquinoctialOrbit from a GCRF position-velocity vector.

  2. I propagate it for 3600s as is with a KeplerianPropagator and store the result

  3. I take the original orbit, convert it into TEME, propagate in to the same date in Keplerian motion again and convert back to GCRF. I get differences almost of the order of a meter!

// Initial date in UTC time scale
final TimeScale utc = TimeScalesFactory.getUTC();
final AbsoluteDate initialDate = new AbsoluteDate(2021, 10, 2, 0, 0, 0.000, utc);

// Frames
final Frame inertialFrame = FramesFactory.getGCRF();
final Frame teme = FramesFactory.getTEME();

// Initial conditions
final double r0 = Constants.WGS84_EARTH_EQUATORIAL_RADIUS + 500e3;
final double v0 = FastMath.sqrt(Constants.WGS84_EARTH_MU / r0);
final double mass = 10.;
final Vector3D pos = new Vector3D(r0, 0., 0.);
final Vector3D vel = new Vector3D(0., v0, 0.);
final PVCoordinates pv = new PVCoordinates(pos, vel);
final double mu = Constants.EGM96_EARTH_MU;
final EquinoctialOrbit orbit = new EquinoctialOrbit(pv, inertialFrame, initialDate, mu);
final SpacecraftState state = new SpacecraftState(orbit, mass);

// Propagate in original frame
final double dt = 3600.;
final AbsoluteDate date = initialDate.shiftedBy(dt);
final KeplerianPropagator prop1 = new KeplerianPropagator(orbit, mu);
final PVCoordinates pvProp = prop1.propagate(date).getPVCoordinates(inertialFrame);

// Convert in TEME, propagate and convert back 
final EquinoctialOrbit orbitTransfo = new EquinoctialOrbit(state.getPVCoordinates(teme), teme, initialDate, mu);
final KeplerianPropagator prop2 = new KeplerianPropagator(orbitTransfo, mu);
final PVCoordinates pvProp2 = prop2.propagate(date).getPVCoordinates(inertialFrame);

final double[] diffPos = (pvProp.getPosition().subtract(pvProp2.getPosition())).toArray();
final double[] diffVel = (pvProp.getVelocity().subtract(pvProp2.getVelocity())).toArray();

I am a bit surprised, TEME is still supposed to be pseudo-inertial no? How can I have such big differences in such short time? Please point out any mistakes I have made.

Cheers,
Romain.

Hi @Serrof

Could you try with a date away from midnight, in order to see if it is related to EOP interpolation, which changes at midnight?

Hi Luc,

I do not see any changes if I set a time away from midnight.

Thank you,
Romain.

Hi Romain, Luc,

I’ve looked a bit into it and I’m wondering if it’s not coming from the initial point error.

If you use a step handler every second you’ll see the error slowly diverging with an exponential harmonic at orbital period.

I’ve tried some conversions at initial point:

        // Convert to TEME and back
        PVCoordinates gcrfPv0 = orbit.getPVCoordinates();
        PVCoordinates temePv1 = orbit.getPVCoordinates(teme);
        Orbit temeOrbit = new CartesianOrbit(temePv1, teme, initialDate, mu);
        PVCoordinates gcrfPv1 = temeOrbit.getPVCoordinates(inertialFrame);
        PVCoordinates diff1 = new PVCoordinates(gcrfPv0, gcrfPv1);
        System.out.println(diff1);

Or more directly

        Transform inertialToTeme = inertialFrame.getTransformTo(teme, initialDate);
        PVCoordinates temePv2 = inertialToTeme.transformPVCoordinates(gcrfPv0);
        PVCoordinates gcrfPv2 = inertialToTeme.getInverse().transformPVCoordinates(temePv2);
        PVCoordinates diff2 = new PVCoordinates(gcrfPv0, gcrfPv2);
        System.out.println(diff1);

Which gives this:
P(2.0489096641540527E-8, -7.275957614183426E-12, -3.637978807091713E-12), V(7.105427360593102E-15, 2.1827872842550278E-11, -8.97600814205382E-18), A(-2.4868995751603507E-14, -1.5635720444679136E-17, -3.976243264630839E-18)}

So, in my opinion, transforming back and forth between GCRF and TEME leads to a nanometer error that builds up with time afterwards.
@luc, does this level of error looks normal to you when doing the transform and inverse transform successively.
I find it a bit high but I’m not sure why it is so.

Maxime

I don’t know about the evolution of errors in almost but not exactly inertial frames.
One way to check this would be to use InertialForces to check how this behaves between EME2000 and TEME.

FYI here is a visualization of how the errors grow over time in QSW frame:

Romain.

This thread seems to have gone dead, but I see references to it as a live bug, yet I think it isn’t a bug.

The TEME frame in OREKIT is TEME of date - i.e. at each date you do a transform to e.g. EME2000, the orientation of the TEME frame is computed.

If you simply take a vector on the same length as in your example, insert it into a sequence of TEME frames over the time period you do, transform each one to EME2000 and compare differences, you will get a difference growing at exactly this rate, driven by the precession of the Earth (~3.8e-5 degrees per day). I asked one of my team to check for me for a single fixed (in TEME) vector :slight_smile: .

This has nothing per se to do with propagation.

In your example you propagate using a KeplerianPropagator in TEME, which I believe simply generates a number of points on the circle in a frame whose relationship to EME2000 is drifting at exactly the above rate. In your example you move through time, but also through space and thus sample the growing difference between the two frame from different perspectives, and hence see the oscillation cross-track as well as the drift.

For SP Ephemeris, the SP data points are in TEME of Date, so this is safe.
For a Keplerian propagator, I think the equations of motion are incorrect for TEME.
For a TLE, i suspect we should be using TEME of Epoch, but the errors are small compare to a TLE, and that is another debate altogether.

Hi Paul,

Thanks for getting back to this.
So just to be sure, what you’re saying is that we’re simply seeing the fact that Orekit’s TEME is redefined at each time and thus slowly rotates w.r.t. GCRF?

Cheers,
Romain.

Yes.
I’m not allowed to post just 3 characters so here is the post I should have made first time round:
6.6e-7 radians per day at 7000km radius = 4.6m per day from precession alone.