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