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