1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import org.hipparchus.analysis.interpolation.HermiteInterpolator;
20 import org.hipparchus.util.MathUtils;
21 import org.orekit.errors.OrekitInternalError;
22 import org.orekit.frames.Frame;
23 import org.orekit.time.AbsoluteDate;
24 import org.orekit.time.TimeInterpolator;
25 import org.orekit.utils.CartesianDerivativesFilter;
26 import org.orekit.utils.TimeStampedPVCoordinates;
27 import org.orekit.utils.TimeStampedPVCoordinatesHermiteInterpolator;
28
29 import java.util.List;
30 import java.util.stream.Stream;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class OrbitHermiteInterpolator extends AbstractOrbitInterpolator {
54
55
56 private final CartesianDerivativesFilter pvaFilter;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 public OrbitHermiteInterpolator(final Frame outputInertialFrame) {
72 this(DEFAULT_INTERPOLATION_POINTS, outputInertialFrame);
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public OrbitHermiteInterpolator(final int interpolationPoints, final Frame outputInertialFrame) {
89 this(interpolationPoints, outputInertialFrame, CartesianDerivativesFilter.USE_PVA);
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public OrbitHermiteInterpolator(final int interpolationPoints, final Frame outputInertialFrame,
105 final CartesianDerivativesFilter pvaFilter) {
106 this(interpolationPoints, DEFAULT_EXTRAPOLATION_THRESHOLD_SEC, outputInertialFrame, pvaFilter);
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public OrbitHermiteInterpolator(final int interpolationPoints, final double extrapolationThreshold,
123 final Frame outputInertialFrame, final CartesianDerivativesFilter pvaFilter) {
124 super(interpolationPoints, extrapolationThreshold, outputInertialFrame);
125 this.pvaFilter = pvaFilter;
126 }
127
128
129
130
131 public CartesianDerivativesFilter getPVAFilter() {
132 return pvaFilter;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156 @Override
157 protected Orbit interpolate(final InterpolationData interpolationData) {
158
159 final List<Orbit> sample = interpolationData.getNeighborList();
160
161
162 final OrbitType orbitType = sample.get(0).getType();
163
164 if (orbitType == OrbitType.CARTESIAN) {
165 return interpolateCartesian(interpolationData.getInterpolationDate(), sample);
166 }
167 else {
168 return interpolateCommon(interpolationData.getInterpolationDate(), sample, orbitType);
169 }
170
171 }
172
173
174
175
176
177
178
179
180
181 private CartesianOrbit interpolateCartesian(final AbsoluteDate interpolationDate, final List<Orbit> sample) {
182
183
184 final TimeInterpolator<TimeStampedPVCoordinates> interpolator =
185 new TimeStampedPVCoordinatesHermiteInterpolator(getNbInterpolationPoints(), getExtrapolationThreshold(),
186 pvaFilter);
187
188
189 final Stream<Orbit> sampleStream = sample.stream();
190
191
192 final Stream<TimeStampedPVCoordinates> sampleTimeStampedPV = sampleStream.map(Orbit::getPVCoordinates);
193
194
195 final TimeStampedPVCoordinates interpolated = interpolator.interpolate(interpolationDate, sampleTimeStampedPV);
196
197
198 final double mu = sample.get(0).getMu();
199
200 return new CartesianOrbit(interpolated, getOutputInertialFrame(), interpolationDate, mu);
201 }
202
203
204
205
206
207
208
209
210
211
212 private Orbit interpolateCommon(final AbsoluteDate interpolationDate, final List<Orbit> orbits,
213 final OrbitType orbitType) {
214
215
216 boolean useDerivatives = true;
217 for (final Orbit orbit : orbits) {
218 useDerivatives = useDerivatives && orbit.hasDerivatives();
219 }
220
221
222 final double mu = orbits.get(0).getMu();
223
224
225 final double[][] interpolated;
226 switch (orbitType) {
227 case CIRCULAR:
228 interpolated = interpolateCircular(interpolationDate, orbits, useDerivatives);
229 return new CircularOrbit(interpolated[0][0], interpolated[0][1], interpolated[0][2],
230 interpolated[0][3], interpolated[0][4], interpolated[0][5],
231 interpolated[1][0], interpolated[1][1], interpolated[1][2],
232 interpolated[1][3], interpolated[1][4], interpolated[1][5],
233 PositionAngleType.MEAN, getOutputInertialFrame(), interpolationDate, mu);
234 case KEPLERIAN:
235 interpolated = interpolateKeplerian(interpolationDate, orbits, useDerivatives);
236 return new KeplerianOrbit(interpolated[0][0], interpolated[0][1], interpolated[0][2],
237 interpolated[0][3], interpolated[0][4], interpolated[0][5],
238 interpolated[1][0], interpolated[1][1], interpolated[1][2],
239 interpolated[1][3], interpolated[1][4], interpolated[1][5],
240 PositionAngleType.MEAN, getOutputInertialFrame(), interpolationDate, mu);
241 case EQUINOCTIAL:
242 interpolated = interpolateEquinoctial(interpolationDate, orbits, useDerivatives);
243 return new EquinoctialOrbit(interpolated[0][0], interpolated[0][1], interpolated[0][2],
244 interpolated[0][3], interpolated[0][4], interpolated[0][5],
245 interpolated[1][0], interpolated[1][1], interpolated[1][2],
246 interpolated[1][3], interpolated[1][4], interpolated[1][5],
247 PositionAngleType.MEAN, getOutputInertialFrame(), interpolationDate, mu);
248 default:
249
250 throw new OrekitInternalError(null);
251 }
252
253 }
254
255
256
257
258
259
260
261
262
263
264 private double[][] interpolateCircular(final AbsoluteDate interpolationDate, final List<Orbit> orbits,
265 final boolean useDerivatives) {
266
267
268 final HermiteInterpolator interpolator = new HermiteInterpolator();
269
270
271 AbsoluteDate previousDate = null;
272 double previousRAAN = Double.NaN;
273 double previousAlphaM = Double.NaN;
274 for (final Orbit orbit : orbits) {
275 final CircularOrbit circ = (CircularOrbit) OrbitType.CIRCULAR.convertType(orbit);
276 final double continuousRAAN;
277 final double continuousAlphaM;
278 if (previousDate == null) {
279 continuousRAAN = circ.getRightAscensionOfAscendingNode();
280 continuousAlphaM = circ.getAlphaM();
281 }
282 else {
283 final double dt = circ.getDate().durationFrom(previousDate);
284 final double keplerAM = previousAlphaM + circ.getKeplerianMeanMotion() * dt;
285 continuousRAAN = MathUtils.normalizeAngle(circ.getRightAscensionOfAscendingNode(), previousRAAN);
286 continuousAlphaM = MathUtils.normalizeAngle(circ.getAlphaM(), keplerAM);
287 }
288 previousDate = circ.getDate();
289 previousRAAN = continuousRAAN;
290 previousAlphaM = continuousAlphaM;
291 if (useDerivatives) {
292 interpolator.addSamplePoint(circ.getDate().durationFrom(interpolationDate),
293 new double[] { circ.getA(),
294 circ.getCircularEx(),
295 circ.getCircularEy(),
296 circ.getI(),
297 continuousRAAN,
298 continuousAlphaM },
299 new double[] { circ.getADot(),
300 circ.getCircularExDot(),
301 circ.getCircularEyDot(),
302 circ.getIDot(),
303 circ.getRightAscensionOfAscendingNodeDot(),
304 circ.getAlphaMDot() });
305 }
306 else {
307 interpolator.addSamplePoint(circ.getDate().durationFrom(interpolationDate),
308 new double[] { circ.getA(),
309 circ.getCircularEx(),
310 circ.getCircularEy(),
311 circ.getI(),
312 continuousRAAN,
313 continuousAlphaM });
314 }
315 }
316
317 return interpolator.derivatives(0.0, 1);
318 }
319
320
321
322
323
324
325
326
327
328
329 private double[][] interpolateKeplerian(final AbsoluteDate interpolationDate, final List<Orbit> orbits,
330 final boolean useDerivatives) {
331
332
333 final HermiteInterpolator interpolator = new HermiteInterpolator();
334
335
336 AbsoluteDate previousDate = null;
337 double previousPA = Double.NaN;
338 double previousRAAN = Double.NaN;
339 double previousM = Double.NaN;
340 for (final Orbit orbit : orbits) {
341 final KeplerianOrbit kep = (KeplerianOrbit) OrbitType.KEPLERIAN.convertType(orbit);
342 final double continuousPA;
343 final double continuousRAAN;
344 final double continuousM;
345 if (previousDate == null) {
346 continuousPA = kep.getPerigeeArgument();
347 continuousRAAN = kep.getRightAscensionOfAscendingNode();
348 continuousM = kep.getMeanAnomaly();
349 }
350 else {
351 final double dt = kep.getDate().durationFrom(previousDate);
352 final double keplerM = previousM + kep.getKeplerianMeanMotion() * dt;
353 continuousPA = MathUtils.normalizeAngle(kep.getPerigeeArgument(), previousPA);
354 continuousRAAN = MathUtils.normalizeAngle(kep.getRightAscensionOfAscendingNode(), previousRAAN);
355 continuousM = MathUtils.normalizeAngle(kep.getMeanAnomaly(), keplerM);
356 }
357 previousDate = kep.getDate();
358 previousPA = continuousPA;
359 previousRAAN = continuousRAAN;
360 previousM = continuousM;
361 if (useDerivatives) {
362 interpolator.addSamplePoint(kep.getDate().durationFrom(interpolationDate),
363 new double[] { kep.getA(),
364 kep.getE(),
365 kep.getI(),
366 continuousPA,
367 continuousRAAN,
368 continuousM },
369 new double[] { kep.getADot(),
370 kep.getEDot(),
371 kep.getIDot(),
372 kep.getPerigeeArgumentDot(),
373 kep.getRightAscensionOfAscendingNodeDot(),
374 kep.getMeanAnomalyDot() });
375 }
376 else {
377 interpolator.addSamplePoint(kep.getDate().durationFrom(interpolationDate),
378 new double[] { kep.getA(),
379 kep.getE(),
380 kep.getI(),
381 continuousPA,
382 continuousRAAN,
383 continuousM });
384 }
385 }
386
387 return interpolator.derivatives(0.0, 1);
388 }
389
390
391
392
393
394
395
396
397
398
399 private double[][] interpolateEquinoctial(final AbsoluteDate interpolationDate, final List<Orbit> orbits,
400 final boolean useDerivatives) {
401
402
403 final HermiteInterpolator interpolator = new HermiteInterpolator();
404
405
406 AbsoluteDate previousDate = null;
407 double previousLm = Double.NaN;
408 for (final Orbit orbit : orbits) {
409 final EquinoctialOrbit equi = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);
410 final double continuousLm;
411 if (previousDate == null) {
412 continuousLm = equi.getLM();
413 }
414 else {
415 final double dt = equi.getDate().durationFrom(previousDate);
416 final double keplerLm = previousLm + equi.getKeplerianMeanMotion() * dt;
417 continuousLm = MathUtils.normalizeAngle(equi.getLM(), keplerLm);
418 }
419 previousDate = equi.getDate();
420 previousLm = continuousLm;
421 if (useDerivatives) {
422 interpolator.addSamplePoint(equi.getDate().durationFrom(interpolationDate),
423 new double[] { equi.getA(),
424 equi.getEquinoctialEx(),
425 equi.getEquinoctialEy(),
426 equi.getHx(),
427 equi.getHy(),
428 continuousLm },
429 new double[] {
430 equi.getADot(),
431 equi.getEquinoctialExDot(),
432 equi.getEquinoctialEyDot(),
433 equi.getHxDot(),
434 equi.getHyDot(),
435 equi.getLMDot() });
436 }
437 else {
438 interpolator.addSamplePoint(equi.getDate().durationFrom(interpolationDate),
439 new double[] { equi.getA(),
440 equi.getEquinoctialEx(),
441 equi.getEquinoctialEy(),
442 equi.getHx(),
443 equi.getHy(),
444 continuousLm });
445 }
446 }
447
448 return interpolator.derivatives(0.0, 1);
449 }
450 }