1   /* Copyright 2002-2022 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.events;
18  
19  import java.util.List;
20  
21  import org.hipparchus.Field;
22  import org.hipparchus.CalculusFieldElement;
23  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24  import org.hipparchus.ode.events.Action;
25  import org.hipparchus.ode.nonstiff.AdaptiveStepsizeFieldIntegrator;
26  import org.hipparchus.ode.nonstiff.DormandPrince853FieldIntegrator;
27  import org.hipparchus.util.Decimal64Field;
28  import org.junit.After;
29  import org.junit.Assert;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.orekit.Utils;
33  import org.orekit.bodies.CelestialBodyFactory;
34  import org.orekit.frames.FramesFactory;
35  import org.orekit.orbits.FieldEquinoctialOrbit;
36  import org.orekit.orbits.FieldOrbit;
37  import org.orekit.orbits.OrbitType;
38  import org.orekit.propagation.FieldSpacecraftState;
39  import org.orekit.propagation.events.handlers.FieldEventHandler;
40  import org.orekit.propagation.numerical.FieldNumericalPropagator;
41  import org.orekit.time.FieldAbsoluteDate;
42  import org.orekit.time.TimeScalesFactory;
43  import org.orekit.utils.FieldPVCoordinates;
44  
45  public class FieldEventsLoggerTest {
46  
47      private double               mu;
48  //    private FieldAbsoluteDate<T>         iniDate;
49  //    private FieldSpacecraftState<T>      initialState;
50      private int                  count;
51  //    private FieldEventDetector<T>        umbraDetector;
52  //    private FieldEventDetector<T>        penumbraDetector;
53  
54  
55      @Before
56      public void setUp() {
57              Utils.setDataRoot("regular-data");
58              mu  = 3.9860047e14;
59      }
60  
61  
62      @Test
63      public void testLogUmbra() {
64          doTestLogUmbra(Decimal64Field.getInstance());
65      }
66      @Test
67      public void testLogPenumbra() {
68          doTestLogPenumbra(Decimal64Field.getInstance());
69      }
70      @Test
71      public void testLogAll() {
72          doTestLogAll(Decimal64Field.getInstance());
73      }
74      @Test
75      public void testImmutableList() {
76          doTestImmutableList(Decimal64Field.getInstance());
77      }
78      @Test
79      public void testClearLog() {
80          doTestClearLog(Decimal64Field.getInstance());
81      }
82  
83      private <T extends CalculusFieldElement<T>> void doTestLogUmbra(Field<T> field) {
84  
85          T zero = field.getZero();
86  
87  
88          final FieldVector3D<T> position  = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.560), zero.add(-25767.25680));
89          final FieldVector3D<T> velocity  = new FieldVector3D<>(zero.add(505.8479685) , zero.add(942.7809215), zero.add(7435.922231));
90          FieldAbsoluteDate<T> iniDate = new FieldAbsoluteDate<>(field, 1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
91          final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position,  velocity),
92                                                                  FramesFactory.getEME2000(), iniDate, zero.add(mu));
93          FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit);
94          double[] absTolerance = {
95              0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
96          };
97          double[] relTolerance = {
98              1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
99          };
100         AdaptiveStepsizeFieldIntegrator<T> integrator =
101             new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, absTolerance, relTolerance);
102         integrator.setInitialStepSize(60);
103         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
104         propagator.setOrbitType(OrbitType.EQUINOCTIAL);
105         propagator.setInitialState(initialState);
106         count = 0;
107         FieldEventDetector<T> umbraDetector = buildDetector(field, true);
108         FieldEventDetector<T> penumbraDetector = buildDetector(field, false);
109 
110 
111 
112         FieldEventsLogger<T> logger = new FieldEventsLogger<>();
113         @SuppressWarnings("unchecked")
114         FieldEventDetector<T> monitored = ((FieldAbstractDetector<FieldEventDetector<T>, T>) logger.monitorDetector(umbraDetector)).
115                 withMaxIter(200);
116         Assert.assertEquals(100, umbraDetector.getMaxIterationCount());
117         Assert.assertEquals(200, monitored.getMaxIterationCount());
118 
119         propagator.addEventDetector(monitored);
120         propagator.addEventDetector(penumbraDetector);
121         count = 0;
122         propagator.propagate(iniDate.shiftedBy(16215)).getDate();
123         Assert.assertEquals(11, count);
124         checkCounts(logger, 3, 3, 0, 0, umbraDetector, penumbraDetector);
125     }
126 
127     private <T extends CalculusFieldElement<T>> void doTestLogPenumbra(final Field<T> field) {
128 
129 
130         T zero = field.getZero();
131 
132 
133         final FieldVector3D<T> position  = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.560), zero.add(-25767.25680));
134         final FieldVector3D<T> velocity  = new FieldVector3D<>(zero.add(505.8479685) , zero.add(942.7809215), zero.add(7435.922231));
135         FieldAbsoluteDate<T> iniDate = new FieldAbsoluteDate<>(field, 1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
136         final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position,  velocity),
137                                                                 FramesFactory.getEME2000(), iniDate, zero.add(mu));
138         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit);
139         double[] absTolerance = {
140             0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
141         };
142         double[] relTolerance = {
143             1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
144         };
145         AdaptiveStepsizeFieldIntegrator<T> integrator =
146             new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, absTolerance, relTolerance);
147         integrator.setInitialStepSize(60);
148         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
149         propagator.setOrbitType(OrbitType.EQUINOCTIAL);
150         propagator.setInitialState(initialState);
151         count = 0;
152         FieldEventDetector<T> umbraDetector = buildDetector(field, true);
153         FieldEventDetector<T> penumbraDetector = buildDetector(field, false);
154 
155         FieldEventsLogger<T> logger = new FieldEventsLogger<>();
156         propagator.addEventDetector(umbraDetector);
157         propagator.addEventDetector(logger.monitorDetector(penumbraDetector));
158         count = 0;
159         propagator.propagate(iniDate.shiftedBy(16215)).getDate();
160         Assert.assertEquals(11, count);
161         checkCounts(logger, 0, 0, 2, 3, umbraDetector, penumbraDetector);
162     }
163 
164     private <T extends CalculusFieldElement<T>> void doTestLogAll(final Field<T> field) {
165 
166         T zero = field.getZero();
167 
168 
169         final FieldVector3D<T> position  = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.560), zero.add(-25767.25680));
170         final FieldVector3D<T> velocity  = new FieldVector3D<>(zero.add(505.8479685) , zero.add(942.7809215), zero.add(7435.922231));
171         FieldAbsoluteDate<T> iniDate = new FieldAbsoluteDate<>(field, 1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
172         final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position,  velocity),
173                                                                 FramesFactory.getEME2000(), iniDate, zero.add(mu));
174         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit);
175         double[] absTolerance = {
176             0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
177         };
178         double[] relTolerance = {
179             1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
180         };
181         AdaptiveStepsizeFieldIntegrator<T> integrator =
182             new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, absTolerance, relTolerance);
183         integrator.setInitialStepSize(60);
184         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
185         propagator.setOrbitType(OrbitType.EQUINOCTIAL);
186         propagator.setInitialState(initialState);
187         count = 0;
188         FieldEventDetector<T> umbraDetector = buildDetector(field, true);
189         FieldEventDetector<T> penumbraDetector = buildDetector(field, false);
190 
191 
192 
193 
194 
195 
196 
197 
198         FieldEventsLogger<T> logger = new FieldEventsLogger<>();
199         propagator.addEventDetector(logger.monitorDetector(umbraDetector));
200         propagator.addEventDetector(logger.monitorDetector(penumbraDetector));
201         count = 0;
202         propagator.propagate(iniDate.shiftedBy(16215));
203         Assert.assertEquals(11, count);
204         checkCounts(logger, 3, 3, 2, 3, umbraDetector, penumbraDetector);
205     }
206 
207     private <T extends CalculusFieldElement<T>> void doTestImmutableList(final Field<T> field) {
208 
209 
210         T zero = field.getZero();
211 
212 
213         final FieldVector3D<T> position  = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.560), zero.add(-25767.25680));
214         final FieldVector3D<T> velocity  = new FieldVector3D<>(zero.add(505.8479685) , zero.add(942.7809215), zero.add(7435.922231));
215         FieldAbsoluteDate<T> iniDate = new FieldAbsoluteDate<>(field, 1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
216         final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position,  velocity),
217                                                                 FramesFactory.getEME2000(), iniDate, zero.add(mu));
218         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit);
219         double[] absTolerance = {
220             0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
221         };
222         double[] relTolerance = {
223             1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
224         };
225         AdaptiveStepsizeFieldIntegrator<T> integrator =
226             new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, absTolerance, relTolerance);
227         integrator.setInitialStepSize(60);
228         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
229         propagator.setOrbitType(OrbitType.EQUINOCTIAL);
230         propagator.setInitialState(initialState);
231         count = 0;
232         FieldEventDetector<T> umbraDetector = buildDetector(field, true);
233         FieldEventDetector<T> penumbraDetector = buildDetector(field, false);
234 
235         FieldEventsLogger<T> logger = new FieldEventsLogger<>();
236         propagator.addEventDetector(logger.monitorDetector(umbraDetector));
237         propagator.addEventDetector(logger.monitorDetector(penumbraDetector));
238         count = 0;
239         propagator.propagate(iniDate.shiftedBy(16215));
240         List<FieldEventsLogger.FieldLoggedEvent<T>> firstList = logger.getLoggedEvents();
241         Assert.assertEquals(11, firstList.size());
242         propagator.propagate(iniDate.shiftedBy(30000));
243         List<FieldEventsLogger.FieldLoggedEvent<T>> secondList = logger.getLoggedEvents();
244         Assert.assertEquals(11, firstList.size());
245         Assert.assertEquals(20, secondList.size());
246         for (int i = 0; i < firstList.size(); ++i) {
247 
248             FieldEventsLogger.FieldLoggedEvent<T> e1 = firstList.get(i);
249             FieldEventsLogger.FieldLoggedEvent<T> e2 = secondList.get(i);
250             FieldPVCoordinates<T> pv1 = e1.getState().getPVCoordinates();
251             FieldPVCoordinates<T> pv2 = e2.getState().getPVCoordinates();
252 
253             Assert.assertTrue(e1.getEventDetector() == e2.getEventDetector());
254             Assert.assertEquals(0, pv1.getPosition().subtract(pv2.getPosition()).getNorm().getReal(), 1.0e-10);
255             Assert.assertEquals(0, pv1.getVelocity().subtract(pv2.getVelocity()).getNorm().getReal(), 1.0e-10);
256             Assert.assertEquals(e1.isIncreasing(), e2.isIncreasing());
257 
258         }
259     }
260 
261     private <T extends CalculusFieldElement<T>> void doTestClearLog(final Field<T> field) {
262 
263 
264 
265 
266         T zero = field.getZero();
267 
268 
269         final FieldVector3D<T> position  = new FieldVector3D<>(zero.add(-6142438.668), zero.add(3492467.560), zero.add(-25767.25680));
270         final FieldVector3D<T> velocity  = new FieldVector3D<>(zero.add(505.8479685) , zero.add(942.7809215), zero.add(7435.922231));
271         FieldAbsoluteDate<T> iniDate = new FieldAbsoluteDate<>(field, 1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
272         final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position,  velocity),
273                                                                 FramesFactory.getEME2000(), iniDate, zero.add(mu));
274         FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(orbit);
275         double[] absTolerance = {
276             0.001, 1.0e-9, 1.0e-9, 1.0e-6, 1.0e-6, 1.0e-6, 0.001
277         };
278         double[] relTolerance = {
279             1.0e-7, 1.0e-4, 1.0e-4, 1.0e-7, 1.0e-7, 1.0e-7, 1.0e-7
280         };
281         AdaptiveStepsizeFieldIntegrator<T> integrator =
282             new DormandPrince853FieldIntegrator<>(field, 0.001, 1000, absTolerance, relTolerance);
283         integrator.setInitialStepSize(60);
284         FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
285         propagator.setOrbitType(OrbitType.EQUINOCTIAL);
286         propagator.setInitialState(initialState);
287         count = 0;
288         FieldEventDetector<T> umbraDetector = buildDetector(field, true);
289         FieldEventDetector<T> penumbraDetector = buildDetector(field, false);
290 
291 
292 
293         FieldEventsLogger<T> logger = new FieldEventsLogger<>();
294         propagator.addEventDetector(logger.monitorDetector(umbraDetector));
295         propagator.addEventDetector(logger.monitorDetector(penumbraDetector));
296         count = 0;
297         propagator.propagate(iniDate.shiftedBy(16215));
298         List<FieldEventsLogger.FieldLoggedEvent<T>> firstList = logger.getLoggedEvents();
299         Assert.assertEquals(11, firstList.size());
300         logger.clearLoggedEvents();
301         propagator.propagate(iniDate.shiftedBy(30000));
302         List<FieldEventsLogger.FieldLoggedEvent<T>> secondList = logger.getLoggedEvents();
303         Assert.assertEquals(11, firstList.size());
304         Assert.assertEquals( 9, secondList.size());
305     }
306 
307     private <T extends CalculusFieldElement<T>> void checkCounts(FieldEventsLogger<T> logger,
308                              int expectedUmbraIncreasingCount, int expectedUmbraDecreasingCount,
309                              int expectedPenumbraIncreasingCount, int expectedPenumbraDecreasingCount,
310                              FieldEventDetector<T> umbraDetector, FieldEventDetector<T> penumbraDetector) {
311         int umbraIncreasingCount = 0;
312         int umbraDecreasingCount = 0;
313         int penumbraIncreasingCount = 0;
314         int penumbraDecreasingCount = 0;
315         for (FieldEventsLogger.FieldLoggedEvent<T> event : logger.getLoggedEvents()) {
316             if (event.getEventDetector() == umbraDetector) {
317                 if (event.isIncreasing()) {
318                     ++umbraIncreasingCount;
319                 } else {
320                     ++umbraDecreasingCount;
321                 }
322             }
323             if (event.getEventDetector() == penumbraDetector) {
324                 if (event.isIncreasing()) {
325                     ++penumbraIncreasingCount;
326                 } else {
327                     ++penumbraDecreasingCount;
328                 }
329             }
330         }
331         Assert.assertEquals(expectedUmbraIncreasingCount,    umbraIncreasingCount);
332         Assert.assertEquals(expectedUmbraDecreasingCount,    umbraDecreasingCount);
333         Assert.assertEquals(expectedPenumbraIncreasingCount, penumbraIncreasingCount);
334         Assert.assertEquals(expectedPenumbraDecreasingCount, penumbraDecreasingCount);
335     }
336 
337     private <T extends CalculusFieldElement<T>> FieldEventDetector<T> buildDetector(Field<T> field, final boolean totalEclipse) {
338 
339         FieldEclipseDetector<T> detector =
340                 new FieldEclipseDetector<>(field.getZero().add(60.), field.getZero().add(1.e-3), CelestialBodyFactory.getSun(), 696000000,
341                                            CelestialBodyFactory.getEarth(), 6400000);
342 
343         if (totalEclipse) {
344             detector = detector.withUmbra();
345         } else {
346             detector = detector.withPenumbra();
347         }
348 
349         detector = detector.withHandler(new FieldEventHandler<FieldEclipseDetector<T>, T>() {
350 
351             public Action eventOccurred(FieldSpacecraftState<T> s, FieldEclipseDetector<T> detector, boolean increasing) {
352                 ++count;
353                 return Action.CONTINUE;
354             }
355 
356         } );
357 
358         return detector;
359 
360     }
361 
362     @After
363     public void tearDown() {
364         count = 0;
365     }
366 
367 }
368