EventMultipleHandler.java

  1. /* Copyright 2020-2025 Airbus Defence and Space
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.propagation.events.handlers;

  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.function.Function;
  23. import java.util.stream.Collectors;
  24. import org.hipparchus.ode.events.Action;
  25. import org.orekit.propagation.SpacecraftState;
  26. import org.orekit.propagation.events.AbstractDetector;
  27. import org.orekit.propagation.events.EventDetector;
  28. import org.orekit.time.AbsoluteDate;

  29. /**
  30.  * Facade handlers that allows to use several handlers for one detector.
  31.  * Otherwise, the use of several detectors, each associated with one handler, that detect
  32.  * the same event can lead to non-deterministic behaviour.
  33.  * This handler manages several handlers. The action returned is based on a priority rule
  34.  * (see {@link #eventOccurred}) :
  35.  * {@link Action#STOP stop} > {@link Action#RESET_STATE resetState} > {@link Action#RESET_DERIVATIVES resetDerivatives} > {@link Action#RESET_EVENTS resetRevents} > {@link Action#CONTINUE continue}
  36.  *
  37.  * @author Lara HuĂ©
  38.  *
  39.  * @since 10.3
  40.  */
  41. public class EventMultipleHandler implements EventHandler {

  42.     /** Default list of handlers for event overrides. */
  43.     private List<EventHandler> handlers;

  44.     /** List of handlers whose Action returned is RESET_STATE. */
  45.     private List<EventHandler> resetStateHandlers;

  46.     /** Constructor with list initialisation. */
  47.     public EventMultipleHandler() {
  48.         handlers = new ArrayList<>();
  49.         resetStateHandlers = new ArrayList<>();
  50.     }

  51.     /** Initialize event handler at the start of a propagation.
  52.      * <p>
  53.      * This method is called once at the start of the propagation. It
  54.      * may be used by the event handler to initialize some internal data
  55.      * if needed.
  56.      * </p>
  57.      * <p>
  58.      * The default implementation does nothing
  59.      * </p>
  60.      * <p>
  61.      * All handlers' init methods are successively called, the order method is
  62.      * the order in which handlers are added
  63.      * </p>
  64.      * @param initialState initial state
  65.      * @param target target date for the propagation
  66.      * @param detector event detector related to the event handler
  67.      */
  68.     @Override
  69.     public void init(final SpacecraftState initialState, final AbsoluteDate target, final EventDetector detector) {
  70.         handlers.forEach(handler -> handler.init(initialState, target, detector));
  71.     }

  72.     /** Handle an event.
  73.      *
  74.      * The MultipleEventHandler class implies a different behaviour on event detections
  75.      * than with other handlers :
  76.      * Without the MultipleEventHandler, there is a total order on event occurrences.
  77.      * Handlers H1, H2, ... that are associated with different instances of
  78.      * {@link AbstractDetector} are successively called and Action from H1 can prevent
  79.      * H2 from happening if H1 returned {@link Action#RESET_STATE resetState}.
  80.      * With the MultipleEventHandler class, when event E occurs, all methods eventOccurred
  81.      * of Handlers H1, H2... from MultiEventHandler attributes are called, then Action is decided.
  82.      *
  83.      * @param s SpaceCraft state to be used in the evaluation
  84.      * @param detector object with appropriate type that can be used in determining correct return state
  85.      * @param increasing with the event occurred in an "increasing" or "decreasing" slope direction
  86.      * @return the Action that the calling detector should pass back to the evaluation system
  87.      *
  88.      */
  89.     @Override
  90.     public Action eventOccurred(final SpacecraftState s, final EventDetector detector, final boolean increasing) {
  91.         final Map<EventHandler, Action> actions =
  92.                 handlers.stream().
  93.                          collect(Collectors.toMap(Function.identity(),
  94.                              handler -> handler.eventOccurred(s, detector, increasing)));

  95.         if (actions.containsValue(Action.STOP)) {
  96.             return Action.STOP;
  97.         }

  98.         if (actions.containsValue(Action.RESET_STATE)) {
  99.             resetStateHandlers = actions.entrySet()
  100.                                         .stream()
  101.                                         .filter(entry -> Action.RESET_STATE.equals(entry.getValue()))
  102.                                         .map(Map.Entry::getKey)
  103.                                         .collect(Collectors.toList());
  104.             return Action.RESET_STATE;
  105.         }

  106.         if (actions.containsValue(Action.RESET_DERIVATIVES)) {
  107.             return Action.RESET_DERIVATIVES;
  108.         }

  109.         if (actions.containsValue(Action.RESET_EVENTS)) {
  110.             return Action.RESET_EVENTS;
  111.         }

  112.         return Action.CONTINUE;
  113.     }

  114.     /** Reset the state prior to continue propagation.
  115.      * <p>
  116.      * All handlers that return {@link Action#RESET_STATE resetState} when calling {@link #eventOccurred}
  117.      * are saved in resetStateHandlers. Their methods resetState are successively called.
  118.      * The order for calling resetState methods is the order in which handlers are added.
  119.      * </p>
  120.      * @param detector object with appropriate type that can be used in determining correct return state
  121.      * @param oldState old state
  122.      * @return new state
  123.      */
  124.     @Override
  125.     public SpacecraftState resetState(final EventDetector detector, final SpacecraftState oldState) {
  126.         SpacecraftState newState = oldState;
  127.         for (EventHandler handler : resetStateHandlers) {
  128.             newState = handler.resetState(detector, newState);
  129.         }
  130.         return newState;
  131.     }

  132.     @Override
  133.     public void finish(final SpacecraftState finalState, final EventDetector detector) {
  134.         for (final EventHandler handler : handlers) {
  135.             handler.finish(finalState, detector);
  136.         }
  137.     }

  138.     /** Add one handler to the managed handlers list.
  139.      * @param handler handler associated with D detector
  140.      * @return this object
  141.      */
  142.     public EventMultipleHandler addHandler(final EventHandler handler) {
  143.         handlers.add(handler);
  144.         return this;
  145.     }

  146.     /** Add several handlers to the managed handlers list.
  147.      * @param newHandlers handlers associated with D detector
  148.      * @return this object
  149.      */
  150.     @SafeVarargs // this method is safe
  151.     public final EventMultipleHandler addHandlers(final EventHandler... newHandlers) {
  152.         Arrays.stream(newHandlers).forEach(this::addHandler);
  153.         return this;
  154.     }

  155.     /** Change handlers list with user input.
  156.      * @param newHandlers new handlers list associated with D detector
  157.      *
  158.      */
  159.     public void setHandlers(final List<EventHandler> newHandlers) {
  160.         handlers = newHandlers;
  161.     }

  162.     /** Retrieve managed handlers list.
  163.      * @return list of handlers for event overrides
  164.      */
  165.     public List<EventHandler> getHandlers() {
  166.         return this.handlers;
  167.     }
  168. }