From Osculating to Mean Elements with Brouwer-Lyddane Propagator

Hi Orekit community
I am trying to convert from my TLE SpacecraftState into mean Keplerian elements, using the BrouwerLyddanePropagator. It has an implemented method: computeMeanOrbit, that, according to my understanding, will give back the Orbit object, with mean Keplerian elements.
Unfortunately, I am encountering some issues: it fails the convergence if I give not the starting state from TLE, but a propagated one.

Here the example:

long start = 1613870730000L;

/* TLEs of the satellite */
TLE tleOrbit = new TLE
            "1 43196U 18015E   21055.59816856  .00000894  00000-0  38966-4 0  9996",
            "2 43196  97.4662 188.8169 0016935 299.6845  60.2706 15.24746686170319");
Propagator propagator = TLEPropagator.selectExtrapolator(tleOrbit);
//Get state at initial date and 3 days before
SpacecraftState tleState = propagator.getInitialState();
SpacecraftState tleStateAtDate = propagator.propagate(Time.getAbsoluteDateFromTimestamp(start));
//BL mean orbit
double epsilon = 1.0e-12;
int maxIter = 500;
UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(7, 7);
Orbit meanOrbitOK = BrouwerLyddanePropagator.computeMeanOrbit(tleState.getOrbit(), provider,
provider.onDate(tleState.getDate()), BrouwerLyddanePropagator.M2, epsilon, maxIter);
Orbit meanOrbitKO = BrouwerLyddanePropagator.computeMeanOrbit(tleStateAtDate.getOrbit(), provider,
provider.onDate(tleStateAtDate.getDate()), BrouwerLyddanePropagator.M2, epsilon, maxIter);


public static AbsoluteDate getAbsoluteDateFromTimestamp(long timestamp) {
    LocalDateTime utcDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), UTC_ZONE_ID);
    val year = utcDate.getYear();
    val month = utcDate.getMonthValue();
    val day = utcDate.getDayOfMonth();
    val hour = utcDate.getHour();
    val minute = utcDate.getMinute();
    val second = utcDate.getSecond();
    val millis = utcDate.getNano() / 1e9;
    return new AbsoluteDate(year, month, day, hour, minute, second, TimeScalesFactory.getUTC()).shiftedBy(millis);

Here the error:

invalid parameter eccentricity: -0 not in range [0, ∞]
org.orekit.errors.OrekitException: invalid parameter eccentricity: -0 not in range [0, ∞]
	at app//org.orekit.orbits.KeplerianOrbit.checkParameterRangeInclusive(
	at app//org.orekit.orbits.KeplerianOrbit.<init>(

Do I make something wrong?
Thanks in advance!

Hi @alberto-ferrero

That’s a strange behavior because we added a check in the method to prevent negative eccentricities.
Could you try using the computeMeanOrbit method of the EcksteinHechlerPropagator?
It should give you very close results.

I have to check for the Brouwer Lyddane method but unfortunately I don’t have my computer now :sweat_smile:

Best regards,

Hi Brian
Thanks for coming back to me quickly.
I think the error I see is for the check on the eccentricity.

I do confirm indeed that the I don’t have any issue with same scenario but with EH propagator.

//EH mean orbit
double epsilon = 1.0e-12;
int maxIter = 500;
UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(7, 7);
Orbit meanEHOrbit = EcksteinHechlerPropagator.computeMeanOrbit(tleState.getOrbit(), provider,
provider.onDate(tleState.getDate()), epsilon, maxIter);
Orbit meanEHOrbitAtDate = EcksteinHechlerPropagator.computeMeanOrbit(tleStateAtDate.getOrbit(), provider,
provider.onDate(tleStateAtDate.getDate()), epsilon, maxIter);


Here another test, starting from a simple Keplerian orbit, same results:

  • EH OK
  • BL KO
long start = 1613870730000L;

double a = 6858137;
double e = 0.0;
double i = FastMath.toRadians(97.331);
double Om = FastMath.toRadians(138.05);
double om = 0.0;
double nu = 0.0;

KeplerianOrbit orb = new KeplerianOrbit(a, e, i, om, Om, nu, PositionAngle.TRUE, FramesFactory.getEME2000(),

//BL mean orbit
double epsilon = 1.0e-12;
int maxIter = 200;
UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(7, 7);

Orbit meanEHOrbitOK = EcksteinHechlerPropagator.computeMeanOrbit(orb, provider,
   provider.onDate(orb.getDate()), epsilon, maxIter);

Orbit meanBLOrbitKO = BrouwerLyddanePropagator.computeMeanOrbit(orb, provider,
    provider.onDate(orb.getDate()), BrouwerLyddanePropagator.M2, epsilon, maxIter);

Hi @alberto-ferrero

I tried and it looks like a bug. I just have one question. Are you sure that your input orbit is an osculating orbit?

Best regards,

Hi Bryan,
oh, do I need to open a bug ticket? It would be better I guess.

Regarding the Keplerian orbit, yes I am not really sure it corresponds to osculating elements. It might be not actually, but still the propagated state from the TLE should not cause issues as it is a ‘real’ case.
Thanks for the investigation

I would like to perform more investigation of this issue. So, yes could you open an issue in our bug tracker?
Also, could you put the link of this current forum discussion in the description of the issue?

Thank you,

Ok, done :slight_smile: