1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.events;
18
19 import java.util.ArrayList;
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.ode.events.Action;
26 import org.orekit.errors.OrekitIllegalArgumentException;
27 import org.orekit.errors.OrekitMessages;
28 import org.orekit.propagation.FieldSpacecraftState;
29 import org.orekit.propagation.events.functions.EventFunction;
30 import org.orekit.propagation.events.functions.EventFunctionModifier;
31 import org.orekit.propagation.events.handlers.EventHandler;
32 import org.orekit.propagation.events.handlers.FieldEventHandler;
33 import org.orekit.propagation.events.handlers.FieldStopOnEvent;
34 import org.orekit.propagation.events.intervals.DateDetectionAdaptableIntervalFactory;
35 import org.orekit.time.AbsoluteDate;
36 import org.orekit.time.FieldAbsoluteDate;
37 import org.orekit.time.FieldTimeStamped;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class FieldDateDetector<T extends CalculusFieldElement<T>> extends FieldAbstractDetector<FieldDateDetector<T>, T>
56 implements FieldTimeStamped<T> {
57
58
59
60
61 public static final double DEFAULT_MAX_CHECK = DateDetector.DEFAULT_MAX_CHECK;
62
63
64
65
66 public static final double DEFAULT_MIN_GAP = DateDetector.DEFAULT_MIN_GAP;
67
68
69
70
71 public static final double DEFAULT_THRESHOLD = DateDetector.DEFAULT_THRESHOLD;
72
73
74
75
76 private final double minGap;
77
78
79 private FieldAbsoluteDate<T> gDate;
80
81
82 private final ArrayList<FieldEventDate<T>> eventDateList;
83
84
85 private final EventFunction eventFunction;
86
87
88 private int currentIndex;
89
90
91
92
93
94 public FieldDateDetector(final FieldAbsoluteDate<T> fieldAbsoluteDate) {
95 this(new FieldEventDetectionSettings<>(DEFAULT_MAX_CHECK, fieldAbsoluteDate.getField().getZero().newInstance(DEFAULT_THRESHOLD),
96 DEFAULT_MAX_ITER), new FieldStopOnEvent<>(), DEFAULT_MIN_GAP, fieldAbsoluteDate);
97 }
98
99
100
101
102
103
104
105
106
107 @SafeVarargs
108 public FieldDateDetector(final Field<T> field, final FieldTimeStamped<T>... dates) {
109 this(new FieldEventDetectionSettings<>(DateDetectionAdaptableIntervalFactory.getDatesDetectionFieldConstantInterval(dates),
110 field.getZero().newInstance(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER), new FieldStopOnEvent<>(), DEFAULT_MIN_GAP, dates);
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124 @SafeVarargs
125 protected FieldDateDetector(final FieldEventDetectionSettings<T> detectionSettings,
126 final FieldEventHandler<T> handler, final double minGap,
127 final FieldTimeStamped<T>... dates) {
128 super(detectionSettings, handler);
129 this.currentIndex = -1;
130 this.gDate = null;
131 this.eventDateList = new ArrayList<>(dates.length);
132 for (final FieldTimeStamped<T> ts : dates) {
133 addEventDate(ts.getDate());
134 }
135 this.minGap = minGap;
136 final EventFunction baseFunction = super.getEventFunction();
137 this.eventFunction = new EventFunctionModifier() {
138 @Override
139 public EventFunction getBaseFunction() {
140 return baseFunction;
141 }
142
143 @Override
144 public boolean dependsOnTimeOnly() {
145 return true;
146 }
147 };
148 }
149
150
151
152
153
154
155
156 public FieldDateDetector<T> withMinGap(final double newMinGap) {
157 @SuppressWarnings("unchecked")
158 final FieldTimeStamped<T>[] dates = eventDateList.toArray(new FieldEventDate[0]);
159 return new FieldDateDetector<>(getDetectionSettings(), getHandler(), newMinGap, dates);
160 }
161
162
163 @Override
164 protected FieldDateDetector<T> create(final FieldEventDetectionSettings<T> detectionSettings,
165 final FieldEventHandler<T> newHandler) {
166 @SuppressWarnings("unchecked")
167 final FieldTimeStamped<T>[] dates = eventDateList.toArray(new FieldEventDate[0]);
168 return new FieldDateDetector<>(detectionSettings, newHandler, minGap, dates);
169 }
170
171 @Override
172 public EventFunction getEventFunction() {
173 return eventFunction;
174 }
175
176
177
178
179
180 public List<FieldTimeStamped<T>> getDates() {
181 return Collections.unmodifiableList(eventDateList);
182 }
183
184
185
186
187
188
189 @Override
190 public T g(final FieldSpacecraftState<T> s) {
191 gDate = s.getDate();
192 if (currentIndex < 0) {
193 return s.getMass().getField().getZero().newInstance(-1);
194 } else {
195 final FieldEventDate<T> event = getClosest(gDate);
196 return event.gIncrease ? gDate.durationFrom(event.getDate()) : event.getDate().durationFrom(gDate);
197 }
198 }
199
200
201
202
203 public FieldAbsoluteDate<T> getDate() {
204 return currentIndex < 0 ? null : eventDateList.get(currentIndex).getDate();
205 }
206
207
208 @Override
209 public DateDetector toEventDetector(final EventHandler eventHandler) {
210 return new DateDetector(getDetectionSettings().toEventDetectionSettings(), eventHandler, minGap,
211 getDates().stream().map(tFieldTimeStamped -> tFieldTimeStamped.getDate().toAbsoluteDate()).toArray(AbsoluteDate[]::new));
212 }
213
214
215
216
217
218
219
220
221
222
223
224 public void addEventDate(final FieldAbsoluteDate<T> target) throws IllegalArgumentException {
225 final boolean increasing;
226 if (currentIndex < 0) {
227 increasing = (gDate == null) ? true : target.durationFrom(gDate).getReal() > 0.0;
228 currentIndex = 0;
229 eventDateList.add(new FieldEventDate<>(target, increasing));
230 } else {
231 final int lastIndex = eventDateList.size() - 1;
232 final FieldAbsoluteDate<T> firstDate = eventDateList.getFirst().getDate();
233 final FieldAbsoluteDate<T> lastDate = eventDateList.get(lastIndex).getDate();
234 if (firstDate.durationFrom(target).getReal() > minGap) {
235 increasing = !eventDateList.getFirst().gIncrease;
236 eventDateList.addFirst(new FieldEventDate<>(target, increasing));
237 currentIndex++;
238 } else if (target.durationFrom(lastDate).getReal() > minGap) {
239 increasing = !eventDateList.get(lastIndex).gIncrease;
240 eventDateList.add(new FieldEventDate<>(target, increasing));
241 } else {
242 throw new OrekitIllegalArgumentException(OrekitMessages.EVENT_DATE_TOO_CLOSE,
243 target.toAbsoluteDate(),
244 firstDate.toAbsoluteDate(),
245 lastDate.toAbsoluteDate(),
246 minGap,
247 firstDate.durationFrom(target).getReal(),
248 target.durationFrom(lastDate).getReal());
249 }
250 }
251 }
252
253
254
255
256
257 private FieldEventDate<T> getClosest(final FieldAbsoluteDate<T> target) {
258 final T dt = target.durationFrom(eventDateList.get(currentIndex).getDate());
259 if (dt.getReal() < 0.0 && currentIndex > 0) {
260 boolean found = false;
261 while (currentIndex > 0 && !found) {
262 if (target.durationFrom(eventDateList.get(currentIndex - 1).getDate()).getReal() < eventDateList.get(currentIndex).getDate().durationFrom(target).getReal()) {
263 currentIndex--;
264 } else {
265 found = true;
266 }
267 }
268 } else if (dt.getReal() > 0.0 && currentIndex < eventDateList.size() - 1) {
269 final int maxIndex = eventDateList.size() - 1;
270 boolean found = false;
271 while (currentIndex < maxIndex && !found) {
272 if (target.durationFrom(eventDateList.get(currentIndex + 1).getDate()).getReal() > eventDateList.get(currentIndex).getDate().durationFrom(target).getReal()) {
273 currentIndex++;
274 } else {
275 found = true;
276 }
277 }
278 }
279 return eventDateList.get(currentIndex);
280 }
281
282
283
284
285
286
287 private record FieldEventDate<T extends CalculusFieldElement<T>>(FieldAbsoluteDate<T> eventDate,
288 boolean gIncrease) implements FieldTimeStamped<T> {
289
290 @Override
291 public FieldAbsoluteDate<T> getDate() {
292 return eventDate;
293 }
294
295 }
296 }