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