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.util.FastMath;
  25. import org.orekit.forces.ForceModel;
  26. import org.orekit.propagation.events.handlers.FieldResetDerivativesOnEvent;
  27. import org.orekit.propagation.events.handlers.ResetDerivativesOnEvent;
  28. import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
  29. import org.orekit.time.AbsoluteDate;
  30. import org.orekit.time.FieldAbsoluteDate;
  31. import org.orekit.time.FieldTimeStamped;
  32. import org.orekit.time.TimeStamped;
  33. import org.orekit.utils.ParameterDriver;

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

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

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

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

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

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

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

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

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

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

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

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