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