EventDetectorsProvider.java

  1. /* Copyright 2002-2024 CS GROUP
  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;

  18. import java.lang.reflect.Array;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. import java.util.stream.Stream;

  22. import org.hipparchus.CalculusFieldElement;
  23. import org.hipparchus.Field;
  24. import org.hipparchus.ode.events.Action;
  25. import org.hipparchus.util.FastMath;
  26. import org.orekit.forces.ForceModel;
  27. import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
  28. import org.orekit.time.AbsoluteDate;
  29. import org.orekit.time.FieldAbsoluteDate;
  30. import org.orekit.time.FieldTimeStamped;
  31. import org.orekit.time.TimeStamped;
  32. import org.orekit.utils.ParameterDriver;

  33. /** Interface for building event detectors for force models and maneuver parameters.
  34.  *
  35.  * <p>
  36.  * Objects implementing this interface are mainly {@link ForceModel} and {@link DSSTForceModel}.
  37.  *
  38.  * @author Luc Maisonobe
  39.  * @author Melina Vanel
  40.  * @author Maxime Journot
  41.  * @since 12.0
  42.  */
  43. public interface EventDetectorsProvider {

  44.     /** Accuracy of switching events dates (s). */
  45.     double DATATION_ACCURACY = 1.0e-10;

  46.     /** Get the discrete events related to the model.
  47.      *
  48.      * <p><b>This method is not intended to be called several time, only once by a propagator</b>,
  49.      * as it has the side effect of rebuilding the events detectors when called
  50.      *
  51.      * @return stream of event detectors
  52.      */
  53.     Stream<EventDetector> getEventDetectors();

  54.     /** Get the discrete events related to the model.
  55.      *
  56.      * <p><b>This method is not intended to be called several time, only once by a propagator</b>,
  57.      * as it has the side effect of rebuilding the events detectors when called
  58.      *
  59.      * @param field field to which the state belongs
  60.      * @param <T> extends CalculusFieldElement&lt;T&gt;
  61.      * @return stream of event detectors
  62.      */
  63.     <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field);

  64.     /** Get the discrete events related to the model from a list of {@link ParameterDriver}
  65.      *
  66.      * <p>Date detectors are used to cleanly stop the propagator and reset
  67.      * the state derivatives at transition dates (if any) of the parameter drivers.
  68.      *
  69.      * <p><b>This method is not intended to be called several times, only once by a propagator</b>,
  70.      * as it has the side effect of rebuilding the events detectors when called.
  71.      *
  72.      * @param parameterDrivers list of parameter drivers
  73.      * @return stream of event detectors
  74.      */
  75.     default Stream<EventDetector> getEventDetectors(List<ParameterDriver> parameterDrivers) {
  76.         // If force model does not have parameter Driver, an empty stream is given as results
  77.         final ArrayList<TimeStamped> transitionDates = new ArrayList<>();
  78.         for (final ParameterDriver driver : parameterDrivers) {
  79.             // Get the transitions' dates from the TimeSpanMap
  80.             for (AbsoluteDate date : driver.getTransitionDates()) {
  81.                 transitionDates.add(date);
  82.             }
  83.         }
  84.         // Either force model does not have any parameter driver or only contains parameter driver with only 1 span
  85.         if (transitionDates.size() == 0) {
  86.             return Stream.empty();

  87.         } else {
  88.             // Sort transition dates chronologically
  89.             transitionDates.sort(null);

  90.             // Find shortest duration between 2 consecutive dates
  91.             double shortestDuration = AbstractDetector.DEFAULT_MAXCHECK;
  92.             for (int i = 1; i < transitionDates.size(); i++) {
  93.                 // Duration from current to previous date
  94.                 shortestDuration = FastMath.min(shortestDuration,
  95.                                                 transitionDates.get(i).durationFrom(transitionDates.get(i - 1)));
  96.             }

  97.             // Create the date detector containing all transition dates and return it
  98.             // Max check set to half the shortest duration between 2 consecutive dates
  99.             final DateDetector datesDetector = new DateDetector(transitionDates.toArray(new TimeStamped[0])).
  100.                             withMaxCheck(0.5 * shortestDuration).
  101.                             withMinGap(0.5 * shortestDuration).
  102.                             withThreshold(DATATION_ACCURACY).
  103.                             withHandler((state, d, increasing) -> {
  104.                                 return Action.RESET_DERIVATIVES;
  105.                             });
  106.             return Stream.of(datesDetector);
  107.         }
  108.     }

  109.     /** Get the discrete events related to the model from a list of {@link ParameterDriver}
  110.      *
  111.      * <p>Date detectors are used to cleanly stop the propagator and reset
  112.      * the state derivatives at transition dates (if any) of the parameter drivers.
  113.      *
  114.      * <p><b>This method is not intended to be called several times, only once by a propagator</b>,
  115.      * as it has the side effect of rebuilding the events detectors when called.
  116.      *
  117.      * @param parameterDrivers list of parameter drivers
  118.      * @param field field to which the state belongs
  119.      * @param <T> extends CalculusFieldElement&lt;T&gt;
  120.      * @return stream of event detectors
  121.      */
  122.     default <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field, List<ParameterDriver> parameterDrivers) {
  123.         // If force model does not have parameter Driver, an empty stream is given as results
  124.         final ArrayList<AbsoluteDate> transitionDates = new ArrayList<>();
  125.         for (ParameterDriver driver : parameterDrivers) {
  126.             // Get the transitions' dates from the TimeSpanMap
  127.             for (AbsoluteDate date : driver.getTransitionDates()) {
  128.                 transitionDates.add(date);
  129.             }
  130.         }
  131.         // Either force model does not have any parameter driver or only contains parameter driver with only 1 span
  132.         if (transitionDates.size() == 0) {
  133.             return Stream.empty();

  134.         } else {
  135.             // Sort transition dates chronologically
  136.             transitionDates.sort(null);

  137.             // Find shortest duration between 2 consecutive dates
  138.             double shortestDuration = AbstractDetector.DEFAULT_MAXCHECK;
  139.             for (int i = 1; i < transitionDates.size(); i++) {
  140.                 // Duration from current to previous date
  141.                 shortestDuration = FastMath.min(shortestDuration,
  142.                                                 transitionDates.get(i).durationFrom(transitionDates.get(i - 1)));
  143.             }

  144.             // Initialize the date detector
  145.             // Max check set to half the shortest duration between 2 consecutive dates
  146.             @SuppressWarnings("unchecked")
  147.             final FieldDateDetector<T> datesDetector =
  148.                             new FieldDateDetector<>(field, (FieldTimeStamped<T>[]) Array.newInstance(FieldTimeStamped.class, 0)).
  149.                             withMaxCheck(0.5 * shortestDuration).
  150.                             withMinGap(0.5 * shortestDuration).
  151.                             withThreshold(field.getZero().newInstance(DATATION_ACCURACY)).
  152.                             withHandler(( state, d, increasing) -> {
  153.                                 return Action.RESET_DERIVATIVES;
  154.                             });
  155.             // Add all transitions' dates to the date detector
  156.             for (int i = 0; i < transitionDates.size(); i++) {
  157.                 datesDetector.addEventDate(new FieldAbsoluteDate<>(field, transitionDates.get(i)));
  158.             }
  159.             // Return the detectors
  160.             return Stream.of(datesDetector);
  161.         }
  162.     }
  163. }