1   /* Copyright 2002-2025 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.analytical;
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.BeforeEach;
23  import org.junit.jupiter.api.Test;
24  import org.orekit.Utils;
25  import org.orekit.bodies.CelestialBodyFactory;
26  import org.orekit.bodies.OneAxisEllipsoid;
27  import org.orekit.errors.OrekitException;
28  import org.orekit.frames.Frame;
29  import org.orekit.frames.FramesFactory;
30  import org.orekit.orbits.KeplerianOrbit;
31  import org.orekit.orbits.Orbit;
32  import org.orekit.orbits.OrbitType;
33  import org.orekit.orbits.PositionAngleType;
34  import org.orekit.propagation.BoundedPropagator;
35  import org.orekit.propagation.Propagator;
36  import org.orekit.propagation.SpacecraftState;
37  import org.orekit.propagation.SpacecraftStateInterpolator;
38  import org.orekit.propagation.events.EclipseDetector;
39  import org.orekit.propagation.events.EventDetector;
40  import org.orekit.propagation.events.handlers.EventHandler;
41  import org.orekit.time.AbsoluteDate;
42  import org.orekit.time.DateComponents;
43  import org.orekit.time.TimeComponents;
44  import org.orekit.time.TimeInterpolator;
45  import org.orekit.time.TimeScalesFactory;
46  import org.orekit.utils.IERSConventions;
47  
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  public class EphemerisEventsTest {
52  
53      @Test
54      public void testEphemKeplerian() throws IllegalArgumentException, OrekitException {
55          checkEphem(OrbitType.KEPLERIAN);
56      }
57  
58      @Test
59      public void testEphemCircular() throws IllegalArgumentException, OrekitException {
60          checkEphem(OrbitType.CIRCULAR);
61      }
62  
63      @Test
64      public void testEphemEquinoctial() throws IllegalArgumentException, OrekitException {
65          checkEphem(OrbitType.EQUINOCTIAL);
66      }
67  
68      @Test
69      public void testEphemCartesian() throws IllegalArgumentException, OrekitException {
70          checkEphem(OrbitType.CARTESIAN);
71      }
72  
73      private Ephemeris buildEphem(OrbitType type)
74          throws IllegalArgumentException, OrekitException {
75  
76          double mass = 2500;
77          double a = 7187990.1979844316;
78          double e = 0.5e-4;
79          double i = 1.7105407051081795;
80          double omega = 1.9674147913622104;
81          double OMEGA = FastMath.toRadians(261);
82          double lv = 0;
83          double mu  = 3.9860047e14;
84          double ae  = 6.378137e6;
85          double c20 = -1.08263e-3;
86          double c30 = 2.54e-6;
87          double c40 = 1.62e-6;
88          double c50 = 2.3e-7;
89          double c60 = -5.5e-7;
90  
91          double deltaT = finalDate.durationFrom(initDate);
92  
93          final Frame frame = FramesFactory.getEME2000();
94  
95          Orbit transPar = new KeplerianOrbit(a, e, i, omega, OMEGA, lv, PositionAngleType.TRUE, frame, initDate, mu);
96  
97          int nbIntervals = 720;
98          Propagator propagator =
99                  new EcksteinHechlerPropagator(transPar, mass, ae, mu, c20, c30, c40, c50, c60);
100 
101         List<SpacecraftState> tab = new ArrayList<SpacecraftState>(nbIntervals + 1);
102         for (int j = 0; j<= nbIntervals; j++) {
103             SpacecraftState state = propagator.propagate(initDate.shiftedBy((j * deltaT) / nbIntervals));
104             tab.add(new SpacecraftState(type.convertType(state.getOrbit()),
105                                         state.getAttitude(), state.getMass()));
106         }
107 
108         final TimeInterpolator<SpacecraftState> interpolator = new SpacecraftStateInterpolator(2, frame, frame);
109 
110         return new Ephemeris(tab, interpolator);
111     }
112 
113     private EclipseDetector buildEclipseDetector(final OrbitType type) {
114 
115         double sunRadius = 696000000.;
116         double earthRadius = 6400000.;
117 
118         EclipseDetector ecl = new EclipseDetector(CelestialBodyFactory.getSun(), sunRadius,
119                                                   new OneAxisEllipsoid(earthRadius,
120                                                                        0.0,
121                                                                        FramesFactory.getITRF(IERSConventions.IERS_2010, true))).
122                               withMaxCheck(60.0).
123                               withThreshold(1.0e-3).
124                               withHandler(new EventHandler() {
125                                 public Action eventOccurred(SpacecraftState s, EventDetector detector,
126                                                             boolean increasing) {
127                                     Assertions.assertEquals(type, s.getOrbit().getType());
128                                     if (increasing) {
129                                         ++inEclipsecounter;
130                                     } else {
131                                         ++outEclipsecounter;
132                                     }
133                                     return Action.CONTINUE;
134                                 }
135                             });
136 
137         return ecl;
138     }
139 
140     private void checkEphem(OrbitType type)
141         throws IllegalArgumentException, OrekitException {
142 
143         initDate = new AbsoluteDate(new DateComponents(2004, 01, 01),
144                                     TimeComponents.H00,
145                                     TimeScalesFactory.getUTC());
146 
147         finalDate = new AbsoluteDate(new DateComponents(2004, 01, 02),
148                                      TimeComponents.H00,
149                                      TimeScalesFactory.getUTC());
150 
151 
152 
153         BoundedPropagator ephem = buildEphem(type);
154 
155         ephem.addEventDetector(buildEclipseDetector(type));
156 
157         AbsoluteDate computeEnd = new AbsoluteDate(finalDate, -1000.0);
158 
159         ephem.clearStepHandlers();
160         SpacecraftState state = ephem.propagate(computeEnd);
161         Assertions.assertEquals(computeEnd, state.getDate());
162         Assertions.assertEquals(14, inEclipsecounter);
163         Assertions.assertEquals(14, outEclipsecounter);
164     }
165 
166     @BeforeEach
167     public void setUp() {
168         Utils.setDataRoot("regular-data");
169         inEclipsecounter = 0;
170         outEclipsecounter = 0;
171     }
172 
173     private AbsoluteDate initDate;
174     private AbsoluteDate finalDate;
175     private int inEclipsecounter;
176     private int outEclipsecounter;
177 
178 }