1   /* Copyright 2002-2025 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.forces.maneuvers.trigger;
18  
19  import java.util.Arrays;
20  import java.util.Collections;
21  import java.util.List;
22  
23  import org.hipparchus.CalculusFieldElement;
24  import org.hipparchus.Field;
25  import org.orekit.propagation.events.EventDetectionSettings;
26  import org.orekit.propagation.events.FieldEventDetectionSettings;
27  import org.orekit.propagation.events.FieldEventDetector;
28  import org.orekit.propagation.events.FieldParameterDrivenDateIntervalDetector;
29  import org.orekit.propagation.events.ParameterDrivenDateIntervalDetector;
30  import org.orekit.time.AbsoluteDate;
31  import org.orekit.utils.ParameterDriver;
32  
33  /** Maneuver triggers based on a start and end date.
34   * @author Maxime Journot
35   * @since 10.2
36   */
37  public class DateBasedManeuverTriggers extends IntervalEventTrigger<ParameterDrivenDateIntervalDetector> {
38  
39      /** Default name for trigger. */
40      public static final String DEFAULT_NAME = "";
41  
42      /** Name of the trigger (used as prefix for start and stop parameters drivers). */
43      private final String name;
44  
45      /** Simple constructor.
46       * @param date start (or end) data of the maneuver
47       * @param duration maneuver duration (if positive, maneuver is from date to date + duration,
48       * if negative, maneuver will be from date - duration to date)
49       */
50      public DateBasedManeuverTriggers(final AbsoluteDate date, final double duration) {
51          this(DEFAULT_NAME, date, duration);
52      }
53  
54      /** Simple constructor.
55       * @param name name of the trigger (used as prefix for start and stop parameters drivers)
56       * @param date start (or end) data of the maneuver
57       * @param duration maneuver duration (if positive, maneuver is from date to date + duration,
58       * if negative, maneuver will be from date - duration to date)
59       * @since 11.1
60       */
61      public DateBasedManeuverTriggers(final String name, final AbsoluteDate date, final double duration) {
62          this(name, date, duration, ParameterDrivenDateIntervalDetector.getDefaultDetectionSettings(date, date.shiftedBy(duration)));
63      }
64  
65      /** Simple constructor.
66       * @param name name of the trigger (used as prefix for start and stop parameters drivers)
67       * @param date start (or end) data of the maneuver
68       * @param duration maneuver duration (if positive, maneuver is from date to date + duration,
69       * if negative, maneuver will be from date - duration to date)
70       * @param detectionSettings date detection settings (warning: choose with care, as poor settings might miss the maneuver)
71       * @since 13.0
72       */
73      public DateBasedManeuverTriggers(final String name, final AbsoluteDate date, final double duration,
74                                       final EventDetectionSettings detectionSettings) {
75          super(createDetector(name, date, duration, detectionSettings));
76          this.name = name;
77      }
78  
79      /** Create a date detector from one boundary and signed duration.
80       * @param prefix for start and stop parameters drivers
81       * @param date start (or end) data of the maneuver
82       * @param duration maneuver duration (if positive, maneuver is from date to date + duration,
83       * if negative, maneuver will be from date - duration to date)
84       * @param detectionSettings event detection settings
85       * @return date detector
86       * @since 13.0
87       */
88      private static ParameterDrivenDateIntervalDetector createDetector(final String prefix, final AbsoluteDate date,
89                                                                        final double duration,
90                                                                        final EventDetectionSettings detectionSettings) {
91          if (duration >= 0) {
92              return new ParameterDrivenDateIntervalDetector(prefix, date, date.shiftedBy(duration)).
93                      withDetectionSettings(detectionSettings);
94          } else {
95              return new ParameterDrivenDateIntervalDetector(prefix, date.shiftedBy(duration), date).
96                      withDetectionSettings(detectionSettings);
97          }
98      }
99  
100     /** {@inheritDoc} */
101     @Override
102     public String getName() {
103         return name;
104     }
105 
106     /** Get the start date.
107      * @return the start date
108      */
109     public AbsoluteDate getStartDate() {
110         return getFiringIntervalDetector().getStartDriver().getDate();
111     }
112 
113     /** Get the end date.
114      * @return the end date
115      */
116     public AbsoluteDate getEndDate() {
117         return getFiringIntervalDetector().getStopDriver().getDate();
118     }
119 
120     /** Get the duration of the maneuver (s).
121      * duration = endDate - startDate
122      * @return the duration of the maneuver (s)
123      */
124     public double getDuration() {
125         return getEndDate().durationFrom(getStartDate());
126     }
127 
128     /** {@inheritDoc} */
129     @Override
130     protected <D extends FieldEventDetector<S>, S extends CalculusFieldElement<S>> D convertIntervalDetector(final Field<S> field,
131                                                                                                              final ParameterDrivenDateIntervalDetector detector) {
132 
133         final FieldParameterDrivenDateIntervalDetector<S> fd =
134                         new FieldParameterDrivenDateIntervalDetector<>(field, "",
135                                         detector.getStartDriver().getBaseDate(),
136                                         detector.getStopDriver().getBaseDate())
137                                 .withDetectionSettings(new FieldEventDetectionSettings<>(field, detector.getDetectionSettings()));
138         fd.getStartDriver().setName(detector.getStartDriver().getName());
139         fd.getStopDriver().setName(detector.getStopDriver().getName());
140         fd.getMedianDriver().setName(detector.getMedianDriver().getName());
141         fd.getDurationDriver().setName(detector.getDurationDriver().getName());
142 
143         @SuppressWarnings("unchecked")
144         final D converted = (D) fd;
145         return converted;
146 
147     }
148 
149     /** {@inheritDoc} */
150     @Override
151     public List<ParameterDriver> getParametersDrivers() {
152         return Collections.unmodifiableList(Arrays.asList(getFiringIntervalDetector().getStartDriver(),
153                                                           getFiringIntervalDetector().getStopDriver(),
154                                                           getFiringIntervalDetector().getMedianDriver(),
155                                                           getFiringIntervalDetector().getDurationDriver()));
156     }
157 }