Hi everyone,
We recently stumbled upon an issue related to the StateCovarianceMatrixProvider in combination with a generated ephemeris (BoundedPropagator). The problem is that the initial state of the BoundedPropagator might be at a different epoch than the initial covariance. When propagate is called, the StateCovarianceMatrixProvider is initialised again, based on the wrong initial state.
Below is a minimal example to reproduce the problem, but I’ll list the steps as well:
- Create an initial state and Cartesian covariance at time t_0.
- Create a numerical propagator with
EQUINOCTIALorbit type - Set up
MatricesHarvesterand addStateCovarianceMatrixProviderto the propagator - Now generate an ephemeris for the interval [t_0 - \Delta t, t_0 + \Delta t]
- This correctly calls
initon theStateCovarianceMatrixProvider, which internally converts the initial covariance toEQUINOCTIALelements using the initial state at time t_0
- This correctly calls
- From the ephemeris, get the covariance matrix at time t_0 – this should be the same as the initial covariance that was originally provided.
BoundedPropagator.propagate(t_0) incorrectly callsinitagain, passing its initial state (which is at t_0 - \Delta t) and the initial covariance (provided at t_0) is now wrongly converted toEQUINOCTIALelements again.
@Test
void testInconsistentCovarianceBoundedPropagator() {
// Some constants
final Frame frame = FramesFactory.getGCRF();
final PositionAngleType angleType = PositionAngleType.MEAN;
final AbsoluteDate initialDate = AbsoluteDate.ARBITRARY_EPOCH;
final double mu = Constants.GRS80_EARTH_MU;
final String stmName = "STM";
final String covName = "CART_COV";
final double dt = 3600.0; // seconds
// Setup initial state and covariance
final Orbit initOrbit = new KeplerianOrbit(7.0e6, 1.e-4, 0.1, 0., 0., 0., angleType, frame, initialDate, mu);
final SpacecraftState initState = new SpacecraftState(initOrbit);
final RealMatrix initCartCovariance = MatrixUtils.createRealDiagonalMatrix(new double[]{1., 1., 1., 1.e-3, 1.e-3, 1.e-3});
final StateCovariance initStateCovariance =
new StateCovariance(initCartCovariance, initialDate, frame, OrbitType.CARTESIAN, angleType);
// Numerical propagator with EQUINOCTIAL ELEMENTS
NumericalPropagator propagator = new NumericalPropagator(new ClassicalRungeKuttaIntegrator(60.));
propagator.setOrbitType(OrbitType.EQUINOCTIAL);
propagator.setInitialState(initState);
// Create covariance matrix provider with initial covariance in CARTESIAN elements
final MatricesHarvester harvester =
propagator.setupMatricesComputation(stmName, null, null);
final StateCovarianceMatrixProvider provider =
new StateCovarianceMatrixProvider(covName, stmName, harvester, initStateCovariance);
propagator.addAdditionalDataProvider(provider);
// Propagate and store ephemeris on [t0 - dt, t0 + dt]
final EphemerisGenerator generator = propagator.getEphemerisGenerator();
propagator.propagate(initialDate.shiftedBy(-dt), initialDate.shiftedBy(dt));
final BoundedPropagator ephemeris = generator.getGeneratedEphemeris();
// Propagate ephemeris
SpacecraftState propagated = ephemeris.propagate(initState.getDate());
final StateCovariance propagatedStateCov = provider.getStateCovariance(propagated);
// Verify that both covariances are equal
Assertions.assertEquals(initState.getDate(), propagatedStateCov.getDate());
Assertions.assertEquals(provider.getCovarianceOrbitType(), propagatedStateCov.getOrbitType());
compareCovariance(initCartCovariance, propagatedStateCov.getMatrix(), 1.e-4);
}
This produces the following error:
[ERROR] org.orekit.propagation.covariance.TmpTest.testInconsistentCovarianceBoundedPropagator -- Time elapsed: 0.602 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <1.0> but was: <10805.9618930703>
A minimal fix that makes the test pass could be to add an early return in StateCovarianceMatrixProvider.init(...) if it was already initialised before. However, I’m wondering if there might be reasons why this would be a bad idea.
Best,
Simon