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  
18  package org.orekit.forces.maneuvers.triggers;
19  
20  import org.hipparchus.geometry.euclidean.threed.Vector3D;
21  import org.hipparchus.ode.nonstiff.DormandPrince853Integrator;
22  import org.hipparchus.util.FastMath;
23  import org.junit.Assert;
24  import org.junit.Before;
25  import org.junit.BeforeClass;
26  import org.junit.Test;
27  import org.orekit.Utils;
28  import org.orekit.forces.maneuvers.Maneuver;
29  import org.orekit.forces.maneuvers.propulsion.BasicConstantThrustPropulsionModel;
30  import org.orekit.forces.maneuvers.trigger.AbstractManeuverTriggers;
31  import org.orekit.forces.maneuvers.trigger.ManeuverTriggersResetter;
32  import org.orekit.frames.Frame;
33  import org.orekit.frames.FramesFactory;
34  import org.orekit.orbits.KeplerianOrbit;
35  import org.orekit.orbits.Orbit;
36  import org.orekit.orbits.OrbitType;
37  import org.orekit.orbits.PositionAngle;
38  import org.orekit.propagation.SpacecraftState;
39  import org.orekit.propagation.numerical.NumericalPropagator;
40  import org.orekit.time.AbsoluteDate;
41  import org.orekit.utils.Constants;
42  
43  /**
44   * Tests the functionality of starting a propagation in between and on start and end times
45   * of a Constant Thrust Maneuver
46   *
47   * @author Greg Carbott
48   */
49  public abstract class AbstractManeuverTriggersInitializationTest<T extends AbstractManeuverTriggers> {
50  
51      protected abstract T createTrigger(AbsoluteDate start, AbsoluteDate stop);
52  
53      private NumericalPropagator propagator;
54      private AbsoluteDate startDate;
55      private SpacecraftState initialState;
56      /** Propagation duration in seconds */
57      private double propDuration = 1200.;
58  
59      /** Maneuver duration in seconds */
60      private double duration = 60.;
61  
62      /** Maneuver Thrust Force in Newtons */
63      private double thrust = 1e3;
64  
65      /** Maneuver Specific Impulse in seconds */
66      private double isp = 100.;
67  
68      /** Mass of Spacecraft in kilograms */
69      private double mass = 2e3;
70  
71      /** Tolerance of deltaV (m/s) difference */
72      private double dvTolerance = 3e-6;
73  
74      /** Tolerance of mass (kg) difference */
75      private double massTolerance = 5e-6;
76  
77      /** Direction of Maneuver */
78      private Vector3D direction = new Vector3D(1, 0, 1);
79  
80      /** Control Items */
81      private double deltaVControlFullForward;
82      private double massControlFullForward;
83      private double massControlHalfForward;
84      private double deltaVControlFullReverse;
85      private double deltaVControlHalfReverse;
86      private double massControlFullReverse;
87      private double massControlHalfReverse;
88  
89      /** trigger dates. */
90      private AbsoluteDate triggerStart;
91      private AbsoluteDate triggerStop;
92  
93      private T configureTrigger(final AbsoluteDate start, final AbsoluteDate stop) {
94          T trigger = createTrigger(start, stop);
95          trigger.addResetter(new ManeuverTriggersResetter() {
96              @Override
97              public void maneuverTriggered(SpacecraftState state, boolean start) {
98                  if (start) {
99                      triggerStart = state.getDate();
100                 } else {
101                     triggerStop  = state.getDate();
102                 }
103             }
104             @Override
105             public SpacecraftState resetState(SpacecraftState state) {
106                 return state;
107             }
108             
109         });
110         return trigger;
111     }
112 
113     /** set orekit data */
114     @BeforeClass
115     public static void setUpBefore() {
116         Utils.setDataRoot("regular-data");
117     }
118 
119     @Before
120     public void setUp() {
121         startDate = new AbsoluteDate();
122         double a = Constants.EGM96_EARTH_EQUATORIAL_RADIUS + 400e3;
123         double e = 0.003;
124         double i = (Math.PI / 4);
125         double pa = 0.0;
126         double raan = 0.0;
127         double anomaly = 0.0;
128         PositionAngle type = PositionAngle.MEAN;
129         Frame frame = FramesFactory.getEME2000();
130         double mu = Constants.EGM96_EARTH_MU;
131         Orbit orbit = new KeplerianOrbit(a, e, i, pa, raan, anomaly,
132                 type, frame, startDate, mu);
133         initialState = new SpacecraftState(orbit, mass);
134 
135         //Numerical Propagator
136         double minStep = 1.0e-5;
137         double maxStep = 1000.0;
138         double positionTolerance = 1.0e-4;
139         OrbitType propagationType = OrbitType.KEPLERIAN;
140         double[][] tolerances =
141                 NumericalPropagator.tolerances(positionTolerance, orbit, propagationType);
142         DormandPrince853Integrator integrator =
143                 new DormandPrince853Integrator(minStep, maxStep,
144                         tolerances[0], tolerances[1]);
145         integrator.setInitialStepSize(10.0);
146         integrator.setMaxGrowth(2.0);
147         //Set up propagator
148         propagator = new NumericalPropagator(integrator);
149         propagator.setOrbitType(propagationType);
150 
151         //Control deltaVs and mass changes
152         double flowRate = -thrust / (Constants.G0_STANDARD_GRAVITY * isp);
153         massControlFullForward = mass + (flowRate * duration);
154         deltaVControlFullForward = isp * Constants.G0_STANDARD_GRAVITY *
155                 FastMath.log(mass / massControlFullForward);
156 
157         massControlHalfForward = mass + (flowRate * duration / 2);
158 
159         massControlFullReverse = mass - (flowRate * duration);
160         deltaVControlFullReverse = isp * Constants.G0_STANDARD_GRAVITY *
161                 FastMath.log(massControlFullReverse / mass);
162 
163         massControlHalfReverse = mass - (flowRate * duration / 2);
164         deltaVControlHalfReverse = isp * Constants.G0_STANDARD_GRAVITY *
165                 FastMath.log(massControlHalfReverse / mass);
166 
167         triggerStart = null;
168         triggerStop  = null;
169     }
170 
171     @Test
172     public void testInBetween() {
173         //Create test Thrust Maneuver
174         Maneuver ctm = new Maneuver(null,
175                                     configureTrigger(startDate.shiftedBy(-(duration / 2)),
176                                                      startDate.shiftedBy( (duration / 2))),
177                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
178 
179         //Reset and populate propagator
180         propagator.removeForceModels();
181         propagator.addForceModel(ctm);
182         propagator.setInitialState(initialState);
183         SpacecraftState finalStateTest =
184                 propagator.propagate(startDate.shiftedBy(propDuration));
185 
186         Assert.assertEquals(massControlHalfForward, finalStateTest.getMass(), massTolerance);
187 
188         Assert.assertNull(triggerStart);
189         Assert.assertEquals(duration / 2, triggerStop.durationFrom(startDate), 1.0e-10);
190 
191     }
192 
193     @Test
194     public void testOnStart() {
195         //Create test Thrust Maneuver
196         Maneuver ctm = new Maneuver(null,
197                                     configureTrigger(startDate,
198                                                      startDate.shiftedBy(duration)),
199                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
200         //Reset and populate propagator
201         propagator.removeForceModels();
202         propagator.addForceModel(ctm);
203         propagator.setInitialState(initialState);
204         SpacecraftState finalStateTest =
205                 propagator.propagate(startDate.shiftedBy(propDuration));
206 
207         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
208                 FastMath.log(mass / finalStateTest.getMass());
209 
210         Assert.assertEquals(deltaVControlFullForward, deltaVTest, dvTolerance);
211         Assert.assertEquals(massControlFullForward, finalStateTest.getMass(), massTolerance);
212 
213         Assert.assertEquals(0.0,      triggerStart.durationFrom(startDate), 1.0e-10);
214         Assert.assertEquals(duration, triggerStop.durationFrom(startDate),  1.0e-10);
215 
216     }
217 
218     @Test
219     public void testOnEnd() {
220         //Create test Thrust Maneuver
221         Maneuver ctm = new Maneuver(null,
222                                     configureTrigger(startDate.shiftedBy(-duration),
223                                                      startDate),
224                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
225         //Reset and populate propagator
226         propagator.removeForceModels();
227         propagator.addForceModel(ctm);
228         propagator.setInitialState(initialState);
229         SpacecraftState finalStateTest =
230                 propagator.propagate(startDate.shiftedBy(propDuration));
231 
232         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
233                 FastMath.log(mass / finalStateTest.getMass());
234 
235         Assert.assertTrue(deltaVTest == 0.0);
236         Assert.assertTrue(finalStateTest.getMass() == mass);
237 
238         Assert.assertNull(triggerStart);
239         Assert.assertEquals(0.0, triggerStop.durationFrom(startDate), 1.0e-10);
240 
241     }
242 
243     @Test
244     public void testOnEndReverse() {
245         //Create test Thrust Maneuver
246         Maneuver ctm = new Maneuver(null,
247                                     configureTrigger(startDate.shiftedBy(-duration),
248                                                      startDate),
249                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
250         //Reset and populate propagator
251         propagator.removeForceModels();
252         propagator.addForceModel(ctm);
253         propagator.setInitialState(initialState);
254         SpacecraftState finalStateTest =
255                 propagator.propagate(startDate.shiftedBy(-propDuration));
256 
257         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
258                 FastMath.log(finalStateTest.getMass() / mass);
259 
260         Assert.assertEquals(deltaVControlFullReverse, deltaVTest, dvTolerance);
261         Assert.assertEquals(massControlFullReverse, finalStateTest.getMass(), massTolerance);
262 
263         Assert.assertEquals(-duration, triggerStart.durationFrom(startDate), 1.0e-10);
264         Assert.assertEquals(0.0,       triggerStop.durationFrom(startDate),  1.0e-10);
265 
266     }
267 
268     @Test
269     public void testOnStartReverse() {
270         //Create test Thrust Maneuver
271         Maneuver ctm = new Maneuver(null,
272                                     configureTrigger(startDate,
273                                                      startDate.shiftedBy(duration)),
274                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
275         //Reset and populate propagator
276         propagator.removeForceModels();
277         propagator.addForceModel(ctm);
278         propagator.setInitialState(initialState);
279         SpacecraftState finalStateTest =
280                 propagator.propagate(startDate.shiftedBy(-propDuration));
281 
282         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
283                 FastMath.log(finalStateTest.getMass() / mass);
284 
285         Assert.assertEquals(0.0, deltaVTest, dvTolerance);
286         Assert.assertTrue(finalStateTest.getMass() == mass);
287 
288         Assert.assertEquals(0.0, triggerStart.durationFrom(startDate), 1.0e-10);
289         Assert.assertNull(triggerStop);
290     }
291 
292     @Test
293     public void testInBetweenReverse() {
294         //Create test Thrust Maneuver
295         Maneuver ctm = new Maneuver(null,
296                                     configureTrigger(startDate.shiftedBy(-duration / 2),
297                                                      startDate.shiftedBy( duration / 2)),
298                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
299         //Reset and populate propagator
300         propagator.removeForceModels();
301         propagator.addForceModel(ctm);
302         propagator.setInitialState(initialState);
303         SpacecraftState finalStateTest =
304                 propagator.propagate(startDate.shiftedBy(-propDuration));
305 
306         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
307                 FastMath.log(finalStateTest.getMass() / mass);
308 
309         Assert.assertEquals(deltaVControlHalfReverse, deltaVTest, dvTolerance);
310         Assert.assertEquals(massControlHalfReverse, finalStateTest.getMass(), massTolerance);
311 
312         Assert.assertEquals(-0.5 * duration, triggerStart.durationFrom(startDate), 1.0e-10);
313         Assert.assertNull(triggerStop);
314 
315     }
316 
317     @Test
318     public void testControlForward() {
319         //Create test Thrust Maneuver
320         Maneuver ctm = new Maneuver(null,
321                                     configureTrigger(startDate.shiftedBy(1.0),
322                                                      startDate.shiftedBy(1.0 + duration)),
323                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
324         //Reset and populate propagator
325         propagator.removeForceModels();
326         propagator.addForceModel(ctm);
327         propagator.setInitialState(initialState);
328         SpacecraftState finalStateTest =
329                 propagator.propagate(startDate.shiftedBy(propDuration));
330 
331         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
332                 FastMath.log(mass / finalStateTest.getMass());
333 
334         Assert.assertEquals(deltaVControlFullForward, deltaVTest, dvTolerance);
335         Assert.assertEquals(massControlFullForward, finalStateTest.getMass(), massTolerance);
336 
337         Assert.assertEquals(1.0,            triggerStart.durationFrom(startDate), 1.0e-10);
338         Assert.assertEquals(1.0 + duration, triggerStop.durationFrom(startDate),  1.0e-10);
339     }
340 
341     @Test
342     public void testControlReverse() {
343         //Create test Thrust Maneuver
344         Maneuver ctm = new Maneuver(null,
345                                     configureTrigger(startDate.shiftedBy(-1.0 - duration),
346                                                      startDate.shiftedBy(-1.0)),
347                                     new BasicConstantThrustPropulsionModel(thrust, isp, direction, ""));
348         //Reset and populate propagator
349         propagator.removeForceModels();
350         propagator.addForceModel(ctm);
351         propagator.setInitialState(initialState);
352         SpacecraftState finalStateTest =
353                 propagator.propagate(startDate.shiftedBy(-propDuration));
354 
355         double deltaVTest = isp * Constants.G0_STANDARD_GRAVITY *
356                 FastMath.log(finalStateTest.getMass() / mass);
357 
358         Assert.assertEquals(deltaVControlFullReverse, deltaVTest, dvTolerance);
359         Assert.assertEquals(massControlFullReverse, finalStateTest.getMass(), massTolerance);
360 
361         Assert.assertEquals(-1.0 - duration, triggerStart.durationFrom(startDate), 1.0e-10);
362         Assert.assertEquals(-1.0,            triggerStop.durationFrom(startDate),  1.0e-10);
363 
364     }
365 
366 }