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.NotSerializableException;
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.SortedSet;
24
25 import org.hipparchus.analysis.differentiation.DSFactory;
26 import org.hipparchus.analysis.differentiation.DerivativeStructure;
27 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
28 import org.hipparchus.geometry.euclidean.threed.Vector3D;
29 import org.hipparchus.util.FastMath;
30 import org.hipparchus.util.MathUtils;
31 import org.orekit.attitudes.AttitudeProvider;
32 import org.orekit.errors.OrekitException;
33 import org.orekit.errors.OrekitInternalError;
34 import org.orekit.errors.OrekitMessages;
35 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider;
36 import org.orekit.forces.gravity.potential.UnnormalizedSphericalHarmonicsProvider.UnnormalizedSphericalHarmonics;
37 import org.orekit.orbits.CartesianOrbit;
38 import org.orekit.orbits.CircularOrbit;
39 import org.orekit.orbits.Orbit;
40 import org.orekit.orbits.OrbitType;
41 import org.orekit.orbits.PositionAngle;
42 import org.orekit.propagation.AdditionalStateProvider;
43 import org.orekit.propagation.SpacecraftState;
44 import org.orekit.time.AbsoluteDate;
45 import org.orekit.utils.TimeSpanMap;
46 import org.orekit.utils.TimeStampedPVCoordinates;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84 public class EcksteinHechlerPropagator extends AbstractAnalyticalPropagator implements Serializable {
85
86
87 private static final long serialVersionUID = 20151202L;
88
89
90 private EHModel initialModel;
91
92
93 private transient TimeSpanMap<EHModel> models;
94
95
96 private double referenceRadius;
97
98
99 private double mu;
100
101
102 private double[] ck0;
103
104
105
106
107
108
109
110
111 public EcksteinHechlerPropagator(final Orbit initialOrbit,
112 final UnnormalizedSphericalHarmonicsProvider provider)
113 throws OrekitException {
114 this(initialOrbit, DEFAULT_LAW, DEFAULT_MASS, provider,
115 provider.onDate(initialOrbit.getDate()));
116 }
117
118
119
120
121
122
123
124
125
126
127 public EcksteinHechlerPropagator(final Orbit initialOrbit,
128 final AttitudeProvider attitude,
129 final double mass,
130 final UnnormalizedSphericalHarmonicsProvider provider,
131 final UnnormalizedSphericalHarmonics harmonics)
132 throws OrekitException {
133 this(initialOrbit, attitude, mass, provider.getAe(), provider.getMu(),
134 harmonics.getUnnormalizedCnm(2, 0),
135 harmonics.getUnnormalizedCnm(3, 0),
136 harmonics.getUnnormalizedCnm(4, 0),
137 harmonics.getUnnormalizedCnm(5, 0),
138 harmonics.getUnnormalizedCnm(6, 0));
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public EcksteinHechlerPropagator(final Orbit initialOrbit,
165 final double referenceRadius, final double mu,
166 final double c20, final double c30, final double c40,
167 final double c50, final double c60)
168 throws OrekitException {
169 this(initialOrbit, DEFAULT_LAW, DEFAULT_MASS, referenceRadius, mu, c20, c30, c40, c50, c60);
170 }
171
172
173
174
175
176
177
178
179
180 public EcksteinHechlerPropagator(final Orbit initialOrbit, final double mass,
181 final UnnormalizedSphericalHarmonicsProvider provider)
182 throws OrekitException {
183 this(initialOrbit, DEFAULT_LAW, mass, provider, provider.onDate(initialOrbit.getDate()));
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209 public EcksteinHechlerPropagator(final Orbit initialOrbit, final double mass,
210 final double referenceRadius, final double mu,
211 final double c20, final double c30, final double c40,
212 final double c50, final double c60)
213 throws OrekitException {
214 this(initialOrbit, DEFAULT_LAW, mass, referenceRadius, mu, c20, c30, c40, c50, c60);
215 }
216
217
218
219
220
221
222
223
224
225 public EcksteinHechlerPropagator(final Orbit initialOrbit,
226 final AttitudeProvider attitudeProv,
227 final UnnormalizedSphericalHarmonicsProvider provider)
228 throws OrekitException {
229 this(initialOrbit, attitudeProv, DEFAULT_MASS, provider, provider.onDate(initialOrbit.getDate()));
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 public EcksteinHechlerPropagator(final Orbit initialOrbit,
256 final AttitudeProvider attitudeProv,
257 final double referenceRadius, final double mu,
258 final double c20, final double c30, final double c40,
259 final double c50, final double c60)
260 throws OrekitException {
261 this(initialOrbit, attitudeProv, DEFAULT_MASS, referenceRadius, mu, c20, c30, c40, c50, c60);
262 }
263
264
265
266
267
268
269
270
271
272 public EcksteinHechlerPropagator(final Orbit initialOrbit,
273 final AttitudeProvider attitudeProv,
274 final double mass,
275 final UnnormalizedSphericalHarmonicsProvider provider)
276 throws OrekitException {
277 this(initialOrbit, attitudeProv, mass, provider, provider.onDate(initialOrbit.getDate()));
278 }
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 public EcksteinHechlerPropagator(final Orbit initialOrbit,
304 final AttitudeProvider attitudeProv,
305 final double mass,
306 final double referenceRadius, final double mu,
307 final double c20, final double c30, final double c40,
308 final double c50, final double c60)
309 throws OrekitException {
310
311 super(attitudeProv);
312
313
314 this.referenceRadius = referenceRadius;
315 this.mu = mu;
316 this.ck0 = new double[] {
317 0.0, 0.0, c20, c30, c40, c50, c60
318 };
319
320
321
322 resetInitialState(new SpacecraftState(initialOrbit,
323 attitudeProv.getAttitude(initialOrbit,
324 initialOrbit.getDate(),
325 initialOrbit.getFrame()),
326 mass));
327
328 }
329
330
331 public void resetInitialState(final SpacecraftState state)
332 throws OrekitException {
333 super.resetInitialState(state);
334 this.initialModel = computeMeanParameters((CircularOrbit) OrbitType.CIRCULAR.convertType(state.getOrbit()),
335 state.getMass());
336 this.models = new TimeSpanMap<EHModel>(initialModel);
337 }
338
339
340 protected void resetIntermediateState(final SpacecraftState state, final boolean forward)
341 throws OrekitException {
342 final EHModel newModel = computeMeanParameters((CircularOrbit) OrbitType.CIRCULAR.convertType(state.getOrbit()),
343 state.getMass());
344 if (forward) {
345 models.addValidAfter(newModel, state.getDate());
346 } else {
347 models.addValidBefore(newModel, state.getDate());
348 }
349 }
350
351
352
353
354
355
356
357
358
359 private EHModel computeMeanParameters(final CircularOrbit osculating, final double mass)
360 throws OrekitException {
361
362
363 if (osculating.getA() < referenceRadius) {
364 throw new OrekitException(OrekitMessages.TRAJECTORY_INSIDE_BRILLOUIN_SPHERE,
365 osculating.getA());
366 }
367
368
369 EHModel current = new EHModel(osculating, mass, referenceRadius, mu, ck0);
370
371
372 final double epsilon = 1.0e-13;
373 final double thresholdA = epsilon * (1 + FastMath.abs(current.mean.getA()));
374 final double thresholdE = epsilon * (1 + current.mean.getE());
375 final double thresholdAngles = epsilon * FastMath.PI;
376
377 int i = 0;
378 while (i++ < 100) {
379
380
381 final DerivativeStructure[] parameters = current.propagateParameters(current.mean.getDate());
382
383
384 final double deltaA = osculating.getA() - parameters[0].getValue();
385 final double deltaEx = osculating.getCircularEx() - parameters[1].getValue();
386 final double deltaEy = osculating.getCircularEy() - parameters[2].getValue();
387 final double deltaI = osculating.getI() - parameters[3].getValue();
388 final double deltaRAAN = MathUtils.normalizeAngle(osculating.getRightAscensionOfAscendingNode() -
389 parameters[4].getValue(),
390 0.0);
391 final double deltaAlphaM = MathUtils.normalizeAngle(osculating.getAlphaM() - parameters[5].getValue(), 0.0);
392
393
394 current = new EHModel(new CircularOrbit(current.mean.getA() + deltaA,
395 current.mean.getCircularEx() + deltaEx,
396 current.mean.getCircularEy() + deltaEy,
397 current.mean.getI() + deltaI,
398 current.mean.getRightAscensionOfAscendingNode() + deltaRAAN,
399 current.mean.getAlphaM() + deltaAlphaM,
400 PositionAngle.MEAN,
401 current.mean.getFrame(),
402 current.mean.getDate(), mu),
403 mass, referenceRadius, mu, ck0);
404
405
406 if ((FastMath.abs(deltaA) < thresholdA) &&
407 (FastMath.abs(deltaEx) < thresholdE) &&
408 (FastMath.abs(deltaEy) < thresholdE) &&
409 (FastMath.abs(deltaI) < thresholdAngles) &&
410 (FastMath.abs(deltaRAAN) < thresholdAngles) &&
411 (FastMath.abs(deltaAlphaM) < thresholdAngles)) {
412 return current;
413 }
414
415 }
416
417 throw new OrekitException(OrekitMessages.UNABLE_TO_COMPUTE_ECKSTEIN_HECHLER_MEAN_PARAMETERS, i);
418
419 }
420
421
422 public CartesianOrbit propagateOrbit(final AbsoluteDate date)
423 throws OrekitException {
424
425
426 final EHModel current = models.get(date);
427 return new CartesianOrbit(toCartesian(date, current.propagateParameters(date)),
428 current.mean.getFrame(), mu);
429 }
430
431
432 private static class EHModel implements Serializable {
433
434
435 private static final long serialVersionUID = 20160115L;
436
437
438 private static final DSFactory FACTORY = new DSFactory(1, 2);
439
440
441 private final CircularOrbit mean;
442
443
444 private final double mass;
445
446
447
448
449 private final double xnotDot;
450 private final double rdpom;
451 private final double rdpomp;
452 private final double eps1;
453 private final double eps2;
454 private final double xim;
455 private final double ommD;
456 private final double rdl;
457 private final double aMD;
458
459 private final double kh;
460 private final double kl;
461
462 private final double ax1;
463 private final double ay1;
464 private final double as1;
465 private final double ac2;
466 private final double axy3;
467 private final double as3;
468 private final double ac4;
469 private final double as5;
470 private final double ac6;
471
472 private final double ex1;
473 private final double exx2;
474 private final double exy2;
475 private final double ex3;
476 private final double ex4;
477
478 private final double ey1;
479 private final double eyx2;
480 private final double eyy2;
481 private final double ey3;
482 private final double ey4;
483
484 private final double rx1;
485 private final double ry1;
486 private final double r2;
487 private final double r3;
488 private final double rl;
489
490 private final double iy1;
491 private final double ix1;
492 private final double i2;
493 private final double i3;
494 private final double ih;
495
496 private final double lx1;
497 private final double ly1;
498 private final double l2;
499 private final double l3;
500 private final double ll;
501
502
503
504
505
506
507
508
509
510
511
512 EHModel(final CircularOrbit mean, final double mass,
513 final double referenceRadius, final double mu, final double[] ck0)
514 throws OrekitException {
515
516 this.mean = mean;
517 this.mass = mass;
518
519
520 double q = referenceRadius / mean.getA();
521 double ql = q * q;
522 final double g2 = ck0[2] * ql;
523 ql *= q;
524 final double g3 = ck0[3] * ql;
525 ql *= q;
526 final double g4 = ck0[4] * ql;
527 ql *= q;
528 final double g5 = ck0[5] * ql;
529 ql *= q;
530 final double g6 = ck0[6] * ql;
531
532 final double cosI1 = FastMath.cos(mean.getI());
533 final double sinI1 = FastMath.sin(mean.getI());
534 final double sinI2 = sinI1 * sinI1;
535 final double sinI4 = sinI2 * sinI2;
536 final double sinI6 = sinI2 * sinI4;
537
538 if (sinI2 < 1.0e-10) {
539 throw new OrekitException(OrekitMessages.ALMOST_EQUATORIAL_ORBIT,
540 FastMath.toDegrees(mean.getI()));
541 }
542
543 if (FastMath.abs(sinI2 - 4.0 / 5.0) < 1.0e-3) {
544 throw new OrekitException(OrekitMessages.ALMOST_CRITICALLY_INCLINED_ORBIT,
545 FastMath.toDegrees(mean.getI()));
546 }
547
548 if (mean.getE() > 0.1) {
549
550 throw new OrekitException(OrekitMessages.TOO_LARGE_ECCENTRICITY_FOR_PROPAGATION_MODEL,
551 mean.getE());
552 }
553
554 xnotDot = FastMath.sqrt(mu / mean.getA()) / mean.getA();
555
556 rdpom = -0.75 * g2 * (4.0 - 5.0 * sinI2);
557 rdpomp = 7.5 * g4 * (1.0 - 31.0 / 8.0 * sinI2 + 49.0 / 16.0 * sinI4) -
558 13.125 * g6 * (1.0 - 8.0 * sinI2 + 129.0 / 8.0 * sinI4 - 297.0 / 32.0 * sinI6);
559
560 q = 3.0 / (32.0 * rdpom);
561 eps1 = q * g4 * sinI2 * (30.0 - 35.0 * sinI2) -
562 175.0 * q * g6 * sinI2 * (1.0 - 3.0 * sinI2 + 2.0625 * sinI4);
563 q = 3.0 * sinI1 / (8.0 * rdpom);
564 eps2 = q * g3 * (4.0 - 5.0 * sinI2) - q * g5 * (10.0 - 35.0 * sinI2 + 26.25 * sinI4);
565
566 xim = mean.getI();
567 ommD = cosI1 * (1.50 * g2 - 2.25 * g2 * g2 * (2.5 - 19.0 / 6.0 * sinI2) +
568 0.9375 * g4 * (7.0 * sinI2 - 4.0) +
569 3.28125 * g6 * (2.0 - 9.0 * sinI2 + 8.25 * sinI4));
570
571 rdl = 1.0 - 1.50 * g2 * (3.0 - 4.0 * sinI2);
572 aMD = rdl +
573 2.25 * g2 * g2 * (9.0 - 263.0 / 12.0 * sinI2 + 341.0 / 24.0 * sinI4) +
574 15.0 / 16.0 * g4 * (8.0 - 31.0 * sinI2 + 24.5 * sinI4) +
575 105.0 / 32.0 * g6 * (-10.0 / 3.0 + 25.0 * sinI2 - 48.75 * sinI4 + 27.5 * sinI6);
576
577 final double qq = -1.5 * g2 / rdl;
578 final double qA = 0.75 * g2 * g2 * sinI2;
579 final double qB = 0.25 * g4 * sinI2;
580 final double qC = 105.0 / 16.0 * g6 * sinI2;
581 final double qD = -0.75 * g3 * sinI1;
582 final double qE = 3.75 * g5 * sinI1;
583 kh = 0.375 / rdpom;
584 kl = kh / sinI1;
585
586 ax1 = qq * (2.0 - 3.5 * sinI2);
587 ay1 = qq * (2.0 - 2.5 * sinI2);
588 as1 = qD * (4.0 - 5.0 * sinI2) +
589 qE * (2.625 * sinI4 - 3.5 * sinI2 + 1.0);
590 ac2 = qq * sinI2 +
591 qA * 7.0 * (2.0 - 3.0 * sinI2) +
592 qB * (15.0 - 17.5 * sinI2) +
593 qC * (3.0 * sinI2 - 1.0 - 33.0 / 16.0 * sinI4);
594 axy3 = qq * 3.5 * sinI2;
595 as3 = qD * 5.0 / 3.0 * sinI2 +
596 qE * 7.0 / 6.0 * sinI2 * (1.0 - 1.125 * sinI2);
597 ac4 = qA * sinI2 +
598 qB * 4.375 * sinI2 +
599 qC * 0.75 * (1.1 * sinI4 - sinI2);
600
601 as5 = qE * 21.0 / 80.0 * sinI4;
602
603 ac6 = qC * -11.0 / 80.0 * sinI4;
604
605 ex1 = qq * (1.0 - 1.25 * sinI2);
606 exx2 = qq * 0.5 * (3.0 - 5.0 * sinI2);
607 exy2 = qq * (2.0 - 1.5 * sinI2);
608 ex3 = qq * 7.0 / 12.0 * sinI2;
609 ex4 = qq * 17.0 / 8.0 * sinI2;
610
611 ey1 = qq * (1.0 - 1.75 * sinI2);
612 eyx2 = qq * (1.0 - 3.0 * sinI2);
613 eyy2 = qq * (2.0 * sinI2 - 1.5);
614 ey3 = qq * 7.0 / 12.0 * sinI2;
615 ey4 = qq * 17.0 / 8.0 * sinI2;
616
617 q = -qq * cosI1;
618 rx1 = 3.5 * q;
619 ry1 = -2.5 * q;
620 r2 = -0.5 * q;
621 r3 = 7.0 / 6.0 * q;
622 rl = g3 * cosI1 * (4.0 - 15.0 * sinI2) -
623 2.5 * g5 * cosI1 * (4.0 - 42.0 * sinI2 + 52.5 * sinI4);
624
625 q = 0.5 * qq * sinI1 * cosI1;
626 iy1 = q;
627 ix1 = -q;
628 i2 = q;
629 i3 = q * 7.0 / 3.0;
630 ih = -g3 * cosI1 * (4.0 - 5.0 * sinI2) +
631 2.5 * g5 * cosI1 * (4.0 - 14.0 * sinI2 + 10.5 * sinI4);
632
633 lx1 = qq * (7.0 - 77.0 / 8.0 * sinI2);
634 ly1 = qq * (55.0 / 8.0 * sinI2 - 7.50);
635 l2 = qq * (1.25 * sinI2 - 0.5);
636 l3 = qq * (77.0 / 24.0 * sinI2 - 7.0 / 6.0);
637 ll = g3 * (53.0 * sinI2 - 4.0 - 57.5 * sinI4) +
638 2.5 * g5 * (4.0 - 96.0 * sinI2 + 269.5 * sinI4 - 183.75 * sinI6);
639
640 }
641
642
643
644
645
646
647 public DerivativeStructure[] propagateParameters(final AbsoluteDate date)
648 throws OrekitException {
649
650
651 final DerivativeStructure dt = FACTORY.variable(0, date.durationFrom(mean.getDate()));
652 final DerivativeStructure xnot = dt.multiply(xnotDot);
653
654
655
656
657 final DerivativeStructure x = xnot.multiply(rdpom + rdpomp);
658 final DerivativeStructure cx = x.cos();
659 final DerivativeStructure sx = x.sin();
660 final DerivativeStructure exm = cx.multiply(mean.getCircularEx()).
661 add(sx.multiply(eps2 - (1.0 - eps1) * mean.getCircularEy()));
662 final DerivativeStructure eym = sx.multiply((1.0 + eps1) * mean.getCircularEx()).
663 add(cx.multiply(mean.getCircularEy() - eps2)).
664 add(eps2);
665
666
667
668
669 final DerivativeStructure omm =
670 FACTORY.build(MathUtils.normalizeAngle(mean.getRightAscensionOfAscendingNode() + ommD * xnot.getValue(),
671 FastMath.PI),
672 ommD * xnotDot,
673 0.0);
674
675
676 final DerivativeStructure xlm =
677 FACTORY.build(MathUtils.normalizeAngle(mean.getAlphaM() + aMD * xnot.getValue(), FastMath.PI),
678 aMD * xnotDot,
679 0.0);
680
681
682 final DerivativeStructure cl1 = xlm.cos();
683 final DerivativeStructure sl1 = xlm.sin();
684 final DerivativeStructure cl2 = cl1.multiply(cl1).subtract(sl1.multiply(sl1));
685 final DerivativeStructure sl2 = cl1.multiply(sl1).add(sl1.multiply(cl1));
686 final DerivativeStructure cl3 = cl2.multiply(cl1).subtract(sl2.multiply(sl1));
687 final DerivativeStructure sl3 = cl2.multiply(sl1).add(sl2.multiply(cl1));
688 final DerivativeStructure cl4 = cl3.multiply(cl1).subtract(sl3.multiply(sl1));
689 final DerivativeStructure sl4 = cl3.multiply(sl1).add(sl3.multiply(cl1));
690 final DerivativeStructure cl5 = cl4.multiply(cl1).subtract(sl4.multiply(sl1));
691 final DerivativeStructure sl5 = cl4.multiply(sl1).add(sl4.multiply(cl1));
692 final DerivativeStructure cl6 = cl5.multiply(cl1).subtract(sl5.multiply(sl1));
693
694 final DerivativeStructure qh = eym.subtract(eps2).multiply(kh);
695 final DerivativeStructure ql = exm.multiply(kl);
696
697 final DerivativeStructure exmCl1 = exm.multiply(cl1);
698 final DerivativeStructure exmSl1 = exm.multiply(sl1);
699 final DerivativeStructure eymCl1 = eym.multiply(cl1);
700 final DerivativeStructure eymSl1 = eym.multiply(sl1);
701 final DerivativeStructure exmCl2 = exm.multiply(cl2);
702 final DerivativeStructure exmSl2 = exm.multiply(sl2);
703 final DerivativeStructure eymCl2 = eym.multiply(cl2);
704 final DerivativeStructure eymSl2 = eym.multiply(sl2);
705 final DerivativeStructure exmCl3 = exm.multiply(cl3);
706 final DerivativeStructure exmSl3 = exm.multiply(sl3);
707 final DerivativeStructure eymCl3 = eym.multiply(cl3);
708 final DerivativeStructure eymSl3 = eym.multiply(sl3);
709 final DerivativeStructure exmCl4 = exm.multiply(cl4);
710 final DerivativeStructure exmSl4 = exm.multiply(sl4);
711 final DerivativeStructure eymCl4 = eym.multiply(cl4);
712 final DerivativeStructure eymSl4 = eym.multiply(sl4);
713
714
715 final DerivativeStructure rda = exmCl1.multiply(ax1).
716 add(eymSl1.multiply(ay1)).
717 add(sl1.multiply(as1)).
718 add(cl2.multiply(ac2)).
719 add(exmCl3.add(eymSl3).multiply(axy3)).
720 add(sl3.multiply(as3)).
721 add(cl4.multiply(ac4)).
722 add(sl5.multiply(as5)).
723 add(cl6.multiply(ac6));
724
725
726 final DerivativeStructure rdex = cl1.multiply(ex1).
727 add(exmCl2.multiply(exx2)).
728 add(eymSl2.multiply(exy2)).
729 add(cl3.multiply(ex3)).
730 add(exmCl4.add(eymSl4).multiply(ex4));
731 final DerivativeStructure rdey = sl1.multiply(ey1).
732 add(exmSl2.multiply(eyx2)).
733 add(eymCl2.multiply(eyy2)).
734 add(sl3.multiply(ey3)).
735 add(exmSl4.subtract(eymCl4).multiply(ey4));
736
737
738 final DerivativeStructure rdom = exmSl1.multiply(rx1).
739 add(eymCl1.multiply(ry1)).
740 add(sl2.multiply(r2)).
741 add(eymCl3.subtract(exmSl3).multiply(r3)).
742 add(ql.multiply(rl));
743
744
745 final DerivativeStructure rdxi = eymSl1.multiply(iy1).
746 add(exmCl1.multiply(ix1)).
747 add(cl2.multiply(i2)).
748 add(exmCl3.add(eymSl3).multiply(i3)).
749 add(qh.multiply(ih));
750
751
752 final DerivativeStructure rdxl = exmSl1.multiply(lx1).
753 add(eymCl1.multiply(ly1)).
754 add(sl2.multiply(l2)).
755 add(exmSl3.subtract(eymCl3).multiply(l3)).
756 add(ql.multiply(ll));
757
758
759 return new DerivativeStructure[] {
760 rda.add(1.0).multiply(mean.getA()),
761 rdex.add(exm),
762 rdey.add(eym),
763 rdxi.add(xim),
764 rdom.add(omm),
765 rdxl.add(xlm)
766 };
767
768 }
769
770 }
771
772
773
774
775
776
777 private TimeStampedPVCoordinates toCartesian(final AbsoluteDate date, final DerivativeStructure[] parameters) {
778
779
780 final DerivativeStructure cosOmega = parameters[4].cos();
781 final DerivativeStructure sinOmega = parameters[4].sin();
782 final DerivativeStructure cosI = parameters[3].cos();
783 final DerivativeStructure sinI = parameters[3].sin();
784 final DerivativeStructure alphaE = meanToEccentric(parameters[5], parameters[1], parameters[2]);
785 final DerivativeStructure cosAE = alphaE.cos();
786 final DerivativeStructure sinAE = alphaE.sin();
787 final DerivativeStructure ex2 = parameters[1].multiply(parameters[1]);
788 final DerivativeStructure ey2 = parameters[2].multiply(parameters[2]);
789 final DerivativeStructure exy = parameters[1].multiply(parameters[2]);
790 final DerivativeStructure q = ex2.add(ey2).subtract(1).negate().sqrt();
791 final DerivativeStructure beta = q.add(1).reciprocal();
792 final DerivativeStructure bx2 = beta.multiply(ex2);
793 final DerivativeStructure by2 = beta.multiply(ey2);
794 final DerivativeStructure bxy = beta.multiply(exy);
795 final DerivativeStructure u = bxy.multiply(sinAE).subtract(parameters[1].add(by2.subtract(1).multiply(cosAE)));
796 final DerivativeStructure v = bxy.multiply(cosAE).subtract(parameters[2].add(bx2.subtract(1).multiply(sinAE)));
797 final DerivativeStructure x = parameters[0].multiply(u);
798 final DerivativeStructure y = parameters[0].multiply(v);
799
800
801 final FieldVector3D<DerivativeStructure> p =
802 new FieldVector3D<>(x.multiply(cosOmega).subtract(y.multiply(cosI.multiply(sinOmega))),
803 x.multiply(sinOmega).add(y.multiply(cosI.multiply(cosOmega))),
804 y.multiply(sinI));
805
806
807 final Vector3D p0 = new Vector3D(p.getX().getValue(),
808 p.getY().getValue(),
809 p.getZ().getValue());
810 final Vector3D p1 = new Vector3D(p.getX().getPartialDerivative(1),
811 p.getY().getPartialDerivative(1),
812 p.getZ().getPartialDerivative(1));
813 final Vector3D p2 = new Vector3D(p.getX().getPartialDerivative(2),
814 p.getY().getPartialDerivative(2),
815 p.getZ().getPartialDerivative(2));
816 return new TimeStampedPVCoordinates(date, p0, p1, p2);
817
818 }
819
820
821
822
823
824
825
826 private DerivativeStructure meanToEccentric(final DerivativeStructure alphaM,
827 final DerivativeStructure ex,
828 final DerivativeStructure ey) {
829
830
831
832 DerivativeStructure alphaE = alphaM;
833 DerivativeStructure shift = alphaM.getField().getZero();
834 DerivativeStructure alphaEMalphaM = alphaM.getField().getZero();
835 DerivativeStructure cosAlphaE = alphaE.cos();
836 DerivativeStructure sinAlphaE = alphaE.sin();
837 int iter = 0;
838 do {
839 final DerivativeStructure f2 = ex.multiply(sinAlphaE).subtract(ey.multiply(cosAlphaE));
840 final DerivativeStructure f1 = alphaM.getField().getOne().subtract(ex.multiply(cosAlphaE)).subtract(ey.multiply(sinAlphaE));
841 final DerivativeStructure f0 = alphaEMalphaM.subtract(f2);
842
843 final DerivativeStructure f12 = f1.multiply(2);
844 shift = f0.multiply(f12).divide(f1.multiply(f12).subtract(f0.multiply(f2)));
845
846 alphaEMalphaM = alphaEMalphaM.subtract(shift);
847 alphaE = alphaM.add(alphaEMalphaM);
848 cosAlphaE = alphaE.cos();
849 sinAlphaE = alphaE.sin();
850
851 } while ((++iter < 50) && (FastMath.abs(shift.getValue()) > 1.0e-12));
852
853 return alphaE;
854
855 }
856
857
858 protected double getMass(final AbsoluteDate date) {
859 return models.get(date).mass;
860 }
861
862
863
864
865
866 private Object writeReplace() throws NotSerializableException {
867 try {
868
869 final List<AdditionalStateProvider> serializableProviders = new ArrayList<AdditionalStateProvider>();
870 for (final AdditionalStateProvider provider : getAdditionalStateProviders()) {
871 if (provider instanceof Serializable) {
872 serializableProviders.add(provider);
873 } else {
874 throw new NotSerializableException(provider.getClass().getName());
875 }
876 }
877
878
879 final AbsoluteDate[] transitionDates;
880 final CircularOrbit[] allOrbits;
881 final double[] allMasses;
882 final SortedSet<TimeSpanMap.Transition<EHModel>> transitions = models.getTransitions();
883 if (transitions.size() == 1 && transitions.first().getBefore() == transitions.first().getAfter()) {
884
885
886 transitionDates = null;
887 allOrbits = null;
888 allMasses = null;
889 } else {
890 transitionDates = new AbsoluteDate[transitions.size()];
891 allOrbits = new CircularOrbit[transitions.size() + 1];
892 allMasses = new double[transitions.size() + 1];
893 int i = 0;
894 for (final TimeSpanMap.Transition<EHModel> transition : transitions) {
895 if (i == 0) {
896
897 allOrbits[i] = transition.getBefore().mean;
898 allMasses[i] = transition.getBefore().mass;
899 }
900 transitionDates[i] = transition.getDate();
901 allOrbits[++i] = transition.getAfter().mean;
902 allMasses[i] = transition.getAfter().mass;
903 }
904 }
905
906 return new DataTransferObject(getInitialState().getOrbit(), initialModel.mass,
907 referenceRadius, mu, ck0, getAttitudeProvider(),
908 transitionDates, allOrbits, allMasses,
909 serializableProviders.toArray(new AdditionalStateProvider[serializableProviders.size()]));
910 } catch (OrekitException orekitException) {
911
912 throw new OrekitInternalError(null);
913 }
914
915 }
916
917
918 private static class DataTransferObject implements Serializable {
919
920
921 private static final long serialVersionUID = 20151202L;
922
923
924 private final Orbit orbit;
925
926
927 private final AttitudeProvider attitudeProvider;
928
929
930 private double[] g;
931
932
933 private final AbsoluteDate[] transitionDates;
934
935
936 private final CircularOrbit[] allOrbits;
937
938
939 private final double[] allMasses;
940
941
942 private final AdditionalStateProvider[] providers;
943
944
945
946
947
948
949
950
951
952
953
954
955
956 DataTransferObject(final Orbit orbit, final double mass,
957 final double referenceRadius, final double mu,
958 final double[] ck0,
959 final AttitudeProvider attitudeProvider,
960 final AbsoluteDate[] transitionDates,
961 final CircularOrbit[] allOrbits,
962 final double[] allMasses,
963 final AdditionalStateProvider[] providers) {
964 this.orbit = orbit;
965 this.attitudeProvider = attitudeProvider;
966 this.g = new double[] {
967 mass, referenceRadius, mu,
968 ck0[2], ck0[3], ck0[4], ck0[5], ck0[6]
969 };
970 this.transitionDates = transitionDates;
971 this.allOrbits = allOrbits;
972 this.allMasses = allMasses;
973 this.providers = providers;
974 }
975
976
977
978
979 private Object readResolve() {
980 try {
981 final EcksteinHechlerPropagator propagator =
982 new EcksteinHechlerPropagator(orbit, attitudeProvider,
983 g[0], g[1], g[2],
984 g[3], g[4], g[5], g[6], g[7]);
985 for (final AdditionalStateProvider provider : providers) {
986 propagator.addAdditionalStateProvider(provider);
987
988 }
989 if (transitionDates != null) {
990
991 final double[] ck0 = new double[] {
992 0, 0, g[3], g[4], g[5], g[6], g[7]
993 };
994 propagator.models = new TimeSpanMap<EHModel>(new EHModel(allOrbits[0], allMasses[0],
995 g[1], g[2], ck0));
996 for (int i = 0; i < transitionDates.length; ++i) {
997 propagator.models.addValidAfter(new EHModel(allOrbits[i + 1], allMasses[i + 1],
998 g[1], g[2], ck0),
999 transitionDates[i]);
1000 }
1001 }
1002
1003 return propagator;
1004 } catch (OrekitException oe) {
1005 throw new OrekitInternalError(oe);
1006 }
1007 }
1008
1009 }
1010
1011 }