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.events;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.Field;
21  import org.hipparchus.util.Binary64Field;
22  import org.hipparchus.util.FastMath;
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.frames.Frame;
28  import org.orekit.frames.FramesFactory;
29  import org.orekit.orbits.FieldKeplerianOrbit;
30  import org.orekit.orbits.PositionAngleType;
31  import org.orekit.propagation.FieldBoundedPropagator;
32  import org.orekit.propagation.FieldEphemerisGenerator;
33  import org.orekit.propagation.FieldSpacecraftState;
34  import org.orekit.propagation.analytical.FieldKeplerianPropagator;
35  import org.orekit.propagation.events.handlers.FieldContinueOnEvent;
36  import org.orekit.time.FieldAbsoluteDate;
37  import org.orekit.time.TimeScalesFactory;
38  import org.orekit.utils.Constants;
39  
40  public class FieldNodeDetectorTest {
41  
42      @Test
43      public void testIssue138() {
44          doTestIssue138(Binary64Field.getInstance());
45      }
46  
47      @Test
48      public void testIssue158() {
49          doTestIssue158(Binary64Field.getInstance());
50      }
51  
52      private <T extends CalculusFieldElement<T>>void doTestIssue138(Field<T> field) {
53          T zero = field.getZero();
54          T a = zero.add(800000 + Constants.WGS84_EARTH_EQUATORIAL_RADIUS);
55          T e = zero.add(0.0001);
56          T i = zero.add(FastMath.toRadians(98));
57          T w = zero.add(-90);
58          T raan = zero;
59          T v = zero;
60          Frame inertialFrame = FramesFactory.getEME2000();
61          FieldAbsoluteDate<T> initialDate = new FieldAbsoluteDate<>(field, 2014, 01, 01, 0, 0, 0, TimeScalesFactory.getUTC());
62          FieldAbsoluteDate<T> finalDate = initialDate.shiftedBy(5000);
63          FieldKeplerianOrbit<T> initialOrbit = new FieldKeplerianOrbit<>(a, e, i, w, raan, v, PositionAngleType.TRUE, inertialFrame, initialDate, zero.add(Constants.WGS84_EARTH_MU));
64          FieldSpacecraftState<T> initialState = new FieldSpacecraftState<>(initialOrbit, zero.add(1000));
65          FieldKeplerianPropagator<T> propagator = new FieldKeplerianPropagator<>(initialOrbit);
66  
67          // Define 2 instances of NodeDetector:
68          FieldEventDetector<T> rawDetector =
69                  new FieldNodeDetector<>(zero.add(1e-6), initialState.getOrbit(), initialState.getFrame()).
70                  withHandler(new FieldContinueOnEvent<>());
71  
72          FieldEventsLogger<T> logger1 = new FieldEventsLogger<>();
73          FieldEventDetector<T> node1 = logger1.monitorDetector(rawDetector);
74          FieldEventsLogger<T> logger2 = new FieldEventsLogger<>();
75          FieldEventDetector<T> node2 = logger2.monitorDetector(rawDetector);
76  
77          propagator.addEventDetector(node1);
78          propagator.addEventDetector(node2);
79  
80          // First propagation
81          final FieldEphemerisGenerator<T> generator = propagator.getEphemerisGenerator();
82          propagator.propagate(finalDate);
83          Assertions.assertEquals(2, logger1.getLoggedEvents().size());
84          Assertions.assertEquals(2, logger2.getLoggedEvents().size());
85          logger1.clearLoggedEvents();
86          logger2.clearLoggedEvents();
87          FieldBoundedPropagator<T> postpro = generator.getGeneratedEphemeris();
88  
89          // Post-processing
90          postpro.addEventDetector(node1);
91          postpro.addEventDetector(node2);
92          postpro.propagate(finalDate);
93          Assertions.assertEquals(2, logger1.getLoggedEvents().size());
94          Assertions.assertEquals(2, logger2.getLoggedEvents().size());
95  
96      }
97  
98      private <T extends CalculusFieldElement<T>>void doTestIssue158(Field<T> field) {
99          T zero = field.getZero();
100         FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field);
101 
102         T a          = zero.add(3.0e7);
103         T e1         = zero.add( 0.8);
104         T e2         = zero.add( 1.0e-4);
105         T i          = zero.add(1.0);
106         T pa         = zero.add(1.5 * FastMath.PI);
107         T raan       = zero.add(5.0);
108         T m          = zero.add(0);
109         Frame frame       = FramesFactory.getEME2000();
110         double mu         = Constants.EIGEN5C_EARTH_MU;
111 
112         // highly eccentric, inclined orbit
113         final FieldKeplerianOrbit<T> orbit1 =
114                 new FieldKeplerianOrbit<>(a, e1, i, pa, raan, m, PositionAngleType.MEAN, frame, date, zero.add(mu));
115         FieldEventDetector<T> detector1 = new FieldNodeDetector<>(orbit1, orbit1.getFrame());
116         T t1 = orbit1.getKeplerianPeriod();
117         Assertions.assertEquals(t1.getReal() / 28.82, detector1.getMaxCheckInterval().currentInterval(null, true), t1.getReal() / 10000);
118 
119         // nearly circular, inclined orbit
120         final FieldKeplerianOrbit<T> orbit2 =
121                 new FieldKeplerianOrbit<>(a, e2, i, pa, raan, m, PositionAngleType.MEAN, frame, date, zero.add(mu));
122         FieldEventDetector<T> detector2 = new FieldNodeDetector<>(orbit2, orbit2.getFrame());
123         T t2 = orbit2.getKeplerianPeriod();
124         Assertions.assertEquals(t1.getReal(), t2.getReal(), t1.getReal() / 10000);
125         Assertions.assertEquals(t2.getReal() / 3, detector2.getMaxCheckInterval().currentInterval(null, true), t2.getReal() / 10000);
126 
127     }
128 
129     @BeforeEach
130     public void setUp() {
131         Utils.setDataRoot("regular-data");
132     }
133 
134 }
135