EventDetectorsProvider.java
- /* Copyright 2002-2025 CS GROUP
- * Licensed to CS GROUP (CS) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * CS licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.orekit.propagation.events;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.SortedSet;
- import java.util.TreeSet;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- import org.hipparchus.CalculusFieldElement;
- import org.hipparchus.Field;
- import org.orekit.forces.ForceModel;
- import org.orekit.propagation.events.handlers.FieldResetDerivativesOnEvent;
- import org.orekit.propagation.events.handlers.ResetDerivativesOnEvent;
- import org.orekit.propagation.events.intervals.AdaptableInterval;
- import org.orekit.propagation.events.intervals.DateDetectionAdaptableIntervalFactory;
- import org.orekit.propagation.events.intervals.FieldAdaptableInterval;
- import org.orekit.propagation.semianalytical.dsst.forces.DSSTForceModel;
- import org.orekit.time.AbsoluteDate;
- import org.orekit.time.ChronologicalComparator;
- import org.orekit.time.FieldAbsoluteDate;
- import org.orekit.time.FieldTimeStamped;
- import org.orekit.time.TimeStamped;
- import org.orekit.utils.ParameterDriver;
- /** Interface for building event detectors for force models and maneuver parameters.
- *
- * <p>
- * Objects implementing this interface are mainly {@link ForceModel} and {@link DSSTForceModel}.
- *
- * @author Luc Maisonobe
- * @author Melina Vanel
- * @author Maxime Journot
- * @since 12.0
- */
- public interface EventDetectorsProvider {
- /** Accuracy of switching events dates (s). */
- double DATATION_ACCURACY = DateDetector.DEFAULT_THRESHOLD;
- /** Get the discrete events related to the model.
- *
- * <p><b>This method is not intended to be called several time, only once by a propagator</b>,
- * as it has the side effect of rebuilding the events detectors when called
- *
- * @return stream of event detectors
- */
- Stream<EventDetector> getEventDetectors();
- /** Get the discrete events related to the model.
- *
- * <p><b>This method is not intended to be called several time, only once by a propagator</b>,
- * as it has the side effect of rebuilding the events detectors when called
- *
- * @param field field to which the state belongs
- * @param <T> extends CalculusFieldElement<T>
- * @return stream of event detectors
- */
- <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field);
- /** Get the discrete events related to the model from a list of {@link ParameterDriver}
- *
- * <p>Date detectors are used to cleanly stop the propagator and reset
- * the state derivatives at transition dates (if any) of the parameter drivers.
- *
- * <p><b>This method is not intended to be called several times, only once by a propagator</b>,
- * as it has the side effect of rebuilding the events detectors when called.
- *
- * @param parameterDrivers list of parameter drivers
- * @return stream of event detectors
- */
- default Stream<EventDetector> getEventDetectors(List<ParameterDriver> parameterDrivers) {
- // If force model does not have parameter Driver, an empty stream is given as results
- final ArrayList<TimeStamped> transitionDates = new ArrayList<>();
- for (final ParameterDriver driver : parameterDrivers) {
- // Get the transitions' dates from the TimeSpanMap
- transitionDates.addAll(Arrays.asList(driver.getTransitionDates()));
- }
- // Either force model does not have any parameter driver or only contains parameter driver with only 1 span
- if (transitionDates.isEmpty()) {
- return Stream.empty();
- } else {
- // Create the date detector containing all transition dates and return it
- final DateDetector detector = getDateDetector(transitionDates.toArray(new TimeStamped[0]));
- return Stream.of(detector);
- }
- }
- /** Get the discrete events related to the model from a list of {@link ParameterDriver}
- *
- * <p>Date detectors are used to cleanly stop the propagator and reset
- * the state derivatives at transition dates (if any) of the parameter drivers.
- *
- * <p><b>This method is not intended to be called several times, only once by a propagator</b>,
- * as it has the side effect of rebuilding the events detectors when called.
- *
- * @param parameterDrivers list of parameter drivers
- * @param field field to which the state belongs
- * @param <T> extends CalculusFieldElement<T>
- * @return stream of event detectors
- */
- default <T extends CalculusFieldElement<T>> Stream<FieldEventDetector<T>> getFieldEventDetectors(Field<T> field,
- List<ParameterDriver> parameterDrivers) {
- // If force model does not have parameter Driver, an empty stream is given as results
- final ArrayList<AbsoluteDate> transitionDates = new ArrayList<>();
- for (ParameterDriver driver : parameterDrivers) {
- // Get the transitions' dates from the TimeSpanMap
- transitionDates.addAll(Arrays.asList(driver.getTransitionDates()));
- }
- // Either force model does not have any parameter driver or only contains parameter driver with only 1 span
- if (transitionDates.isEmpty()) {
- return Stream.empty();
- } else {
- // Initialize the date detector
- final FieldDateDetector<T> datesDetector = getFieldDateDetector(field,
- transitionDates.toArray(new AbsoluteDate[0]));
- // Return the detectors
- return Stream.of(datesDetector);
- }
- }
- /**
- * Method building dates' detector.
- * @param timeStampeds dates to detect
- * @return dates detector
- * @since 13.0
- */
- default DateDetector getDateDetector(final TimeStamped... timeStampeds) {
- final AdaptableInterval maxCheck = DateDetectionAdaptableIntervalFactory.getDatesDetectionInterval(
- timeStampeds);
- final double minGap = DateDetectionAdaptableIntervalFactory.getMinGap(timeStampeds) / 2;
- final DateDetector dateDetector = new DateDetector().withMaxCheck(maxCheck).withMinGap(minGap).
- withThreshold(DATATION_ACCURACY).withHandler(new ResetDerivativesOnEvent());
- final SortedSet<AbsoluteDate> sortedDates = new TreeSet<>(new ChronologicalComparator());
- sortedDates.addAll(Arrays.stream(timeStampeds).map(TimeStamped::getDate).collect(Collectors.toList()));
- for (final AbsoluteDate date : sortedDates) {
- dateDetector.addEventDate(date);
- }
- return dateDetector;
- }
- /**
- * Method building dates' detector.
- * @param field field
- * @param timeStampeds dates to detect
- * @param <T> field type
- * @return dates detector
- * @since 13.0
- */
- default <T extends CalculusFieldElement<T>> FieldDateDetector<T> getFieldDateDetector(final Field<T> field,
- final TimeStamped... timeStampeds) {
- @SuppressWarnings("unchecked")
- final FieldAdaptableInterval<T> maxCheck = DateDetectionAdaptableIntervalFactory.getDatesDetectionFieldInterval(
- Arrays.stream(timeStampeds).map(timeStamped -> new FieldAbsoluteDate<>(field, timeStamped.getDate()))
- .toArray(FieldTimeStamped[]::new));
- final double minGap = DateDetectionAdaptableIntervalFactory.getMinGap(timeStampeds) / 2;
- final FieldDateDetector<T> fieldDateDetector = new FieldDateDetector<>(field).
- withHandler(new FieldResetDerivativesOnEvent<>()).withMaxCheck(maxCheck).withMinGap(minGap).
- withThreshold(field.getZero().newInstance(DATATION_ACCURACY));
- final SortedSet<AbsoluteDate> sortedDates = new TreeSet<>(new ChronologicalComparator());
- sortedDates.addAll(Arrays.stream(timeStampeds).map(TimeStamped::getDate).collect(Collectors.toList()));
- for (final AbsoluteDate date : sortedDates) {
- fieldDateDetector.addEventDate(new FieldAbsoluteDate<>(field, date));
- }
- return fieldDateDetector;
- }
- }