ApsideStartStopEventsTrigger fires at the wrong time. (Java)

Hi there.

Using Java Orekit 13.0

What I want to do is fire thrust at the Apogee of the elliptic orbit. I’ve extended the abstract class StartStopEventsTrigger and implemented the convertStartDetector and convertStopDetector. The event is triggered at the perigee everytime, not at the apogee. Can anyone give me some pointers?

I’ll post the code on request.

Hi @Tungsten welcome

What raw event detector do you use to detect apogee? Beware that if you use ApsideDetector, its g function is simply the dot product of position and velocity. This implies that at apogee, this function will switch from positive before apogee (satellite is going away for central body) to negative after apogee (satellite closing towards central body), which means the event will be a decreasing event at apogee, and an increasing event at perigee. This may be counter-intuitive.

Here is what I did. In my add trigger method:

        ApsideDetector startApoapsisDetector = new ApsideDetector(orbit)
                .withHandler((spacecraftState, eventDetector, b) -> {
                    if (b) {
                        System.out.println("🟢\uD83D\uDE80 Reached apoapsis at " + spacecraftState.getDate());
                    } else {
                        System.out.println("🟢\uD83D\uDE80 Reached periapsis at " + spacecraftState.getDate());
                    }
                    return Action.CONTINUE;
                });
        AbsoluteDate stopDateDate = new AbsoluteDate(new java.util.Date(), TimeScalesFactory.getUTC()).shiftedBy((long)duration, TimeUnit.SECONDS);
        DateDetector stopDateDetector = new DateDetector(stopDateDate);
        final ManeuverTriggers triggers = new ApsideStartStopEventsTriggerImpl(orbit, startApoapsisDetector, stopDateDetector){
            private boolean lastFiring = false;
            @Override
            public boolean isFiring(final AbsoluteDate date, final double[] parameters) {
                boolean firing = super.isFiring(date, parameters);
                if (lastFiring != firing) {
                    lastFiring = firing;
                    if (firing) {
                        System.out.println("🔥 Custom maneuver started at " + date);
                    } else {
                        System.out.println("🔥 Custom maneuver ended at " + date);
                    }
                }
                return firing;
            }
        };

And my concrete class:

public class ApsideStartStopEventsTriggerImpl extends StartStopEventsTrigger<ApsideDetector, DateDetector> {
    private final Orbit orbit;

    public ApsideStartStopEventsTriggerImpl(Orbit orbit, ApsideDetector prototypeStartDetector, DateDetector prototypeStopDetector) {
        super(prototypeStartDetector, prototypeStopDetector);
        this.orbit = orbit;
    }

    @Override
    public <D extends FieldEventDetector<S>, S extends CalculusFieldElement<S>> D convertStartDetector(Field<S> field, ApsideDetector apsideDetector) {
        FieldOrbit<S> fieldOrbit = OrbitType.KEPLERIAN.convertToFieldOrbit(field, orbit);
        @SuppressWarnings("unchecked") final D converted = (D) new FieldApsideDetector<>(fieldOrbit);
        return converted;
    }
    
    @Override
    public <D extends FieldEventDetector<S>, S extends CalculusFieldElement<S>> D convertStopDetector(Field<S> field, DateDetector detector) {
        final FieldAbsoluteDate<S> target = new FieldAbsoluteDate<>(field, detector.getDates().get(0).getDate());
        @SuppressWarnings("unchecked")
        final D converted = (D) new FieldDateDetector<>(field, target);
        return converted;
    }

    @Override
    public List<ParameterDriver> getParametersDrivers() {
        return Collections.emptyList();
    }
}

I not sure what the convertStartDetector method is supposed to do.

Only the "Custom maneuver started at " and "Custom maneuver ended at " is output. Debug run doesn’t stop at breakpoints in ApsideStartStopEventsTriggerImpl

This should be the other way round. b is true at perigee and false at apogee.

And here, you should probably use new NegateDetector(startApoapsisDetector) instead of startApoapsisDetector, so the detector becomes positive at apogee.