1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import java.io.Serializable;
20
21 import org.hipparchus.analysis.differentiation.UnivariateDerivative1;
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.hipparchus.util.FastMath;
24 import org.hipparchus.util.SinCos;
25 import org.orekit.annotation.DefaultDataContext;
26 import org.orekit.data.DataContext;
27 import org.orekit.errors.OrekitException;
28 import org.orekit.errors.OrekitIllegalArgumentException;
29 import org.orekit.errors.OrekitInternalError;
30 import org.orekit.errors.OrekitMessages;
31 import org.orekit.frames.Frame;
32 import org.orekit.time.AbsoluteDate;
33 import org.orekit.utils.PVCoordinates;
34 import org.orekit.utils.TimeStampedPVCoordinates;
35
36
37
38
39
40
41
42
43
44
45
46
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 public class KeplerianOrbit extends Orbit implements PositionAngleBased {
77
78
79 private static final long serialVersionUID = 20231217L;
80
81
82 private static final String ECCENTRICITY = "eccentricity";
83
84
85 private final double a;
86
87
88 private final double e;
89
90
91 private final double i;
92
93
94 private final double pa;
95
96
97 private final double raan;
98
99
100 private final double cachedAnomaly;
101
102
103 private final double aDot;
104
105
106 private final double eDot;
107
108
109 private final double iDot;
110
111
112 private final double paDot;
113
114
115 private final double raanDot;
116
117
118 private final double cachedAnomalyDot;
119
120
121 private final PositionAngleType cachedPositionAngleType;
122
123
124 private transient PVCoordinates partialPV;
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 public KeplerianOrbit(final double a, final double e, final double i,
145 final double pa, final double raan, final double anomaly,
146 final PositionAngleType type, final PositionAngleType cachedPositionAngleType,
147 final Frame frame, final AbsoluteDate date, final double mu)
148 throws IllegalArgumentException {
149 this(a, e, i, pa, raan, anomaly,
150 Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN,
151 type, cachedPositionAngleType, frame, date, mu);
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public KeplerianOrbit(final double a, final double e, final double i,
171 final double pa, final double raan, final double anomaly,
172 final PositionAngleType type,
173 final Frame frame, final AbsoluteDate date, final double mu)
174 throws IllegalArgumentException {
175 this(a, e, i, pa, raan, anomaly, type, type, frame, date, mu);
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public KeplerianOrbit(final double a, final double e, final double i,
203 final double pa, final double raan, final double anomaly,
204 final double aDot, final double eDot, final double iDot,
205 final double paDot, final double raanDot, final double anomalyDot,
206 final PositionAngleType type, final PositionAngleType cachedPositionAngleType,
207 final Frame frame, final AbsoluteDate date, final double mu)
208 throws IllegalArgumentException {
209 super(frame, date, mu);
210 this.cachedPositionAngleType = cachedPositionAngleType;
211
212 if (a * (1 - e) < 0) {
213 throw new OrekitIllegalArgumentException(OrekitMessages.ORBIT_A_E_MISMATCH_WITH_CONIC_TYPE, a, e);
214 }
215
216
217 checkParameterRangeInclusive(ECCENTRICITY, e, 0.0, Double.POSITIVE_INFINITY);
218
219 this.a = a;
220 this.aDot = aDot;
221 this.e = e;
222 this.eDot = eDot;
223 this.i = i;
224 this.iDot = iDot;
225 this.pa = pa;
226 this.paDot = paDot;
227 this.raan = raan;
228 this.raanDot = raanDot;
229
230 if (hasDerivatives()) {
231 final UnivariateDerivative1 cachedAnomalyUD = initializeCachedAnomaly(anomaly, anomalyDot, type);
232 this.cachedAnomaly = cachedAnomalyUD.getValue();
233 this.cachedAnomalyDot = cachedAnomalyUD.getFirstDerivative();
234 } else {
235 this.cachedAnomaly = initializeCachedAnomaly(anomaly, type);
236 this.cachedAnomalyDot = Double.NaN;
237 }
238
239
240 if (!isElliptical()) {
241 final double trueAnomaly = getTrueAnomaly();
242 if (1 + e * FastMath.cos(trueAnomaly) <= 0) {
243 final double vMax = FastMath.acos(-1 / e);
244 throw new OrekitIllegalArgumentException(OrekitMessages.ORBIT_ANOMALY_OUT_OF_HYPERBOLIC_RANGE,
245 trueAnomaly, e, -vMax, vMax);
246 }
247 }
248
249 this.partialPV = null;
250
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public KeplerianOrbit(final double a, final double e, final double i,
277 final double pa, final double raan, final double anomaly,
278 final double aDot, final double eDot, final double iDot,
279 final double paDot, final double raanDot, final double anomalyDot,
280 final PositionAngleType type,
281 final Frame frame, final AbsoluteDate date, final double mu)
282 throws IllegalArgumentException {
283 this(a, e, i, pa, raan, anomaly, aDot, eDot, iDot, paDot, raanDot, anomalyDot, type, type,
284 frame, date, mu);
285 }
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301 public KeplerianOrbit(final TimeStampedPVCoordinates pvCoordinates,
302 final Frame frame, final double mu)
303 throws IllegalArgumentException {
304 this(pvCoordinates, frame, mu, hasNonKeplerianAcceleration(pvCoordinates, mu));
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 private KeplerianOrbit(final TimeStampedPVCoordinates pvCoordinates,
323 final Frame frame, final double mu,
324 final boolean reliableAcceleration)
325 throws IllegalArgumentException {
326 super(pvCoordinates, frame, mu);
327
328
329 final Vector3D momentum = pvCoordinates.getMomentum();
330 final double m2 = momentum.getNormSq();
331 i = Vector3D.angle(momentum, Vector3D.PLUS_K);
332
333
334 raan = Vector3D.crossProduct(Vector3D.PLUS_K, momentum).getAlpha();
335
336
337 final Vector3D pvP = pvCoordinates.getPosition();
338 final Vector3D pvV = pvCoordinates.getVelocity();
339 final Vector3D pvA = pvCoordinates.getAcceleration();
340 final double r2 = pvP.getNormSq();
341 final double r = FastMath.sqrt(r2);
342 final double V2 = pvV.getNormSq();
343 final double rV2OnMu = r * V2 / mu;
344
345
346 a = r / (2 - rV2OnMu);
347 final double muA = mu * a;
348
349
350 if (isElliptical()) {
351
352 final double eSE = Vector3D.dotProduct(pvP, pvV) / FastMath.sqrt(muA);
353 final double eCE = rV2OnMu - 1;
354 e = FastMath.sqrt(eSE * eSE + eCE * eCE);
355 this.cachedPositionAngleType = PositionAngleType.ECCENTRIC;
356 cachedAnomaly = FastMath.atan2(eSE, eCE);
357 } else {
358
359 final double eSH = Vector3D.dotProduct(pvP, pvV) / FastMath.sqrt(-muA);
360 final double eCH = rV2OnMu - 1;
361 e = FastMath.sqrt(1 - m2 / muA);
362 this.cachedPositionAngleType = PositionAngleType.TRUE;
363 cachedAnomaly = KeplerianAnomalyUtility.hyperbolicEccentricToTrue(e, FastMath.log((eCH + eSH) / (eCH - eSH)) / 2);
364 }
365
366
367 checkParameterRangeInclusive(ECCENTRICITY, e, 0.0, Double.POSITIVE_INFINITY);
368
369
370 final Vector3D node = new Vector3D(raan, 0.0);
371 final double px = Vector3D.dotProduct(pvP, node);
372 final double py = Vector3D.dotProduct(pvP, Vector3D.crossProduct(momentum, node)) / FastMath.sqrt(m2);
373 pa = FastMath.atan2(py, px) - getTrueAnomaly();
374
375 partialPV = pvCoordinates;
376
377 if (reliableAcceleration) {
378
379
380 final double[][] jacobian = new double[6][6];
381 getJacobianWrtCartesian(PositionAngleType.MEAN, jacobian);
382
383 final Vector3D keplerianAcceleration = new Vector3D(-mu / (r * r2), pvP);
384 final Vector3D nonKeplerianAcceleration = pvA.subtract(keplerianAcceleration);
385 final double aX = nonKeplerianAcceleration.getX();
386 final double aY = nonKeplerianAcceleration.getY();
387 final double aZ = nonKeplerianAcceleration.getZ();
388 aDot = jacobian[0][3] * aX + jacobian[0][4] * aY + jacobian[0][5] * aZ;
389 eDot = jacobian[1][3] * aX + jacobian[1][4] * aY + jacobian[1][5] * aZ;
390 iDot = jacobian[2][3] * aX + jacobian[2][4] * aY + jacobian[2][5] * aZ;
391 paDot = jacobian[3][3] * aX + jacobian[3][4] * aY + jacobian[3][5] * aZ;
392 raanDot = jacobian[4][3] * aX + jacobian[4][4] * aY + jacobian[4][5] * aZ;
393
394
395
396 final double MDot = getKeplerianMeanMotion() +
397 jacobian[5][3] * aX + jacobian[5][4] * aY + jacobian[5][5] * aZ;
398 final UnivariateDerivative1 eUD = new UnivariateDerivative1(e, eDot);
399 final UnivariateDerivative1 MUD = new UnivariateDerivative1(getMeanAnomaly(), MDot);
400 if (cachedPositionAngleType == PositionAngleType.ECCENTRIC) {
401 final UnivariateDerivative1 EUD = (a < 0) ?
402 FieldKeplerianAnomalyUtility.hyperbolicMeanToEccentric(eUD, MUD) :
403 FieldKeplerianAnomalyUtility.ellipticMeanToEccentric(eUD, MUD);
404 cachedAnomalyDot = EUD.getFirstDerivative();
405 } else {
406 final UnivariateDerivative1 vUD = (a < 0) ?
407 FieldKeplerianAnomalyUtility.hyperbolicMeanToTrue(eUD, MUD) :
408 FieldKeplerianAnomalyUtility.ellipticMeanToTrue(eUD, MUD);
409 cachedAnomalyDot = vUD.getFirstDerivative();
410 }
411
412 } else {
413
414
415
416 aDot = Double.NaN;
417 eDot = Double.NaN;
418 iDot = Double.NaN;
419 paDot = Double.NaN;
420 raanDot = Double.NaN;
421 cachedAnomalyDot = Double.NaN;
422 }
423
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441 public KeplerianOrbit(final PVCoordinates pvCoordinates,
442 final Frame frame, final AbsoluteDate date, final double mu)
443 throws IllegalArgumentException {
444 this(new TimeStampedPVCoordinates(date, pvCoordinates), frame, mu);
445 }
446
447
448
449
450 public KeplerianOrbit(final Orbit op) {
451 this(op.getPVCoordinates(), op.getFrame(), op.getMu(), op.hasDerivatives());
452 }
453
454
455 @Override
456 public OrbitType getType() {
457 return OrbitType.KEPLERIAN;
458 }
459
460
461 @Override
462 public double getA() {
463 return a;
464 }
465
466
467 @Override
468 public double getADot() {
469 return aDot;
470 }
471
472
473 @Override
474 public double getE() {
475 return e;
476 }
477
478
479 @Override
480 public double getEDot() {
481 return eDot;
482 }
483
484
485 @Override
486 public double getI() {
487 return i;
488 }
489
490
491 @Override
492 public double getIDot() {
493 return iDot;
494 }
495
496
497
498
499 public double getPerigeeArgument() {
500 return pa;
501 }
502
503
504
505
506
507
508
509
510 public double getPerigeeArgumentDot() {
511 return paDot;
512 }
513
514
515
516
517 public double getRightAscensionOfAscendingNode() {
518 return raan;
519 }
520
521
522
523
524
525
526
527
528 public double getRightAscensionOfAscendingNodeDot() {
529 return raanDot;
530 }
531
532
533
534
535 public double getTrueAnomaly() {
536 switch (cachedPositionAngleType) {
537 case MEAN: return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicMeanToTrue(e, cachedAnomaly) :
538 KeplerianAnomalyUtility.ellipticMeanToTrue(e, cachedAnomaly);
539
540 case TRUE: return cachedAnomaly;
541
542 case ECCENTRIC: return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicEccentricToTrue(e, cachedAnomaly) :
543 KeplerianAnomalyUtility.ellipticEccentricToTrue(e, cachedAnomaly);
544
545 default: throw new OrekitInternalError(null);
546 }
547 }
548
549
550
551
552 public double getTrueAnomalyDot() {
553 if (hasDerivatives()) {
554 switch (cachedPositionAngleType) {
555 case MEAN:
556 final UnivariateDerivative1 eUD = new UnivariateDerivative1(e, eDot);
557 final UnivariateDerivative1 MUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
558 final UnivariateDerivative1 vUD = (a < 0) ?
559 FieldKeplerianAnomalyUtility.hyperbolicMeanToTrue(eUD, MUD) :
560 FieldKeplerianAnomalyUtility.ellipticMeanToTrue(eUD, MUD);
561 return vUD.getFirstDerivative();
562
563 case TRUE:
564 return cachedAnomalyDot;
565
566 case ECCENTRIC:
567 final UnivariateDerivative1 eUD2 = new UnivariateDerivative1(e, eDot);
568 final UnivariateDerivative1 EUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
569 final UnivariateDerivative1 vUD2 = (a < 0) ?
570 FieldKeplerianAnomalyUtility.hyperbolicEccentricToTrue(eUD2, EUD) :
571 FieldKeplerianAnomalyUtility.ellipticEccentricToTrue(eUD2, EUD);
572 return vUD2.getFirstDerivative();
573
574 default:
575 throw new OrekitInternalError(null);
576 }
577 } else {
578 return Double.NaN;
579 }
580 }
581
582
583
584
585 public double getEccentricAnomaly() {
586 switch (cachedPositionAngleType) {
587 case MEAN:
588 return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicMeanToEccentric(e, cachedAnomaly) :
589 KeplerianAnomalyUtility.ellipticMeanToEccentric(e, cachedAnomaly);
590
591 case ECCENTRIC:
592 return cachedAnomaly;
593
594 case TRUE:
595 return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicTrueToEccentric(e, cachedAnomaly) :
596 KeplerianAnomalyUtility.ellipticTrueToEccentric(e, cachedAnomaly);
597
598 default:
599 throw new OrekitInternalError(null);
600 }
601 }
602
603
604
605
606
607 public double getEccentricAnomalyDot() {
608 if (hasDerivatives()) {
609 switch (cachedPositionAngleType) {
610 case ECCENTRIC:
611 return cachedAnomalyDot;
612
613 case TRUE:
614 final UnivariateDerivative1 eUD = new UnivariateDerivative1(e, eDot);
615 final UnivariateDerivative1 vUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
616 final UnivariateDerivative1 EUD = (a < 0) ?
617 FieldKeplerianAnomalyUtility.hyperbolicTrueToEccentric(eUD, vUD) :
618 FieldKeplerianAnomalyUtility.ellipticTrueToEccentric(eUD, vUD);
619 return EUD.getFirstDerivative();
620
621 case MEAN:
622 final UnivariateDerivative1 eUD2 = new UnivariateDerivative1(e, eDot);
623 final UnivariateDerivative1 MUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
624 final UnivariateDerivative1 EUD2 = (a < 0) ?
625 FieldKeplerianAnomalyUtility.hyperbolicMeanToEccentric(eUD2, MUD) :
626 FieldKeplerianAnomalyUtility.ellipticMeanToEccentric(eUD2, MUD);
627 return EUD2.getFirstDerivative();
628
629 default:
630 throw new OrekitInternalError(null);
631 }
632 } else {
633 return Double.NaN;
634 }
635 }
636
637
638
639
640 public double getMeanAnomaly() {
641 switch (cachedPositionAngleType) {
642 case ECCENTRIC: return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicEccentricToMean(e, cachedAnomaly) :
643 KeplerianAnomalyUtility.ellipticEccentricToMean(e, cachedAnomaly);
644
645 case MEAN: return cachedAnomaly;
646
647 case TRUE: return (a < 0.) ? KeplerianAnomalyUtility.hyperbolicTrueToMean(e, cachedAnomaly) :
648 KeplerianAnomalyUtility.ellipticTrueToMean(e, cachedAnomaly);
649
650 default: throw new OrekitInternalError(null);
651 }
652 }
653
654
655
656
657
658 public double getMeanAnomalyDot() {
659 if (hasDerivatives()) {
660 switch (cachedPositionAngleType) {
661 case MEAN:
662 return cachedAnomalyDot;
663
664 case ECCENTRIC:
665 final UnivariateDerivative1 eUD = new UnivariateDerivative1(e, eDot);
666 final UnivariateDerivative1 EUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
667 final UnivariateDerivative1 MUD = (a < 0) ?
668 FieldKeplerianAnomalyUtility.hyperbolicEccentricToMean(eUD, EUD) :
669 FieldKeplerianAnomalyUtility.ellipticEccentricToMean(eUD, EUD);
670 return MUD.getFirstDerivative();
671
672 case TRUE:
673 final UnivariateDerivative1 eUD2 = new UnivariateDerivative1(e, eDot);
674 final UnivariateDerivative1 vUD = new UnivariateDerivative1(cachedAnomaly, cachedAnomalyDot);
675 final UnivariateDerivative1 MUD2 = (a < 0) ?
676 FieldKeplerianAnomalyUtility.hyperbolicTrueToMean(eUD2, vUD) :
677 FieldKeplerianAnomalyUtility.ellipticTrueToMean(eUD2, vUD);
678 return MUD2.getFirstDerivative();
679
680 default:
681 throw new OrekitInternalError(null);
682 }
683 } else {
684 return Double.NaN;
685 }
686 }
687
688
689
690
691
692 public double getAnomaly(final PositionAngleType type) {
693 return (type == PositionAngleType.MEAN) ? getMeanAnomaly() :
694 ((type == PositionAngleType.ECCENTRIC) ? getEccentricAnomaly() :
695 getTrueAnomaly());
696 }
697
698
699
700
701
702
703 public double getAnomalyDot(final PositionAngleType type) {
704 return (type == PositionAngleType.MEAN) ? getMeanAnomalyDot() :
705 ((type == PositionAngleType.ECCENTRIC) ? getEccentricAnomalyDot() :
706 getTrueAnomalyDot());
707 }
708
709
710 @Override
711 public double getEquinoctialEx() {
712 return e * FastMath.cos(pa + raan);
713 }
714
715
716 @Override
717 public double getEquinoctialExDot() {
718 final double paPraan = pa + raan;
719 final SinCos sc = FastMath.sinCos(paPraan);
720 return eDot * sc.cos() - e * sc.sin() * (paDot + raanDot);
721 }
722
723
724 @Override
725 public double getEquinoctialEy() {
726 return e * FastMath.sin(pa + raan);
727 }
728
729
730 @Override
731 public double getEquinoctialEyDot() {
732 final double paPraan = pa + raan;
733 final SinCos sc = FastMath.sinCos(paPraan);
734 return eDot * sc.sin() + e * sc.cos() * (paDot + raanDot);
735 }
736
737
738 @Override
739 public double getHx() {
740
741 if (FastMath.abs(i - FastMath.PI) < 1.0e-10) {
742 return Double.NaN;
743 }
744 return FastMath.cos(raan) * FastMath.tan(0.5 * i);
745 }
746
747
748 @Override
749 public double getHxDot() {
750
751 if (FastMath.abs(i - FastMath.PI) < 1.0e-10) {
752 return Double.NaN;
753 }
754 final SinCos sc = FastMath.sinCos(raan);
755 final double tan = FastMath.tan(0.5 * i);
756 return 0.5 * (1 + tan * tan) * sc.cos() * iDot - tan * sc.sin() * raanDot;
757 }
758
759
760 @Override
761 public double getHy() {
762
763 if (FastMath.abs(i - FastMath.PI) < 1.0e-10) {
764 return Double.NaN;
765 }
766 return FastMath.sin(raan) * FastMath.tan(0.5 * i);
767 }
768
769
770 @Override
771 public double getHyDot() {
772
773 if (FastMath.abs(i - FastMath.PI) < 1.0e-10) {
774 return Double.NaN;
775 }
776 final SinCos sc = FastMath.sinCos(raan);
777 final double tan = FastMath.tan(0.5 * i);
778 return 0.5 * (1 + tan * tan) * sc.sin() * iDot + tan * sc.cos() * raanDot;
779 }
780
781
782 @Override
783 public double getLv() {
784 return pa + raan + getTrueAnomaly();
785 }
786
787
788 @Override
789 public double getLvDot() {
790 return paDot + raanDot + getTrueAnomalyDot();
791 }
792
793
794 @Override
795 public double getLE() {
796 return pa + raan + getEccentricAnomaly();
797 }
798
799
800 @Override
801 public double getLEDot() {
802 return paDot + raanDot + getEccentricAnomalyDot();
803 }
804
805
806 @Override
807 public double getLM() {
808 return pa + raan + getMeanAnomaly();
809 }
810
811
812 @Override
813 public double getLMDot() {
814 return paDot + raanDot + getMeanAnomalyDot();
815 }
816
817
818
819
820
821
822
823
824 private UnivariateDerivative1 initializeCachedAnomaly(final double anomaly, final double anomalyDot,
825 final PositionAngleType inputType) {
826 if (cachedPositionAngleType == inputType) {
827 return new UnivariateDerivative1(anomaly, anomalyDot);
828
829 } else {
830 final UnivariateDerivative1 eUD = new UnivariateDerivative1(e, eDot);
831 final UnivariateDerivative1 anomalyUD = new UnivariateDerivative1(anomaly, anomalyDot);
832
833 if (a < 0) {
834 switch (cachedPositionAngleType) {
835 case MEAN:
836 if (inputType == PositionAngleType.ECCENTRIC) {
837 return FieldKeplerianAnomalyUtility.hyperbolicEccentricToMean(eUD, anomalyUD);
838 } else {
839 return FieldKeplerianAnomalyUtility.hyperbolicTrueToMean(eUD, anomalyUD);
840 }
841
842 case ECCENTRIC:
843 if (inputType == PositionAngleType.MEAN) {
844 return FieldKeplerianAnomalyUtility.hyperbolicMeanToEccentric(eUD, anomalyUD);
845 } else {
846 return FieldKeplerianAnomalyUtility.hyperbolicTrueToEccentric(eUD, anomalyUD);
847 }
848
849 case TRUE:
850 if (inputType == PositionAngleType.MEAN) {
851 return FieldKeplerianAnomalyUtility.hyperbolicMeanToTrue(eUD, anomalyUD);
852 } else {
853 return FieldKeplerianAnomalyUtility.hyperbolicEccentricToTrue(eUD, anomalyUD);
854 }
855
856 default:
857 break;
858 }
859
860 } else {
861 switch (cachedPositionAngleType) {
862 case MEAN:
863 if (inputType == PositionAngleType.ECCENTRIC) {
864 return FieldKeplerianAnomalyUtility.ellipticEccentricToMean(eUD, anomalyUD);
865 } else {
866 return FieldKeplerianAnomalyUtility.ellipticTrueToMean(eUD, anomalyUD);
867 }
868
869 case ECCENTRIC:
870 if (inputType == PositionAngleType.MEAN) {
871 return FieldKeplerianAnomalyUtility.ellipticMeanToEccentric(eUD, anomalyUD);
872 } else {
873 return FieldKeplerianAnomalyUtility.ellipticTrueToEccentric(eUD, anomalyUD);
874 }
875
876 case TRUE:
877 if (inputType == PositionAngleType.MEAN) {
878 return FieldKeplerianAnomalyUtility.ellipticMeanToTrue(eUD, anomalyUD);
879 } else {
880 return FieldKeplerianAnomalyUtility.ellipticEccentricToTrue(eUD, anomalyUD);
881 }
882
883 default:
884 break;
885 }
886
887 }
888 throw new OrekitInternalError(null);
889 }
890
891 }
892
893
894
895
896
897
898
899 private double initializeCachedAnomaly(final double anomaly, final PositionAngleType inputType) {
900 if (inputType == cachedPositionAngleType) {
901 return anomaly;
902
903 } else {
904 if (a < 0) {
905 switch (cachedPositionAngleType) {
906 case MEAN:
907 if (inputType == PositionAngleType.ECCENTRIC) {
908 return KeplerianAnomalyUtility.hyperbolicEccentricToMean(e, anomaly);
909 } else {
910 return KeplerianAnomalyUtility.hyperbolicTrueToMean(e, anomaly);
911 }
912
913 case ECCENTRIC:
914 if (inputType == PositionAngleType.MEAN) {
915 return KeplerianAnomalyUtility.hyperbolicMeanToEccentric(e, anomaly);
916 } else {
917 return KeplerianAnomalyUtility.hyperbolicTrueToEccentric(e, anomaly);
918 }
919
920 case TRUE:
921 if (inputType == PositionAngleType.ECCENTRIC) {
922 return KeplerianAnomalyUtility.hyperbolicEccentricToTrue(e, anomaly);
923 } else {
924 return KeplerianAnomalyUtility.hyperbolicMeanToTrue(e, anomaly);
925 }
926
927 default:
928 break;
929 }
930
931 } else {
932 switch (cachedPositionAngleType) {
933 case MEAN:
934 if (inputType == PositionAngleType.ECCENTRIC) {
935 return KeplerianAnomalyUtility.ellipticEccentricToMean(e, anomaly);
936 } else {
937 return KeplerianAnomalyUtility.ellipticTrueToMean(e, anomaly);
938 }
939
940 case ECCENTRIC:
941 if (inputType == PositionAngleType.MEAN) {
942 return KeplerianAnomalyUtility.ellipticMeanToEccentric(e, anomaly);
943 } else {
944 return KeplerianAnomalyUtility.ellipticTrueToEccentric(e, anomaly);
945 }
946
947 case TRUE:
948 if (inputType == PositionAngleType.ECCENTRIC) {
949 return KeplerianAnomalyUtility.ellipticEccentricToTrue(e, anomaly);
950 } else {
951 return KeplerianAnomalyUtility.ellipticMeanToTrue(e, anomaly);
952 }
953
954 default:
955 break;
956 }
957 }
958 throw new OrekitInternalError(null);
959 }
960 }
961
962
963
964
965
966 private Vector3D[] referenceAxes() {
967
968 final SinCos scRaan = FastMath.sinCos(raan);
969 final SinCos scPa = FastMath.sinCos(pa);
970 final SinCos scI = FastMath.sinCos(i);
971 final double cosRaan = scRaan.cos();
972 final double sinRaan = scRaan.sin();
973 final double cosPa = scPa.cos();
974 final double sinPa = scPa.sin();
975 final double cosI = scI.cos();
976 final double sinI = scI.sin();
977
978 final double crcp = cosRaan * cosPa;
979 final double crsp = cosRaan * sinPa;
980 final double srcp = sinRaan * cosPa;
981 final double srsp = sinRaan * sinPa;
982
983
984 return new Vector3D[] {
985 new Vector3D( crcp - cosI * srsp, srcp + cosI * crsp, sinI * sinPa),
986 new Vector3D(-crsp - cosI * srcp, -srsp + cosI * crcp, sinI * cosPa)
987 };
988
989 }
990
991
992
993 private void computePVWithoutA() {
994
995 if (partialPV != null) {
996
997 return;
998 }
999
1000 final Vector3D[] axes = referenceAxes();
1001
1002 if (isElliptical()) {
1003
1004
1005
1006
1007 final double uME2 = (1 - e) * (1 + e);
1008 final double s1Me2 = FastMath.sqrt(uME2);
1009 final SinCos scE = FastMath.sinCos(getEccentricAnomaly());
1010 final double cosE = scE.cos();
1011 final double sinE = scE.sin();
1012
1013
1014 final double x = a * (cosE - e);
1015 final double y = a * sinE * s1Me2;
1016 final double factor = FastMath.sqrt(getMu() / a) / (1 - e * cosE);
1017 final double xDot = -sinE * factor;
1018 final double yDot = cosE * s1Me2 * factor;
1019
1020 final Vector3D position = new Vector3D(x, axes[0], y, axes[1]);
1021 final Vector3D velocity = new Vector3D(xDot, axes[0], yDot, axes[1]);
1022 partialPV = new PVCoordinates(position, velocity);
1023
1024 } else {
1025
1026
1027
1028
1029 final SinCos scV = FastMath.sinCos(getTrueAnomaly());
1030 final double sinV = scV.sin();
1031 final double cosV = scV.cos();
1032 final double f = a * (1 - e * e);
1033 final double posFactor = f / (1 + e * cosV);
1034 final double velFactor = FastMath.sqrt(getMu() / f);
1035
1036 final double x = posFactor * cosV;
1037 final double y = posFactor * sinV;
1038 final double xDot = -velFactor * sinV;
1039 final double yDot = velFactor * (e + cosV);
1040
1041 final Vector3D position = new Vector3D(x, axes[0], y, axes[1]);
1042 final Vector3D velocity = new Vector3D(xDot, axes[0], yDot, axes[1]);
1043 partialPV = new PVCoordinates(position, velocity);
1044
1045 }
1046
1047 }
1048
1049
1050
1051
1052
1053
1054
1055 private Vector3D nonKeplerianAcceleration() {
1056
1057 final double[][] dCdP = new double[6][6];
1058 getJacobianWrtParameters(PositionAngleType.MEAN, dCdP);
1059
1060 final double nonKeplerianMeanMotion = getMeanAnomalyDot() - getKeplerianMeanMotion();
1061 final double nonKeplerianAx = dCdP[3][0] * aDot + dCdP[3][1] * eDot + dCdP[3][2] * iDot +
1062 dCdP[3][3] * paDot + dCdP[3][4] * raanDot + dCdP[3][5] * nonKeplerianMeanMotion;
1063 final double nonKeplerianAy = dCdP[4][0] * aDot + dCdP[4][1] * eDot + dCdP[4][2] * iDot +
1064 dCdP[4][3] * paDot + dCdP[4][4] * raanDot + dCdP[4][5] * nonKeplerianMeanMotion;
1065 final double nonKeplerianAz = dCdP[5][0] * aDot + dCdP[5][1] * eDot + dCdP[5][2] * iDot +
1066 dCdP[5][3] * paDot + dCdP[5][4] * raanDot + dCdP[5][5] * nonKeplerianMeanMotion;
1067
1068 return new Vector3D(nonKeplerianAx, nonKeplerianAy, nonKeplerianAz);
1069
1070 }
1071
1072
1073 @Override
1074 protected Vector3D initPosition() {
1075
1076 final Vector3D[] axes = referenceAxes();
1077
1078 if (isElliptical()) {
1079
1080
1081
1082
1083 final double uME2 = (1 - e) * (1 + e);
1084 final double s1Me2 = FastMath.sqrt(uME2);
1085 final SinCos scE = FastMath.sinCos(getEccentricAnomaly());
1086 final double cosE = scE.cos();
1087 final double sinE = scE.sin();
1088
1089 return new Vector3D(a * (cosE - e), axes[0], a * sinE * s1Me2, axes[1]);
1090
1091 } else {
1092
1093
1094
1095
1096 final SinCos scV = FastMath.sinCos(getTrueAnomaly());
1097 final double sinV = scV.sin();
1098 final double cosV = scV.cos();
1099 final double f = a * (1 - e * e);
1100 final double posFactor = f / (1 + e * cosV);
1101
1102 return new Vector3D(posFactor * cosV, axes[0], posFactor * sinV, axes[1]);
1103
1104 }
1105
1106 }
1107
1108
1109 @Override
1110 protected TimeStampedPVCoordinates initPVCoordinates() {
1111
1112
1113 computePVWithoutA();
1114
1115
1116 final double r2 = partialPV.getPosition().getNormSq();
1117 final Vector3D keplerianAcceleration = new Vector3D(-getMu() / (r2 * FastMath.sqrt(r2)), partialPV.getPosition());
1118 final Vector3D acceleration = hasDerivatives() ?
1119 keplerianAcceleration.add(nonKeplerianAcceleration()) :
1120 keplerianAcceleration;
1121
1122 return new TimeStampedPVCoordinates(getDate(), partialPV.getPosition(), partialPV.getVelocity(), acceleration);
1123
1124 }
1125
1126
1127 @Override
1128 public KeplerianOrbit shiftedBy(final double dt) {
1129
1130
1131 final KeplerianOrbit keplerianShifted = new KeplerianOrbit(a, e, i, pa, raan,
1132 getMeanAnomaly() + getKeplerianMeanMotion() * dt, PositionAngleType.MEAN,
1133 cachedPositionAngleType, getFrame(), getDate().shiftedBy(dt), getMu());
1134
1135 if (hasDerivatives()) {
1136
1137
1138 final Vector3D nonKeplerianAcceleration = nonKeplerianAcceleration();
1139
1140
1141 keplerianShifted.computePVWithoutA();
1142 final Vector3D fixedP = new Vector3D(1, keplerianShifted.partialPV.getPosition(),
1143 0.5 * dt * dt, nonKeplerianAcceleration);
1144 final double fixedR2 = fixedP.getNormSq();
1145 final double fixedR = FastMath.sqrt(fixedR2);
1146 final Vector3D fixedV = new Vector3D(1, keplerianShifted.partialPV.getVelocity(),
1147 dt, nonKeplerianAcceleration);
1148 final Vector3D fixedA = new Vector3D(-getMu() / (fixedR2 * fixedR), keplerianShifted.partialPV.getPosition(),
1149 1, nonKeplerianAcceleration);
1150
1151
1152 return new KeplerianOrbit(new TimeStampedPVCoordinates(keplerianShifted.getDate(),
1153 fixedP, fixedV, fixedA),
1154 keplerianShifted.getFrame(), keplerianShifted.getMu());
1155
1156 } else {
1157
1158 return keplerianShifted;
1159 }
1160
1161 }
1162
1163
1164 @Override
1165 protected double[][] computeJacobianMeanWrtCartesian() {
1166 if (isElliptical()) {
1167 return computeJacobianMeanWrtCartesianElliptical();
1168 } else {
1169 return computeJacobianMeanWrtCartesianHyperbolic();
1170 }
1171 }
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181 private double[][] computeJacobianMeanWrtCartesianElliptical() {
1182
1183 final double[][] jacobian = new double[6][6];
1184
1185
1186 computePVWithoutA();
1187 final Vector3D position = partialPV.getPosition();
1188 final Vector3D velocity = partialPV.getVelocity();
1189 final Vector3D momentum = partialPV.getMomentum();
1190 final double v2 = velocity.getNormSq();
1191 final double r2 = position.getNormSq();
1192 final double r = FastMath.sqrt(r2);
1193 final double r3 = r * r2;
1194
1195 final double px = position.getX();
1196 final double py = position.getY();
1197 final double pz = position.getZ();
1198 final double vx = velocity.getX();
1199 final double vy = velocity.getY();
1200 final double vz = velocity.getZ();
1201 final double mx = momentum.getX();
1202 final double my = momentum.getY();
1203 final double mz = momentum.getZ();
1204
1205 final double mu = getMu();
1206 final double sqrtMuA = FastMath.sqrt(a * mu);
1207 final double sqrtAoMu = FastMath.sqrt(a / mu);
1208 final double a2 = a * a;
1209 final double twoA = 2 * a;
1210 final double rOnA = r / a;
1211
1212 final double oMe2 = 1 - e * e;
1213 final double epsilon = FastMath.sqrt(oMe2);
1214 final double sqrtRec = 1 / epsilon;
1215
1216 final SinCos scI = FastMath.sinCos(i);
1217 final SinCos scPA = FastMath.sinCos(pa);
1218 final double cosI = scI.cos();
1219 final double sinI = scI.sin();
1220 final double cosPA = scPA.cos();
1221 final double sinPA = scPA.sin();
1222
1223 final double pv = Vector3D.dotProduct(position, velocity);
1224 final double cosE = (a - r) / (a * e);
1225 final double sinE = pv / (e * sqrtMuA);
1226
1227
1228 final Vector3D vectorAR = new Vector3D(2 * a2 / r3, position);
1229 final Vector3D vectorARDot = velocity.scalarMultiply(2 * a2 / mu);
1230 fillHalfRow(1, vectorAR, jacobian[0], 0);
1231 fillHalfRow(1, vectorARDot, jacobian[0], 3);
1232
1233
1234 final double factorER3 = pv / twoA;
1235 final Vector3D vectorER = new Vector3D(cosE * v2 / (r * mu), position,
1236 sinE / sqrtMuA, velocity,
1237 -factorER3 * sinE / sqrtMuA, vectorAR);
1238 final Vector3D vectorERDot = new Vector3D(sinE / sqrtMuA, position,
1239 cosE * 2 * r / mu, velocity,
1240 -factorER3 * sinE / sqrtMuA, vectorARDot);
1241 fillHalfRow(1, vectorER, jacobian[1], 0);
1242 fillHalfRow(1, vectorERDot, jacobian[1], 3);
1243
1244
1245 final double coefE = cosE / (e * sqrtMuA);
1246 final Vector3D vectorEAnR =
1247 new Vector3D(-sinE * v2 / (e * r * mu), position, coefE, velocity,
1248 -factorER3 * coefE, vectorAR);
1249
1250
1251 final Vector3D vectorEAnRDot =
1252 new Vector3D(-sinE * 2 * r / (e * mu), velocity, coefE, position,
1253 -factorER3 * coefE, vectorARDot);
1254
1255
1256 final double s1 = -sinE * pz / r - cosE * vz * sqrtAoMu;
1257 final double s2 = -cosE * pz / r3;
1258 final double s3 = -sinE * vz / (2 * sqrtMuA);
1259 final double t1 = sqrtRec * (cosE * pz / r - sinE * vz * sqrtAoMu);
1260 final double t2 = sqrtRec * (-sinE * pz / r3);
1261 final double t3 = sqrtRec * (cosE - e) * vz / (2 * sqrtMuA);
1262 final double t4 = sqrtRec * (e * sinI * cosPA * sqrtRec - vz * sqrtAoMu);
1263 final Vector3D s = new Vector3D(cosE / r, Vector3D.PLUS_K,
1264 s1, vectorEAnR,
1265 s2, position,
1266 s3, vectorAR);
1267 final Vector3D sDot = new Vector3D(-sinE * sqrtAoMu, Vector3D.PLUS_K,
1268 s1, vectorEAnRDot,
1269 s3, vectorARDot);
1270 final Vector3D t =
1271 new Vector3D(sqrtRec * sinE / r, Vector3D.PLUS_K).add(new Vector3D(t1, vectorEAnR,
1272 t2, position,
1273 t3, vectorAR,
1274 t4, vectorER));
1275 final Vector3D tDot = new Vector3D(sqrtRec * (cosE - e) * sqrtAoMu, Vector3D.PLUS_K,
1276 t1, vectorEAnRDot,
1277 t3, vectorARDot,
1278 t4, vectorERDot);
1279
1280
1281 final double factorI1 = -sinI * sqrtRec / sqrtMuA;
1282 final double i1 = factorI1;
1283 final double i2 = -factorI1 * mz / twoA;
1284 final double i3 = factorI1 * mz * e / oMe2;
1285 final double i4 = cosI * sinPA;
1286 final double i5 = cosI * cosPA;
1287 fillHalfRow(i1, new Vector3D(vy, -vx, 0), i2, vectorAR, i3, vectorER, i4, s, i5, t,
1288 jacobian[2], 0);
1289 fillHalfRow(i1, new Vector3D(-py, px, 0), i2, vectorARDot, i3, vectorERDot, i4, sDot, i5, tDot,
1290 jacobian[2], 3);
1291
1292
1293 fillHalfRow(cosPA / sinI, s, -sinPA / sinI, t, jacobian[3], 0);
1294 fillHalfRow(cosPA / sinI, sDot, -sinPA / sinI, tDot, jacobian[3], 3);
1295
1296
1297 final double factorRaanR = 1 / (mu * a * oMe2 * sinI * sinI);
1298 fillHalfRow(-factorRaanR * my, new Vector3D( 0, vz, -vy),
1299 factorRaanR * mx, new Vector3D(-vz, 0, vx),
1300 jacobian[4], 0);
1301 fillHalfRow(-factorRaanR * my, new Vector3D( 0, -pz, py),
1302 factorRaanR * mx, new Vector3D(pz, 0, -px),
1303 jacobian[4], 3);
1304
1305
1306 fillHalfRow(rOnA, vectorEAnR, -sinE, vectorER, jacobian[5], 0);
1307 fillHalfRow(rOnA, vectorEAnRDot, -sinE, vectorERDot, jacobian[5], 3);
1308
1309 return jacobian;
1310
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321 private double[][] computeJacobianMeanWrtCartesianHyperbolic() {
1322
1323 final double[][] jacobian = new double[6][6];
1324
1325
1326 computePVWithoutA();
1327 final Vector3D position = partialPV.getPosition();
1328 final Vector3D velocity = partialPV.getVelocity();
1329 final Vector3D momentum = partialPV.getMomentum();
1330 final double r2 = position.getNormSq();
1331 final double r = FastMath.sqrt(r2);
1332 final double r3 = r * r2;
1333
1334 final double x = position.getX();
1335 final double y = position.getY();
1336 final double z = position.getZ();
1337 final double vx = velocity.getX();
1338 final double vy = velocity.getY();
1339 final double vz = velocity.getZ();
1340 final double mx = momentum.getX();
1341 final double my = momentum.getY();
1342 final double mz = momentum.getZ();
1343
1344 final double mu = getMu();
1345 final double absA = -a;
1346 final double sqrtMuA = FastMath.sqrt(absA * mu);
1347 final double a2 = a * a;
1348 final double rOa = r / absA;
1349
1350 final SinCos scI = FastMath.sinCos(i);
1351 final double cosI = scI.cos();
1352 final double sinI = scI.sin();
1353
1354 final double pv = Vector3D.dotProduct(position, velocity);
1355
1356
1357 final Vector3D vectorAR = new Vector3D(-2 * a2 / r3, position);
1358 final Vector3D vectorARDot = velocity.scalarMultiply(-2 * a2 / mu);
1359 fillHalfRow(-1, vectorAR, jacobian[0], 0);
1360 fillHalfRow(-1, vectorARDot, jacobian[0], 3);
1361
1362
1363 final double m = momentum.getNorm();
1364 final double oOm = 1 / m;
1365 final Vector3D dcXP = new Vector3D( 0, vz, -vy);
1366 final Vector3D dcYP = new Vector3D(-vz, 0, vx);
1367 final Vector3D dcZP = new Vector3D( vy, -vx, 0);
1368 final Vector3D dcXV = new Vector3D( 0, -z, y);
1369 final Vector3D dcYV = new Vector3D( z, 0, -x);
1370 final Vector3D dcZV = new Vector3D( -y, x, 0);
1371 final Vector3D dCP = new Vector3D(mx * oOm, dcXP, my * oOm, dcYP, mz * oOm, dcZP);
1372 final Vector3D dCV = new Vector3D(mx * oOm, dcXV, my * oOm, dcYV, mz * oOm, dcZV);
1373
1374
1375 final double mOMu = m / mu;
1376 final Vector3D dpP = new Vector3D(2 * mOMu, dCP);
1377 final Vector3D dpV = new Vector3D(2 * mOMu, dCV);
1378
1379
1380 final double p = m * mOMu;
1381 final double moO2ae = 1 / (2 * absA * e);
1382 final double m2OaMu = -p / absA;
1383 fillHalfRow(moO2ae, dpP, m2OaMu * moO2ae, vectorAR, jacobian[1], 0);
1384 fillHalfRow(moO2ae, dpV, m2OaMu * moO2ae, vectorARDot, jacobian[1], 3);
1385
1386
1387 final double cI1 = 1 / (m * sinI);
1388 final double cI2 = cosI * cI1;
1389 fillHalfRow(cI2, dCP, -cI1, dcZP, jacobian[2], 0);
1390 fillHalfRow(cI2, dCV, -cI1, dcZV, jacobian[2], 3);
1391
1392
1393 final double cP1 = y * oOm;
1394 final double cP2 = -x * oOm;
1395 final double cP3 = -(mx * cP1 + my * cP2);
1396 final double cP4 = cP3 * oOm;
1397 final double cP5 = -1 / (r2 * sinI * sinI);
1398 final double cP6 = z * cP5;
1399 final double cP7 = cP3 * cP5;
1400 final Vector3D dacP = new Vector3D(cP1, dcXP, cP2, dcYP, cP4, dCP, oOm, new Vector3D(-my, mx, 0));
1401 final Vector3D dacV = new Vector3D(cP1, dcXV, cP2, dcYV, cP4, dCV);
1402 final Vector3D dpoP = new Vector3D(cP6, dacP, cP7, Vector3D.PLUS_K);
1403 final Vector3D dpoV = new Vector3D(cP6, dacV);
1404
1405 final double re2 = r2 * e * e;
1406 final double recOre2 = (p - r) / re2;
1407 final double resOre2 = (pv * mOMu) / re2;
1408 final Vector3D dreP = new Vector3D(mOMu, velocity, pv / mu, dCP);
1409 final Vector3D dreV = new Vector3D(mOMu, position, pv / mu, dCV);
1410 final Vector3D davP = new Vector3D(-resOre2, dpP, recOre2, dreP, resOre2 / r, position);
1411 final Vector3D davV = new Vector3D(-resOre2, dpV, recOre2, dreV);
1412 fillHalfRow(1, dpoP, -1, davP, jacobian[3], 0);
1413 fillHalfRow(1, dpoV, -1, davV, jacobian[3], 3);
1414
1415
1416 final double cO0 = cI1 * cI1;
1417 final double cO1 = mx * cO0;
1418 final double cO2 = -my * cO0;
1419 fillHalfRow(cO1, dcYP, cO2, dcXP, jacobian[4], 0);
1420 fillHalfRow(cO1, dcYV, cO2, dcXV, jacobian[4], 3);
1421
1422
1423 final double s2a = pv / (2 * absA);
1424 final double oObux = 1 / FastMath.sqrt(m * m + mu * absA);
1425 final double scasbu = pv * oObux;
1426 final Vector3D dauP = new Vector3D(1 / sqrtMuA, velocity, -s2a / sqrtMuA, vectorAR);
1427 final Vector3D dauV = new Vector3D(1 / sqrtMuA, position, -s2a / sqrtMuA, vectorARDot);
1428 final Vector3D dbuP = new Vector3D(oObux * mu / 2, vectorAR, m * oObux, dCP);
1429 final Vector3D dbuV = new Vector3D(oObux * mu / 2, vectorARDot, m * oObux, dCV);
1430 final Vector3D dcuP = new Vector3D(oObux, velocity, -scasbu * oObux, dbuP);
1431 final Vector3D dcuV = new Vector3D(oObux, position, -scasbu * oObux, dbuV);
1432 fillHalfRow(1, dauP, -e / (1 + rOa), dcuP, jacobian[5], 0);
1433 fillHalfRow(1, dauV, -e / (1 + rOa), dcuV, jacobian[5], 3);
1434
1435 return jacobian;
1436
1437 }
1438
1439
1440 @Override
1441 protected double[][] computeJacobianEccentricWrtCartesian() {
1442 if (isElliptical()) {
1443 return computeJacobianEccentricWrtCartesianElliptical();
1444 } else {
1445 return computeJacobianEccentricWrtCartesianHyperbolic();
1446 }
1447 }
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 private double[][] computeJacobianEccentricWrtCartesianElliptical() {
1458
1459
1460 final double[][] jacobian = computeJacobianMeanWrtCartesianElliptical();
1461
1462
1463
1464
1465
1466 final SinCos scE = FastMath.sinCos(getEccentricAnomaly());
1467 final double aOr = 1 / (1 - e * scE.cos());
1468
1469
1470 final double[] eRow = jacobian[1];
1471 final double[] anomalyRow = jacobian[5];
1472 for (int j = 0; j < anomalyRow.length; ++j) {
1473 anomalyRow[j] = aOr * (anomalyRow[j] + scE.sin() * eRow[j]);
1474 }
1475
1476 return jacobian;
1477
1478 }
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488 private double[][] computeJacobianEccentricWrtCartesianHyperbolic() {
1489
1490
1491 final double[][] jacobian = computeJacobianMeanWrtCartesianHyperbolic();
1492
1493
1494
1495
1496
1497 final double H = getEccentricAnomaly();
1498 final double coshH = FastMath.cosh(H);
1499 final double sinhH = FastMath.sinh(H);
1500 final double absaOr = 1 / (e * coshH - 1);
1501
1502
1503 final double[] eRow = jacobian[1];
1504 final double[] anomalyRow = jacobian[5];
1505 for (int j = 0; j < anomalyRow.length; ++j) {
1506 anomalyRow[j] = absaOr * (anomalyRow[j] - sinhH * eRow[j]);
1507 }
1508
1509 return jacobian;
1510
1511 }
1512
1513
1514 @Override
1515 protected double[][] computeJacobianTrueWrtCartesian() {
1516 if (isElliptical()) {
1517 return computeJacobianTrueWrtCartesianElliptical();
1518 } else {
1519 return computeJacobianTrueWrtCartesianHyperbolic();
1520 }
1521 }
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531 private double[][] computeJacobianTrueWrtCartesianElliptical() {
1532
1533
1534 final double[][] jacobian = computeJacobianEccentricWrtCartesianElliptical();
1535
1536
1537
1538
1539
1540
1541 final double e2 = e * e;
1542 final double oMe2 = 1 - e2;
1543 final double epsilon = FastMath.sqrt(oMe2);
1544 final SinCos scE = FastMath.sinCos(getEccentricAnomaly());
1545 final double aOr = 1 / (1 - e * scE.cos());
1546 final double aFactor = epsilon * aOr;
1547 final double eFactor = scE.sin() * aOr / epsilon;
1548
1549
1550 final double[] eRow = jacobian[1];
1551 final double[] anomalyRow = jacobian[5];
1552 for (int j = 0; j < anomalyRow.length; ++j) {
1553 anomalyRow[j] = aFactor * anomalyRow[j] + eFactor * eRow[j];
1554 }
1555
1556 return jacobian;
1557
1558 }
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568 private double[][] computeJacobianTrueWrtCartesianHyperbolic() {
1569
1570
1571 final double[][] jacobian = computeJacobianEccentricWrtCartesianHyperbolic();
1572
1573
1574
1575
1576
1577
1578 final double e2 = e * e;
1579 final double e2Mo = e2 - 1;
1580 final double epsilon = FastMath.sqrt(e2Mo);
1581 final double H = getEccentricAnomaly();
1582 final double coshH = FastMath.cosh(H);
1583 final double sinhH = FastMath.sinh(H);
1584 final double aOr = 1 / (e * coshH - 1);
1585 final double aFactor = epsilon * aOr;
1586 final double eFactor = sinhH * aOr / epsilon;
1587
1588
1589 final double[] eRow = jacobian[1];
1590 final double[] anomalyRow = jacobian[5];
1591 for (int j = 0; j < anomalyRow.length; ++j) {
1592 anomalyRow[j] = aFactor * anomalyRow[j] - eFactor * eRow[j];
1593 }
1594
1595 return jacobian;
1596
1597 }
1598
1599
1600 @Override
1601 public void addKeplerContribution(final PositionAngleType type, final double gm,
1602 final double[] pDot) {
1603 final double oMe2;
1604 final double ksi;
1605 final double absA = FastMath.abs(a);
1606 final double n = FastMath.sqrt(gm / absA) / absA;
1607 switch (type) {
1608 case MEAN :
1609 pDot[5] += n;
1610 break;
1611 case ECCENTRIC :
1612 oMe2 = FastMath.abs(1 - e * e);
1613 ksi = 1 + e * FastMath.cos(getTrueAnomaly());
1614 pDot[5] += n * ksi / oMe2;
1615 break;
1616 case TRUE :
1617 oMe2 = FastMath.abs(1 - e * e);
1618 ksi = 1 + e * FastMath.cos(getTrueAnomaly());
1619 pDot[5] += n * ksi * ksi / (oMe2 * FastMath.sqrt(oMe2));
1620 break;
1621 default :
1622 throw new OrekitInternalError(null);
1623 }
1624 }
1625
1626
1627
1628
1629 public String toString() {
1630 return new StringBuilder().append("Keplerian parameters: ").append('{').
1631 append("a: ").append(a).
1632 append("; e: ").append(e).
1633 append("; i: ").append(FastMath.toDegrees(i)).
1634 append("; pa: ").append(FastMath.toDegrees(pa)).
1635 append("; raan: ").append(FastMath.toDegrees(raan)).
1636 append("; v: ").append(FastMath.toDegrees(getTrueAnomaly())).
1637 append(";}").toString();
1638 }
1639
1640
1641 @Override
1642 public PositionAngleType getCachedPositionAngleType() {
1643 return cachedPositionAngleType;
1644 }
1645
1646
1647 @Override
1648 public boolean hasRates() {
1649 return hasDerivatives();
1650 }
1651
1652
1653 @Override
1654 public KeplerianOrbit removeRates() {
1655 final PositionAngleType positionAngleType = getCachedPositionAngleType();
1656 return new KeplerianOrbit(a, e, i, pa, raan, cachedAnomaly, positionAngleType, positionAngleType,
1657 getFrame(), getDate(), getMu());
1658 }
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674 private void checkParameterRangeInclusive(final String parameterName, final double parameter,
1675 final double lowerBound, final double upperBound) {
1676 if (parameter < lowerBound || parameter > upperBound) {
1677 throw new OrekitException(OrekitMessages.INVALID_PARAMETER_RANGE, parameterName,
1678 parameter, lowerBound, upperBound);
1679 }
1680 }
1681
1682
1683
1684
1685 @DefaultDataContext
1686 private Object writeReplace() {
1687 return new DTO(this);
1688 }
1689
1690
1691 @DefaultDataContext
1692 private static class DTO implements Serializable {
1693
1694
1695 private static final long serialVersionUID = 20231217L;
1696
1697
1698 private final double[] d;
1699
1700
1701 private final PositionAngleType positionAngleType;
1702
1703
1704 private final Frame frame;
1705
1706
1707
1708
1709 private DTO(final KeplerianOrbit orbit) {
1710
1711 final TimeStampedPVCoordinates pv = orbit.getPVCoordinates();
1712 this.positionAngleType = orbit.cachedPositionAngleType;
1713
1714
1715 final AbsoluteDate j2000Epoch =
1716 DataContext.getDefault().getTimeScales().getJ2000Epoch();
1717 final double epoch = FastMath.floor(pv.getDate().durationFrom(j2000Epoch));
1718 final double offset = pv.getDate().durationFrom(j2000Epoch.shiftedBy(epoch));
1719
1720 if (orbit.hasDerivatives()) {
1721
1722 this.d = new double[] {
1723 epoch, offset, orbit.getMu(),
1724 orbit.a, orbit.e, orbit.i,
1725 orbit.pa, orbit.raan, orbit.cachedAnomaly,
1726 orbit.aDot, orbit.eDot, orbit.iDot,
1727 orbit.paDot, orbit.raanDot, orbit.cachedAnomalyDot
1728 };
1729 } else {
1730
1731 this.d = new double[] {
1732 epoch, offset, orbit.getMu(),
1733 orbit.a, orbit.e, orbit.i,
1734 orbit.pa, orbit.raan, orbit.cachedAnomaly
1735 };
1736 }
1737
1738 this.frame = orbit.getFrame();
1739
1740 }
1741
1742
1743
1744
1745 private Object readResolve() {
1746 final AbsoluteDate j2000Epoch =
1747 DataContext.getDefault().getTimeScales().getJ2000Epoch();
1748 if (d.length >= 15) {
1749
1750 return new KeplerianOrbit(d[ 3], d[ 4], d[ 5], d[ 6], d[ 7], d[ 8],
1751 d[ 9], d[10], d[11], d[12], d[13], d[14],
1752 positionAngleType, positionAngleType,
1753 frame, j2000Epoch.shiftedBy(d[0]).shiftedBy(d[1]), d[2]);
1754 } else {
1755
1756 return new KeplerianOrbit(d[3], d[4], d[5], d[6], d[7], d[8],
1757 positionAngleType, positionAngleType,
1758 frame, j2000Epoch.shiftedBy(d[0]).shiftedBy(d[1]), d[2]);
1759 }
1760 }
1761
1762 }
1763
1764 }