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 org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.ode.events.Action;
22 import org.hipparchus.util.FastMath;
23 import org.junit.jupiter.api.Assertions;
24 import org.junit.jupiter.api.BeforeAll;
25 import org.junit.jupiter.api.Test;
26 import org.orekit.Utils;
27 import org.orekit.bodies.OneAxisEllipsoid;
28 import org.orekit.frames.Frame;
29 import org.orekit.frames.FramesFactory;
30 import org.orekit.orbits.FieldKeplerianOrbit;
31 import org.orekit.orbits.PositionAngleType;
32 import org.orekit.propagation.FieldPropagator;
33 import org.orekit.propagation.FieldSpacecraftState;
34 import org.orekit.propagation.SpacecraftState;
35 import org.orekit.propagation.events.handlers.EventHandler;
36 import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
37 import org.orekit.propagation.events.handlers.FieldEventHandler;
38 import org.orekit.propagation.events.handlers.FieldRecordAndContinue;
39 import org.orekit.propagation.events.handlers.FieldRecordAndContinue.Event;
40 import org.orekit.propagation.events.handlers.FieldStopOnEvent;
41 import org.orekit.propagation.sampling.FieldOrekitStepHandler;
42 import org.orekit.propagation.sampling.FieldOrekitStepInterpolator;
43 import org.orekit.time.AbsoluteDate;
44 import org.orekit.time.FieldAbsoluteDate;
45 import org.orekit.utils.Constants;
46
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.List;
50
51
52
53
54
55
56 public abstract class FieldCloseEventsAbstractTest<T extends CalculusFieldElement<T>>{
57
58 public static final double mu = Constants.EIGEN5C_EARTH_MU;
59 public static final Frame eci = FramesFactory.getGCRF();
60 public static final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS, Constants.WGS84_EARTH_FLATTENING, eci);
61
62 public final Field<T> field;
63 public final FieldAbsoluteDate<T> epoch;
64 public final FieldKeplerianOrbit<T> initialOrbit;
65
66 @BeforeAll
67 public static void setUpBefore() {
68 Utils.setDataRoot("regular-data");
69 }
70
71 public FieldCloseEventsAbstractTest(final Field<T> field) {
72 this.field = field;
73 this.epoch = new FieldAbsoluteDate<>(field, AbsoluteDate.J2000_EPOCH);
74 this.initialOrbit = new FieldKeplerianOrbit<>(
75 v(6378137 + 500e3), v(0), v(0), v(0), v(0), v(0), PositionAngleType.TRUE,
76 eci, epoch, v(mu));
77 }
78
79
80
81
82
83
84
85 public abstract FieldPropagator<T> getPropagator(double stepSize);
86
87 @Test
88 public void testCloseEventsFirstOneIsReset() {
89
90
91
92
93
94
95
96
97
98
99 FieldPropagator<T> propagator = getPropagator(10.0);
100
101 double t1 = 49, t2 = t1 + 1e-15, t3 = t1 + 4.9;
102 List<Event<T>> events = new ArrayList<>();
103 TimeDetector detector1 = new TimeDetector(t1)
104 .withHandler(new Handler<>(events, Action.RESET_DERIVATIVES))
105 .withMaxCheck(10)
106 .withThreshold(v(1e-9));
107 propagator.addEventDetector(detector1);
108 TimeDetector detector2 = new TimeDetector(t2, t3)
109 .withHandler(new FieldRecordAndContinue<>(events))
110 .withMaxCheck(11)
111 .withThreshold(v(1e-9));
112 propagator.addEventDetector(detector2);
113
114
115 propagator.propagate(epoch.shiftedBy(60));
116
117
118 Assertions.assertEquals(1, events.size());
119 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
120 Assertions.assertEquals(detector1, events.get(0).getDetector());
121 }
122
123 @Test
124 public void testCloseEvents() {
125
126 double tolerance = 1;
127 FieldPropagator<T> propagator = getPropagator(10);
128
129 FieldRecordAndContinue<T> handler = new FieldRecordAndContinue<>();
130 TimeDetector detector1 = new TimeDetector(5)
131 .withHandler(handler)
132 .withMaxCheck(10)
133 .withThreshold(v(tolerance));
134 propagator.addEventDetector(detector1);
135 TimeDetector detector2 = new TimeDetector(5.5)
136 .withHandler(handler)
137 .withMaxCheck(10)
138 .withThreshold(v(tolerance));
139 propagator.addEventDetector(detector2);
140
141
142 propagator.propagate(epoch.shiftedBy(20));
143
144
145 List<Event<T>> events = handler.getEvents();
146 Assertions.assertEquals(2, events.size());
147 Assertions.assertEquals(5, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
148 Assertions.assertEquals(detector1, events.get(0).getDetector());
149 Assertions.assertEquals(5.5, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
150 Assertions.assertEquals(detector2, events.get(1).getDetector());
151 }
152
153 @Test
154 public void testSimultaneousEvents() {
155
156 FieldPropagator<T> propagator = getPropagator(10);
157
158 FieldRecordAndContinue<T> handler1 = new FieldRecordAndContinue<>();
159 TimeDetector detector1 = new TimeDetector(5)
160 .withHandler(handler1)
161 .withMaxCheck(10)
162 .withThreshold(v(1));
163 propagator.addEventDetector(detector1);
164 FieldRecordAndContinue<T> handler2 = new FieldRecordAndContinue<>();
165 TimeDetector detector2 = new TimeDetector(5)
166 .withHandler(handler2)
167 .withMaxCheck(10)
168 .withThreshold(v(1));
169 propagator.addEventDetector(detector2);
170
171
172 propagator.propagate(epoch.shiftedBy(20));
173
174
175 List<Event<T>> events1 = handler1.getEvents();
176 Assertions.assertEquals(1, events1.size());
177 Assertions.assertEquals(5, events1.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
178 List<Event<T>> events2 = handler2.getEvents();
179 Assertions.assertEquals(1, events2.size());
180 Assertions.assertEquals(5, events2.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
181 }
182
183
184
185
186
187
188 @Test
189 public void testSimultaneousEventsReset() {
190
191 double tol = 1e-10;
192 FieldPropagator<T> propagator = getPropagator(10);
193 boolean[] firstEventOccurred = {false};
194 List<FieldRecordAndContinue.Event<T>> events = new ArrayList<>();
195
196 TimeDetector detector1 = new TimeDetector(5)
197 .withMaxCheck(10)
198 .withThreshold(v(tol))
199 .withHandler(new Handler<FieldEventDetector<T>>(events, Action.RESET_STATE) {
200 @Override
201 public Action eventOccurred(FieldSpacecraftState<T> s, FieldEventDetector<T> detector, boolean increasing) {
202 firstEventOccurred[0] = true;
203 return super.eventOccurred(s, detector, increasing);
204 }
205
206 @Override
207 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> oldState) {
208 return oldState;
209 }
210 });
211 propagator.addEventDetector(detector1);
212
213 FieldFunctionalDetector<T> detector2 = new FieldFunctionalDetector<>(field)
214 .withMaxCheck(1)
215 .withThreshold(v(tol))
216 .withHandler(new FieldRecordAndContinue<>(events))
217 .withFunction(state -> {
218 if (firstEventOccurred[0]) {
219 return new TimeDetector(1, 3, 5).g(state);
220 }
221 return new TimeDetector(5).g(state);
222 }
223 );
224 propagator.addEventDetector(detector2);
225
226
227 propagator.propagate(epoch.shiftedBy(20));
228
229
230
231 Assertions.assertEquals(5, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
232 Assertions.assertTrue(events.get(0).isIncreasing());
233 Assertions.assertEquals(detector1, events.get(0).getDetector());
234 Assertions.assertEquals(5, events.get(1).getState().getDate().durationFrom(epoch).getReal(), 0.0);
235 Assertions.assertTrue(events.get(1).isIncreasing());
236 Assertions.assertEquals(detector2, events.get(1).getDetector());
237 Assertions.assertEquals(2, events.size());
238 }
239
240
241
242
243
244
245
246 @Test
247 public void testSimultaneousDiscontinuousEventsAfterReset() {
248
249 double t = FastMath.PI;
250 double tol = 1e-10;
251 FieldPropagator<T> propagator = getPropagator(10);
252 List<FieldRecordAndContinue.Event<T>> events = new ArrayList<>();
253 FieldSpacecraftState<T> newState = new FieldSpacecraftState<>(new FieldKeplerianOrbit<>(
254 v(42e6), v(0), v(0), v(0), v(0), v(0), PositionAngleType.TRUE, eci, epoch.shiftedBy(t), v(mu)));
255
256 TimeDetector resetDetector = new TimeDetector(t)
257 .withHandler(new ResetHandler<>(events, newState))
258 .withMaxCheck(10)
259 .withThreshold(v(tol));
260 propagator.addEventDetector(resetDetector);
261 List<FieldEventDetector<T>> detectors = new ArrayList<>();
262 for (int i = 0; i < 2; i++) {
263 FieldFunctionalDetector<T> detector1 = new FieldFunctionalDetector<>(field)
264 .withFunction(s -> s.getA().subtract(10e6))
265 .withThreshold(v(tol))
266 .withMaxCheck(10)
267 .withHandler(new FieldRecordAndContinue<>(events));
268 propagator.addEventDetector(detector1);
269 detectors.add(detector1);
270 }
271
272
273 propagator.propagate(epoch.shiftedBy(10));
274
275
276 Assertions.assertEquals(t, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tol);
277 Assertions.assertTrue(events.get(0).isIncreasing());
278 Assertions.assertEquals(resetDetector, events.get(0).getDetector());
279
280 Assertions.assertEquals(t, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tol);
281 Assertions.assertTrue(events.get(1).isIncreasing());
282 Assertions.assertEquals(detectors.get(0), events.get(1).getDetector());
283 Assertions.assertEquals(t, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tol);
284 Assertions.assertTrue(events.get(2).isIncreasing());
285 Assertions.assertEquals(detectors.get(1), events.get(2).getDetector());
286 Assertions.assertEquals(events.size(), 3);
287 }
288
289
290
291
292
293
294 @Test
295 public void testFastSwitching() {
296
297
298 FieldPropagator<T> propagator = getPropagator(10);
299
300 FieldRecordAndContinue<T> handler = new FieldRecordAndContinue<>();
301 TimeDetector detector1 = new TimeDetector(9.9, 10.1, 12)
302 .withHandler(handler)
303 .withMaxCheck(10)
304 .withThreshold(v(0.2));
305 propagator.addEventDetector(detector1);
306
307
308 propagator.propagate(epoch.shiftedBy(20));
309
310
311
312 List<Event<T>> events1 = handler.getEvents();
313 Assertions.assertEquals(1, events1.size());
314 Assertions.assertEquals(9.9, events1.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.1);
315 Assertions.assertEquals(true, events1.get(0).isIncreasing());
316 }
317
318
319 @Test
320 public void testTrickyCaseLower() {
321
322 double maxCheck = 10;
323 double tolerance = 1e-6;
324 double t1 = 1.0, t2 = 15, t3 = 16, t4 = 17, t5 = 18;
325
326 List<Event<T>> events = new ArrayList<>();
327 TimeDetector detectorA = new TimeDetector(t3)
328 .withHandler(new FieldRecordAndContinue<>(events))
329 .withMaxCheck(maxCheck)
330 .withThreshold(v(tolerance));
331 TimeDetector detectorB = new TimeDetector(-10, t1, t2, t5)
332 .withHandler(new FieldRecordAndContinue<>(events))
333 .withMaxCheck(maxCheck)
334 .withThreshold(v(tolerance));
335 TimeDetector detectorC = new TimeDetector(t4)
336 .withHandler(new Handler<>(events, Action.RESET_DERIVATIVES))
337 .withMaxCheck(maxCheck)
338 .withThreshold(v(tolerance));
339
340 FieldPropagator<T> propagator = getPropagator(10);
341 propagator.addEventDetector(detectorA);
342 propagator.addEventDetector(detectorB);
343 propagator.addEventDetector(detectorC);
344
345
346 propagator.propagate(epoch.shiftedBy(30));
347
348
349
350
351 Assertions.assertEquals(5, events.size());
352 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
353 Assertions.assertEquals(false, events.get(0).isIncreasing());
354 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
355 Assertions.assertEquals(true, events.get(1).isIncreasing());
356 Assertions.assertEquals(t3, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
357 Assertions.assertEquals(true, events.get(2).isIncreasing());
358 Assertions.assertEquals(t4, events.get(3).getState().getDate().durationFrom(epoch).getReal(), tolerance);
359 Assertions.assertEquals(true, events.get(3).isIncreasing());
360 Assertions.assertEquals(t5, events.get(4).getState().getDate().durationFrom(epoch).getReal(), tolerance);
361 Assertions.assertEquals(false, events.get(4).isIncreasing());
362 }
363
364
365
366
367
368
369 @Test
370 public void testRootFindingTolerance() {
371
372 double maxCheck = 10;
373 double t2 = 11, t3 = t2 + 1e-5;
374 List<Event<T>> events = new ArrayList<>();
375 TimeDetector detectorA = new TimeDetector(t2)
376 .withHandler(new FieldRecordAndContinue<>(events))
377 .withMaxCheck(maxCheck)
378 .withThreshold(v(1e-6));
379 FlatDetector detectorB = new FlatDetector(t3)
380 .withHandler(new FieldRecordAndContinue<>(events))
381 .withMaxCheck(maxCheck)
382 .withThreshold(v(0.5));
383 FieldPropagator<T> propagator = getPropagator(10);
384 propagator.addEventDetector(detectorA);
385 propagator.addEventDetector(detectorB);
386
387
388 propagator.propagate(epoch.shiftedBy(30));
389
390
391
392
393 Assertions.assertSame(detectorB, events.get(0).getDetector());
394 Assertions.assertSame(detectorA, events.get(1).getDetector());
395 Assertions.assertTrue(events.get(0).getState().getDate().compareTo(
396 events.get(1).getState().getDate()) < 0);
397
398
399 Assertions.assertEquals(2, events.size());
400 Assertions.assertEquals(t3, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.5);
401 Assertions.assertEquals(true, events.get(0).isIncreasing());
402 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), 1e-6);
403 Assertions.assertEquals(true, events.get(1).isIncreasing());
404 }
405
406
407 @Test
408 public void testRootPlusToleranceHasWrongSign() {
409
410 double maxCheck = 10;
411 double tolerance = 1e-6;
412 final double toleranceB = 0.3;
413 double t1 = 11, t2 = 11.1, t3 = 11.2;
414
415 List<Event<T>> events = new ArrayList<>();
416 TimeDetector detectorA = new TimeDetector(t2)
417 .withHandler(new FieldRecordAndContinue<>(events))
418 .withMaxCheck(maxCheck)
419 .withThreshold(v(1e-6));
420 TimeDetector detectorB = new TimeDetector(t1, t3)
421 .withHandler(new FieldRecordAndContinue<>(events))
422 .withMaxCheck(maxCheck)
423 .withThreshold(v(toleranceB));
424 FieldPropagator<T> propagator = getPropagator(10);
425 propagator.addEventDetector(detectorA);
426 propagator.addEventDetector(detectorB);
427
428
429 propagator.propagate(epoch.shiftedBy(30));
430
431
432
433 Assertions.assertEquals(3, events.size());
434 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), toleranceB);
435 Assertions.assertEquals(true, events.get(0).isIncreasing());
436 Assertions.assertSame(detectorB, events.get(0).getDetector());
437
438 try {
439 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
440 Assertions.assertEquals(true, events.get(1).isIncreasing());
441 Assertions.assertSame(detectorA, events.get(1).getDetector());
442 Assertions.assertEquals(t3, events.get(2).getState().getDate().durationFrom(epoch).getReal(), toleranceB);
443 Assertions.assertEquals(false, events.get(2).isIncreasing());
444 Assertions.assertSame(detectorB, events.get(2).getDetector());
445 } catch (AssertionError e) {
446 Assertions.assertEquals(t3, events.get(1).getState().getDate().durationFrom(epoch).getReal(), toleranceB);
447 Assertions.assertEquals(false, events.get(1).isIncreasing());
448 Assertions.assertSame(detectorB, events.get(1).getDetector());
449 Assertions.assertEquals(t2, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
450 Assertions.assertEquals(true, events.get(2).isIncreasing());
451 Assertions.assertSame(detectorA, events.get(2).getDetector());
452 }
453
454 for (int i = 1; i < events.size(); i++) {
455 Assertions.assertTrue(events.get(i).getState().getDate().compareTo(
456 events.get(i - 1).getState().getDate()) >= 0);
457 }
458 }
459
460
461 @Test
462 public void testRootPlusToleranceHasWrongSignAndLessThanTb() {
463
464
465 double maxCheck = 10;
466 double tolerance = 0.5;
467 double t1 = 11, t2 = 11.4, t3 = 12.0;
468
469 List<Event<T>> events = new ArrayList<>();
470 FlatDetector detectorB = new FlatDetector(t1, t2, t3)
471 .withHandler(new FieldRecordAndContinue<>(events))
472 .withMaxCheck(maxCheck)
473 .withThreshold(v(tolerance));
474 FieldPropagator<T> propagator = getPropagator(10);
475 propagator.addEventDetector(detectorB);
476
477
478 propagator.propagate(epoch.shiftedBy(30));
479
480
481
482 Assertions.assertEquals(1, events.size());
483 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
484 Assertions.assertEquals(true, events.get(0).isIncreasing());
485 Assertions.assertSame(detectorB, events.get(0).getDetector());
486 }
487
488
489
490
491
492 @Test
493 public void testDoubleRoot() {
494
495 double maxCheck = 10;
496 double tolerance = 1e-6;
497 double t1 = 11;
498
499 List<Event<T>> events = new ArrayList<>();
500 TimeDetector detectorA = new TimeDetector(t1)
501 .withHandler(new FieldRecordAndContinue<>(events))
502 .withMaxCheck(maxCheck)
503 .withThreshold(v(tolerance));
504 TimeDetector detectorB = new TimeDetector(t1, t1)
505 .withHandler(new FieldRecordAndContinue<>(events))
506 .withMaxCheck(maxCheck)
507 .withThreshold(v(tolerance));
508 FieldPropagator<T> propagator = getPropagator(10);
509 propagator.addEventDetector(detectorA);
510 propagator.addEventDetector(detectorB);
511
512
513 propagator.propagate(epoch.shiftedBy(30));
514
515
516 Assertions.assertEquals(1, events.size());
517 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
518 Assertions.assertEquals(true, events.get(0).isIncreasing());
519 Assertions.assertSame(detectorA, events.get(0).getDetector());
520
521 Assertions.assertTrue(detectorB.g(state(t1)).getReal() == 0.0);
522 Assertions.assertTrue(detectorB.g(state(t1 - 1e-6)).getReal() < 0);
523 Assertions.assertTrue(detectorB.g(state(t1 + 1e-6)).getReal() < 0);
524 }
525
526
527
528
529
530 @Test
531 public void testDoubleRootOppositeSign() {
532
533 double maxCheck = 10;
534 double tolerance = 1e-6;
535 double t1 = 11;
536
537 List<Event<T>> events = new ArrayList<>();
538 TimeDetector detectorA = new TimeDetector(t1)
539 .withHandler(new FieldRecordAndContinue<>(events))
540 .withMaxCheck(maxCheck)
541 .withThreshold(v(tolerance));
542 ContinuousDetector detectorB = new ContinuousDetector(-20, t1, t1)
543 .withHandler(new FieldRecordAndContinue<>(events))
544 .withMaxCheck(maxCheck)
545 .withThreshold(v(tolerance));
546 FieldPropagator<T> propagator = getPropagator(10);
547 propagator.addEventDetector(detectorA);
548 propagator.addEventDetector(detectorB);
549
550
551 propagator.propagate(epoch.shiftedBy(30));
552
553
554 Assertions.assertEquals(1, events.size());
555 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
556 Assertions.assertEquals(true, events.get(0).isIncreasing());
557 Assertions.assertSame(detectorA, events.get(0).getDetector());
558
559 Assertions.assertEquals(0.0, detectorB.g(state(t1)).getReal(), 0.0);
560 Assertions.assertTrue(detectorB.g(state(t1 - 1e-6)).getReal() > 0);
561 Assertions.assertTrue(detectorB.g(state(t1 + 1e-6)).getReal() > 0);
562 }
563
564
565 @Test
566 public void testZeroAtBeginningAndEndOfInterval() {
567
568 double maxCheck = 10;
569 double tolerance = 1e-6;
570 double t1 = 10, t2 = 20;
571
572 List<Event<T>> events = new ArrayList<>();
573 ContinuousDetector detectorA = new ContinuousDetector(t1, t2)
574 .withHandler(new FieldRecordAndContinue<>(events))
575 .withMaxCheck(maxCheck)
576 .withThreshold(v(tolerance));
577 FieldPropagator<T> propagator = getPropagator(10);
578 propagator.addEventDetector(detectorA);
579
580 propagator.propagate(epoch.shiftedBy(30));
581
582
583 Assertions.assertEquals(2, events.size());
584 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
585 Assertions.assertEquals(true, events.get(0).isIncreasing());
586 Assertions.assertSame(detectorA, events.get(0).getDetector());
587 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
588 Assertions.assertEquals(false, events.get(1).isIncreasing());
589 Assertions.assertSame(detectorA, events.get(1).getDetector());
590 }
591
592
593 @Test
594 public void testZeroAtBeginningAndEndOfIntervalOppositeSign() {
595
596 double maxCheck = 10;
597 double tolerance = 1e-6;
598 double t1 = 10, t2 = 20;
599
600 List<Event<T>> events = new ArrayList<>();
601 ContinuousDetector detectorA = new ContinuousDetector(-10, t1, t2)
602 .withHandler(new FieldRecordAndContinue<>(events))
603 .withMaxCheck(maxCheck)
604 .withThreshold(v(tolerance));
605 FieldPropagator<T> propagator = getPropagator(10);
606 propagator.addEventDetector(detectorA);
607
608
609 propagator.propagate(epoch.shiftedBy(30));
610
611
612 Assertions.assertEquals(2, events.size());
613 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
614 Assertions.assertEquals(false, events.get(0).isIncreasing());
615 Assertions.assertSame(detectorA, events.get(0).getDetector());
616 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
617 Assertions.assertEquals(true, events.get(1).isIncreasing());
618 Assertions.assertSame(detectorA, events.get(1).getDetector());
619 }
620
621
622 @Test
623 public void testMultipleBackups() {
624
625 double maxCheck = 10;
626 double tolerance = 1e-6;
627 double t1 = 1.0, t2 = 2, t3 = 3, t4 = 4, t5 = 5, t6 = 6.5, t7 = 7;
628
629 List<Event<T>> events = new ArrayList<>();
630 ContinuousDetector detectorA = new ContinuousDetector(t6)
631 .withHandler(new FieldRecordAndContinue<>(events))
632 .withMaxCheck(maxCheck)
633 .withThreshold(v(tolerance));
634 FlatDetector detectorB = new FlatDetector(t1, t3, t4, t7)
635 .withHandler(new FieldRecordAndContinue<>(events))
636 .withMaxCheck(maxCheck)
637 .withThreshold(v(tolerance));
638 ContinuousDetector detectorC = new ContinuousDetector(t2, t5)
639 .withHandler(new FieldRecordAndContinue<>(events))
640 .withMaxCheck(maxCheck)
641 .withThreshold(v(tolerance));
642
643 FieldPropagator<T> propagator = getPropagator(10);
644 propagator.addEventDetector(detectorA);
645 propagator.addEventDetector(detectorB);
646 propagator.addEventDetector(detectorC);
647
648
649 propagator.propagate(epoch.shiftedBy(30));
650
651
652
653 Assertions.assertEquals(5, events.size());
654 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
655 Assertions.assertEquals(true, events.get(0).isIncreasing());
656 Assertions.assertEquals(detectorB, events.get(0).getDetector());
657 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
658 Assertions.assertEquals(true, events.get(1).isIncreasing());
659 Assertions.assertEquals(detectorC, events.get(1).getDetector());
660
661
662
663
664
665
666
667
668
669
670 Assertions.assertEquals(t5, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
671 Assertions.assertEquals(false, events.get(2).isIncreasing());
672 Assertions.assertEquals(detectorC, events.get(2).getDetector());
673 Assertions.assertEquals(t6, events.get(3).getState().getDate().durationFrom(epoch).getReal(), tolerance);
674 Assertions.assertEquals(true, events.get(3).isIncreasing());
675 Assertions.assertEquals(detectorA, events.get(3).getDetector());
676 Assertions.assertEquals(t7, events.get(4).getState().getDate().durationFrom(epoch).getReal(), tolerance);
677 Assertions.assertEquals(false, events.get(4).isIncreasing());
678 Assertions.assertEquals(detectorB, events.get(4).getDetector());
679 }
680
681
682 @Test
683 public void testEventCausedByStateReset() {
684
685 double maxCheck = 10;
686 double tolerance = 1e-6;
687 double t1 = 15.0;
688 FieldSpacecraftState<T> newState = new FieldSpacecraftState<>(new FieldKeplerianOrbit<>(
689 v(6378137 + 500e3), v(0), v(FastMath.PI / 2), v(0), v(0),
690 v(FastMath.PI / 2), PositionAngleType.TRUE, eci, epoch.shiftedBy(t1), v(mu)));
691
692 List<Event<T>> events = new ArrayList<>();
693 TimeDetector detectorA = new TimeDetector(t1)
694 .withHandler(new Handler<FieldEventDetector<T>>(events, Action.RESET_STATE) {
695 @Override
696 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector,
697 FieldSpacecraftState<T> oldState) {
698 return newState;
699 }
700 })
701 .withMaxCheck(maxCheck)
702 .withThreshold(v(tolerance));
703 FieldLatitudeCrossingDetector<T> detectorB =
704 new FieldLatitudeCrossingDetector<T>(field, earth, FastMath.toRadians(80))
705 .withHandler(new FieldRecordAndContinue<>(events))
706 .withMaxCheck(maxCheck)
707 .withThreshold(v(tolerance));
708
709 FieldPropagator<T> propagator = getPropagator(10);
710 propagator.addEventDetector(detectorA);
711 propagator.addEventDetector(detectorB);
712
713
714 propagator.propagate(epoch.shiftedBy(40.0));
715
716
717
718 Assertions.assertEquals(2, events.size());
719 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
720 Assertions.assertEquals(true, events.get(0).isIncreasing());
721 Assertions.assertEquals(detectorA, events.get(0).getDetector());
722 Assertions.assertEquals(t1, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
723 Assertions.assertEquals(true, events.get(1).isIncreasing());
724 Assertions.assertEquals(detectorB, events.get(1).getDetector());
725 }
726
727
728 @Test
729 public void testConvergenceTooTight() {
730
731 double maxCheck = 10;
732 double tolerance = 1e-18;
733 double t1 = 15;
734
735 List<Event<T>> events = new ArrayList<>();
736 ContinuousDetector detectorA = new ContinuousDetector(t1)
737 .withHandler(new FieldRecordAndContinue<>(events))
738 .withMaxCheck(maxCheck)
739 .withThreshold(v(tolerance));
740 FieldPropagator<T> propagator = getPropagator(10);
741 propagator.addEventDetector(detectorA);
742
743
744 propagator.propagate(epoch.shiftedBy(30));
745
746
747 Assertions.assertEquals(1, events.size());
748 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
749 Assertions.assertEquals(true, events.get(0).isIncreasing());
750 Assertions.assertSame(detectorA, events.get(0).getDetector());
751 }
752
753
754
755
756
757
758
759 @Test
760 public void testEventChangesGFunctionDefinition() {
761
762 double maxCheck = 5;
763 double tolerance = 1e-6;
764 double t1 = 11, t2 = 19;
765
766 List<Event<T>> events = new ArrayList<>();
767
768 boolean[] swap = new boolean[1];
769 final ContinuousDetector detectorA = new ContinuousDetector(t1)
770 .withMaxCheck(maxCheck)
771 .withThreshold(v(tolerance))
772 .withHandler(new FieldRecordAndContinue<T>(events) {
773 @Override
774 public Action eventOccurred(FieldSpacecraftState<T> s,
775 FieldEventDetector<T> detector,
776 boolean increasing) {
777 swap[0] = true;
778 return super.eventOccurred(s, detector, increasing);
779 }
780 });
781 ContinuousDetector detectorB = new ContinuousDetector(t2);
782 FieldEventDetector<T> detectorC = new Definition(maxCheck, tolerance, swap, detectorB, detectorB, events);
783 FieldPropagator<T> propagator = getPropagator(10);
784 propagator.addEventDetector(detectorA);
785 propagator.addEventDetector(detectorC);
786
787
788 propagator.propagate(epoch.shiftedBy(30));
789
790
791 Assertions.assertEquals(2, events.size());
792 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
793 Assertions.assertEquals(true, events.get(0).isIncreasing());
794 Assertions.assertSame(detectorA, events.get(0).getDetector());
795 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
796 Assertions.assertEquals(true, events.get(1).isIncreasing());
797 Assertions.assertSame(detectorC, events.get(1).getDetector());
798 }
799
800
801
802
803
804
805 @Test
806 public void testEventChangesGFunctionDefinitionCancel() {
807
808 double maxCheck = 5;
809 double tolerance = 1e-6;
810 double t1 = 11, t2 = 11.1;
811
812 List<Event<T>> events = new ArrayList<>();
813
814 boolean[] swap = new boolean[1];
815 final ContinuousDetector detectorA = new ContinuousDetector(t1)
816 .withMaxCheck(maxCheck)
817 .withThreshold(v(tolerance))
818 .withHandler(new FieldRecordAndContinue<T>(events) {
819 @Override
820 public Action eventOccurred(FieldSpacecraftState<T> state,
821 FieldEventDetector<T> detector,
822 boolean increasing) {
823 swap[0] = true;
824 super.eventOccurred(state, detector, increasing);
825 return Action.RESET_EVENTS;
826 }
827 });
828 final ContinuousDetector detectorB = new ContinuousDetector(t2);
829 FieldEventDetector<T> detectorC = new Cancel(maxCheck, tolerance, swap, detectorB, detectorB, events);
830 FieldPropagator<T> propagator = getPropagator(10);
831 propagator.addEventDetector(detectorA);
832 propagator.addEventDetector(detectorC);
833
834
835 propagator.propagate(epoch.shiftedBy(30));
836
837
838 Assertions.assertEquals(1, events.size());
839 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
840 Assertions.assertEquals(true, events.get(0).isIncreasing());
841 Assertions.assertSame(detectorA, events.get(0).getDetector());
842 }
843
844
845
846
847
848
849 @Test
850 public void testEventChangesGFunctionDefinitionDelay() {
851
852 double maxCheck = 5;
853 double tolerance = 1e-6;
854 double t1 = 11, t2 = 11.1, t3 = 11.2;
855
856 List<Event<T>> events = new ArrayList<>();
857
858 boolean[] swap = new boolean[1];
859 final ContinuousDetector detectorA = new ContinuousDetector(t1)
860 .withMaxCheck(maxCheck)
861 .withThreshold(v(tolerance))
862 .withHandler(new FieldRecordAndContinue<T>(events) {
863 @Override
864 public Action eventOccurred(FieldSpacecraftState<T> state,
865 FieldEventDetector<T> detector,
866 boolean increasing) {
867 swap[0] = true;
868 super.eventOccurred(state, detector, increasing);
869 return Action.RESET_EVENTS;
870 }
871 });
872 final ContinuousDetector detectorB = new ContinuousDetector(t2);
873 final ContinuousDetector detectorD = new ContinuousDetector(t3);
874 FieldEventDetector<T> detectorC = new Delay(maxCheck, tolerance, swap, detectorB, detectorD, events);
875 FieldPropagator<T> propagator = getPropagator(10);
876 propagator.addEventDetector(detectorA);
877 propagator.addEventDetector(detectorC);
878
879
880 propagator.propagate(epoch.shiftedBy(30));
881
882
883 Assertions.assertEquals(2, events.size());
884 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
885 Assertions.assertEquals(true, events.get(0).isIncreasing());
886 Assertions.assertSame(detectorA, events.get(0).getDetector());
887 Assertions.assertEquals(t3, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
888 Assertions.assertEquals(true, events.get(1).isIncreasing());
889 Assertions.assertSame(detectorC, events.get(1).getDetector());
890 }
891
892
893
894
895
896
897 @Test
898 public void testEventChangesGFunctionDefinitionAccelerate() {
899
900 double maxCheck = 5;
901 double tolerance = 1e-6;
902 double t1 = 11, t2 = 11.1, t3 = 11.2;
903
904 List<Event<T>> events = new ArrayList<>();
905
906 boolean[] swap = new boolean[1];
907 final ContinuousDetector detectorA = new ContinuousDetector(t1)
908 .withMaxCheck(maxCheck)
909 .withThreshold(v(tolerance))
910 .withHandler(new FieldRecordAndContinue<T>(events) {
911 @Override
912 public Action eventOccurred(FieldSpacecraftState<T> state,
913 FieldEventDetector<T> detector,
914 boolean increasing) {
915 swap[0] = true;
916 super.eventOccurred(state, detector, increasing);
917 return Action.RESET_EVENTS;
918 }
919 });
920 final ContinuousDetector detectorB = new ContinuousDetector(t2);
921 final ContinuousDetector detectorD = new ContinuousDetector(t3);
922 FieldEventDetector<T> detectorC = new Accelerate(maxCheck, tolerance, swap, detectorB, detectorD, events);
923 FieldPropagator<T> propagator = getPropagator(10);
924 propagator.addEventDetector(detectorA);
925 propagator.addEventDetector(detectorC);
926
927
928 propagator.propagate(epoch.shiftedBy(30));
929
930
931 Assertions.assertEquals(2, events.size());
932 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
933 Assertions.assertEquals(true, events.get(0).isIncreasing());
934 Assertions.assertSame(detectorA, events.get(0).getDetector());
935 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
936 Assertions.assertEquals(true, events.get(1).isIncreasing());
937 Assertions.assertSame(detectorC, events.get(1).getDetector());
938 }
939
940
941 @Test
942 public void testToleranceStop() {
943
944 double maxCheck = 10;
945 double tolerance = 1e-18;
946 double t1 = 15.1;
947
948 List<Event<T>> events = new ArrayList<>();
949 FlatDetector detectorA = new FlatDetector(t1)
950 .withHandler(new Handler<>(events, Action.STOP))
951 .withMaxCheck(maxCheck)
952 .withThreshold(v(tolerance));
953 FieldPropagator<T> propagator = getPropagator(10);
954 propagator.addEventDetector(detectorA);
955
956
957 FieldSpacecraftState<T> finalState = propagator.propagate(epoch.shiftedBy(30));
958
959
960 Assertions.assertEquals(1, events.size());
961
962 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
963 Assertions.assertEquals(true, events.get(0).isIncreasing());
964 Assertions.assertSame(detectorA, events.get(0).getDetector());
965 Assertions.assertEquals(t1, finalState.getDate().durationFrom(epoch).getReal(), tolerance);
966
967
968 finalState = propagator.propagate(epoch.shiftedBy(30));
969
970
971 Assertions.assertEquals(30.0, finalState.getDate().durationFrom(epoch).getReal(), 0.0);
972 }
973
974
975
976
977
978
979 @Test
980 public void testShortBracketingInterval() {
981
982 double maxCheck = 10;
983 double tolerance = 1e-6;
984 final double t1 = FastMath.nextUp(10.0), t2 = 10.5;
985
986 List<Event<T>> events = new ArrayList<>();
987
988 FieldEventDetector<T> detectorA = new ShortInfDetector(maxCheck, tolerance, t1, t2, events);
989 TimeDetector detectorB = new TimeDetector(t1)
990 .withHandler(new FieldRecordAndContinue<>(events))
991 .withMaxCheck(maxCheck)
992 .withThreshold(v(tolerance));
993 FieldPropagator<T> propagator = getPropagator(10);
994 propagator.addEventDetector(detectorA);
995 propagator.addEventDetector(detectorB);
996
997
998 propagator.propagate(epoch.shiftedBy(30.0));
999
1000
1001 Assertions.assertEquals(3, events.size());
1002 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1003 Assertions.assertEquals(true, events.get(0).isIncreasing());
1004 Assertions.assertSame(detectorA, events.get(0).getDetector());
1005 Assertions.assertEquals(t1, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1006 Assertions.assertEquals(true, events.get(1).isIncreasing());
1007 Assertions.assertSame(detectorB, events.get(1).getDetector());
1008 Assertions.assertEquals(t2, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1009 Assertions.assertEquals(false, events.get(2).isIncreasing());
1010 Assertions.assertSame(detectorA, events.get(2).getDetector());
1011 }
1012
1013
1014 @Test
1015 public void testToleranceMaxIterations() {
1016
1017 double maxCheck = 10;
1018 double tolerance = 1e-18;
1019 FieldAbsoluteDate<T> t1 = epoch.shiftedBy(15).shiftedBy(FastMath.ulp(15.0) / 8);
1020
1021 List<Event<T>> events = new ArrayList<>();
1022 FlatDetector detectorA = new FlatDetector(t1)
1023 .withHandler(new FieldRecordAndContinue<>(events))
1024 .withMaxCheck(maxCheck)
1025 .withThreshold(v(tolerance));
1026 FieldPropagator<T> propagator = getPropagator(10);
1027 propagator.addEventDetector(detectorA);
1028
1029
1030 propagator.propagate(epoch.shiftedBy(30));
1031
1032
1033 Assertions.assertEquals(1, events.size());
1034
1035 Assertions.assertEquals(t1.durationFrom(epoch).getReal(),
1036 events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1037 Assertions.assertEquals(true, events.get(0).isIncreasing());
1038 Assertions.assertSame(detectorA, events.get(0).getDetector());
1039 }
1040
1041
1042 @Test
1043 public void testEventStepHandler() {
1044
1045 double tolerance = 1e-18;
1046 FieldPropagator<T> propagator = getPropagator(10);
1047 propagator.addEventDetector(new TimeDetector(5)
1048 .withHandler(new Handler<>(Action.CONTINUE))
1049 .withThreshold(v(tolerance)));
1050 StepHandler<T> stepHandler = new StepHandler<>();
1051 propagator.setStepHandler(stepHandler);
1052
1053
1054 FieldSpacecraftState<T> finalState = propagator.propagate(epoch.shiftedBy(10));
1055
1056
1057 Assertions.assertEquals(10.0, finalState.getDate().durationFrom(epoch).getReal(), tolerance);
1058 Assertions.assertEquals(0.0,
1059 stepHandler.initialState.getDate().durationFrom(epoch).getReal(), tolerance);
1060 Assertions.assertEquals(10.0, stepHandler.targetDate.durationFrom(epoch).getReal(), tolerance);
1061 Assertions.assertEquals(10.0,
1062 stepHandler.finalState.getDate().durationFrom(epoch).getReal(), tolerance);
1063 FieldOrekitStepInterpolator<T> interpolator = stepHandler.interpolators.get(0);
1064 Assertions.assertEquals(0.0,
1065 interpolator.getPreviousState().getDate().durationFrom(epoch).getReal(), tolerance);
1066 Assertions.assertEquals(5.0,
1067 interpolator.getCurrentState().getDate().durationFrom(epoch).getReal(), tolerance);
1068 interpolator = stepHandler.interpolators.get(1);
1069 Assertions.assertEquals(5.0,
1070 interpolator.getPreviousState().getDate().durationFrom(epoch).getReal(), tolerance);
1071 Assertions.assertEquals(10.0,
1072 interpolator.getCurrentState().getDate().durationFrom(epoch).getReal(), tolerance);
1073 Assertions.assertEquals(2, stepHandler.interpolators.size());
1074 }
1075
1076
1077
1078
1079
1080 @Test
1081 public void testEventCausedByDerivativesReset() {
1082
1083 TimeDetector detectorA = new TimeDetector(15.0)
1084 .withHandler(new Handler<TimeDetector>(Action.RESET_STATE){
1085 @Override
1086 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> d,
1087 FieldSpacecraftState<T> s) {
1088 return null;
1089 }
1090 })
1091 .withMaxCheck(10)
1092 .withThreshold(v(1e-6));
1093 FieldPropagator<T> propagator = getPropagator(10);
1094 propagator.addEventDetector(detectorA);
1095
1096 try {
1097
1098 propagator.propagate(epoch.shiftedBy(20.0));
1099 Assertions.fail("Expected Exception");
1100 } catch (NullPointerException e) {
1101
1102 }
1103 }
1104
1105
1106
1107
1108
1109
1110
1111 @Test
1112 public void testCloseEventsFirstOneIsResetReverse() {
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123 FieldPropagator<T> propagator = getPropagator(10.0);
1124
1125
1126 double t1 = -1;
1127 Handler<FieldEventDetector<T>> handler1 = new Handler<>(Action.RESET_DERIVATIVES);
1128 TimeDetector detector1 = new TimeDetector(t1)
1129 .withHandler(handler1)
1130 .withMaxCheck(10)
1131 .withThreshold(v(1e-9));
1132 propagator.addEventDetector(detector1);
1133 FieldRecordAndContinue<T> handler2 = new FieldRecordAndContinue<>();
1134 TimeDetector detector2 = new TimeDetector(t1 - 1e-15, t1 - 4.9)
1135 .withHandler(handler2)
1136 .withMaxCheck(11)
1137 .withThreshold(v(1e-9));
1138 propagator.addEventDetector(detector2);
1139
1140
1141 propagator.propagate(epoch.shiftedBy(-20));
1142
1143
1144 List<Event<T>> events1 = handler1.getEvents();
1145 Assertions.assertEquals(1, events1.size());
1146 Assertions.assertEquals(t1, events1.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1147 List<Event<T>> events2 = handler2.getEvents();
1148 Assertions.assertEquals(0, events2.size());
1149 }
1150
1151 @Test
1152 public void testCloseEventsReverse() {
1153
1154 double tolerance = 1;
1155 FieldPropagator<T> propagator = getPropagator(10);
1156
1157 FieldRecordAndContinue<T> handler1 = new FieldRecordAndContinue<>();
1158 TimeDetector detector1 = new TimeDetector(-5)
1159 .withHandler(handler1)
1160 .withMaxCheck(10)
1161 .withThreshold(v(tolerance));
1162 propagator.addEventDetector(detector1);
1163 FieldRecordAndContinue<T> handler2 = new FieldRecordAndContinue<>();
1164 TimeDetector detector2 = new TimeDetector(-5.5)
1165 .withHandler(handler2)
1166 .withMaxCheck(10)
1167 .withThreshold(v(tolerance));
1168 propagator.addEventDetector(detector2);
1169
1170
1171 propagator.propagate(epoch.shiftedBy(-20));
1172
1173
1174 List<Event<T>> events1 = handler1.getEvents();
1175 Assertions.assertEquals(1, events1.size());
1176 Assertions.assertEquals(-5, events1.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1177 List<Event<T>> events2 = handler2.getEvents();
1178 Assertions.assertEquals(1, events2.size());
1179 Assertions.assertEquals(-5.5, events2.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1180 }
1181
1182 @Test
1183 public void testSimultaneousEventsReverse() {
1184
1185 FieldPropagator<T> propagator = getPropagator(10);
1186
1187 FieldRecordAndContinue<T> handler1 = new FieldRecordAndContinue<>();
1188 TimeDetector detector1 = new TimeDetector(-5)
1189 .withHandler(handler1)
1190 .withMaxCheck(10)
1191 .withThreshold(v(1));
1192 propagator.addEventDetector(detector1);
1193 FieldRecordAndContinue<T> handler2 = new FieldRecordAndContinue<>();
1194 TimeDetector detector2 = new TimeDetector(-5)
1195 .withHandler(handler2)
1196 .withMaxCheck(10)
1197 .withThreshold(v(1));
1198 propagator.addEventDetector(detector2);
1199
1200
1201 propagator.propagate(epoch.shiftedBy(-20));
1202
1203
1204 List<Event<T>> events1 = handler1.getEvents();
1205 Assertions.assertEquals(1, events1.size());
1206 Assertions.assertEquals(-5, events1.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1207 List<Event<T>> events2 = handler2.getEvents();
1208 Assertions.assertEquals(1, events2.size());
1209 Assertions.assertEquals(-5, events2.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1210 }
1211
1212
1213
1214
1215
1216
1217 @Test
1218 public void testSimultaneousEventsResetReverse() {
1219
1220 double tol = 1e-10;
1221 FieldPropagator<T> propagator = getPropagator(10);
1222 boolean[] firstEventOccurred = {false};
1223 List<FieldRecordAndContinue.Event<T>> events = new ArrayList<>();
1224
1225 TimeDetector detector1 = new TimeDetector(-5)
1226 .withMaxCheck(10)
1227 .withThreshold(v(tol))
1228 .withHandler(new Handler<FieldEventDetector<T>>(events, Action.RESET_STATE) {
1229 @Override
1230 public Action eventOccurred(FieldSpacecraftState<T> s, FieldEventDetector<T> detector, boolean increasing) {
1231 firstEventOccurred[0] = true;
1232 return super.eventOccurred(s, detector, increasing);
1233 }
1234
1235 @Override
1236 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> oldState) {
1237 return oldState;
1238 }
1239 });
1240 propagator.addEventDetector(detector1);
1241
1242 FieldFunctionalDetector<T> detector2 = new FieldFunctionalDetector<>(field)
1243 .withMaxCheck(1)
1244 .withThreshold(v(tol))
1245 .withHandler(new FieldRecordAndContinue<>(events))
1246 .withFunction(state -> {
1247 if (firstEventOccurred[0]) {
1248 return new TimeDetector(-1, -3, -5).g(state);
1249 }
1250 return new TimeDetector(-5).g(state);
1251 }
1252 );
1253 propagator.addEventDetector(detector2);
1254
1255
1256 propagator.propagate(epoch.shiftedBy(-20));
1257
1258
1259
1260 Assertions.assertEquals(-5, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1261 Assertions.assertTrue(events.get(0).isIncreasing());
1262 Assertions.assertEquals(detector1, events.get(0).getDetector());
1263 Assertions.assertEquals(-5, events.get(1).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1264 Assertions.assertTrue(events.get(1).isIncreasing());
1265 Assertions.assertEquals(detector2, events.get(1).getDetector());
1266 Assertions.assertEquals(2, events.size());
1267 }
1268
1269
1270
1271
1272
1273
1274
1275 @Test
1276 public void testSimultaneousDiscontinuousEventsAfterResetReverse() {
1277
1278 double t = -FastMath.PI;
1279 double tol = 1e-10;
1280 FieldPropagator<T> propagator = getPropagator(10);
1281 List<FieldRecordAndContinue.Event<T>> events = new ArrayList<>();
1282 FieldSpacecraftState<T> newState = new FieldSpacecraftState<>(new FieldKeplerianOrbit<>(
1283 v(42e6), v(0), v(0), v(0), v(0), v(0), PositionAngleType.TRUE, eci, epoch.shiftedBy(t), v(mu)));
1284
1285 TimeDetector resetDetector = new TimeDetector(t)
1286 .withHandler(new ResetHandler<>(events, newState))
1287 .withMaxCheck(10)
1288 .withThreshold(v(tol));
1289 propagator.addEventDetector(resetDetector);
1290 List<FieldEventDetector<T>> detectors = new ArrayList<>();
1291 for (int i = 0; i < 2; i++) {
1292 FieldFunctionalDetector<T> detector1 = new FieldFunctionalDetector<>(field)
1293 .withFunction(s -> s.getA().subtract(10e6))
1294 .withThreshold(v(tol))
1295 .withMaxCheck(10)
1296 .withHandler(new FieldRecordAndContinue<>(events));
1297 propagator.addEventDetector(detector1);
1298 detectors.add(detector1);
1299 }
1300
1301
1302 propagator.propagate(epoch.shiftedBy(-10));
1303
1304
1305 Assertions.assertEquals(t, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tol);
1306 Assertions.assertTrue(events.get(0).isIncreasing());
1307 Assertions.assertEquals(resetDetector, events.get(0).getDetector());
1308
1309 Assertions.assertEquals(t, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tol);
1310 Assertions.assertFalse(events.get(1).isIncreasing());
1311 Assertions.assertEquals(detectors.get(0), events.get(1).getDetector());
1312 Assertions.assertEquals(t, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tol);
1313 Assertions.assertFalse(events.get(2).isIncreasing());
1314 Assertions.assertEquals(detectors.get(1), events.get(2).getDetector());
1315 Assertions.assertEquals(events.size(), 3);
1316 }
1317
1318
1319
1320
1321
1322
1323 @Test
1324 public void testFastSwitchingReverse() {
1325
1326
1327 FieldPropagator<T> propagator = getPropagator(10);
1328
1329 List<Event<T>> events = new ArrayList<>();
1330 TimeDetector detector1 = new TimeDetector(-9.9, -10.1, -12)
1331 .withHandler(new FieldRecordAndContinue<>(events))
1332 .withMaxCheck(10)
1333 .withThreshold(v(0.2));
1334 propagator.addEventDetector(detector1);
1335
1336
1337 propagator.propagate(epoch.shiftedBy(-20));
1338
1339
1340
1341 Assertions.assertEquals(1, events.size());
1342 Assertions.assertEquals(-9.9, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.2);
1343 Assertions.assertEquals(true, events.get(0).isIncreasing());
1344 }
1345
1346
1347 @Test
1348 public void testTrickyCaseLowerReverse() {
1349
1350 double maxCheck = 10;
1351 double tolerance = 1e-6;
1352 double t1 = -1.0, t2 = -15, t3 = -16, t4 = -17, t5 = -18;
1353
1354 List<Event<T>> events = new ArrayList<>();
1355 TimeDetector detectorA = new TimeDetector(t3)
1356 .withHandler(new FieldRecordAndContinue<>(events))
1357 .withMaxCheck(maxCheck)
1358 .withThreshold(v(tolerance));
1359 TimeDetector detectorB = new TimeDetector(-50, t1, t2, t5)
1360 .withHandler(new FieldRecordAndContinue<>(events))
1361 .withMaxCheck(maxCheck)
1362 .withThreshold(v(tolerance));
1363 TimeDetector detectorC = new TimeDetector(t4)
1364 .withHandler(new Handler<>(events, Action.RESET_DERIVATIVES))
1365 .withMaxCheck(maxCheck)
1366 .withThreshold(v(tolerance));
1367
1368 FieldPropagator<T> propagator = getPropagator(10);
1369 propagator.addEventDetector(detectorA);
1370 propagator.addEventDetector(detectorB);
1371 propagator.addEventDetector(detectorC);
1372
1373
1374 propagator.propagate(epoch.shiftedBy(-30));
1375
1376
1377
1378
1379 Assertions.assertEquals(5, events.size());
1380 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1381 Assertions.assertEquals(false, events.get(0).isIncreasing());
1382 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1383 Assertions.assertEquals(true, events.get(1).isIncreasing());
1384 Assertions.assertEquals(t3, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1385 Assertions.assertEquals(true, events.get(2).isIncreasing());
1386 Assertions.assertEquals(t4, events.get(3).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1387 Assertions.assertEquals(true, events.get(3).isIncreasing());
1388 Assertions.assertEquals(t5, events.get(4).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1389 Assertions.assertEquals(false, events.get(4).isIncreasing());
1390 }
1391
1392
1393
1394
1395
1396
1397 @Test
1398 public void testRootFindingToleranceReverse() {
1399
1400 double maxCheck = 10;
1401 double t2 = -11, t3 = t2 - 1e-5;
1402 List<Event<T>> events = new ArrayList<>();
1403 TimeDetector detectorA = new TimeDetector(t2)
1404 .withHandler(new FieldRecordAndContinue<>(events))
1405 .withMaxCheck(maxCheck)
1406 .withThreshold(v(1e-6));
1407 FlatDetector detectorB = new FlatDetector(t3)
1408 .withHandler(new FieldRecordAndContinue<>(events))
1409 .withMaxCheck(maxCheck)
1410 .withThreshold(v(0.5));
1411 FieldPropagator<T> propagator = getPropagator(10);
1412 propagator.addEventDetector(detectorA);
1413 propagator.addEventDetector(detectorB);
1414
1415
1416 propagator.propagate(epoch.shiftedBy(-30.0));
1417
1418
1419
1420
1421 Assertions.assertSame(detectorB, events.get(0).getDetector());
1422 Assertions.assertSame(detectorA, events.get(1).getDetector());
1423 Assertions.assertTrue(events.get(0).getState().getDate().compareTo(
1424 events.get(1).getState().getDate()) > 0);
1425
1426
1427 Assertions.assertEquals(2, events.size());
1428 Assertions.assertEquals(t3, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.5);
1429 Assertions.assertEquals(true, events.get(0).isIncreasing());
1430 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), 1e-6);
1431 Assertions.assertEquals(true, events.get(1).isIncreasing());
1432 }
1433
1434
1435 @Test
1436 public void testRootPlusToleranceHasWrongSignReverse() {
1437
1438 double maxCheck = 10;
1439 double tolerance = 1e-6;
1440 final double toleranceB = 0.3;
1441 double t1 = -11, t2 = -11.1, t3 = -11.2;
1442
1443 List<Event<T>> events = new ArrayList<>();
1444 TimeDetector detectorA = new TimeDetector(t2)
1445 .withHandler(new FieldRecordAndContinue<>(events))
1446 .withMaxCheck(maxCheck)
1447 .withThreshold(v(tolerance));
1448 TimeDetector detectorB = new TimeDetector(-50, t1, t3)
1449 .withHandler(new FieldRecordAndContinue<>(events))
1450 .withMaxCheck(maxCheck)
1451 .withThreshold(v(toleranceB));
1452 FieldPropagator<T> propagator = getPropagator(10);
1453 propagator.addEventDetector(detectorA);
1454 propagator.addEventDetector(detectorB);
1455
1456
1457 propagator.propagate(epoch.shiftedBy(-30.0));
1458
1459
1460
1461 Assertions.assertEquals(3, events.size());
1462 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), toleranceB);
1463 Assertions.assertEquals(true, events.get(0).isIncreasing());
1464 Assertions.assertSame(detectorB, events.get(0).getDetector());
1465 Assertions.assertEquals(t3, events.get(1).getState().getDate().durationFrom(epoch).getReal(), toleranceB);
1466 Assertions.assertEquals(false, events.get(1).isIncreasing());
1467 Assertions.assertSame(detectorB, events.get(1).getDetector());
1468 Assertions.assertEquals(t2, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1469 Assertions.assertEquals(true, events.get(2).isIncreasing());
1470 Assertions.assertSame(detectorA, events.get(2).getDetector());
1471
1472 Assertions.assertTrue(events.get(0).getState().getDate().compareTo(
1473 events.get(1).getState().getDate()) >= 0);
1474 Assertions.assertTrue(events.get(1).getState().getDate().compareTo(
1475 events.get(2).getState().getDate()) >= 0);
1476 }
1477
1478
1479 @Test
1480 public void testRootPlusToleranceHasWrongSignAndLessThanTbReverse() {
1481
1482
1483 double maxCheck = 10;
1484 double tolerance = 0.5;
1485 double t1 = -11, t2 = -11.4, t3 = -12.0;
1486
1487 List<Event<T>> events = new ArrayList<>();
1488 FlatDetector detectorB = new FlatDetector(t1, t2, t3)
1489 .withHandler(new FieldRecordAndContinue<>(events))
1490 .withMaxCheck(maxCheck)
1491 .withThreshold(v(tolerance));
1492 FieldPropagator<T> propagator = getPropagator(10);
1493 propagator.addEventDetector(detectorB);
1494
1495
1496 propagator.propagate(epoch.shiftedBy(-30.0));
1497
1498
1499
1500 Assertions.assertEquals(1, events.size());
1501 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1502 Assertions.assertEquals(true, events.get(0).isIncreasing());
1503 Assertions.assertSame(detectorB, events.get(0).getDetector());
1504 }
1505
1506
1507
1508
1509
1510 @Test
1511 public void testDoubleRootReverse() {
1512
1513 double maxCheck = 10;
1514 double tolerance = 1e-6;
1515 double t1 = -11;
1516
1517 List<Event<T>> events = new ArrayList<>();
1518 TimeDetector detectorA = new TimeDetector(t1)
1519 .withHandler(new FieldRecordAndContinue<>(events))
1520 .withMaxCheck(maxCheck)
1521 .withThreshold(v(tolerance));
1522 TimeDetector detectorB = new TimeDetector(t1, t1)
1523 .withHandler(new FieldRecordAndContinue<>(events))
1524 .withMaxCheck(maxCheck)
1525 .withThreshold(v(tolerance));
1526 FieldPropagator<T> propagator = getPropagator(10);
1527 propagator.addEventDetector(detectorA);
1528 propagator.addEventDetector(detectorB);
1529
1530
1531 propagator.propagate(epoch.shiftedBy(-30.0));
1532
1533
1534 Assertions.assertEquals(1, events.size());
1535 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1536 Assertions.assertEquals(true, events.get(0).isIncreasing());
1537 Assertions.assertSame(detectorA, events.get(0).getDetector());
1538
1539 Assertions.assertTrue(detectorB.g(state(t1)).getReal() == 0.0);
1540 Assertions.assertTrue(detectorB.g(state(t1 + 1e-6)).getReal() < 0);
1541 Assertions.assertTrue(detectorB.g(state(t1 - 1e-6)).getReal() < 0);
1542 }
1543
1544
1545
1546
1547
1548 @Test
1549 public void testDoubleRootOppositeSignReverse() {
1550
1551 double maxCheck = 10;
1552 double tolerance = 1e-6;
1553 double t1 = -11;
1554
1555 List<Event<T>> events = new ArrayList<>();
1556 TimeDetector detectorA = new TimeDetector(t1)
1557 .withHandler(new FieldRecordAndContinue<>(events))
1558 .withMaxCheck(maxCheck)
1559 .withThreshold(v(tolerance));
1560 ContinuousDetector detectorB = new ContinuousDetector(-50, t1, t1)
1561 .withHandler(new FieldRecordAndContinue<>(events))
1562 .withMaxCheck(maxCheck)
1563 .withThreshold(v(tolerance));
1564 detectorB.g(state(t1));
1565 FieldPropagator<T> propagator = getPropagator(10);
1566 propagator.addEventDetector(detectorA);
1567 propagator.addEventDetector(detectorB);
1568
1569
1570 propagator.propagate(epoch.shiftedBy(-30.0));
1571
1572
1573 Assertions.assertEquals(1, events.size());
1574 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1575 Assertions.assertEquals(true, events.get(0).isIncreasing());
1576 Assertions.assertSame(detectorA, events.get(0).getDetector());
1577
1578 Assertions.assertEquals(0.0, detectorB.g(state(t1)).getReal(), 0.0);
1579 Assertions.assertTrue(detectorB.g(state(t1 + 1e-6)).getReal() > 0);
1580 Assertions.assertTrue(detectorB.g(state(t1 - 1e-6)).getReal() > 0);
1581 }
1582
1583
1584 @Test
1585 public void testZeroAtBeginningAndEndOfIntervalReverse() {
1586
1587 double maxCheck = 10;
1588 double tolerance = 1e-6;
1589 double t1 = -10, t2 = -20;
1590
1591 List<Event<T>> events = new ArrayList<>();
1592 ContinuousDetector detectorA = new ContinuousDetector(-50, t1, t2)
1593 .withHandler(new FieldRecordAndContinue<>(events))
1594 .withMaxCheck(maxCheck)
1595 .withThreshold(v(tolerance));
1596 FieldPropagator<T> propagator = getPropagator(10);
1597 propagator.addEventDetector(detectorA);
1598
1599
1600 propagator.propagate(epoch.shiftedBy(-30.0));
1601
1602
1603 Assertions.assertEquals(2, events.size());
1604 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1605 Assertions.assertEquals(true, events.get(0).isIncreasing());
1606 Assertions.assertSame(detectorA, events.get(0).getDetector());
1607 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1608 Assertions.assertEquals(false, events.get(1).isIncreasing());
1609 Assertions.assertSame(detectorA, events.get(1).getDetector());
1610 }
1611
1612
1613 @Test
1614 public void testZeroAtBeginningAndEndOfIntervalOppositeSignReverse() {
1615
1616 double maxCheck = 10;
1617 double tolerance = 1e-6;
1618 double t1 = -10, t2 = -20;
1619
1620 List<Event<T>> events = new ArrayList<>();
1621 ContinuousDetector detectorA = new ContinuousDetector(t1, t2)
1622 .withHandler(new FieldRecordAndContinue<>(events))
1623 .withMaxCheck(maxCheck)
1624 .withThreshold(v(tolerance));
1625 FieldPropagator<T> propagator = getPropagator(10);
1626 propagator.addEventDetector(detectorA);
1627
1628
1629 propagator.propagate(epoch.shiftedBy(-30));
1630
1631
1632 Assertions.assertEquals(2, events.size());
1633 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1634 Assertions.assertEquals(false, events.get(0).isIncreasing());
1635 Assertions.assertSame(detectorA, events.get(0).getDetector());
1636 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1637 Assertions.assertEquals(true, events.get(1).isIncreasing());
1638 Assertions.assertSame(detectorA, events.get(1).getDetector());
1639 }
1640
1641
1642 @Test
1643 public void testMultipleBackupsReverse() {
1644
1645 double maxCheck = 10;
1646 double tolerance = 1e-6;
1647 double t1 = -1.0, t2 = -2, t3 = -3, t4 = -4, t5 = -5, t6 = -6.5, t7 = -7;
1648
1649 List<Event<T>> events = new ArrayList<>();
1650 ContinuousDetector detectorA = new ContinuousDetector(t6)
1651 .withHandler(new FieldRecordAndContinue<>(events))
1652 .withMaxCheck(maxCheck)
1653 .withThreshold(v(tolerance));
1654 ContinuousDetector detectorB = new ContinuousDetector(-50, t1, t3, t4, t7)
1655 .withHandler(new FieldRecordAndContinue<>(events))
1656 .withMaxCheck(maxCheck)
1657 .withThreshold(v(tolerance));
1658 ContinuousDetector detectorC = new ContinuousDetector(-50, t2, t5)
1659 .withHandler(new FieldRecordAndContinue<>(events))
1660 .withMaxCheck(maxCheck)
1661 .withThreshold(v(tolerance));
1662
1663 FieldPropagator<T> propagator = getPropagator(10);
1664 propagator.addEventDetector(detectorA);
1665 propagator.addEventDetector(detectorB);
1666 propagator.addEventDetector(detectorC);
1667
1668
1669 propagator.propagate(epoch.shiftedBy(-30.0));
1670
1671
1672
1673 Assertions.assertEquals(5, events.size());
1674 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1675 Assertions.assertEquals(true, events.get(0).isIncreasing());
1676 Assertions.assertEquals(detectorB, events.get(0).getDetector());
1677 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1678 Assertions.assertEquals(true, events.get(1).isIncreasing());
1679 Assertions.assertEquals(detectorC, events.get(1).getDetector());
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690 Assertions.assertEquals(t5, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1691 Assertions.assertEquals(false, events.get(2).isIncreasing());
1692 Assertions.assertEquals(detectorC, events.get(2).getDetector());
1693 Assertions.assertEquals(t6, events.get(3).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1694 Assertions.assertEquals(true, events.get(3).isIncreasing());
1695 Assertions.assertEquals(detectorA, events.get(3).getDetector());
1696 Assertions.assertEquals(t7, events.get(4).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1697 Assertions.assertEquals(false, events.get(4).isIncreasing());
1698 Assertions.assertEquals(detectorB, events.get(4).getDetector());
1699 }
1700
1701
1702 @Test
1703 public void testEventCausedByStateResetReverse() {
1704
1705 double maxCheck = 10;
1706 double tolerance = 1e-6;
1707 double t1 = -15.0;
1708 FieldSpacecraftState<T> newState = new FieldSpacecraftState<T>(new FieldKeplerianOrbit<T>(
1709 v(6378137 + 500e3), v(0), v(FastMath.PI / 2), v(0), v(0),
1710 v(FastMath.PI / 2), PositionAngleType.TRUE, eci, epoch.shiftedBy(t1), v(mu)));
1711
1712 List<Event<T>> events = new ArrayList<>();
1713 TimeDetector detectorA = new TimeDetector(t1)
1714 .withHandler(new Handler<FieldEventDetector<T>>(events, Action.RESET_STATE) {
1715 @Override
1716 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector,
1717 FieldSpacecraftState<T> oldState) {
1718 return newState;
1719 }
1720 })
1721 .withMaxCheck(maxCheck)
1722 .withThreshold(v(tolerance));
1723 FieldLatitudeCrossingDetector<T> detectorB =
1724 new FieldLatitudeCrossingDetector<T>(field, earth, FastMath.toRadians(80))
1725 .withHandler(new FieldRecordAndContinue<>(events))
1726 .withMaxCheck(maxCheck)
1727 .withThreshold(v(tolerance));
1728
1729 FieldPropagator<T> propagator = getPropagator(10);
1730 propagator.addEventDetector(detectorA);
1731 propagator.addEventDetector(detectorB);
1732
1733
1734 propagator.propagate(epoch.shiftedBy(-40.0));
1735
1736
1737
1738 Assertions.assertEquals(2, events.size());
1739 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1740 Assertions.assertEquals(true, events.get(0).isIncreasing());
1741 Assertions.assertEquals(detectorA, events.get(0).getDetector());
1742 Assertions.assertEquals(t1, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1743 Assertions.assertEquals(false, events.get(1).isIncreasing());
1744 Assertions.assertEquals(detectorB, events.get(1).getDetector());
1745 }
1746
1747
1748 @Test
1749 public void testConvergenceTooTightReverse() {
1750
1751 double maxCheck = 10;
1752 double tolerance = 1e-18;
1753 double t1 = -15;
1754
1755 List<Event<T>> events = new ArrayList<>();
1756 ContinuousDetector detectorA = new ContinuousDetector(t1)
1757 .withHandler(new FieldRecordAndContinue<>(events))
1758 .withMaxCheck(maxCheck)
1759 .withThreshold(v(tolerance));
1760 FieldPropagator<T> propagator = getPropagator(10);
1761 propagator.addEventDetector(detectorA);
1762
1763
1764 propagator.propagate(epoch.shiftedBy(-30.0));
1765
1766
1767 Assertions.assertEquals(1, events.size());
1768 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), 0.0);
1769 Assertions.assertEquals(true, events.get(0).isIncreasing());
1770 Assertions.assertSame(detectorA, events.get(0).getDetector());
1771 }
1772
1773
1774
1775
1776
1777
1778
1779 @Test
1780 public void testEventChangesGFunctionDefinitionReverse() {
1781
1782 double maxCheck = 5;
1783 double tolerance = 1e-6;
1784 double t1 = -11, t2 = -19;
1785
1786 List<Event<T>> events = new ArrayList<>();
1787
1788 boolean[] swap = new boolean[1];
1789 ContinuousDetector detectorA = new ContinuousDetector(t1)
1790 .withMaxCheck(maxCheck)
1791 .withThreshold(v(tolerance))
1792 .withHandler(new FieldRecordAndContinue<T>(events) {
1793 @Override
1794 public Action eventOccurred(FieldSpacecraftState<T> s,
1795 FieldEventDetector<T> detector,
1796 boolean increasing) {
1797 swap[0] = true;
1798 return super.eventOccurred(s, detector, increasing);
1799 }
1800 });
1801 ContinuousDetector detectorB = new ContinuousDetector(t2);
1802 FieldEventDetector<T> detectorC = new Reverse(maxCheck, tolerance, swap, detectorB, detectorB, events);
1803 FieldPropagator<T> propagator = getPropagator(10);
1804 propagator.addEventDetector(detectorA);
1805 propagator.addEventDetector(detectorC);
1806
1807
1808 propagator.propagate(epoch.shiftedBy(-30.0));
1809
1810
1811 Assertions.assertEquals(2, events.size());
1812 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1813 Assertions.assertEquals(true, events.get(0).isIncreasing());
1814 Assertions.assertSame(detectorA, events.get(0).getDetector());
1815 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1816 Assertions.assertEquals(true, events.get(1).isIncreasing());
1817 Assertions.assertSame(detectorC, events.get(1).getDetector());
1818 }
1819
1820
1821
1822
1823
1824
1825 @Test
1826 public void testEventChangesGFunctionDefinitionCancelReverse() {
1827
1828 double maxCheck = 5;
1829 double tolerance = 1e-6;
1830 double t1 = -11, t2 = -11.1;
1831
1832 List<Event<T>> events = new ArrayList<>();
1833
1834 boolean[] swap = new boolean[1];
1835 final ContinuousDetector detectorA = new ContinuousDetector(t1)
1836 .withMaxCheck(maxCheck)
1837 .withThreshold(v(tolerance))
1838 .withHandler(new FieldRecordAndContinue<T>(events) {
1839 @Override
1840 public Action eventOccurred(FieldSpacecraftState<T> state,
1841 FieldEventDetector<T> detector,
1842 boolean increasing) {
1843 swap[0] = true;
1844 super.eventOccurred(state, detector, increasing);
1845 return Action.RESET_EVENTS;
1846 }
1847 });
1848 final ContinuousDetector detectorB = new ContinuousDetector(t2);
1849 FieldEventDetector<T> detectorC = new CancelReverse(maxCheck, tolerance, swap, detectorB, detectorB, events);
1850 FieldPropagator<T> propagator = getPropagator(10);
1851 propagator.addEventDetector(detectorA);
1852 propagator.addEventDetector(detectorC);
1853
1854
1855 propagator.propagate(epoch.shiftedBy(-30));
1856
1857
1858 Assertions.assertEquals(1, events.size());
1859 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1860 Assertions.assertEquals(true, events.get(0).isIncreasing());
1861 Assertions.assertSame(detectorA, events.get(0).getDetector());
1862 }
1863
1864
1865
1866
1867
1868
1869 @Test
1870 public void testEventChangesGFunctionDefinitionDelayReverse() {
1871
1872 double maxCheck = 5;
1873 double tolerance = 1e-6;
1874 double t1 = -11, t2 = -11.1, t3 = -11.2;
1875
1876 List<Event<T>> events = new ArrayList<>();
1877
1878 boolean[] swap = new boolean[1];
1879 final ContinuousDetector detectorA = new ContinuousDetector(t1)
1880 .withMaxCheck(maxCheck)
1881 .withThreshold(v(tolerance))
1882 .withHandler(new FieldRecordAndContinue<T>(events) {
1883 @Override
1884 public Action eventOccurred(FieldSpacecraftState<T> state,
1885 FieldEventDetector<T> detector,
1886 boolean increasing) {
1887 swap[0] = true;
1888 super.eventOccurred(state, detector, increasing);
1889 return Action.RESET_EVENTS;
1890 }
1891 });
1892 final ContinuousDetector detectorB = new ContinuousDetector(t2);
1893 final ContinuousDetector detectorD = new ContinuousDetector(t3);
1894 FieldEventDetector<T> detectorC = new DelayReverse(maxCheck, tolerance, swap, detectorB, detectorD, events);
1895 FieldPropagator<T> propagator = getPropagator(10);
1896 propagator.addEventDetector(detectorA);
1897 propagator.addEventDetector(detectorC);
1898
1899
1900 propagator.propagate(epoch.shiftedBy(-30));
1901
1902
1903 Assertions.assertEquals(2, events.size());
1904 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1905 Assertions.assertEquals(true, events.get(0).isIncreasing());
1906 Assertions.assertSame(detectorA, events.get(0).getDetector());
1907 Assertions.assertEquals(t3, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1908 Assertions.assertEquals(true, events.get(1).isIncreasing());
1909 Assertions.assertSame(detectorC, events.get(1).getDetector());
1910 }
1911
1912
1913
1914
1915
1916
1917 @Test
1918 public void testEventChangesGFunctionDefinitionAccelerateReverse() {
1919
1920 double maxCheck = 5;
1921 double tolerance = 1e-6;
1922 double t1 = -11, t2 = -11.1, t3 = -11.2;
1923
1924 List<Event<T>> events = new ArrayList<>();
1925
1926 boolean[] swap = new boolean[1];
1927 final ContinuousDetector detectorA = new ContinuousDetector(t1)
1928 .withMaxCheck(maxCheck)
1929 .withThreshold(v(tolerance))
1930 .withHandler(new FieldRecordAndContinue<T>(events) {
1931 @Override
1932 public Action eventOccurred(FieldSpacecraftState<T> state,
1933 FieldEventDetector<T> detector,
1934 boolean increasing) {
1935 swap[0] = true;
1936 super.eventOccurred(state, detector, increasing);
1937 return Action.RESET_EVENTS;
1938 }
1939 });
1940 final ContinuousDetector detectorB = new ContinuousDetector(t2);
1941 final ContinuousDetector detectorD = new ContinuousDetector(t3);
1942 FieldEventDetector<T> detectorC = new AccelerateReverse(maxCheck, tolerance, swap, detectorB, detectorD, events);
1943 FieldPropagator<T> propagator = getPropagator(10);
1944 propagator.addEventDetector(detectorA);
1945 propagator.addEventDetector(detectorC);
1946
1947
1948 propagator.propagate(epoch.shiftedBy(-30));
1949
1950
1951 Assertions.assertEquals(2, events.size());
1952 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1953 Assertions.assertEquals(true, events.get(0).isIncreasing());
1954 Assertions.assertSame(detectorA, events.get(0).getDetector());
1955 Assertions.assertEquals(t2, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
1956 Assertions.assertEquals(true, events.get(1).isIncreasing());
1957 Assertions.assertSame(detectorC, events.get(1).getDetector());
1958 }
1959
1960 private abstract class AbstractTestDetector<D extends AbstractTestDetector<D>> extends FieldAbstractDetector<D, T> {
1961 AbstractTestDetector(final double maxCheck, final double tolerance, final List<Event<T>> events) {
1962 super(s -> maxCheck, v(tolerance), 100, new FieldRecordAndContinue<>(events));
1963 }
1964
1965 @Override
1966 protected D create(FieldAdaptableInterval<T> newMaxCheck, T newThreshold, int newMaxIter, FieldEventHandler<T> newHandler) {
1967 return null;
1968 }
1969 }
1970
1971 private abstract class AbstractChangeDetector<D extends AbstractTestDetector<D>> extends AbstractTestDetector<D> {
1972 final boolean[] swap;
1973 final ContinuousDetector detectorB;
1974 final ContinuousDetector detectorD;
1975 AbstractChangeDetector(final double maxCheck, final double tolerance, final boolean[] swap,
1976 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
1977 final List<Event<T>> events) {
1978 super(maxCheck, tolerance, events);
1979 this.swap = swap;
1980 this.detectorB = detectorB;
1981 this.detectorD = detectorD;
1982 }
1983
1984 @Override
1985 protected D create(FieldAdaptableInterval<T> newMaxCheck, T newThreshold, int newMaxIter, FieldEventHandler<T> newHandler) {
1986 return null;
1987 }
1988 }
1989
1990 private class Definition extends AbstractChangeDetector<Definition> {
1991 Definition(final double maxCheck, final double tolerance, final boolean[] swap,
1992 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
1993 final List<Event<T>> events) {
1994 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
1995 }
1996 @Override
1997 public T g(FieldSpacecraftState<T> state) {
1998 if (swap[0]) {
1999 return detectorB.g(state);
2000 } else {
2001 return v(-1);
2002 }
2003 }
2004 }
2005
2006 private class Reverse extends AbstractChangeDetector<Reverse> {
2007 Reverse(final double maxCheck, final double tolerance, final boolean[] swap,
2008 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2009 final List<Event<T>> events) {
2010 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2011 }
2012 @Override
2013 public T g(FieldSpacecraftState<T> state) {
2014 if (swap[0]) {
2015 return detectorB.g(state);
2016 } else {
2017 return v(1);
2018 }
2019 }
2020 }
2021
2022 private class Cancel extends AbstractChangeDetector<Cancel> {
2023 Cancel(final double maxCheck, final double tolerance, final boolean[] swap,
2024 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2025 final List<Event<T>> events) {
2026 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2027 }
2028 @Override
2029 public T g(FieldSpacecraftState<T> state) {
2030 if (!swap[0]) {
2031 return detectorB.g(state);
2032 } else {
2033 return v(-1);
2034 }
2035 }
2036 }
2037
2038 private class CancelReverse extends AbstractChangeDetector<CancelReverse> {
2039 CancelReverse(final double maxCheck, final double tolerance, final boolean[] swap,
2040 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2041 final List<Event<T>> events) {
2042 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2043 }
2044 @Override
2045 public T g(FieldSpacecraftState<T> state) {
2046 if (!swap[0]) {
2047 return detectorB.g(state);
2048 } else {
2049 return v(1);
2050 }
2051 }
2052 }
2053
2054 private class Delay extends AbstractChangeDetector<Delay> {
2055 Delay(final double maxCheck, final double tolerance, final boolean[] swap,
2056 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2057 final List<Event<T>> events) {
2058 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2059 }
2060 @Override
2061 public T g(FieldSpacecraftState<T> state) {
2062 if (!swap[0]) {
2063 return detectorB.g(state);
2064 } else {
2065 return detectorD.g(state);
2066 }
2067 }
2068 }
2069
2070 private class DelayReverse extends AbstractChangeDetector<DelayReverse> {
2071 DelayReverse(final double maxCheck, final double tolerance, final boolean[] swap,
2072 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2073 final List<Event<T>> events) {
2074 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2075 }
2076 @Override
2077 public T g(FieldSpacecraftState<T> state) {
2078 if (!swap[0]) {
2079 return detectorB.g(state);
2080 } else {
2081 return detectorD.g(state);
2082 }
2083 }
2084 }
2085
2086 private class Accelerate extends AbstractChangeDetector<Accelerate> {
2087 Accelerate(final double maxCheck, final double tolerance, final boolean[] swap,
2088 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2089 final List<Event<T>> events) {
2090 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2091 }
2092 @Override
2093 public T g(FieldSpacecraftState<T> state) {
2094 if (swap[0]) {
2095 return detectorB.g(state);
2096 } else {
2097 return detectorD.g(state);
2098 }
2099 }
2100 }
2101
2102 private class AccelerateReverse extends AbstractChangeDetector<AccelerateReverse> {
2103 AccelerateReverse(final double maxCheck, final double tolerance, final boolean[] swap,
2104 final ContinuousDetector detectorB, final ContinuousDetector detectorD,
2105 final List<Event<T>> events) {
2106 super(maxCheck, tolerance, swap, detectorB, detectorD, events);
2107 }
2108 @Override
2109 public T g(FieldSpacecraftState<T> state) {
2110 if (swap[0]) {
2111 return detectorB.g(state);
2112 } else {
2113 return detectorD.g(state);
2114 }
2115 }
2116 }
2117
2118
2119 @Test
2120 public void testToleranceStopReverse() {
2121
2122 double maxCheck = 10;
2123 double tolerance = 1e-18;
2124 double t1 = -15.1;
2125
2126 List<Event<T>> events = new ArrayList<>();
2127 FlatDetector detectorA = new FlatDetector(t1)
2128 .withHandler(new Handler<>(events, Action.STOP))
2129 .withMaxCheck(maxCheck)
2130 .withThreshold(v(tolerance));
2131 FieldPropagator<T> propagator = getPropagator(10);
2132 propagator.addEventDetector(detectorA);
2133
2134
2135 FieldSpacecraftState<T> finalState = propagator.propagate(epoch.shiftedBy(-30.0));
2136
2137
2138 Assertions.assertEquals(1, events.size());
2139
2140 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
2141 Assertions.assertEquals(true, events.get(0).isIncreasing());
2142 Assertions.assertSame(detectorA, events.get(0).getDetector());
2143 Assertions.assertEquals(t1, finalState.getDate().durationFrom(epoch).getReal(), tolerance);
2144
2145
2146 finalState = propagator.propagate(epoch.shiftedBy(-30.0));
2147
2148
2149 Assertions.assertEquals(-30.0, finalState.getDate().durationFrom(epoch).getReal(), 0.0);
2150 }
2151
2152
2153
2154
2155
2156
2157 @Test
2158 public void testShortBracketingIntervalReverse() {
2159
2160 double maxCheck = 10;
2161 double tolerance = 1e-6;
2162 final double t1 = FastMath.nextDown(-10.0), t2 = -10.5;
2163
2164 List<Event<T>> events = new ArrayList<>();
2165
2166 FieldEventDetector<T> detectorA = new ShortSupDetector(maxCheck, tolerance, t1, t2, events);
2167 TimeDetector detectorB = new TimeDetector(t1)
2168 .withHandler(new FieldRecordAndContinue<>(events))
2169 .withMaxCheck(maxCheck)
2170 .withThreshold(v(tolerance));
2171 FieldPropagator<T> propagator = getPropagator(10);
2172 propagator.addEventDetector(detectorA);
2173 propagator.addEventDetector(detectorB);
2174
2175
2176 propagator.propagate(epoch.shiftedBy(-30.0));
2177
2178
2179 Assertions.assertEquals(3, events.size());
2180 Assertions.assertEquals(t1, events.get(0).getState().getDate().durationFrom(epoch).getReal(), tolerance);
2181 Assertions.assertEquals(false, events.get(0).isIncreasing());
2182 Assertions.assertSame(detectorA, events.get(0).getDetector());
2183 Assertions.assertEquals(t1, events.get(1).getState().getDate().durationFrom(epoch).getReal(), tolerance);
2184 Assertions.assertEquals(true, events.get(1).isIncreasing());
2185 Assertions.assertSame(detectorB, events.get(1).getDetector());
2186 Assertions.assertEquals(t2, events.get(2).getState().getDate().durationFrom(epoch).getReal(), tolerance);
2187 Assertions.assertEquals(true, events.get(2).isIncreasing());
2188 Assertions.assertSame(detectorA, events.get(2).getDetector());
2189 }
2190
2191 private class ShortInfDetector extends AbstractTestDetector<ShortInfDetector> {
2192
2193 final double t1;
2194 final double t2;
2195
2196 ShortInfDetector(final double maxCheck, final double tolerance,
2197 final double t1, final double t2, final List<Event<T>> events) {
2198 super(maxCheck, tolerance, events);
2199 this.t1 = t1;
2200 this.t2 = t2;
2201 }
2202
2203 @Override
2204 public T g(FieldSpacecraftState<T> state) {
2205 final FieldAbsoluteDate<T> t = state.getDate();
2206 if (t.compareTo(epoch.shiftedBy(t1)) < 0) {
2207 return v(-1);
2208 } else if (t.compareTo(epoch.shiftedBy(t2)) < 0) {
2209 return v(1);
2210 } else {
2211 return v(-1);
2212 }
2213 }
2214 }
2215
2216 private class ShortSupDetector extends AbstractTestDetector<ShortSupDetector> {
2217
2218 final double t1;
2219 final double t2;
2220
2221 ShortSupDetector(final double maxCheck, final double tolerance,
2222 final double t1, final double t2, final List<Event<T>> events) {
2223 super(maxCheck, tolerance, events);
2224 this.t1 = t1;
2225 this.t2 = t2;
2226 }
2227
2228 @Override
2229 public T g(FieldSpacecraftState<T> state) {
2230 final FieldAbsoluteDate<T> t = state.getDate();
2231 if (t.compareTo(epoch.shiftedBy(t1)) > 0) {
2232 return v(-1);
2233 } else if (t.compareTo(epoch.shiftedBy(t2)) > 0) {
2234 return v(1);
2235 } else {
2236 return v(-1);
2237 }
2238 }
2239 }
2240
2241
2242 @Test
2243 public void testToleranceMaxIterationsReverse() {
2244
2245 double maxCheck = 10;
2246 double tolerance = 1e-18;
2247 FieldAbsoluteDate<T> t1 = epoch.shiftedBy(-15).shiftedBy(FastMath.ulp(-15.0) / 8);
2248
2249 List<Event<T>> events = new ArrayList<>();
2250 FlatDetector detectorA = new FlatDetector(t1)
2251 .withHandler(new FieldRecordAndContinue<>(events))
2252 .withMaxCheck(maxCheck)
2253 .withThreshold(v(tolerance));
2254 FieldPropagator<T> propagator = getPropagator(10);
2255 propagator.addEventDetector(detectorA);
2256
2257
2258 propagator.propagate(epoch.shiftedBy(-30));
2259
2260
2261 Assertions.assertEquals(1, events.size());
2262
2263 Assertions.assertEquals(t1.durationFrom(epoch).getReal(),
2264 events.get(0).getState().getDate().durationFrom(epoch).getReal(),
2265 FastMath.ulp(-15.0));
2266 Assertions.assertEquals(true, events.get(0).isIncreasing());
2267 Assertions.assertSame(detectorA, events.get(0).getDetector());
2268 }
2269
2270
2271 @Test
2272 public void testEventStepHandlerReverse() {
2273
2274 double tolerance = 1e-18;
2275 FieldPropagator<T> propagator = getPropagator(10);
2276 propagator.addEventDetector(new TimeDetector(-5)
2277 .withHandler(new Handler<>(Action.CONTINUE))
2278 .withThreshold(v(tolerance)));
2279 StepHandler<T> stepHandler = new StepHandler<>();
2280 propagator.setStepHandler(stepHandler);
2281
2282
2283 FieldSpacecraftState<T> finalState = propagator.propagate(epoch.shiftedBy(-10));
2284
2285
2286 Assertions.assertEquals(-10.0, finalState.getDate().durationFrom(epoch).getReal(), tolerance);
2287 Assertions.assertEquals(0.0,
2288 stepHandler.initialState.getDate().durationFrom(epoch).getReal(), tolerance);
2289 Assertions.assertEquals(-10.0, stepHandler.targetDate.durationFrom(epoch).getReal(), tolerance);
2290 Assertions.assertEquals(-10.0,
2291 stepHandler.finalState.getDate().durationFrom(epoch).getReal(), tolerance);
2292 FieldOrekitStepInterpolator<T> interpolator = stepHandler.interpolators.get(0);
2293 Assertions.assertEquals(0.0,
2294 interpolator.getPreviousState().getDate().durationFrom(epoch).getReal(), tolerance);
2295 Assertions.assertEquals(-5.0,
2296 interpolator.getCurrentState().getDate().durationFrom(epoch).getReal(), tolerance);
2297 interpolator = stepHandler.interpolators.get(1);
2298 Assertions.assertEquals(-5.0,
2299 interpolator.getPreviousState().getDate().durationFrom(epoch).getReal(), tolerance);
2300 Assertions.assertEquals(-10.0,
2301 interpolator.getCurrentState().getDate().durationFrom(epoch).getReal(), tolerance);
2302 Assertions.assertEquals(2, stepHandler.interpolators.size());
2303 }
2304
2305
2306
2307
2308
2309 @Test
2310 public void testEventCausedByDerivativesResetReverse() {
2311
2312 TimeDetector detectorA = new TimeDetector(-15.0)
2313 .withHandler(new Handler<TimeDetector>(Action.RESET_STATE){
2314 @Override
2315 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> d, FieldSpacecraftState<T> s) {
2316 return null;
2317 }
2318 })
2319 .withMaxCheck(10)
2320 .withThreshold(v(1e-6));
2321 FieldPropagator<T> propagator = getPropagator(10);
2322 propagator.addEventDetector(detectorA);
2323
2324 try {
2325
2326 propagator.propagate(epoch.shiftedBy(-20.0));
2327 Assertions.fail("Expected Exception");
2328 } catch (NullPointerException e) {
2329
2330 }
2331 }
2332
2333 @Test
2334 public void testResetChangesSign() {
2335 FieldPropagator<T> propagator = getPropagator(2.5);
2336 FieldAbsoluteDate<T> t0 = propagator.getInitialState().getDate();
2337 final double small = 1.25e-11;
2338 ResetChangesSignGenerator eventsGenerator = new ResetChangesSignGenerator(t0, 0.75, 1.125, -0.5 * small).
2339 withMaxCheck(1).
2340 withThreshold(t0.getField().getZero().newInstance(small)).
2341 withMaxIter(1000);
2342 propagator.addEventDetector(eventsGenerator);
2343 final FieldSpacecraftState<T> end = propagator.propagate(propagator.getInitialState().getDate().shiftedBy(12.5));
2344 Assertions.assertEquals(2, eventsGenerator.getCount());
2345 Assertions.assertEquals(1.125 + 0.5 * small, end.getDate().durationFrom(t0).getReal(), 1.0e-12);
2346 }
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356 private FieldSpacecraftState<T> state(double t) {
2357 return new FieldSpacecraftState<>(new FieldKeplerianOrbit<>(
2358 v(6378137 + 500e3), v(0), v(0), v(0), v(0), v(0),
2359 PositionAngleType.TRUE, eci, epoch.shiftedBy(t),
2360 v(mu)));
2361 }
2362
2363 private List<FieldAbsoluteDate<T>> toDates(double[] eventTs) {
2364 Arrays.sort(eventTs);
2365 final List<FieldAbsoluteDate<T>> ret = new ArrayList<>();
2366 for (double eventT : eventTs) {
2367 ret.add(epoch.shiftedBy(eventT));
2368 }
2369 return ret;
2370 }
2371
2372
2373
2374
2375
2376
2377 public T v(double value) {
2378 return field.getZero().add(value);
2379 }
2380
2381
2382 protected class TimeDetector extends FieldAbstractDetector<TimeDetector, T> {
2383
2384
2385 private final List<FieldAbsoluteDate<T>> eventTs;
2386
2387
2388
2389
2390
2391
2392 public TimeDetector(double... eventTs) {
2393 this(s -> DEFAULT_MAXCHECK, v(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER,
2394 new FieldStopOnEvent<>(), toDates(eventTs));
2395 }
2396
2397
2398
2399
2400
2401
2402 @SafeVarargs
2403 public TimeDetector(FieldAbsoluteDate<T>... eventTs) {
2404 this(s -> DEFAULT_MAXCHECK, v(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER,
2405 new FieldStopOnEvent<>(), Arrays.asList(eventTs));
2406 }
2407
2408 private TimeDetector(FieldAdaptableInterval<T> newMaxCheck,
2409 T newThreshold,
2410 int newMaxIter,
2411 FieldEventHandler<T> newHandler,
2412 List<FieldAbsoluteDate<T>> dates) {
2413 super(newMaxCheck, newThreshold, newMaxIter, newHandler);
2414 this.eventTs = dates;
2415 }
2416
2417 @Override
2418 public T g(FieldSpacecraftState<T> s) {
2419 final FieldAbsoluteDate<T> t = s.getDate();
2420 int i = 0;
2421 while (i < eventTs.size() && t.compareTo(eventTs.get(i)) > 0) {
2422 i++;
2423 }
2424 i--;
2425 if (i < 0) {
2426 return t.durationFrom(eventTs.get(0));
2427 } else {
2428 int sign = (i % 2) * 2 - 1;
2429 return (t.durationFrom(eventTs.get(i))).multiply(-sign);
2430 }
2431 }
2432
2433 @Override
2434 protected TimeDetector create(FieldAdaptableInterval<T> newMaxCheck,
2435 T newThreshold,
2436 int newMaxIter,
2437 FieldEventHandler<T> newHandler) {
2438 return new TimeDetector(newMaxCheck, newThreshold, newMaxIter, newHandler, eventTs);
2439 }
2440
2441 }
2442
2443
2444
2445
2446
2447 private class FlatDetector extends FieldAbstractDetector<FlatDetector, T> {
2448
2449 private final FieldEventDetector<T> g;
2450
2451 public FlatDetector(double... eventTs) {
2452 this(s -> DEFAULT_MAXCHECK, v(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER,
2453 new FieldStopOnEvent<>(), new TimeDetector(eventTs));
2454 }
2455
2456 @SafeVarargs
2457 public FlatDetector(FieldAbsoluteDate<T>... eventTs) {
2458 this(s -> DEFAULT_MAXCHECK, v(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER,
2459 new FieldStopOnEvent<>(), new TimeDetector(eventTs));
2460 }
2461
2462 private FlatDetector(FieldAdaptableInterval<T> newMaxCheck,
2463 T newThreshold,
2464 int newMaxIter,
2465 FieldEventHandler<T> newHandler,
2466 FieldEventDetector<T> g) {
2467 super(newMaxCheck, newThreshold, newMaxIter, newHandler);
2468 this.g = g;
2469 }
2470
2471 @Override
2472 public T g(FieldSpacecraftState<T> s) {
2473 return FastMath.sign(g.g(s));
2474 }
2475
2476 @Override
2477 protected FlatDetector create(FieldAdaptableInterval<T> newMaxCheck,
2478 T newThreshold,
2479 int newMaxIter,
2480 FieldEventHandler<T> newHandler) {
2481 return new FlatDetector(newMaxCheck, newThreshold, newMaxIter, newHandler, g);
2482 }
2483
2484 }
2485
2486
2487 private class ContinuousDetector extends FieldAbstractDetector<ContinuousDetector, T> {
2488
2489
2490 private final List<FieldAbsoluteDate<T>> eventTs;
2491
2492 public ContinuousDetector(double... eventTs) {
2493 this(s -> DEFAULT_MAXCHECK, v(DEFAULT_THRESHOLD), DEFAULT_MAX_ITER,
2494 new FieldStopOnEvent<>(), toDates(eventTs));
2495 }
2496
2497 private ContinuousDetector(FieldAdaptableInterval<T> newMaxCheck,
2498 T newThreshold,
2499 int newMaxIter,
2500 FieldEventHandler<T> newHandler,
2501 List<FieldAbsoluteDate<T>> eventDates) {
2502 super(newMaxCheck, newThreshold, newMaxIter, newHandler);
2503 this.eventTs = eventDates;
2504 }
2505
2506 @Override
2507 public T g(FieldSpacecraftState<T> s) {
2508 final FieldAbsoluteDate<T> t = s.getDate();
2509 int i = 0;
2510 while (i < eventTs.size() && t.compareTo(eventTs.get(i)) > 0) {
2511 i++;
2512 }
2513 i--;
2514 if (i < 0) {
2515 return t.durationFrom(eventTs.get(0));
2516 } else if (i < eventTs.size() - 1) {
2517 int sign = (i % 2) * 2 - 1;
2518 return (t.durationFrom(eventTs.get(i)))
2519 .multiply(eventTs.get(i + 1).durationFrom(t)).multiply(-sign);
2520 } else {
2521 int sign = (i % 2) * 2 - 1;
2522 return (t.durationFrom(eventTs.get(i))).multiply(-sign);
2523 }
2524 }
2525
2526 @Override
2527 protected ContinuousDetector create(
2528 FieldAdaptableInterval<T> newMaxCheck,
2529 T newThreshold,
2530 int newMaxIter,
2531 FieldEventHandler<T> newHandler) {
2532 return new ContinuousDetector(newMaxCheck, newThreshold, newMaxIter, newHandler, eventTs);
2533 }
2534
2535 }
2536
2537 private class Handler<D extends FieldEventDetector<T>> extends FieldRecordAndContinue<T> {
2538
2539 private final Action action;
2540
2541 public Handler(Action action) {
2542 this.action = action;
2543 }
2544
2545 public Handler(List<Event<T>> events, Action action) {
2546 super(events);
2547 this.action = action;
2548 }
2549
2550 @Override
2551 public Action eventOccurred(FieldSpacecraftState<T> s,
2552 FieldEventDetector<T> detector,
2553 boolean increasing) {
2554 super.eventOccurred(s, detector, increasing);
2555 return this.action;
2556 }
2557
2558 }
2559
2560 private class ResetHandler<D extends FieldEventDetector<T>> extends Handler<D> {
2561
2562 private final FieldSpacecraftState<T> newState;
2563 private final int times;
2564 private long i = 0;
2565
2566 public ResetHandler(List<Event<T>> events, FieldSpacecraftState<T> newState) {
2567 this(events, newState, Integer.MAX_VALUE);
2568 }
2569
2570 public ResetHandler(List<Event<T>> events, FieldSpacecraftState<T> newState, int times) {
2571 super(events, Action.RESET_STATE);
2572 this.newState = newState;
2573 this.times = times;
2574 }
2575
2576 @Override
2577 public Action eventOccurred(final FieldSpacecraftState<T> s, final FieldEventDetector<T> detector, final boolean increasing) {
2578 super.eventOccurred(s, detector, increasing);
2579 if (i++ < times) {
2580 return Action.RESET_STATE;
2581 }
2582 return Action.CONTINUE;
2583 }
2584
2585 @Override
2586 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> oldState) {
2587 Assertions.assertEquals(0, newState.getDate().durationFrom(oldState.getDate()).getReal(), 0);
2588 return newState;
2589 }
2590 }
2591
2592 private static class StepHandler<D extends CalculusFieldElement<D>>
2593 implements FieldOrekitStepHandler<D> {
2594
2595 private FieldSpacecraftState<D> initialState;
2596 private FieldAbsoluteDate<D> targetDate;
2597 private List<FieldOrekitStepInterpolator<D>> interpolators = new ArrayList<>();
2598 private FieldSpacecraftState<D> finalState;
2599
2600 @Override
2601 public void init(FieldSpacecraftState<D> s0, FieldAbsoluteDate<D> t) {
2602 initialState = s0;
2603 targetDate = t;
2604 }
2605
2606 @Override
2607 public void handleStep(FieldOrekitStepInterpolator<D> interpolator) {
2608 interpolators.add(interpolator);
2609 }
2610
2611 @Override
2612 public void finish(FieldSpacecraftState<D> finalState) {
2613 this.finalState = finalState;
2614 }
2615 }
2616
2617 private class ResetChangesSignGenerator extends FieldAbstractDetector<ResetChangesSignGenerator, T> {
2618
2619 final FieldAbsoluteDate<T> t0;
2620 final double y1;
2621 final double y2;
2622 final double change;
2623 double delta;
2624 int count;
2625
2626 public ResetChangesSignGenerator(final FieldAbsoluteDate<T> t0, final double y1, final double y2, final double change) {
2627 this(s -> DEFAULT_MAXCHECK,
2628 t0.getField().getZero().newInstance(DEFAULT_THRESHOLD),
2629 DEFAULT_MAX_ITER,
2630 new FieldContinueOnEvent<>(), t0, y1, y2, change);
2631 }
2632
2633 private ResetChangesSignGenerator(final FieldAdaptableInterval<T> newMaxCheck, final T newThreshold, final int newMaxIter,
2634 final FieldEventHandler<T> newHandler,
2635 final FieldAbsoluteDate<T> t0, final double y1, final double y2, final double change ) {
2636 super(newMaxCheck, newThreshold, newMaxIter, newHandler);
2637 this.t0 = t0;
2638 this.y1 = y1;
2639 this.y2 = y2;
2640 this.change = change;
2641 this.delta = 0;
2642 this.count = 0;
2643 }
2644
2645 protected ResetChangesSignGenerator create(final FieldAdaptableInterval<T> newMaxCheck, final T newThreshold, final int newMaxIter,
2646 final FieldEventHandler<T> newHandler) {
2647 return new ResetChangesSignGenerator(newMaxCheck, newThreshold, newMaxIter, newHandler,
2648 t0, y1, y2, change);
2649 }
2650
2651 public T g(FieldSpacecraftState<T> s) {
2652 T dt = s.getDate().durationFrom(t0).add(delta);
2653 return dt.subtract(y1).multiply(dt.subtract(y2));
2654 }
2655
2656 public FieldEventHandler<T> getHandler() {
2657 return new FieldEventHandler<T>() {
2658 public Action eventOccurred(FieldSpacecraftState<T> s, FieldEventDetector<T> detector, boolean increasing) {
2659 return ++count < 2 ? Action.RESET_STATE : Action.STOP;
2660 }
2661
2662 public FieldSpacecraftState<T> resetState(FieldEventDetector<T> detector, FieldSpacecraftState<T> s) {
2663 delta = change;
2664 return s;
2665 }
2666 };
2667 }
2668
2669 public int getCount() {
2670 return count;
2671 }
2672
2673 }
2674
2675 }