1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.ode.nonstiff.AdaptiveStepsizeFieldIntegrator;
24 import org.hipparchus.ode.nonstiff.DormandPrince54FieldIntegrator;
25 import org.hipparchus.util.Binary64Field;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.MathArrays;
28 import org.junit.jupiter.api.Assertions;
29 import org.junit.jupiter.api.BeforeEach;
30 import org.junit.jupiter.api.Test;
31 import org.orekit.Utils;
32 import org.orekit.attitudes.FieldAttitude;
33 import org.orekit.forces.gravity.potential.GravityFieldFactory;
34 import org.orekit.forces.gravity.potential.SHMFormatReader;
35 import org.orekit.frames.FramesFactory;
36 import org.orekit.orbits.FieldEquinoctialOrbit;
37 import org.orekit.orbits.FieldOrbit;
38 import org.orekit.orbits.OrbitType;
39 import org.orekit.propagation.analytical.BrouwerLyddanePropagator;
40 import org.orekit.propagation.analytical.FieldBrouwerLyddanePropagator;
41 import org.orekit.propagation.numerical.FieldNumericalPropagator;
42 import org.orekit.propagation.semianalytical.dsst.FieldDSSTPropagator;
43 import org.orekit.time.FieldAbsoluteDate;
44 import org.orekit.utils.FieldPVCoordinates;
45
46 public class FieldAdditionalDataProviderTest {
47
48 private double mu;
49 private static final double DURATION = 600.0;
50 private static final String STRING_BEFORE = "Let's go!";
51 private static final String STRING_AFTER = "Good job!";
52
53 @BeforeEach
54 public void setUp() {
55 Utils.setDataRoot("regular-data:potential/shm-format");
56 GravityFieldFactory.addPotentialCoefficientsReader(new SHMFormatReader("^eigen_cg03c_coef$", false));
57 mu = GravityFieldFactory.getUnnormalizedProvider(0, 0).getMu();
58 }
59
60 private <T extends CalculusFieldElement<T>> FieldSpacecraftState<T> createState(final Field<T> field) {
61 final T zero = field.getZero();
62 final FieldVector3D<T> position = new FieldVector3D<>(zero.add(7.0e6), zero.add(1.0e6), zero.add(4.0e6));
63 final FieldVector3D<T> velocity = new FieldVector3D<>(zero.add(-500.0), zero.add(8000.0), zero.add(1000.0));
64 final FieldAbsoluteDate<T> initDate = FieldAbsoluteDate.getJ2000Epoch(field);
65 final FieldOrbit<T> orbit = new FieldEquinoctialOrbit<>(new FieldPVCoordinates<>(position, velocity),
66 FramesFactory.getEME2000(), initDate, zero.add(mu));
67 return new FieldSpacecraftState<>(orbit);
68 }
69
70 private <T extends CalculusFieldElement<T>> AdaptiveStepsizeFieldIntegrator<T> createIntegrator(final Field<T> field, final FieldSpacecraftState<T> state) {
71 double[][] tolerance = ToleranceProvider.getDefaultToleranceProvider(0.001).getTolerances(state.getOrbit(), OrbitType.EQUINOCTIAL);
72 AdaptiveStepsizeFieldIntegrator<T> integrator = new DormandPrince54FieldIntegrator<>(field, 0.001, 200, tolerance[0], tolerance[1]);
73 integrator.setInitialStepSize(60);
74 return integrator;
75 }
76
77 @Test
78 public void testModifyMainState() {
79 doTestModifyMainState(Binary64Field.getInstance());
80 }
81
82 private <T extends CalculusFieldElement<T>> void doTestModifyMainState(final Field<T> field) {
83
84
85 final FieldSpacecraftState<T> state = createState(field);
86 final AdaptiveStepsizeFieldIntegrator<T> integrator = createIntegrator(field, state);
87 final FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
88 propagator.setInitialState(state);
89
90
91 final MainStateModifier<T> modifier = new MainStateModifier<>();
92
93
94 propagator.addAdditionalDataProvider(modifier);
95
96
97 final double dt = 600.0;
98 final FieldSpacecraftState<T> propagated = propagator.propagate(state.getDate().shiftedBy(dt));
99
100
101 Assertions.assertEquals(2 * SpacecraftState.DEFAULT_MASS, propagated.getMass().getReal(), 1.0e-12);
102 Assertions.assertEquals(FastMath.PI,
103 propagated.getAttitude().getRotation().getAngle().getReal(),
104 1.0e-15);
105
106 }
107
108 @Test
109 public void testIssue900Numerical() {
110 doTestIssue900Numerical(Binary64Field.getInstance());
111 }
112
113 private <T extends CalculusFieldElement<T>> void doTestIssue900Numerical(final Field<T> field) {
114
115
116 final FieldSpacecraftState<T> state = createState(field);
117 final AdaptiveStepsizeFieldIntegrator<T> integrator = createIntegrator(field, state);
118 final FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
119 propagator.setInitialState(state);
120
121
122 final String name = "init";
123 final TimeDifferenceProvider<T> provider = new TimeDifferenceProvider<>(name, field);
124 Assertions.assertFalse(provider.wasCalled());
125
126
127 propagator.addAdditionalDataProvider(provider);
128
129
130 final double dt = 600.0;
131 final FieldSpacecraftState<T> propagated = propagator.propagate(state.getDate().shiftedBy(dt));
132
133
134 Assertions.assertTrue(provider.wasCalled());
135 Assertions.assertEquals(dt, propagated.getAdditionalState(name)[0].getReal(), 0.01);
136
137 }
138
139 @Test
140 public void testIssue900Dsst() {
141 doTestIssue900Dsst(Binary64Field.getInstance());
142 }
143
144 private <T extends CalculusFieldElement<T>> void doTestIssue900Dsst(final Field<T> field) {
145
146
147 final FieldSpacecraftState<T> state = createState(field);
148 final AdaptiveStepsizeFieldIntegrator<T> integrator = createIntegrator(field, state);
149 final FieldDSSTPropagator<T> propagator = new FieldDSSTPropagator<>(field, integrator);
150 propagator.setInitialState(state, PropagationType.MEAN);
151
152
153 final String name = "init";
154 final TimeDifferenceProvider<T> provider = new TimeDifferenceProvider<>(name, field);
155 Assertions.assertFalse(provider.wasCalled());
156
157
158 propagator.addAdditionalDataProvider(provider);
159
160
161 final double dt = 600.0;
162 final FieldSpacecraftState<T> propagated = propagator.propagate(state.getDate().shiftedBy(dt));
163
164
165 Assertions.assertTrue(provider.wasCalled());
166 Assertions.assertEquals(dt, propagated.getAdditionalState(name)[0].getReal(), 0.01);
167
168 }
169
170 @Test
171 public void testIssue900BrouwerLyddane() {
172 doTestIssue900BrouwerLyddane(Binary64Field.getInstance());
173 }
174
175 private <T extends CalculusFieldElement<T>> void doTestIssue900BrouwerLyddane(final Field<T> field) {
176
177
178 final FieldSpacecraftState<T> state = createState(field);
179 final FieldBrouwerLyddanePropagator<T> propagator =
180 new FieldBrouwerLyddanePropagator<>(state.getOrbit(), GravityFieldFactory.getUnnormalizedProvider(5, 0), BrouwerLyddanePropagator.M2);
181
182
183 final String name = "init";
184 final TimeDifferenceProvider<T> provider = new TimeDifferenceProvider<>(name, field);
185 Assertions.assertFalse(provider.wasCalled());
186
187
188 propagator.addAdditionalDataProvider(provider);
189
190
191 final double dt = 600.0;
192 final FieldSpacecraftState<T> propagated = propagator.propagate(state.getDate().shiftedBy(dt));
193
194
195 Assertions.assertTrue(provider.wasCalled());
196 Assertions.assertEquals(dt, propagated.getAdditionalState(name)[0].getReal(), 0.01);
197
198 }
199
200 @Test
201 void testPropagateAdditionalStringData() {
202 doTestPropagateAdditionalStringData(Binary64Field.getInstance());
203 }
204
205 private <T extends CalculusFieldElement<T>> void doTestPropagateAdditionalStringData(Field<T> field) {
206
207 final FieldSpacecraftState<T> state = createState(field);
208 final AdaptiveStepsizeFieldIntegrator<T> integrator = createIntegrator(field, state);
209 final FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
210 propagator.setInitialState(state);
211
212 final MainStringDataModifier<T> modifier = new MainStringDataModifier<>();
213 propagator.addAdditionalDataProvider(modifier);
214
215 final FieldSpacecraftState<T> propagated = propagator.propagate(state.getDate().shiftedBy(DURATION));
216 Assertions.assertEquals(STRING_AFTER, propagated.getAdditionalData(MainStringDataModifier.class.getSimpleName()));
217 }
218
219 @Test
220 void testInterpolationAdditionalStringData() {
221 doTestInterpolationAdditionalStringData(Binary64Field.getInstance());
222 }
223
224 private <T extends CalculusFieldElement<T>> void doTestInterpolationAdditionalStringData(Field<T> field) {
225 final FieldSpacecraftState<T> state = createState(field);
226 final AdaptiveStepsizeFieldIntegrator<T> integrator = createIntegrator(field, state);
227 final FieldNumericalPropagator<T> propagator = new FieldNumericalPropagator<>(field, integrator);
228 propagator.setInitialState(state);
229
230 final MainStringDataModifier<T> modifier = new MainStringDataModifier<>();
231 propagator.addAdditionalDataProvider(modifier);
232 FieldEphemerisGenerator<T> generator = propagator.getEphemerisGenerator();
233 propagator.propagate(state.getDate().shiftedBy(DURATION));
234 FieldBoundedPropagator<T> ephemeris = generator.getGeneratedEphemeris();
235
236 Assertions.assertEquals(STRING_BEFORE, getAdditionalDataAt(ephemeris, state.getDate().shiftedBy(DURATION / 2 - 0.1)));
237 Assertions.assertEquals(STRING_AFTER, getAdditionalDataAt(ephemeris, state.getDate().shiftedBy(DURATION / 2)));
238 Assertions.assertEquals(STRING_AFTER, getAdditionalDataAt(ephemeris, state.getDate().shiftedBy(DURATION / 2 + 0.1)));
239 }
240
241 private <T extends CalculusFieldElement<T>> Object getAdditionalDataAt(FieldPropagator<T> propagator, FieldAbsoluteDate<T> date) {
242 return propagator.propagate(date).getAdditionalData(MainStringDataModifier.class.getSimpleName());
243 }
244
245 private static class MainStringDataModifier<T extends CalculusFieldElement<T>> implements FieldAdditionalDataProvider<String, T> {
246
247 private String value;
248
249 @Override
250 public void init(FieldSpacecraftState<T> initialState, FieldAbsoluteDate<T> target) {
251 value = target.getDate().isBefore(initialState.getDate().shiftedBy(DURATION / 2)) ? STRING_BEFORE : STRING_AFTER;
252 }
253
254 @Override
255 public String getAdditionalData(FieldSpacecraftState<T> state) {
256 return value;
257 }
258
259 @Override
260 public String getName() {
261 return MainStringDataModifier.class.getSimpleName();
262 }
263 }
264
265 private static class MainStateModifier<T extends CalculusFieldElement<T>> extends FieldAbstractStateModifier<T> {
266
267 @Override
268 public FieldSpacecraftState<T> change(final FieldSpacecraftState<T> state) {
269 final Field<T> field = state.getDate().getField();
270 return new FieldSpacecraftState<>(state.getOrbit(),
271 new FieldAttitude<>(state.getDate(),
272 state.getFrame(),
273 new FieldRotation<>(field.getZero(),
274 field.getZero(),
275 field.getZero(),
276 field.getOne(),
277 false),
278 FieldVector3D.getZero(field),
279 FieldVector3D.getZero(field)),
280 field.getZero().newInstance(2 * SpacecraftState.DEFAULT_MASS));
281 }
282 }
283
284 private static class TimeDifferenceProvider<T extends CalculusFieldElement<T>> implements FieldAdditionalDataProvider<T[], T> {
285
286 private final String name;
287 private boolean called;
288 private T dt;
289 private final Field<T> field;
290
291 public TimeDifferenceProvider(final String name, final Field<T> field) {
292 this.name = name;
293 this.called = false;
294 this.dt = field.getZero();
295 this.field = field;
296 }
297
298 @Override
299 public void init(FieldSpacecraftState<T> initialState, FieldAbsoluteDate<T> target) {
300 this.called = true;
301 this.dt = target.durationFrom(initialState.getDate());
302 }
303
304 @Override
305 public String getName() {
306 return name;
307 }
308
309 @Override
310 public T[] getAdditionalData(FieldSpacecraftState<T> state) {
311 final T[] array = MathArrays.buildArray(field, 1);
312 array[0] = dt;
313 return array;
314 }
315
316 public boolean wasCalled() {
317 return called;
318 }
319
320 }
321
322 }