I’m running into a strange issue while using event detectors. I’ve created an example that is similar enough to my use case. I’m using a DateDetector with a RecordAndContinue handler to store states at a certain time step. But the states that are stored do not match what I get if I just propagate to that epochs directly.
In my example, I first propagate to each test epoch and calculate the range between the states using two identical propagators. I get back 0 as expected. Next, I add DateDetectors with a RecordAndContinue handler to one of the propagators. I propagate to the stop time and record all the events. For each event, I then propagate to the event epoch with a second propagator that is identical to the first, but it does not have event detectors. When I calculate the range between the two states (the event state and the propagated state), I get a non-zero result.
@Log4j2
public class OrekitTest {
@Test
public void testOrekit() {
// Initialize Orekit.
File orekitData = new File("PATH_TO_OREKIT_DATA");
DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();
manager.addProvider(new DirectoryCrawler(orekitData));
// Establish time range.
TimeScale utc = TimeScalesFactory.getUTC();
AbsoluteDate initialEpoch = new AbsoluteDate("2023-09-01T00:00:00.000", utc);
AbsoluteDate finalEpoch = new AbsoluteDate("2023-09-03T00:00:00.000", utc);
// Set initial state.
TimeStampedPVCoordinates pv = new TimeStampedPVCoordinates(initialEpoch,
new Vector3D(3.202221011875539e+07, 2.743293506737402e+07, -7.418022649217934e+04),
new Vector3D(-2.000287709983509e+03, 2.334929394216369e+03, 4.490568450445024e-00));
KeplerianOrbit orbit = new KeplerianOrbit(pv, FramesFactory.getGCRF(),
Constants.IERS2010_EARTH_MU);
SpacecraftState initialState = new SpacecraftState(orbit);
// Create propagators.
Propagator prop = createPropagator(initialState);
Propagator propNoDetectors = createPropagator(initialState);
// Get the epochs to propagate to.
double step = 6 * 3600.0; // 6 hours.
List<AbsoluteDate> epochs = new ArrayList<>();
for (AbsoluteDate epoch = initialEpoch; epoch.compareTo(finalEpoch.shiftedBy(-step)) < 0; ) {
epoch = epoch.shiftedBy(step);
epochs.add(epoch);
}
// Propagate to dates and get range.
for (AbsoluteDate epoch : epochs) {
SpacecraftState state1 = prop.propagate(epoch);
SpacecraftState state2 = propNoDetectors.propagate(epoch);
double range = calculateRange(state1, state2);
log.error("Range: {} m", range);
}
// Re-create the propagators.
prop = createPropagator(initialState);
propNoDetectors = createPropagator(initialState);
// Add the date detectors.
RecordAndContinue<EventDetector> rac = new RecordAndContinue<>();
for (AbsoluteDate epoch : epochs) {
prop.addEventDetector(new DateDetector(epoch).withHandler(rac));
}
// Propagate (and record events).
prop.propagate(finalEpoch);
// Compare states at event times.
for (int i = 0; i < rac.getEvents().size(); ++i) {
Event<?> event = rac.getEvents().get(i);
AbsoluteDate epoch = epochs.get(i);
double epochDifference = event.getState().getDate().durationFrom(epoch);
log.error("Epoch Difference: {} sec", epochDifference);
AbsoluteDate eventEpoch = event.getState().getDate();
SpacecraftState state = propNoDetectors.propagate(eventEpoch);
double range = calculateRange(event.getState(), state);
log.error("Range: {} m", range);
}
}
private double calculateRange(SpacecraftState first, SpacecraftState second) {
return first.getPVCoordinates().getPosition().subtract(second.getPVCoordinates().getPosition())
.getNorm();
}
private Propagator createPropagator(SpacecraftState initialState) {
// Create the integrator.
double minStep = initialState.getKeplerianPeriod() / 100.0;
double maxStep = initialState.getKeplerianPeriod();
double[][] tol = DSSTPropagator.tolerances(10.0, initialState.getOrbit());
AdaptiveStepsizeIntegrator integrator =
new DormandPrince853Integrator(minStep, maxStep, tol[0], tol[1]);
// Initialize the propagator.
NumericalPropagator propagator = new NumericalPropagator(integrator);
propagator.setInitialState(initialState);
// Add J22 perturbations.
Frame itrf = FramesFactory.getITRF(IERSConventions.IERS_2010, true);
HolmesFeatherstoneAttractionModel gravityModel = new HolmesFeatherstoneAttractionModel(itrf,
GravityFieldFactory.getNormalizedProvider(2, 2));
// Add the force models to the propagator
propagator.addForceModel(gravityModel);
return propagator;
}
}
It seems to have something to do with the event detection and handling itself. Any idea what’s going on here? Maybe I’m getting the event state incorrectly? Thanks in advance!