1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import org.hipparchus.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.differentiation.FieldUnivariateDerivative1;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.util.FastMath;
24 import org.hipparchus.util.FieldSinCos;
25 import org.hipparchus.util.MathArrays;
26 import org.orekit.errors.OrekitIllegalArgumentException;
27 import org.orekit.errors.OrekitInternalError;
28 import org.orekit.errors.OrekitMessages;
29 import org.orekit.frames.FieldKinematicTransform;
30 import org.orekit.frames.Frame;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.utils.FieldPVCoordinates;
33 import org.orekit.utils.TimeStampedFieldPVCoordinates;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 public class FieldEquinoctialOrbit<T extends CalculusFieldElement<T>> extends FieldOrbit<T>
77 implements PositionAngleBased {
78
79
80 private final T a;
81
82
83 private final T ex;
84
85
86 private final T ey;
87
88
89 private final T hx;
90
91
92 private final T hy;
93
94
95 private final T cachedL;
96
97
98 private final PositionAngleType cachedPositionAngleType;
99
100
101 private final T aDot;
102
103
104 private final T exDot;
105
106
107 private final T eyDot;
108
109
110 private final T hxDot;
111
112
113 private final T hyDot;
114
115
116 private final T cachedLDot;
117
118
119 private FieldPVCoordinates<T> partialPV;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public FieldEquinoctialOrbit(final T a, final T ex, final T ey,
139 final T hx, final T hy, final T l,
140 final PositionAngleType type, final PositionAngleType cachedPositionAngleType,
141 final Frame frame, final FieldAbsoluteDate<T> date, final T mu)
142 throws IllegalArgumentException {
143 this(a, ex, ey, hx, hy, l,
144 a.getField().getZero(), a.getField().getZero(), a.getField().getZero(), a.getField().getZero(), a.getField().getZero(),
145 computeKeplerianLDot(type, a, ex, ey, mu, l, type), type, cachedPositionAngleType, frame, date, mu);
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 public FieldEquinoctialOrbit(final T a, final T ex, final T ey,
164 final T hx, final T hy, final T l,
165 final PositionAngleType type,
166 final Frame frame, final FieldAbsoluteDate<T> date, final T mu)
167 throws IllegalArgumentException {
168 this(a, ex, ey, hx, hy, l,
169 a.getField().getZero(), a.getField().getZero(), a.getField().getZero(), a.getField().getZero(), a.getField().getZero(),
170 computeKeplerianLDot(type, a, ex, ey, mu, l, type), type, type, frame, date, mu);
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196 public FieldEquinoctialOrbit(final T a, final T ex, final T ey,
197 final T hx, final T hy, final T l,
198 final T aDot, final T exDot, final T eyDot,
199 final T hxDot, final T hyDot, final T lDot,
200 final PositionAngleType type, final PositionAngleType cachedPositionAngleType,
201 final Frame frame, final FieldAbsoluteDate<T> date, final T mu)
202 throws IllegalArgumentException {
203 super(frame, date, mu);
204
205 if (ex.getReal() * ex.getReal() + ey.getReal() * ey.getReal() >= 1.0) {
206 throw new OrekitIllegalArgumentException(OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS,
207 getClass().getName());
208 }
209 this.cachedPositionAngleType = cachedPositionAngleType;
210 this.a = a;
211 this.aDot = aDot;
212 this.ex = ex;
213 this.exDot = exDot;
214 this.ey = ey;
215 this.eyDot = eyDot;
216 this.hx = hx;
217 this.hxDot = hxDot;
218 this.hy = hy;
219 this.hyDot = hyDot;
220
221 final FieldUnivariateDerivative1<T> lUD = initializeCachedL(l, lDot, type);
222 this.cachedL = lUD.getValue();
223 this.cachedLDot = lUD.getFirstDerivative();
224
225 this.partialPV = null;
226
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251 public FieldEquinoctialOrbit(final T a, final T ex, final T ey,
252 final T hx, final T hy, final T l,
253 final T aDot, final T exDot, final T eyDot,
254 final T hxDot, final T hyDot, final T lDot,
255 final PositionAngleType type,
256 final Frame frame, final FieldAbsoluteDate<T> date, final T mu)
257 throws IllegalArgumentException {
258 this(a, ex, ey, hx, hy, l, aDot, exDot, eyDot, hxDot, hyDot, lDot, type, type, frame, date, mu);
259 }
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275 public FieldEquinoctialOrbit(final TimeStampedFieldPVCoordinates<T> pvCoordinates,
276 final Frame frame, final T mu)
277 throws IllegalArgumentException {
278 super(pvCoordinates, frame, mu);
279
280
281 final FieldVector3D<T> pvP = pvCoordinates.getPosition();
282 final FieldVector3D<T> pvV = pvCoordinates.getVelocity();
283 final FieldVector3D<T> pvA = pvCoordinates.getAcceleration();
284 final T r2 = pvP.getNormSq();
285 final T r = r2.sqrt();
286 final T V2 = pvV.getNormSq();
287 final T rV2OnMu = r.multiply(V2).divide(mu);
288
289
290 a = r.divide(rV2OnMu.negate().add(2));
291
292 if (!isElliptical()) {
293 throw new OrekitIllegalArgumentException(OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS,
294 getClass().getName());
295 }
296
297
298 final FieldVector3D<T> w = pvCoordinates.getMomentum().normalize();
299 final T d = getOne().divide(getOne().add(w.getZ()));
300 hx = d.negate().multiply(w.getY());
301 hy = d.multiply(w.getX());
302
303
304 cachedPositionAngleType = PositionAngleType.TRUE;
305 final T cLv = (pvP.getX().subtract(d.multiply(pvP.getZ()).multiply(w.getX()))).divide(r);
306 final T sLv = (pvP.getY().subtract(d.multiply(pvP.getZ()).multiply(w.getY()))).divide(r);
307 cachedL = sLv.atan2(cLv);
308
309
310 final T eSE = FieldVector3D.dotProduct(pvP, pvV).divide(a.multiply(mu).sqrt());
311 final T eCE = rV2OnMu.subtract(1);
312 final T e2 = eCE.square().add(eSE.square());
313 final T f = eCE.subtract(e2);
314 final T g = e2.negate().add(1).sqrt().multiply(eSE);
315 ex = a.multiply(f.multiply(cLv).add( g.multiply(sLv))).divide(r);
316 ey = a.multiply(f.multiply(sLv).subtract(g.multiply(cLv))).divide(r);
317
318 partialPV = pvCoordinates;
319
320 if (hasNonKeplerianAcceleration(pvCoordinates, mu)) {
321
322
323 final T[][] jacobian = MathArrays.buildArray(a.getField(), 6, 6);
324 getJacobianWrtCartesian(PositionAngleType.MEAN, jacobian);
325
326 final FieldVector3D<T> keplerianAcceleration = new FieldVector3D<>(r.multiply(r2).reciprocal().multiply(mu.negate()), pvP);
327 final FieldVector3D<T> nonKeplerianAcceleration = pvA.subtract(keplerianAcceleration);
328 final T aX = nonKeplerianAcceleration.getX();
329 final T aY = nonKeplerianAcceleration.getY();
330 final T aZ = nonKeplerianAcceleration.getZ();
331 aDot = jacobian[0][3].multiply(aX).add(jacobian[0][4].multiply(aY)).add(jacobian[0][5].multiply(aZ));
332 exDot = jacobian[1][3].multiply(aX).add(jacobian[1][4].multiply(aY)).add(jacobian[1][5].multiply(aZ));
333 eyDot = jacobian[2][3].multiply(aX).add(jacobian[2][4].multiply(aY)).add(jacobian[2][5].multiply(aZ));
334 hxDot = jacobian[3][3].multiply(aX).add(jacobian[3][4].multiply(aY)).add(jacobian[3][5].multiply(aZ));
335 hyDot = jacobian[4][3].multiply(aX).add(jacobian[4][4].multiply(aY)).add(jacobian[4][5].multiply(aZ));
336
337
338
339 final T lMDot = getKeplerianMeanMotion().
340 add(jacobian[5][3].multiply(aX)).add(jacobian[5][4].multiply(aY)).add(jacobian[5][5].multiply(aZ));
341 final FieldUnivariateDerivative1<T> exUD = new FieldUnivariateDerivative1<>(ex, exDot);
342 final FieldUnivariateDerivative1<T> eyUD = new FieldUnivariateDerivative1<>(ey, eyDot);
343 final FieldUnivariateDerivative1<T> lMUD = new FieldUnivariateDerivative1<>(getLM(), lMDot);
344 final FieldUnivariateDerivative1<T> lvUD = FieldEquinoctialLongitudeArgumentUtility.meanToTrue(exUD, eyUD, lMUD);
345 cachedLDot = lvUD.getFirstDerivative();
346
347 } else {
348
349
350
351 aDot = getZero();
352 exDot = getZero();
353 eyDot = getZero();
354 hxDot = getZero();
355 hyDot = getZero();
356 cachedLDot = computeKeplerianLDot(cachedPositionAngleType, a, ex, ey, mu, cachedL, cachedPositionAngleType);
357 }
358
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376 public FieldEquinoctialOrbit(final FieldPVCoordinates<T> pvCoordinates, final Frame frame,
377 final FieldAbsoluteDate<T> date, final T mu)
378 throws IllegalArgumentException {
379 this(new TimeStampedFieldPVCoordinates<>(date, pvCoordinates), frame, mu);
380 }
381
382
383
384
385 public FieldEquinoctialOrbit(final FieldOrbit<T> op) {
386 super(op.getFrame(), op.getDate(), op.getMu());
387
388 a = op.getA();
389 ex = op.getEquinoctialEx();
390 ey = op.getEquinoctialEy();
391 hx = op.getHx();
392 hy = op.getHy();
393 cachedPositionAngleType = PositionAngleType.TRUE;
394 cachedL = op.getLv();
395
396 aDot = op.getADot();
397 exDot = op.getEquinoctialExDot();
398 eyDot = op.getEquinoctialEyDot();
399 hxDot = op.getHxDot();
400 hyDot = op.getHyDot();
401 cachedLDot = op.getLvDot();
402 }
403
404
405
406
407
408
409
410 public FieldEquinoctialOrbit(final Field<T> field, final EquinoctialOrbit op) {
411 super(op.getFrame(), new FieldAbsoluteDate<>(field, op.getDate()), field.getZero().newInstance(op.getMu()));
412
413 a = getZero().newInstance(op.getA());
414 ex = getZero().newInstance(op.getEquinoctialEx());
415 ey = getZero().newInstance(op.getEquinoctialEy());
416 hx = getZero().newInstance(op.getHx());
417 hy = getZero().newInstance(op.getHy());
418 cachedPositionAngleType = op.getCachedPositionAngleType();
419 cachedL = getZero().newInstance(op.getL(cachedPositionAngleType));
420
421 aDot = getZero().newInstance(op.getADot());
422 exDot = getZero().newInstance(op.getEquinoctialExDot());
423 eyDot = getZero().newInstance(op.getEquinoctialEyDot());
424 hxDot = getZero().newInstance(op.getHxDot());
425 hyDot = getZero().newInstance(op.getHyDot());
426 cachedLDot = getZero().newInstance(op.getLDot(cachedPositionAngleType));
427 }
428
429
430
431
432
433
434
435 public FieldEquinoctialOrbit(final Field<T> field, final Orbit op) {
436 this(field, (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(op));
437 }
438
439
440 @Override
441 public OrbitType getType() {
442 return OrbitType.EQUINOCTIAL;
443 }
444
445
446 @Override
447 public T getA() {
448 return a;
449 }
450
451
452 @Override
453 public T getADot() {
454 return aDot;
455 }
456
457
458 @Override
459 public T getEquinoctialEx() {
460 return ex;
461 }
462
463
464 @Override
465 public T getEquinoctialExDot() {
466 return exDot;
467 }
468
469
470 @Override
471 public T getEquinoctialEy() {
472 return ey;
473 }
474
475
476 @Override
477 public T getEquinoctialEyDot() {
478 return eyDot;
479 }
480
481
482 @Override
483 public T getHx() {
484 return hx;
485 }
486
487
488 @Override
489 public T getHxDot() {
490 return hxDot;
491 }
492
493
494 @Override
495 public T getHy() {
496 return hy;
497 }
498
499
500 @Override
501 public T getHyDot() {
502 return hyDot;
503 }
504
505
506 @Override
507 public T getLv() {
508 switch (cachedPositionAngleType) {
509 case TRUE:
510 return cachedL;
511
512 case ECCENTRIC:
513 return FieldEquinoctialLongitudeArgumentUtility.eccentricToTrue(ex, ey, cachedL);
514
515 case MEAN:
516 return FieldEquinoctialLongitudeArgumentUtility.meanToTrue(ex, ey, cachedL);
517
518 default:
519 throw new OrekitInternalError(null);
520 }
521 }
522
523
524 @Override
525 public T getLvDot() {
526 switch (cachedPositionAngleType) {
527 case ECCENTRIC:
528 final FieldUnivariateDerivative1<T> lEUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
529 final FieldUnivariateDerivative1<T> exUD = new FieldUnivariateDerivative1<>(ex, exDot);
530 final FieldUnivariateDerivative1<T> eyUD = new FieldUnivariateDerivative1<>(ey, eyDot);
531 final FieldUnivariateDerivative1<T> lvUD = FieldEquinoctialLongitudeArgumentUtility.eccentricToTrue(exUD, eyUD,
532 lEUD);
533 return lvUD.getFirstDerivative();
534
535 case TRUE:
536 return cachedLDot;
537
538 case MEAN:
539 final FieldUnivariateDerivative1<T> lMUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
540 final FieldUnivariateDerivative1<T> exUD2 = new FieldUnivariateDerivative1<>(ex, exDot);
541 final FieldUnivariateDerivative1<T> eyUD2 = new FieldUnivariateDerivative1<>(ey, eyDot);
542 final FieldUnivariateDerivative1<T> lvUD2 = FieldEquinoctialLongitudeArgumentUtility.meanToTrue(exUD2,
543 eyUD2, lMUD);
544 return lvUD2.getFirstDerivative();
545
546 default:
547 throw new OrekitInternalError(null);
548 }
549 }
550
551
552 @Override
553 public T getLE() {
554 switch (cachedPositionAngleType) {
555 case TRUE:
556 return FieldEquinoctialLongitudeArgumentUtility.trueToEccentric(ex, ey, cachedL);
557
558 case ECCENTRIC:
559 return cachedL;
560
561 case MEAN:
562 return FieldEquinoctialLongitudeArgumentUtility.meanToEccentric(ex, ey, cachedL);
563
564 default:
565 throw new OrekitInternalError(null);
566 }
567 }
568
569
570 @Override
571 public T getLEDot() {
572
573 switch (cachedPositionAngleType) {
574 case TRUE:
575 final FieldUnivariateDerivative1<T> lvUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
576 final FieldUnivariateDerivative1<T> exUD = new FieldUnivariateDerivative1<>(ex, exDot);
577 final FieldUnivariateDerivative1<T> eyUD = new FieldUnivariateDerivative1<>(ey, eyDot);
578 final FieldUnivariateDerivative1<T> lEUD = FieldEquinoctialLongitudeArgumentUtility.trueToEccentric(exUD, eyUD,
579 lvUD);
580 return lEUD.getFirstDerivative();
581
582 case ECCENTRIC:
583 return cachedLDot;
584
585 case MEAN:
586 final FieldUnivariateDerivative1<T> lMUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
587 final FieldUnivariateDerivative1<T> exUD2 = new FieldUnivariateDerivative1<>(ex, exDot);
588 final FieldUnivariateDerivative1<T> eyUD2 = new FieldUnivariateDerivative1<>(ey, eyDot);
589 final FieldUnivariateDerivative1<T> lEUD2 = FieldEquinoctialLongitudeArgumentUtility.meanToEccentric(exUD2,
590 eyUD2, lMUD);
591 return lEUD2.getFirstDerivative();
592
593 default:
594 throw new OrekitInternalError(null);
595 }
596 }
597
598
599 @Override
600 public T getLM() {
601 switch (cachedPositionAngleType) {
602 case TRUE:
603 return FieldEquinoctialLongitudeArgumentUtility.trueToMean(ex, ey, cachedL);
604
605 case MEAN:
606 return cachedL;
607
608 case ECCENTRIC:
609 return FieldEquinoctialLongitudeArgumentUtility.eccentricToMean(ex, ey, cachedL);
610
611 default:
612 throw new OrekitInternalError(null);
613 }
614 }
615
616
617 @Override
618 public T getLMDot() {
619
620 switch (cachedPositionAngleType) {
621 case TRUE:
622 final FieldUnivariateDerivative1<T> lvUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
623 final FieldUnivariateDerivative1<T> exUD = new FieldUnivariateDerivative1<>(ex, exDot);
624 final FieldUnivariateDerivative1<T> eyUD = new FieldUnivariateDerivative1<>(ey, eyDot);
625 final FieldUnivariateDerivative1<T> lMUD = FieldEquinoctialLongitudeArgumentUtility.trueToMean(exUD, eyUD, lvUD);
626 return lMUD.getFirstDerivative();
627
628 case MEAN:
629 return cachedLDot;
630
631 case ECCENTRIC:
632 final FieldUnivariateDerivative1<T> lEUD = new FieldUnivariateDerivative1<>(cachedL, cachedLDot);
633 final FieldUnivariateDerivative1<T> exUD2 = new FieldUnivariateDerivative1<>(ex, exDot);
634 final FieldUnivariateDerivative1<T> eyUD2 = new FieldUnivariateDerivative1<>(ey, eyDot);
635 final FieldUnivariateDerivative1<T> lMUD2 = FieldEquinoctialLongitudeArgumentUtility.eccentricToMean(exUD2,
636 eyUD2, lEUD);
637 return lMUD2.getFirstDerivative();
638
639 default:
640 throw new OrekitInternalError(null);
641 }
642 }
643
644
645
646
647
648 public T getL(final PositionAngleType type) {
649 return (type == PositionAngleType.MEAN) ? getLM() :
650 ((type == PositionAngleType.ECCENTRIC) ? getLE() :
651 getLv());
652 }
653
654
655
656
657
658 public T getLDot(final PositionAngleType type) {
659 return (type == PositionAngleType.MEAN) ? getLMDot() :
660 ((type == PositionAngleType.ECCENTRIC) ? getLEDot() :
661 getLvDot());
662 }
663
664
665 @Override
666 public boolean hasNonKeplerianAcceleration() {
667 return aDot.getReal() != 0. || exDot.getReal() != 0 || hxDot.getReal() != 0. || eyDot.getReal() != 0. || hyDot.getReal() != 0. ||
668 FastMath.abs(cachedLDot.subtract(computeKeplerianLDot(cachedPositionAngleType, a, ex, ey, getMu(), cachedL, cachedPositionAngleType)).getReal()) > TOLERANCE_POSITION_ANGLE_RATE;
669 }
670
671
672 @Override
673 public T getE() {
674 return ex.square().add(ey.square()).sqrt();
675 }
676
677
678 @Override
679 public T getEDot() {
680 if (!hasNonKeplerianRates()) {
681 return getZero();
682 }
683 return ex.multiply(exDot).add(ey.multiply(eyDot)).divide(ex.square().add(ey.square()).sqrt());
684
685 }
686
687
688 @Override
689 public T getI() {
690 return hx.square().add(hy.square()).sqrt().atan().multiply(2);
691 }
692
693
694 @Override
695 public T getIDot() {
696 if (!hasNonKeplerianRates()) {
697 return getZero();
698 }
699 final T h2 = hx.square().add(hy.square());
700 final T h = h2.sqrt();
701 return hx.multiply(hxDot).add(hy.multiply(hyDot)).multiply(2).divide(h.multiply(h2.add(1)));
702
703 }
704
705
706
707 private void computePVWithoutA() {
708
709 if (partialPV != null) {
710
711 return;
712 }
713
714
715 final T lE = getLE();
716
717
718 final T hx2 = hx.square();
719 final T hy2 = hy.square();
720 final T factH = getOne().divide(hx2.add(1.0).add(hy2));
721
722
723 final T ux = hx2.add(1.0).subtract(hy2).multiply(factH);
724 final T uy = hx.multiply(hy).multiply(factH).multiply(2);
725 final T uz = hy.multiply(-2).multiply(factH);
726
727 final T vx = uy;
728 final T vy = (hy2.subtract(hx2).add(1)).multiply(factH);
729 final T vz = hx.multiply(factH).multiply(2);
730
731
732 final T ex2 = ex.square();
733 final T exey = ex.multiply(ey);
734 final T ey2 = ey.square();
735 final T e2 = ex2.add(ey2);
736 final T eta = getOne().subtract(e2).sqrt().add(1);
737 final T beta = getOne().divide(eta);
738
739
740 final FieldSinCos<T> scLe = FastMath.sinCos(lE);
741 final T cLe = scLe.cos();
742 final T sLe = scLe.sin();
743 final T exCeyS = ex.multiply(cLe).add(ey.multiply(sLe));
744
745
746 final T x = a.multiply(getOne().subtract(beta.multiply(ey2)).multiply(cLe).add(beta.multiply(exey).multiply(sLe)).subtract(ex));
747 final T y = a.multiply(getOne().subtract(beta.multiply(ex2)).multiply(sLe).add(beta .multiply(exey).multiply(cLe)).subtract(ey));
748
749 final T factor = getMu().divide(a).sqrt().divide(getOne().subtract(exCeyS));
750 final T xdot = factor.multiply(sLe.negate().add(beta.multiply(ey).multiply(exCeyS)));
751 final T ydot = factor.multiply(cLe.subtract(beta.multiply(ex).multiply(exCeyS)));
752
753 final FieldVector3D<T> position =
754 new FieldVector3D<>(x.multiply(ux).add(y.multiply(vx)),
755 x.multiply(uy).add(y.multiply(vy)),
756 x.multiply(uz).add(y.multiply(vz)));
757 final FieldVector3D<T> velocity =
758 new FieldVector3D<>(xdot.multiply(ux).add(ydot.multiply(vx)), xdot.multiply(uy).add(ydot.multiply(vy)), xdot.multiply(uz).add(ydot.multiply(vz)));
759
760 partialPV = new FieldPVCoordinates<>(position, velocity);
761
762 }
763
764
765
766
767
768
769
770
771 private FieldUnivariateDerivative1<T> initializeCachedL(final T l, final T lDot,
772 final PositionAngleType inputType) {
773 if (cachedPositionAngleType == inputType) {
774 return new FieldUnivariateDerivative1<>(l, lDot);
775
776 } else {
777 final FieldUnivariateDerivative1<T> exUD = new FieldUnivariateDerivative1<>(ex, exDot);
778 final FieldUnivariateDerivative1<T> eyUD = new FieldUnivariateDerivative1<>(ey, eyDot);
779 final FieldUnivariateDerivative1<T> lUD = new FieldUnivariateDerivative1<>(l, lDot);
780
781 switch (cachedPositionAngleType) {
782
783 case ECCENTRIC:
784 if (inputType == PositionAngleType.MEAN) {
785 return FieldEquinoctialLongitudeArgumentUtility.meanToEccentric(exUD, eyUD, lUD);
786 } else {
787 return FieldEquinoctialLongitudeArgumentUtility.trueToEccentric(exUD, eyUD, lUD);
788 }
789
790 case TRUE:
791 if (inputType == PositionAngleType.MEAN) {
792 return FieldEquinoctialLongitudeArgumentUtility.meanToTrue(exUD, eyUD, lUD);
793 } else {
794 return FieldEquinoctialLongitudeArgumentUtility.eccentricToTrue(exUD, eyUD, lUD);
795 }
796
797 case MEAN:
798 if (inputType == PositionAngleType.TRUE) {
799 return FieldEquinoctialLongitudeArgumentUtility.trueToMean(exUD, eyUD, lUD);
800 } else {
801 return FieldEquinoctialLongitudeArgumentUtility.eccentricToMean(exUD, eyUD, lUD);
802 }
803
804 default:
805 throw new OrekitInternalError(null);
806
807 }
808
809 }
810
811 }
812
813
814
815
816
817
818
819 private T initializeCachedL(final T l, final PositionAngleType positionAngleType) {
820 return FieldEquinoctialLongitudeArgumentUtility.convertL(positionAngleType, l, ex, ey, cachedPositionAngleType);
821 }
822
823
824
825
826 private FieldVector3D<T> nonKeplerianAcceleration() {
827
828 final T[][] dCdP = MathArrays.buildArray(a.getField(), 6, 6);
829 getJacobianWrtParameters(PositionAngleType.MEAN, dCdP);
830
831 final T nonKeplerianMeanMotion = getLMDot().subtract(getKeplerianMeanMotion());
832 final T nonKeplerianAx = dCdP[3][0].multiply(aDot).
833 add(dCdP[3][1].multiply(exDot)).
834 add(dCdP[3][2].multiply(eyDot)).
835 add(dCdP[3][3].multiply(hxDot)).
836 add(dCdP[3][4].multiply(hyDot)).
837 add(dCdP[3][5].multiply(nonKeplerianMeanMotion));
838 final T nonKeplerianAy = dCdP[4][0].multiply(aDot).
839 add(dCdP[4][1].multiply(exDot)).
840 add(dCdP[4][2].multiply(eyDot)).
841 add(dCdP[4][3].multiply(hxDot)).
842 add(dCdP[4][4].multiply(hyDot)).
843 add(dCdP[4][5].multiply(nonKeplerianMeanMotion));
844 final T nonKeplerianAz = dCdP[5][0].multiply(aDot).
845 add(dCdP[5][1].multiply(exDot)).
846 add(dCdP[5][2].multiply(eyDot)).
847 add(dCdP[5][3].multiply(hxDot)).
848 add(dCdP[5][4].multiply(hyDot)).
849 add(dCdP[5][5].multiply(nonKeplerianMeanMotion));
850
851 return new FieldVector3D<>(nonKeplerianAx, nonKeplerianAy, nonKeplerianAz);
852
853 }
854
855
856 @Override
857 protected FieldVector3D<T> initPosition() {
858
859
860 final T lE = getLE();
861
862
863 final T hx2 = hx.square();
864 final T hy2 = hy.square();
865 final T factH = getOne().divide(hx2.add(1.0).add(hy2));
866
867
868 final T ux = hx2.add(1.0).subtract(hy2).multiply(factH);
869 final T uy = hx.multiply(hy).multiply(factH).multiply(2);
870 final T uz = hy.multiply(-2).multiply(factH);
871
872 final T vx = uy;
873 final T vy = (hy2.subtract(hx2).add(1)).multiply(factH);
874 final T vz = hx.multiply(factH).multiply(2);
875
876
877 final T ex2 = ex.square();
878 final T exey = ex.multiply(ey);
879 final T ey2 = ey.square();
880 final T e2 = ex2.add(ey2);
881 final T eta = getOne().subtract(e2).sqrt().add(1);
882 final T beta = getOne().divide(eta);
883
884
885 final FieldSinCos<T> scLe = FastMath.sinCos(lE);
886 final T cLe = scLe.cos();
887 final T sLe = scLe.sin();
888
889
890 final T x = a.multiply(getOne().subtract(beta.multiply(ey2)).multiply(cLe).add(beta.multiply(exey).multiply(sLe)).subtract(ex));
891 final T y = a.multiply(getOne().subtract(beta.multiply(ex2)).multiply(sLe).add(beta .multiply(exey).multiply(cLe)).subtract(ey));
892
893 return new FieldVector3D<>(x.multiply(ux).add(y.multiply(vx)),
894 x.multiply(uy).add(y.multiply(vy)),
895 x.multiply(uz).add(y.multiply(vz)));
896
897 }
898
899
900 @Override
901 protected TimeStampedFieldPVCoordinates<T> initPVCoordinates() {
902
903
904 computePVWithoutA();
905
906
907 final T r2 = partialPV.getPosition().getNormSq();
908 final FieldVector3D<T> keplerianAcceleration = new FieldVector3D<>(r2.multiply(r2.sqrt()).reciprocal().multiply(getMu().negate()),
909 partialPV.getPosition());
910 final FieldVector3D<T> acceleration = hasNonKeplerianRates() ?
911 keplerianAcceleration.add(nonKeplerianAcceleration()) :
912 keplerianAcceleration;
913
914 return new TimeStampedFieldPVCoordinates<>(getDate(), partialPV.getPosition(), partialPV.getVelocity(), acceleration);
915
916 }
917
918
919 @Override
920 public FieldEquinoctialOrbit<T> withFrame(final Frame inertialFrame) {
921 if (hasNonKeplerianAcceleration()) {
922 return new FieldEquinoctialOrbit<>(getPVCoordinates(inertialFrame), inertialFrame, getMu());
923 } else {
924 final FieldKinematicTransform<T> transform = getFrame().getKinematicTransformTo(inertialFrame, getDate());
925 return new FieldEquinoctialOrbit<>(transform.transformOnlyPV(getPVCoordinates()), inertialFrame, getDate(), getMu());
926 }
927 }
928
929
930 @Override
931 public FieldEquinoctialOrbit<T> shiftedBy(final double dt) {
932 return shiftedBy(getZero().newInstance(dt));
933 }
934
935
936 @Override
937 public FieldEquinoctialOrbit<T> shiftedBy(final T dt) {
938
939
940 final FieldEquinoctialOrbit<T> keplerianShifted = new FieldEquinoctialOrbit<>(a, ex, ey, hx, hy,
941 getLM().add(getKeplerianMeanMotion().multiply(dt)),
942 PositionAngleType.MEAN, cachedPositionAngleType, getFrame(),
943 getDate().shiftedBy(dt), getMu());
944
945 if (hasNonKeplerianRates()) {
946
947
948 final FieldVector3D<T> nonKeplerianAcceleration = nonKeplerianAcceleration();
949
950
951 keplerianShifted.computePVWithoutA();
952 final FieldVector3D<T> fixedP = new FieldVector3D<>(getOne(), keplerianShifted.partialPV.getPosition(),
953 dt.square().multiply(0.5), nonKeplerianAcceleration);
954 final T fixedR2 = fixedP.getNormSq();
955 final T fixedR = fixedR2.sqrt();
956 final FieldVector3D<T> fixedV = new FieldVector3D<>(getOne(), keplerianShifted.partialPV.getVelocity(),
957 dt, nonKeplerianAcceleration);
958 final FieldVector3D<T> fixedA = new FieldVector3D<>(fixedR2.multiply(fixedR).reciprocal().multiply(getMu().negate()),
959 keplerianShifted.partialPV.getPosition(),
960 getOne(), nonKeplerianAcceleration);
961
962
963 return new FieldEquinoctialOrbit<>(new TimeStampedFieldPVCoordinates<>(keplerianShifted.getDate(),
964 fixedP, fixedV, fixedA),
965 keplerianShifted.getFrame(), keplerianShifted.getMu());
966
967 } else {
968
969 return keplerianShifted;
970 }
971
972 }
973
974
975 @Override
976 protected T[][] computeJacobianMeanWrtCartesian() {
977
978 final T[][] jacobian = MathArrays.buildArray(getField(), 6, 6);
979
980
981 computePVWithoutA();
982 final FieldVector3D<T> position = partialPV.getPosition();
983 final FieldVector3D<T> velocity = partialPV.getVelocity();
984 final T r2 = position.getNormSq();
985 final T r = r2.sqrt();
986 final T r3 = r.multiply(r2);
987
988 final T mu = getMu();
989 final T sqrtMuA = a.multiply(mu).sqrt();
990 final T a2 = a.square();
991
992 final T e2 = ex.square().add(ey.square());
993 final T oMe2 = getOne().subtract(e2);
994 final T epsilon = oMe2.sqrt();
995 final T beta = getOne().divide(epsilon.add(1));
996 final T ratio = epsilon.multiply(beta);
997
998 final T hx2 = hx.square();
999 final T hy2 = hy.square();
1000 final T hxhy = hx.multiply(hy);
1001
1002
1003 final FieldVector3D<T> f = new FieldVector3D<>(hx2.subtract(hy2).add(1), hxhy.multiply(2), hy.multiply(-2)).normalize();
1004 final FieldVector3D<T> g = new FieldVector3D<>(hxhy.multiply(2), hy2.add(1).subtract(hx2), hx.multiply(2)).normalize();
1005 final FieldVector3D<T> w = FieldVector3D.crossProduct(position, velocity).normalize();
1006
1007
1008 final T x = FieldVector3D.dotProduct(position, f);
1009 final T y = FieldVector3D.dotProduct(position, g);
1010 final T xDot = FieldVector3D.dotProduct(velocity, f);
1011 final T yDot = FieldVector3D.dotProduct(velocity, g);
1012
1013
1014 final T c1 = a.divide(sqrtMuA.multiply(epsilon));
1015 final T c1N = c1.negate();
1016 final T c2 = a.multiply(sqrtMuA).multiply(beta).divide(r3);
1017 final T c3 = sqrtMuA.divide(r3.multiply(epsilon));
1018 final FieldVector3D<T> drDotSdEx = new FieldVector3D<>(c1.multiply(xDot).multiply(yDot).subtract(c2.multiply(ey).multiply(x)).subtract(c3.multiply(x).multiply(y)), f,
1019 c1N.multiply(xDot).multiply(xDot).subtract(c2.multiply(ey).multiply(y)).add(c3.multiply(x).multiply(x)), g);
1020
1021
1022 final FieldVector3D<T> drDotSdEy = new FieldVector3D<>(c1.multiply(yDot).multiply(yDot).add(c2.multiply(ex).multiply(x)).subtract(c3.multiply(y).multiply(y)), f,
1023 c1N.multiply(xDot).multiply(yDot).add(c2.multiply(ex).multiply(y)).add(c3.multiply(x).multiply(y)), g);
1024
1025
1026 final FieldVector3D<T> vectorAR = new FieldVector3D<>(a2.multiply(2).divide(r3), position);
1027 final FieldVector3D<T> vectorARDot = new FieldVector3D<>(a2.multiply(2).divide(mu), velocity);
1028 fillHalfRow(getOne(), vectorAR, jacobian[0], 0);
1029 fillHalfRow(getOne(), vectorARDot, jacobian[0], 3);
1030
1031
1032 final T d1 = a.negate().multiply(ratio).divide(r3);
1033 final T d2 = (hy.multiply(xDot).subtract(hx.multiply(yDot))).divide(sqrtMuA.multiply(epsilon));
1034 final T d3 = hx.multiply(y).subtract(hy.multiply(x)).divide(sqrtMuA);
1035 final FieldVector3D<T> vectorExRDot =
1036 new FieldVector3D<>(x.multiply(2).multiply(yDot).subtract(xDot.multiply(y)).divide(mu), g, y.negate().multiply(yDot).divide(mu), f, ey.negate().multiply(d3).divide(epsilon), w);
1037 fillHalfRow(ex.multiply(d1), position, ey.negate().multiply(d2), w, epsilon.divide(sqrtMuA), drDotSdEy, jacobian[1], 0);
1038 fillHalfRow(getOne(), vectorExRDot, jacobian[1], 3);
1039
1040
1041 final FieldVector3D<T> vectorEyRDot =
1042 new FieldVector3D<>(xDot.multiply(2).multiply(y).subtract(x.multiply(yDot)).divide(mu), f, x.negate().multiply(xDot).divide(mu), g, ex.multiply(d3).divide(epsilon), w);
1043 fillHalfRow(ey.multiply(d1), position, ex.multiply(d2), w, epsilon.negate().divide(sqrtMuA), drDotSdEx, jacobian[2], 0);
1044 fillHalfRow(getOne(), vectorEyRDot, jacobian[2], 3);
1045
1046
1047 final T h = (hx2.add(1).add(hy2)).divide(sqrtMuA.multiply(2).multiply(epsilon));
1048 fillHalfRow( h.negate().multiply(xDot), w, jacobian[3], 0);
1049 fillHalfRow( h.multiply(x), w, jacobian[3], 3);
1050
1051
1052 fillHalfRow( h.negate().multiply(yDot), w, jacobian[4], 0);
1053 fillHalfRow( h.multiply(y), w, jacobian[4], 3);
1054
1055
1056 final T l = ratio.negate().divide(sqrtMuA);
1057 fillHalfRow(getOne().negate().divide(sqrtMuA), velocity, d2, w, l.multiply(ex), drDotSdEx, l.multiply(ey), drDotSdEy, jacobian[5], 0);
1058 fillHalfRow(getZero().newInstance(-2).divide(sqrtMuA), position, ex.multiply(beta), vectorEyRDot, ey.negate().multiply(beta), vectorExRDot, d3, w, jacobian[5], 3);
1059
1060 return jacobian;
1061
1062 }
1063
1064
1065 @Override
1066 protected T[][] computeJacobianEccentricWrtCartesian() {
1067
1068
1069 final T[][] jacobian = computeJacobianMeanWrtCartesian();
1070
1071
1072
1073
1074
1075 final FieldSinCos<T> scLe = FastMath.sinCos(getLE());
1076 final T cosLe = scLe.cos();
1077 final T sinLe = scLe.sin();
1078 final T aOr = getOne().divide(getOne().subtract(ex.multiply(cosLe)).subtract(ey.multiply(sinLe)));
1079
1080
1081 final T[] rowEx = jacobian[1];
1082 final T[] rowEy = jacobian[2];
1083 final T[] rowL = jacobian[5];
1084
1085 for (int j = 0; j < 6; ++j) {
1086 rowL[j] = aOr.multiply(rowL[j].add(sinLe.multiply(rowEx[j])).subtract(cosLe.multiply(rowEy[j])));
1087 }
1088 return jacobian;
1089
1090 }
1091
1092
1093 @Override
1094 protected T[][] computeJacobianTrueWrtCartesian() {
1095
1096
1097 final T[][] jacobian = computeJacobianEccentricWrtCartesian();
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111 final FieldSinCos<T> scLe = FastMath.sinCos(getLE());
1112 final T cosLe = scLe.cos();
1113 final T sinLe = scLe.sin();
1114 final T eSinE = ex.multiply(sinLe).subtract(ey.multiply(cosLe));
1115 final T ecosE = ex.multiply(cosLe).add(ey.multiply(sinLe));
1116 final T e2 = ex.square().add(ey.square());
1117 final T epsilon = getOne().subtract(e2).sqrt();
1118 final T onePeps = epsilon.add(1);
1119 final T d = onePeps.subtract(ecosE);
1120 final T cT = d.multiply(d).add(eSinE.multiply(eSinE)).divide(2);
1121 final T cE = ecosE.multiply(onePeps).subtract(e2);
1122 final T cX = ex.multiply(eSinE).divide(epsilon).subtract(ey).add(sinLe.multiply(onePeps));
1123 final T cY = ey.multiply(eSinE).divide(epsilon).add( ex).subtract(cosLe.multiply(onePeps));
1124 final T factorLe = cT.add(cE).divide(cT);
1125 final T factorEx = cX.divide(cT);
1126 final T factorEy = cY.divide(cT);
1127
1128
1129 final T[] rowEx = jacobian[1];
1130 final T[] rowEy = jacobian[2];
1131 final T[] rowL = jacobian[5];
1132 for (int j = 0; j < 6; ++j) {
1133 rowL[j] = factorLe.multiply(rowL[j]).add(factorEx.multiply(rowEx[j])).add(factorEy.multiply(rowEy[j]));
1134 }
1135
1136 return jacobian;
1137
1138 }
1139
1140
1141 @Override
1142 public void addKeplerContribution(final PositionAngleType type, final T gm,
1143 final T[] pDot) {
1144 pDot[5] = pDot[5].add(computeKeplerianLDot(type, a, ex, ey, gm, cachedL, cachedPositionAngleType));
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160 private static <T extends CalculusFieldElement<T>> T computeKeplerianLDot(final PositionAngleType type, final T a, final T ex,
1161 final T ey, final T mu, final T l, final PositionAngleType cachedType) {
1162 final T n = mu.divide(a).sqrt().divide(a);
1163 if (type == PositionAngleType.MEAN) {
1164 return n;
1165 }
1166 final FieldSinCos<T> sc;
1167 final T ksi;
1168 if (type == PositionAngleType.ECCENTRIC) {
1169 sc = FastMath.sinCos(FieldEquinoctialLongitudeArgumentUtility.convertL(cachedType, l, ex, ey, type));
1170 ksi = ((ex.multiply(sc.cos())).add(ey.multiply(sc.sin()))).negate().add(1).reciprocal();
1171 return n.multiply(ksi);
1172 } else {
1173 sc = FastMath.sinCos(FieldEquinoctialLongitudeArgumentUtility.convertL(cachedType, l, ex, ey, type));
1174 final T oMe2 = a.getField().getOne().subtract(ex.square()).subtract(ey.square());
1175 ksi = ex.multiply(sc.cos()).add(1).add(ey.multiply(sc.sin()));
1176 return n.multiply(ksi).multiply(ksi).divide(oMe2.multiply(oMe2.sqrt()));
1177 }
1178 }
1179
1180
1181
1182
1183 public String toString() {
1184 return new StringBuilder().append("equinoctial parameters: ").append('{').
1185 append("a: ").append(a.getReal()).
1186 append("; ex: ").append(ex.getReal()).append("; ey: ").append(ey.getReal()).
1187 append("; hx: ").append(hx.getReal()).append("; hy: ").append(hy.getReal()).
1188 append("; lv: ").append(FastMath.toDegrees(getLv().getReal())).
1189 append(";}").toString();
1190 }
1191
1192
1193 @Override
1194 public PositionAngleType getCachedPositionAngleType() {
1195 return cachedPositionAngleType;
1196 }
1197
1198
1199 @Override
1200 public boolean hasNonKeplerianRates() {
1201 return hasNonKeplerianAcceleration();
1202 }
1203
1204
1205 @Override
1206 public FieldEquinoctialOrbit<T> withKeplerianRates() {
1207 return new FieldEquinoctialOrbit<>(getA(), getEquinoctialEx(), getEquinoctialEy(), getHx(), getHy(),
1208 cachedL, cachedPositionAngleType, getFrame(), getDate(), getMu());
1209 }
1210
1211
1212 @Override
1213 public EquinoctialOrbit toOrbit() {
1214 final double cachedPositionAngle = cachedL.getReal();
1215 if (hasNonKeplerianRates()) {
1216 return new EquinoctialOrbit(a.getReal(), ex.getReal(), ey.getReal(),
1217 hx.getReal(), hy.getReal(), cachedPositionAngle,
1218 aDot.getReal(), exDot.getReal(), eyDot.getReal(),
1219 hxDot.getReal(), hyDot.getReal(), cachedLDot.getReal(),
1220 cachedPositionAngleType, getFrame(),
1221 getDate().toAbsoluteDate(), getMu().getReal());
1222 } else {
1223 return new EquinoctialOrbit(a.getReal(), ex.getReal(), ey.getReal(),
1224 hx.getReal(), hy.getReal(), cachedPositionAngle,
1225 cachedPositionAngleType, getFrame(),
1226 getDate().toAbsoluteDate(), getMu().getReal());
1227 }
1228 }
1229
1230 }