EventEnablingPredicateFilter inverting g value?

Hello everyone,

I am using the EventEnablingPredicateFilter for the first time to keep values *if the spacecraft is in some state.

If the condition is true during all the propagation, I can handle sucessfully the events.
But in the case the condition is false at start at propagation and then becomes true, the events are at the right date but the increasing value is the opposite.

I wrote a unit test in the EventEnablingPredicateFilterTest class so I can reuse some class field. It demonstrates my problem, :

  private class RecordIncreasingsHandler implements EventHandler<AbstractDetector<?>> {

        Map<AbsoluteDate, Boolean> records = new TreeMap<>();

        @Override
        public Action eventOccurred(SpacecraftState s, AbstractDetector<?> detector, boolean increasing) {
            records.put(s.getDate(), increasing);
            return Action.CONTINUE;
        }

        public boolean findClosest(AbsoluteDate date) {
            return records.get(records.keySet().stream().filter(filteredDate -> FastMath.abs(filteredDate.durationFrom(date)) < 1).findAny().get());
        }
    }

    @Test
    public void testSign() {
        RecordIncreasingsHandler filteredHandler = new RecordIncreasingsHandler();
        AbsoluteDate filterStart = orbit.getDate().shiftedBy(12 * 3600);
        AbstractDetector filter = new EventEnablingPredicateFilter(new ElevationDetector(new TopocentricFrame(earth, gp, "test")),
                                                                   (state, eventDetector, g) -> state.getDate().isAfter(filterStart)).withHandler(filteredHandler);
        Propagator propagator = new EcksteinHechlerPropagator(orbit, Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS, Constants.EIGEN5C_EARTH_MU, Constants.EIGEN5C_EARTH_C20,
                                                              Constants.EIGEN5C_EARTH_C30, Constants.EIGEN5C_EARTH_C40, Constants.EIGEN5C_EARTH_C50, Constants.EIGEN5C_EARTH_C60);
        propagator.addEventDetector(filter);
        RecordIncreasingsHandler handler = new RecordIncreasingsHandler();
        propagator.addEventDetector(new ElevationDetector(new TopocentricFrame(earth, gp, "test")).withHandler(handler));
        propagator.propagate(orbit.getDate(), orbit.getDate().shiftedBy(24 * 3600));
        Assert.assertFalse(filteredHandler.records.isEmpty());
        Assert.assertTrue(filteredHandler.records.keySet().stream().noneMatch(date -> date.isBefore(filterStart)));
        handler.records.keySet()
                       .stream()
                       .filter(date -> date.isAfter(filterStart))
                       .forEach(date -> Assert.assertEquals(date.toString(), handler.records.get(date), filteredHandler.findClosest(date)));
    }

With the breakpoint at the last line, you can easily view that all booleans values are opposite.

Am I right ? I might have been misused the class ?

Best regards,

Anne-Laure

Did you try adding the event handler to the wrapped detector instead of the EventEnablingPredicateFilter?

Hello, Thank you for the suggestion.

Did you mean that change :

        AbstractDetector filter = new EventEnablingPredicateFilter(new ElevationDetector(new TopocentricFrame(earth, gp, "test")).withHandler(filteredHandler),   (state, eventDetector, g) -> state.getDate().isAfter(filterStart));

I would expect that the handler is notified without filtering ?! But it seems that is still filtered and the bug remains :
image

Hello,

I am going on with the investigation and please note that when the condition is true at the start of propagation, the problem does not occurs :

@Test
    public void testGValueAlwaysTrue() {
        RecordIncreasingsHandler filteredHandler = new RecordIncreasingsHandler();
        AbstractDetector filter = new EventEnablingPredicateFilter(new ElevationDetector(new TopocentricFrame(earth, gp, "test")), (state, eventDetector, g) -> true).withHandler(
                filteredHandler);
        Propagator propagator = new EcksteinHechlerPropagator(orbit, Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS, Constants.EIGEN5C_EARTH_MU, Constants.EIGEN5C_EARTH_C20,
                                                              Constants.EIGEN5C_EARTH_C30, Constants.EIGEN5C_EARTH_C40, Constants.EIGEN5C_EARTH_C50, Constants.EIGEN5C_EARTH_C60);
        propagator.addEventDetector(filter);
        RecordIncreasingsHandler handler = new RecordIncreasingsHandler();
        propagator.addEventDetector(new ElevationDetector(new TopocentricFrame(earth, gp, "test")).withHandler(handler));
        propagator.propagate(orbit.getDate(), orbit.getDate().shiftedBy(24 * 3600));
        Assert.assertFalse(filteredHandler.records.isEmpty());
        handler.records.keySet().forEach(date -> Assert.assertEquals(date.toString(), handler.records.get(date), filteredHandler.findClosest(date)));
    }

I also have some cases, in my project, where the PredicateFilter works fine : the value is the good one, even during filter activation. It’s like the filter changes the g value “sometimes” : never at start, only sometimes at activation during propagation ? This is only a feeling… based on few cases.

Best regards,

Anne-Laure

Hi @Anne-Laure ,

I’m not sure I understand your concern here.
According to the screenshot, the filteredHandler only displays events after the filter date, so the filtering works, and the events detected do have the same date and status (true/false) as those detected by the unfiltered handler.

Damned! You are right! I did not reproduce the problem while adding the handler to the detector instead of the predicatefilter.

For information, the screen of the results with handler added to predicate :

So that’s mean that you recommend to add handler to the dectector and never on the predicate?

Could it been handled properly in Orekit ?
With final fields and the fact that withHandler() recreates a new instance, I see no easy ways?
Maybe, it could be forbidden in the EventEnablingPredicateFilter class:

 @Override
    public EventEnablingPredicateFilter withHandler(EventHandler newHandler) {
        throw new UnsupportedOperationException("Please add the handler to wrapped detector");
    }

What do you think?

Best regards,

Anne-Laure

The fact that we cannot override the PredicateFilter.withHandler() methods reminds me and old discussion :wink: : Inheriting from orekit detectors is impossible?

(only for the information)

Indeed, the handler must be added to the wrapped detector if the increasing/decreasing status is meaningful (as in the case of the elevation or eclipse detectors), but it can be added to the filter without any problem if the status is not really significant (as in the case of the longitude crossing detector).
I agree that the EventEnablingPredicateFilter javadoc should be clearer on this point (the status can indeed be modified by the filter and the user can’t know), but there’s no reason to completely prohibit the addition of a handler to EventEnablingPredicateFilter. So my preferred solution is to improve the documentation.
By the way, thanks for this topic, it will be useful to many users :slight_smile: (me first as I wasn’t really aware of the problem until now :wink: ).