1   /* Copyright 2002-2024 CS GROUP
2    * Licensed to CS GROUP (CS) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * CS licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.orekit.propagation.events;
18  
19  import org.hipparchus.geometry.euclidean.threed.Vector3D;
20  import org.hipparchus.ode.events.Action;
21  import org.hipparchus.util.FastMath;
22  import org.junit.jupiter.api.AfterEach;
23  import org.junit.jupiter.api.Assertions;
24  import org.junit.jupiter.api.BeforeEach;
25  import org.junit.jupiter.api.Test;
26  import org.orekit.Utils;
27  import org.orekit.bodies.CelestialBodyFactory;
28  import org.orekit.bodies.OneAxisEllipsoid;
29  import org.orekit.errors.OrekitException;
30  import org.orekit.frames.FramesFactory;
31  import org.orekit.orbits.EquinoctialOrbit;
32  import org.orekit.orbits.Orbit;
33  import org.orekit.propagation.Propagator;
34  import org.orekit.propagation.SpacecraftState;
35  import org.orekit.propagation.analytical.EcksteinHechlerPropagator;
36  import org.orekit.propagation.events.handlers.EventHandler;
37  import org.orekit.time.AbsoluteDate;
38  import org.orekit.time.TimeScalesFactory;
39  import org.orekit.utils.IERSConventions;
40  import org.orekit.utils.PVCoordinates;
41  
42  import java.util.ArrayList;
43  import java.util.List;
44  
45  public class EventShifterTest {
46  
47      private double           mu;
48      private AbsoluteDate     iniDate;
49      private Propagator       propagator;
50      private List<EventEntry> log;
51  
52      private double sunRadius = 696000000.;
53      private double earthRadius = 6400000.;
54  
55      @Test
56      public void testNegNeg() {
57          propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
58          EclipseDetector raw = createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3);
59          final EventHandler h = raw.getHandler();
60          raw = raw.withHandler(new EventHandler() {
61  
62              @Override
63              public Action eventOccurred(SpacecraftState s,
64                                          EventDetector detector,
65                                          boolean increasing) {
66                  h.eventOccurred(s, detector, increasing);
67                  return Action.RESET_STATE;
68              }
69  
70              @Override
71              public SpacecraftState resetState(EventDetector detector, SpacecraftState oldState)
72                                                    {
73                  return h.resetState(detector, oldState);
74              }
75  
76          });
77          EventShifter shifter = new EventShifter(raw, true, -15, -20).withMaxIter(200);
78          Assertions.assertEquals(-15, shifter.getIncreasingTimeShift(), 1.0e-15);
79          Assertions.assertEquals(-20, shifter.getDecreasingTimeShift(), 1.0e-15);
80          Assertions.assertEquals(200, shifter.getMaxIterationCount());
81          Assertions.assertEquals(100, raw.getMaxIterationCount());
82          propagator.addEventDetector(shifter);
83          propagator.addEventDetector(new EventShifter(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
84                                                       false, -5, -10));
85          propagator.propagate(iniDate.shiftedBy(6000));
86          Assertions.assertEquals(6, log.size());
87          log.get(0).checkExpected(log.get(2).getDT() - 20, "shifted decreasing");
88          log.get(1).checkExpected(log.get(2).getDT(),      "unshifted decreasing");
89          log.get(3).checkExpected(log.get(5).getDT() - 15, "shifted increasing");
90          log.get(4).checkExpected(log.get(5).getDT(),      "unshifted increasing");
91      }
92  
93      @Test
94      public void testNegPos() {
95          propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
96          propagator.addEventDetector(new EventShifter(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
97                                                       true, -15,  20));
98          propagator.addEventDetector(new EventShifter(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
99                                                       false, -5,  10));
100         propagator.propagate(iniDate.shiftedBy(6000));
101         Assertions.assertEquals(6, log.size());
102         log.get(1).checkExpected(log.get(0).getDT(),      "unshifted decreasing");
103         log.get(2).checkExpected(log.get(0).getDT() + 20, "shifted decreasing");
104         log.get(3).checkExpected(log.get(5).getDT() - 15, "shifted increasing");
105         log.get(4).checkExpected(log.get(5).getDT(),      "unshifted increasing");
106     }
107 
108     @Test
109     public void testPosNeg() {
110         propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
111         propagator.addEventDetector(new EventShifter(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
112                                                      true,  15, -20));
113         propagator.addEventDetector(new EventShifter(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
114                                                      false,  5, -10));
115         propagator.propagate(iniDate.shiftedBy(6000));
116         Assertions.assertEquals(6, log.size());
117         log.get(0).checkExpected(log.get(2).getDT() - 20, "shifted decreasing");
118         log.get(1).checkExpected(log.get(2).getDT(),      "unshifted decreasing");
119         log.get(4).checkExpected(log.get(3).getDT(),      "unshifted increasing");
120         log.get(5).checkExpected(log.get(3).getDT() + 15, "shifted increasing");
121     }
122 
123     @Test
124     public void testPosPos() {
125         propagator.addEventDetector(createRawDetector("raw increasing", "raw decreasing", 1.0e-9));
126         propagator.addEventDetector(new EventShifter(createRawDetector("shifted increasing", "shifted decreasing", 1.0e-3),
127                                                      true,  15,  20));
128         propagator.addEventDetector(new EventShifter(createRawDetector("unshifted increasing", "unshifted decreasing", 1.0e-3),
129                                                      false,  5,  10));
130         propagator.propagate(iniDate.shiftedBy(6000));
131         Assertions.assertEquals(6, log.size());
132         log.get(1).checkExpected(log.get(0).getDT(),      "unshifted decreasing");
133         log.get(2).checkExpected(log.get(0).getDT() + 20, "shifted decreasing");
134         log.get(4).checkExpected(log.get(3).getDT(),      "unshifted increasing");
135         log.get(5).checkExpected(log.get(3).getDT() + 15, "shifted increasing");
136     }
137 
138     @Test
139     public void testIncreasingError() {
140         final EclipseDetector raw0000 = createRawDetector("raw increasing",    "raw decreasing", 2.0e-9);
141         final EclipseDetector raw0010 = createRawDetector("-10s increasing",   "-10s decreasing", 2.0e-3);
142         final EclipseDetector raw0100 = createRawDetector("-100s increasing",  "-100s decreasing", 3.0e-2);
143         final EclipseDetector raw1000 = createRawDetector("-1000s increasing", "-1000s decreasing", 5.0);
144         final EventShifter shift0010 = new EventShifter(raw0010, true,   -10,   -10);
145         final EventShifter shift0100 = new EventShifter(raw0100, true,  -100,  -100);
146         final EventShifter shift1000 = new EventShifter(raw1000, true, -1000, -1000);
147         Assertions.assertSame(raw0010, shift0010.getDetector());
148         Assertions.assertSame(raw0100, shift0100.getDetector());
149         Assertions.assertSame(raw1000, shift1000.getDetector());
150         propagator.addEventDetector(raw0000);
151         propagator.addEventDetector(shift0010);
152         propagator.addEventDetector(shift0100);
153         propagator.addEventDetector(shift1000);
154         propagator.propagate(iniDate.shiftedBy(20100));
155 
156         // the raw eclipses (not all within the propagation range) are at times:
157         // [ 2300.238,  4376.986]
158         // [ 8210.859, 10287.573]
159         // [14121.478, 16198.159]
160         // [20032.098, 22108.745]
161         // [25942.717, 28019.331]
162         // [31853.335, 33929.916]
163         // [37763.954, 39840.500]
164         Assertions.assertEquals(28, log.size());
165         for (int i = 0; i < log.size() / 4; ++i) {
166             EventEntry ref = log.get(4 * i + 3);
167             String increasingOrDecreasing = ref.getName().split(" ")[1];
168             log.get(4 * i + 0).checkExpected(ref.getDT() - 1000, "-1000s " + increasingOrDecreasing);
169             log.get(4 * i + 1).checkExpected(ref.getDT() -  100, "-100s "  + increasingOrDecreasing);
170             log.get(4 * i + 2).checkExpected(ref.getDT() -   10, "-10s "   + increasingOrDecreasing);
171         }
172 
173         for (EventEntry entry : log) {
174             double error = entry.getTimeError();
175             if (entry.name.contains("10s")) {
176                 Assertions.assertTrue(error > 1.0e-6);
177                 Assertions.assertTrue(error < 3.0e-6);
178             } else if (entry.name.contains("100s")) {
179                 Assertions.assertTrue(error > 0.001);
180                 Assertions.assertTrue(error < 0.003);
181             } else if (entry.name.contains("1000s")) {
182                 Assertions.assertTrue(error > 0.7);
183                 Assertions.assertTrue(error < 1.1);
184             }
185         }
186     }
187 
188     private EclipseDetector createRawDetector(final String nameIncreasing, final String nameDecreasing,
189                                               final double tolerance) {
190         return new EclipseDetector(CelestialBodyFactory.getSun(), sunRadius,
191                                    new OneAxisEllipsoid(earthRadius,
192                                                         0.0,
193                                                         FramesFactory.getITRF(IERSConventions.IERS_2010, true))).
194                withMaxCheck(60.0).
195                withThreshold(1.0e-10).
196                withHandler(new EventHandler() {
197                                        public Action eventOccurred(SpacecraftState s, EventDetector detector, boolean increasing) {
198                                            log.add(new EventEntry(s.getDate().durationFrom(iniDate), tolerance,
199                                                                   increasing ? nameIncreasing : nameDecreasing));
200                                            return Action.CONTINUE;
201                                        }
202                                    });
203     }
204 
205     @BeforeEach
206     public void setUp() {
207         try {
208             Utils.setDataRoot("regular-data");
209             mu  = 3.9860047e14;
210             double ae  = 6.378137e6;
211             double c20 = -1.08263e-3;
212             double c30 = 2.54e-6;
213             double c40 = 1.62e-6;
214             double c50 = 2.3e-7;
215             double c60 = -5.5e-7;
216             final Vector3D position  = new Vector3D(-6142438.668, 3492467.560, -25767.25680);
217             final Vector3D velocity  = new Vector3D(505.8479685, 942.7809215, 7435.922231);
218             iniDate = new AbsoluteDate(1969, 7, 28, 4, 0, 0.0, TimeScalesFactory.getTT());
219             final Orbit orbit = new EquinoctialOrbit(new PVCoordinates(position,  velocity),
220                                                      FramesFactory.getGCRF(), iniDate, mu);
221             propagator =
222                 new EcksteinHechlerPropagator(orbit, ae, mu, c20, c30, c40, c50, c60);
223             log = new ArrayList<EventEntry>();
224         } catch (OrekitException oe) {
225             Assertions.fail(oe.getLocalizedMessage());
226         }
227     }
228 
229     @AfterEach
230     public void tearDown() {
231         iniDate = null;
232         propagator = null;
233         log = null;
234     }
235 
236     private static class EventEntry {
237 
238         private final double dt;
239         private double expectedDT;
240         private final double tolerance;
241         private final String name;
242 
243         public EventEntry(final double dt, final double tolerance, final String name) {
244             this.dt         = dt;
245             this.expectedDT = Double.NaN;
246             this.tolerance  = tolerance;
247             this.name       = name;
248         }
249 
250         public void checkExpected(final double expectedDT, final String name) {
251             this.expectedDT = expectedDT;
252             Assertions.assertEquals(expectedDT, dt, tolerance);
253             Assertions.assertEquals(name, this.name);
254         }
255 
256         public double getDT() {
257             return dt;
258         }
259 
260         public String getName() {
261             return name;
262         }
263 
264         public double getTimeError() {
265             return FastMath.abs(dt - expectedDT);
266         }
267 
268     }
269 
270 }
271