1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.propagation.analytical;
18
19 import java.io.Serializable;
20 import java.util.List;
21 import java.util.stream.Collectors;
22
23 import org.hipparchus.exception.LocalizedCoreFormats;
24 import org.hipparchus.exception.MathIllegalArgumentException;
25 import org.hipparchus.util.FastMath;
26 import org.orekit.attitudes.Attitude;
27 import org.orekit.attitudes.AttitudeProvider;
28 import org.orekit.attitudes.InertialProvider;
29 import org.orekit.errors.OrekitException;
30 import org.orekit.errors.OrekitMessages;
31 import org.orekit.frames.Frame;
32 import org.orekit.orbits.Orbit;
33 import org.orekit.propagation.BoundedPropagator;
34 import org.orekit.propagation.SpacecraftState;
35 import org.orekit.time.AbsoluteDate;
36 import org.orekit.utils.DoubleArrayDictionary;
37 import org.orekit.utils.ImmutableTimeStampedCache;
38 import org.orekit.utils.PVCoordinatesProvider;
39 import org.orekit.utils.TimeStampedPVCoordinates;
40
41
42
43
44
45
46
47
48
49 public class Ephemeris extends AbstractAnalyticalPropagator implements BoundedPropagator {
50
51
52
53
54 public static final double DEFAULT_EXTRAPOLATION_THRESHOLD_SEC = 1e-3;
55
56
57 private final AbsoluteDate minDate;
58
59
60 private final AbsoluteDate maxDate;
61
62
63 private final double extrapolationThreshold;
64
65
66 private final Frame frame;
67
68
69 private final String[] additional;
70
71
72 private LocalPVProvider pvProvider;
73
74
75 private final transient ImmutableTimeStampedCache<SpacecraftState> cache;
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 public Ephemeris(final List<SpacecraftState> states, final int interpolationPoints)
92 throws MathIllegalArgumentException {
93 this(states, interpolationPoints, DEFAULT_EXTRAPOLATION_THRESHOLD_SEC);
94 }
95
96
97
98
99
100
101
102
103
104
105
106
107 public Ephemeris(final List<SpacecraftState> states, final int interpolationPoints,
108 final double extrapolationThreshold)
109 throws MathIllegalArgumentException {
110 this(states, interpolationPoints, extrapolationThreshold,
111
112 states.isEmpty() ? null : InertialProvider.of(states.get(0).getFrame()));
113 }
114
115
116
117
118
119
120
121
122
123
124
125 public Ephemeris(final List<SpacecraftState> states,
126 final int interpolationPoints,
127 final double extrapolationThreshold,
128 final AttitudeProvider attitudeProvider)
129 throws MathIllegalArgumentException {
130
131 super(attitudeProvider);
132
133 if (states.size() < interpolationPoints) {
134 throw new MathIllegalArgumentException(LocalizedCoreFormats.INSUFFICIENT_DIMENSION,
135 states.size(), interpolationPoints);
136 }
137
138 final SpacecraftState s0 = states.get(0);
139 minDate = s0.getDate();
140 maxDate = states.get(states.size() - 1).getDate();
141 frame = s0.getFrame();
142
143 final List<DoubleArrayDictionary.Entry> as = s0.getAdditionalStatesValues().getData();
144 additional = new String[as.size()];
145 for (int i = 0; i < additional.length; ++i) {
146 additional[i] = as.get(i).getKey();
147 }
148
149
150 for (final SpacecraftState state : states) {
151 s0.ensureCompatibleAdditionalStates(state);
152 }
153
154 pvProvider = new LocalPVProvider(states, interpolationPoints, extrapolationThreshold);
155
156
157 setAttitudeProvider(null);
158
159
160 cache = new ImmutableTimeStampedCache<SpacecraftState>(interpolationPoints, states);
161
162 this.extrapolationThreshold = extrapolationThreshold;
163 }
164
165
166
167
168 public AbsoluteDate getMinDate() {
169 return minDate;
170 }
171
172
173
174
175 public AbsoluteDate getMaxDate() {
176 return maxDate;
177 }
178
179
180
181
182
183 public double getExtrapolationThreshold() {
184 return extrapolationThreshold;
185 }
186
187 @Override
188 public Frame getFrame() {
189 return frame;
190 }
191
192 @Override
193
194 public SpacecraftState basicPropagate(final AbsoluteDate date) {
195 final SpacecraftState evaluatedState;
196
197 final AbsoluteDate central;
198 if (date.compareTo(minDate) < 0 && FastMath.abs(date.durationFrom(minDate)) <= extrapolationThreshold) {
199
200 central = minDate;
201 } else if (date.compareTo(maxDate) > 0 && FastMath.abs(date.durationFrom(maxDate)) <= extrapolationThreshold) {
202
203 central = maxDate;
204 } else {
205 central = date;
206 }
207 final List<SpacecraftState> neighbors = cache.getNeighbors(central).collect(Collectors.toList());
208 evaluatedState = neighbors.get(0).interpolate(date, neighbors);
209
210 final AttitudeProvider attitudeProvider = getAttitudeProvider();
211
212 if (attitudeProvider == null) {
213 return evaluatedState;
214 } else {
215 pvProvider.setCurrentState(evaluatedState);
216 final Attitude calculatedAttitude = attitudeProvider.getAttitude(pvProvider, date,
217 evaluatedState.getFrame());
218
219
220 if (evaluatedState.isOrbitDefined()) {
221 return new SpacecraftState(evaluatedState.getOrbit(), calculatedAttitude, evaluatedState.getMass(),
222 evaluatedState.getAdditionalStatesValues(), evaluatedState.getAdditionalStatesDerivatives());
223 } else {
224 return new SpacecraftState(evaluatedState.getAbsPVA(), calculatedAttitude, evaluatedState.getMass(),
225 evaluatedState.getAdditionalStatesValues(), evaluatedState.getAdditionalStatesDerivatives());
226 }
227
228 }
229 }
230
231
232 protected Orbit propagateOrbit(final AbsoluteDate date) {
233 return basicPropagate(date).getOrbit();
234 }
235
236
237 protected double getMass(final AbsoluteDate date) {
238 return basicPropagate(date).getMass();
239 }
240
241
242 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame f) {
243 return propagate(date).getPVCoordinates(f);
244 }
245
246
247
248
249
250
251
252 public void resetInitialState(final SpacecraftState state) {
253 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
254 }
255
256
257 protected void resetIntermediateState(final SpacecraftState state, final boolean forward) {
258 throw new OrekitException(OrekitMessages.NON_RESETABLE_STATE);
259 }
260
261
262 public SpacecraftState getInitialState() {
263 return basicPropagate(getMinDate());
264 }
265
266
267 @Override
268 public boolean isAdditionalStateManaged(final String name) {
269
270
271 if (super.isAdditionalStateManaged(name)) {
272 return true;
273 }
274
275
276 for (final String a : additional) {
277 if (a.equals(name)) {
278 return true;
279 }
280 }
281
282 return false;
283
284 }
285
286
287 @Override
288 public String[] getManagedAdditionalStates() {
289 final String[] upperManaged = super.getManagedAdditionalStates();
290 final String[] managed = new String[upperManaged.length + additional.length];
291 System.arraycopy(upperManaged, 0, managed, 0, upperManaged.length);
292 System.arraycopy(additional, 0, managed, upperManaged.length, additional.length);
293 return managed;
294 }
295
296
297 private static class LocalPVProvider implements PVCoordinatesProvider, Serializable {
298
299
300 private static final long serialVersionUID = 20160115L;
301
302
303 private SpacecraftState currentState;
304
305
306 private List<SpacecraftState> states;
307
308
309 private int interpolationPoints;
310
311
312 private double extrapolationThreshold;
313
314
315
316
317
318
319 LocalPVProvider(final List<SpacecraftState> states, final int interpolationPoints,
320 final double extrapolationThreshold) {
321
322 this.states = states;
323 this.interpolationPoints = interpolationPoints;
324 this.extrapolationThreshold = extrapolationThreshold;
325 }
326
327
328
329
330 public SpacecraftState getCurrentState() {
331 return currentState;
332 }
333
334
335
336
337 public void setCurrentState(final SpacecraftState state) {
338 this.currentState = state;
339 }
340
341
342 public TimeStampedPVCoordinates getPVCoordinates(final AbsoluteDate date, final Frame f) {
343 final double dt = getCurrentState().getDate().durationFrom(date);
344 final double closeEnoughTimeInSec = 1e-9;
345
346 if (FastMath.abs(dt) > closeEnoughTimeInSec) {
347
348
349 final Ephemeris ephemeris = new Ephemeris(states, interpolationPoints, extrapolationThreshold, null);
350 return ephemeris.getPVCoordinates(date, f);
351 }
352
353 return currentState.getPVCoordinates(f);
354
355 }
356
357 }
358
359 }