Hello everyone,
I came accross a diverging behaviour of the DSST propagator when certain detectors are used.
It is likely linked to DSST propagator in osculating elements failed with several detectors (I will discuss it below), that we raised last year. I believe to have now a more complete view of the issue, as detailed hereafter.
Typical encounter is the following:
- A detector (e.g.
ApsideDetector), associated with a handler withAction.RESET_STATE, is in use. - In
AbstractIntegrator#acceptStep, the detection of the even leads to the call ofhandleStep(comment in the code is “// handle the first part of the step, up to the event”). The handleStep function leads to an update of the short period viaDSSTPropagator.ShortPeriodicsHandler#handleStep. - Since a “reset state” action is called, the integration is resumed at the epoch of the event Te. However, it can happen that the event is (falsely) detected a second time (likely due to the reset of the state?), very close the current epoch (time difference is DT ~ 5e-11 s in the test below). This second occurence also triggers the update of the short periods, but the corresponding time span is [Te, Te+DT]. This timespan is infinitesimal, likely too short too make sense for an interpolation grid, and the next interpolation of the short periods breaks (typically in
DSSTTesseral$getCijmor equivalent) and leads to unrealistic orbit.
Our understanding is that the short periods should not be updated by default in DSSTPropagator.ShortPeriodicsHandler#handleStep, which is called several times before, between and after the events during a single integration step within AbstractIntegrator#acceptStep.
I believe that the issue in DSST propagator in osculating elements failed with several detectors is similar except that, in this case, two detectors are used, which also triggers the update of the short period on infinitesimal time spans.
Beyond the bug itself, does anybody have an idea on how to workaround this (except avoiding RESET_STATE in the handlers)?
Please find below a script to reproduce the bug (typically added in DSSTPropagatorTest)![]()
@Test
public void testApsideDetectorAndDsstLeadsToHyperbolicOrbit() {
// Spacecraft state
final SpacecraftState state = getLEOState();
// Body frame
final Frame itrf = FramesFactory .getITRF(IERSConventions.IERS_2010, true);
// Earth
final UnnormalizedSphericalHarmonicsProvider provider = GravityFieldFactory.getUnnormalizedProvider(4, 4);
final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
Constants.WGS84_EARTH_FLATTENING, itrf);
// Detectors
final List<EventDetector> events = new ArrayList<>();
events.add(new ApsideDetector(state.getOrbit()).withHandler(new ApsideHandlerWithResetState()));
// Force models
final List<DSSTForceModel> forceModels = new ArrayList<>();
forceModels.add(new DSSTZonal(provider));
forceModels.add(new DSSTTesseral(itrf, Constants.WGS84_EARTH_ANGULAR_VELOCITY, provider));
// Set up DSST propagator
final double[][] tol = ToleranceProvider.getDefaultToleranceProvider(10.).getTolerances(state.getOrbit(), OrbitType.EQUINOCTIAL);
final ODEIntegrator integrator = new DormandPrince54Integrator(60.0, 3600.0, tol[0], tol[1]);
final DSSTPropagator propagator = new DSSTPropagator(integrator, PropagationType.OSCULATING);
for (DSSTForceModel force : forceModels) {
propagator.addForceModel(force);
}
for (EventDetector event : events) {
propagator.addEventDetector(event);
}
propagator.setInitialState(state);
// Propagation
propagator.propagate(state.getDate().shiftedBy(3600));
}
public class ApsideHandlerWithResetState implements EventHandler {
@Override
public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
return Action.RESET_STATE;
}
}
Expected stacktrace is:
org.orekit.errors.OrekitIllegalArgumentException: hyperbolic orbits cannot be handled as org.orekit.orbits.EquinoctialOrbit instances
at org.orekit.orbits.EquinoctialOrbit.<init>(EquinoctialOrbit.java:199)
at org.orekit.orbits.EquinoctialOrbit.<init>(EquinoctialOrbit.java:250)
at org.orekit.orbits.OrbitType$3.mapArrayToOrbit(OrbitType.java:462)
at org.orekit.orbits.OrbitType$3.mapArrayToOrbit(OrbitType.java:1)
at org.orekit.propagation.semianalytical.dsst.DSSTPropagator$MeanPlusShortPeriodicMapper.mapArrayToState(DSSTPropagator.java:1036)
at org.orekit.propagation.integration.StateMapper.mapArrayToState(StateMapper.java:169)
at org.orekit.propagation.integration.AbstractIntegratedPropagator.convertToOrekitWithoutAdditional(AbstractIntegratedPropagator.java:723)
at org.orekit.propagation.integration.AbstractIntegratedPropagator.convertToOrekitWithAdditional(AbstractIntegratedPropagator.java:713)