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