1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.orbits;
18
19 import java.io.Serializable;
20 import java.util.List;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
23
24 import org.hipparchus.analysis.differentiation.DSFactory;
25 import org.hipparchus.analysis.differentiation.DerivativeStructure;
26 import org.hipparchus.analysis.interpolation.HermiteInterpolator;
27 import org.hipparchus.geometry.euclidean.threed.Vector3D;
28 import org.hipparchus.util.FastMath;
29 import org.hipparchus.util.MathUtils;
30 import org.orekit.errors.OrekitIllegalArgumentException;
31 import org.orekit.errors.OrekitInternalError;
32 import org.orekit.errors.OrekitMessages;
33 import org.orekit.frames.Frame;
34 import org.orekit.time.AbsoluteDate;
35 import org.orekit.utils.PVCoordinates;
36 import org.orekit.utils.TimeStampedPVCoordinates;
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 public class EquinoctialOrbit extends Orbit {
78
79
80 private static final long serialVersionUID = 20170414L;
81
82
83 private static final DSFactory FACTORY = new DSFactory(1, 1);
84
85
86 private final double a;
87
88
89 private final double ex;
90
91
92 private final double ey;
93
94
95 private final double hx;
96
97
98 private final double hy;
99
100
101 private final double lv;
102
103
104 private final double aDot;
105
106
107 private final double exDot;
108
109
110 private final double eyDot;
111
112
113 private final double hxDot;
114
115
116 private final double hyDot;
117
118
119 private final double lvDot;
120
121
122 private transient PVCoordinates partialPV;
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 public EquinoctialOrbit(final double a, final double ex, final double ey,
140 final double hx, final double hy, final double l,
141 final PositionAngle type,
142 final Frame frame, final AbsoluteDate date, final double mu)
143 throws IllegalArgumentException {
144 this(a, ex, ey, hx, hy, l,
145 Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN,
146 type, frame, date, mu);
147 }
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public EquinoctialOrbit(final double a, final double ex, final double ey,
171 final double hx, final double hy, final double l,
172 final double aDot, final double exDot, final double eyDot,
173 final double hxDot, final double hyDot, final double lDot,
174 final PositionAngle type,
175 final Frame frame, final AbsoluteDate date, final double mu)
176 throws IllegalArgumentException {
177 super(frame, date, mu);
178 if (ex * ex + ey * ey >= 1.0) {
179 throw new OrekitIllegalArgumentException(OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS,
180 getClass().getName());
181 }
182 this.a = a;
183 this.aDot = aDot;
184 this.ex = ex;
185 this.exDot = exDot;
186 this.ey = ey;
187 this.eyDot = eyDot;
188 this.hx = hx;
189 this.hxDot = hxDot;
190 this.hy = hy;
191 this.hyDot = hyDot;
192
193 if (hasDerivatives()) {
194 final DerivativeStructure exDS = FACTORY.build(ex, exDot);
195 final DerivativeStructure eyDS = FACTORY.build(ey, eyDot);
196 final DerivativeStructure lDS = FACTORY.build(l, lDot);
197 final DerivativeStructure lvDS;
198 switch (type) {
199 case MEAN :
200 lvDS = FieldEquinoctialOrbit.eccentricToTrue(FieldEquinoctialOrbit.meanToEccentric(lDS, exDS, eyDS), exDS, eyDS);
201 break;
202 case ECCENTRIC :
203 lvDS = FieldEquinoctialOrbit.eccentricToTrue(lDS, exDS, eyDS);
204 break;
205 case TRUE :
206 lvDS = lDS;
207 break;
208 default :
209 throw new OrekitInternalError(null);
210 }
211 this.lv = lvDS.getValue();
212 this.lvDot = lvDS.getPartialDerivative(1);
213 } else {
214 switch (type) {
215 case MEAN :
216 this.lv = eccentricToTrue(meanToEccentric(l, ex, ey), ex, ey);
217 break;
218 case ECCENTRIC :
219 this.lv = eccentricToTrue(l, ex, ey);
220 break;
221 case TRUE :
222 this.lv = l;
223 break;
224 default :
225 throw new OrekitInternalError(null);
226 }
227 this.lvDot = Double.NaN;
228 }
229
230 this.partialPV = null;
231
232 }
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248 public EquinoctialOrbit(final TimeStampedPVCoordinates pvCoordinates,
249 final Frame frame, final double mu)
250 throws IllegalArgumentException {
251 super(pvCoordinates, frame, mu);
252
253
254 final Vector3D pvP = pvCoordinates.getPosition();
255 final Vector3D pvV = pvCoordinates.getVelocity();
256 final Vector3D pvA = pvCoordinates.getAcceleration();
257 final double r2 = pvP.getNormSq();
258 final double r = FastMath.sqrt(r2);
259 final double V2 = pvV.getNormSq();
260 final double rV2OnMu = r * V2 / mu;
261
262 if (rV2OnMu > 2) {
263 throw new OrekitIllegalArgumentException(OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS,
264 getClass().getName());
265 }
266
267
268 final Vector3D w = pvCoordinates.getMomentum().normalize();
269 final double d = 1.0 / (1 + w.getZ());
270 hx = -d * w.getY();
271 hy = d * w.getX();
272
273
274 final double cLv = (pvP.getX() - d * pvP.getZ() * w.getX()) / r;
275 final double sLv = (pvP.getY() - d * pvP.getZ() * w.getY()) / r;
276 lv = FastMath.atan2(sLv, cLv);
277
278
279
280 a = r / (2 - rV2OnMu);
281
282
283 final double eSE = Vector3D.dotProduct(pvP, pvV) / FastMath.sqrt(mu * a);
284 final double eCE = rV2OnMu - 1;
285 final double e2 = eCE * eCE + eSE * eSE;
286 final double f = eCE - e2;
287 final double g = FastMath.sqrt(1 - e2) * eSE;
288 ex = a * (f * cLv + g * sLv) / r;
289 ey = a * (f * sLv - g * cLv) / r;
290
291 partialPV = pvCoordinates;
292
293 if (hasNonKeplerianAcceleration(pvCoordinates, mu)) {
294
295
296 final double[][] jacobian = new double[6][6];
297 getJacobianWrtCartesian(PositionAngle.MEAN, jacobian);
298
299 final Vector3D keplerianAcceleration = new Vector3D(-mu / (r * r2), pvP);
300 final Vector3D nonKeplerianAcceleration = pvA.subtract(keplerianAcceleration);
301 final double aX = nonKeplerianAcceleration.getX();
302 final double aY = nonKeplerianAcceleration.getY();
303 final double aZ = nonKeplerianAcceleration.getZ();
304 aDot = jacobian[0][3] * aX + jacobian[0][4] * aY + jacobian[0][5] * aZ;
305 exDot = jacobian[1][3] * aX + jacobian[1][4] * aY + jacobian[1][5] * aZ;
306 eyDot = jacobian[2][3] * aX + jacobian[2][4] * aY + jacobian[2][5] * aZ;
307 hxDot = jacobian[3][3] * aX + jacobian[3][4] * aY + jacobian[3][5] * aZ;
308 hyDot = jacobian[4][3] * aX + jacobian[4][4] * aY + jacobian[4][5] * aZ;
309
310
311
312 final double lMDot = getKeplerianMeanMotion() +
313 jacobian[5][3] * aX + jacobian[5][4] * aY + jacobian[5][5] * aZ;
314 final DerivativeStructure exDS = FACTORY.build(ex, exDot);
315 final DerivativeStructure eyDS = FACTORY.build(ey, eyDot);
316 final DerivativeStructure lMDS = FACTORY.build(getLM(), lMDot);
317 final DerivativeStructure lvDS = FieldEquinoctialOrbit.eccentricToTrue(FieldEquinoctialOrbit.meanToEccentric(lMDS, exDS, eyDS), exDS, eyDS);
318 lvDot = lvDS.getPartialDerivative(1);
319
320 } else {
321
322
323
324 aDot = Double.NaN;
325 exDot = Double.NaN;
326 eyDot = Double.NaN;
327 hxDot = Double.NaN;
328 hyDot = Double.NaN;
329 lvDot = Double.NaN;
330 }
331
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349 public EquinoctialOrbit(final PVCoordinates pvCoordinates, final Frame frame,
350 final AbsoluteDate date, final double mu)
351 throws IllegalArgumentException {
352 this(new TimeStampedPVCoordinates(date, pvCoordinates), frame, mu);
353 }
354
355
356
357
358 public EquinoctialOrbit(final Orbit op) {
359 super(op.getFrame(), op.getDate(), op.getMu());
360 a = op.getA();
361 aDot = op.getADot();
362 ex = op.getEquinoctialEx();
363 exDot = op.getEquinoctialExDot();
364 ey = op.getEquinoctialEy();
365 eyDot = op.getEquinoctialEyDot();
366 hx = op.getHx();
367 hxDot = op.getHxDot();
368 hy = op.getHy();
369 hyDot = op.getHyDot();
370 lv = op.getLv();
371 lvDot = op.getLvDot();
372 partialPV = null;
373 }
374
375
376 public OrbitType getType() {
377 return OrbitType.EQUINOCTIAL;
378 }
379
380
381 public double getA() {
382 return a;
383 }
384
385
386 public double getADot() {
387 return aDot;
388 }
389
390
391 public double getEquinoctialEx() {
392 return ex;
393 }
394
395
396 public double getEquinoctialExDot() {
397 return exDot;
398 }
399
400
401 public double getEquinoctialEy() {
402 return ey;
403 }
404
405
406 public double getEquinoctialEyDot() {
407 return eyDot;
408 }
409
410
411 public double getHx() {
412 return hx;
413 }
414
415
416 public double getHxDot() {
417 return hxDot;
418 }
419
420
421 public double getHy() {
422 return hy;
423 }
424
425
426 public double getHyDot() {
427 return hyDot;
428 }
429
430
431 public double getLv() {
432 return lv;
433 }
434
435
436 public double getLvDot() {
437 return lvDot;
438 }
439
440
441 public double getLE() {
442 return trueToEccentric(lv, ex, ey);
443 }
444
445
446 public double getLEDot() {
447 final DerivativeStructure lVDS = FACTORY.build(lv, lvDot);
448 final DerivativeStructure exDS = FACTORY.build(ex, exDot);
449 final DerivativeStructure eyDS = FACTORY.build(ey, eyDot);
450 final DerivativeStructure lEDS = FieldEquinoctialOrbit.trueToEccentric(lVDS, exDS, eyDS);
451 return lEDS.getPartialDerivative(1);
452 }
453
454
455 public double getLM() {
456 return eccentricToMean(trueToEccentric(lv, ex, ey), ex, ey);
457 }
458
459
460 public double getLMDot() {
461 final DerivativeStructure lVDS = FACTORY.build(lv, lvDot);
462 final DerivativeStructure exDS = FACTORY.build(ex, exDot);
463 final DerivativeStructure eyDS = FACTORY.build(ey, eyDot);
464 final DerivativeStructure lMDS = FieldEquinoctialOrbit.eccentricToMean(FieldEquinoctialOrbit.trueToEccentric(lVDS, exDS, eyDS), exDS, eyDS);
465 return lMDS.getPartialDerivative(1);
466 }
467
468
469
470
471
472 public double getL(final PositionAngle type) {
473 return (type == PositionAngle.MEAN) ? getLM() :
474 ((type == PositionAngle.ECCENTRIC) ? getLE() :
475 getLv());
476 }
477
478
479
480
481
482 public double getLDot(final PositionAngle type) {
483 return (type == PositionAngle.MEAN) ? getLMDot() :
484 ((type == PositionAngle.ECCENTRIC) ? getLEDot() :
485 getLvDot());
486 }
487
488
489
490
491
492
493
494 public static double eccentricToTrue(final double lE, final double ex, final double ey) {
495 final double epsilon = FastMath.sqrt(1 - ex * ex - ey * ey);
496 final double cosLE = FastMath.cos(lE);
497 final double sinLE = FastMath.sin(lE);
498 final double num = ex * sinLE - ey * cosLE;
499 final double den = epsilon + 1 - ex * cosLE - ey * sinLE;
500 return lE + 2 * FastMath.atan(num / den);
501 }
502
503
504
505
506
507
508
509 public static double trueToEccentric(final double lv, final double ex, final double ey) {
510 final double epsilon = FastMath.sqrt(1 - ex * ex - ey * ey);
511 final double cosLv = FastMath.cos(lv);
512 final double sinLv = FastMath.sin(lv);
513 final double num = ey * cosLv - ex * sinLv;
514 final double den = epsilon + 1 + ex * cosLv + ey * sinLv;
515 return lv + 2 * FastMath.atan(num / den);
516 }
517
518
519
520
521
522
523
524 public static double meanToEccentric(final double lM, final double ex, final double ey) {
525
526
527
528 double lE = lM;
529 double shift = 0.0;
530 double lEmlM = 0.0;
531 double cosLE = FastMath.cos(lE);
532 double sinLE = FastMath.sin(lE);
533 int iter = 0;
534 do {
535 final double f2 = ex * sinLE - ey * cosLE;
536 final double f1 = 1.0 - ex * cosLE - ey * sinLE;
537 final double f0 = lEmlM - f2;
538
539 final double f12 = 2.0 * f1;
540 shift = f0 * f12 / (f1 * f12 - f0 * f2);
541
542 lEmlM -= shift;
543 lE = lM + lEmlM;
544 cosLE = FastMath.cos(lE);
545 sinLE = FastMath.sin(lE);
546
547 } while ((++iter < 50) && (FastMath.abs(shift) > 1.0e-12));
548
549 return lE;
550
551 }
552
553
554
555
556
557
558
559 public static double eccentricToMean(final double lE, final double ex, final double ey) {
560 return lE - ex * FastMath.sin(lE) + ey * FastMath.cos(lE);
561 }
562
563
564 public double getE() {
565 return FastMath.sqrt(ex * ex + ey * ey);
566 }
567
568
569 public double getEDot() {
570 return (ex * exDot + ey * eyDot) / FastMath.sqrt(ex * ex + ey * ey);
571 }
572
573
574 public double getI() {
575 return 2 * FastMath.atan(FastMath.sqrt(hx * hx + hy * hy));
576 }
577
578
579 public double getIDot() {
580 final double h2 = hx * hx + hy * hy;
581 final double h = FastMath.sqrt(h2);
582 return 2 * (hx * hxDot + hy * hyDot) / (h * (1 + h2));
583 }
584
585
586
587 private void computePVWithoutA() {
588
589 if (partialPV != null) {
590
591 return;
592 }
593
594
595 final double lE = getLE();
596
597
598 final double hx2 = hx * hx;
599 final double hy2 = hy * hy;
600 final double factH = 1. / (1 + hx2 + hy2);
601
602
603 final double ux = (1 + hx2 - hy2) * factH;
604 final double uy = 2 * hx * hy * factH;
605 final double uz = -2 * hy * factH;
606
607 final double vx = uy;
608 final double vy = (1 - hx2 + hy2) * factH;
609 final double vz = 2 * hx * factH;
610
611
612 final double exey = ex * ey;
613 final double ex2 = ex * ex;
614 final double ey2 = ey * ey;
615 final double e2 = ex2 + ey2;
616 final double eta = 1 + FastMath.sqrt(1 - e2);
617 final double beta = 1. / eta;
618
619
620 final double cLe = FastMath.cos(lE);
621 final double sLe = FastMath.sin(lE);
622 final double exCeyS = ex * cLe + ey * sLe;
623
624
625 final double x = a * ((1 - beta * ey2) * cLe + beta * exey * sLe - ex);
626 final double y = a * ((1 - beta * ex2) * sLe + beta * exey * cLe - ey);
627
628 final double factor = FastMath.sqrt(getMu() / a) / (1 - exCeyS);
629 final double xdot = factor * (-sLe + beta * ey * exCeyS);
630 final double ydot = factor * ( cLe - beta * ex * exCeyS);
631
632 final Vector3D position =
633 new Vector3D(x * ux + y * vx, x * uy + y * vy, x * uz + y * vz);
634 final Vector3D velocity =
635 new Vector3D(xdot * ux + ydot * vx, xdot * uy + ydot * vy, xdot * uz + ydot * vz);
636 partialPV = new PVCoordinates(position, velocity);
637
638 }
639
640
641
642
643
644
645
646 private Vector3D nonKeplerianAcceleration() {
647
648 final double[][] dCdP = new double[6][6];
649 getJacobianWrtParameters(PositionAngle.MEAN, dCdP);
650
651 final double nonKeplerianMeanMotion = getLMDot() - getKeplerianMeanMotion();
652 final double nonKeplerianAx = dCdP[3][0] * aDot + dCdP[3][1] * exDot + dCdP[3][2] * eyDot +
653 dCdP[3][3] * hxDot + dCdP[3][4] * hyDot + dCdP[3][5] * nonKeplerianMeanMotion;
654 final double nonKeplerianAy = dCdP[4][0] * aDot + dCdP[4][1] * exDot + dCdP[4][2] * eyDot +
655 dCdP[4][3] * hxDot + dCdP[4][4] * hyDot + dCdP[4][5] * nonKeplerianMeanMotion;
656 final double nonKeplerianAz = dCdP[5][0] * aDot + dCdP[5][1] * exDot + dCdP[5][2] * eyDot +
657 dCdP[5][3] * hxDot + dCdP[5][4] * hyDot + dCdP[5][5] * nonKeplerianMeanMotion;
658
659 return new Vector3D(nonKeplerianAx, nonKeplerianAy, nonKeplerianAz);
660
661 }
662
663
664 protected TimeStampedPVCoordinates initPVCoordinates() {
665
666
667 computePVWithoutA();
668
669
670 final double r2 = partialPV.getPosition().getNormSq();
671 final Vector3D keplerianAcceleration = new Vector3D(-getMu() / (r2 * FastMath.sqrt(r2)), partialPV.getPosition());
672 final Vector3D acceleration = hasDerivatives() ?
673 keplerianAcceleration.add(nonKeplerianAcceleration()) :
674 keplerianAcceleration;
675
676 return new TimeStampedPVCoordinates(getDate(), partialPV.getPosition(), partialPV.getVelocity(), acceleration);
677
678 }
679
680
681 public EquinoctialOrbit shiftedBy(final double dt) {
682
683
684 final EquinoctialOrbit keplerianShifted = new EquinoctialOrbit(a, ex, ey, hx, hy,
685 getLM() + getKeplerianMeanMotion() * dt,
686 PositionAngle.MEAN, getFrame(),
687 getDate().shiftedBy(dt), getMu());
688
689 if (hasDerivatives()) {
690
691
692 final Vector3D nonKeplerianAcceleration = nonKeplerianAcceleration();
693
694
695 keplerianShifted.computePVWithoutA();
696 final Vector3D fixedP = new Vector3D(1, keplerianShifted.partialPV.getPosition(),
697 0.5 * dt * dt, nonKeplerianAcceleration);
698 final double fixedR2 = fixedP.getNormSq();
699 final double fixedR = FastMath.sqrt(fixedR2);
700 final Vector3D fixedV = new Vector3D(1, keplerianShifted.partialPV.getVelocity(),
701 dt, nonKeplerianAcceleration);
702 final Vector3D fixedA = new Vector3D(-getMu() / (fixedR2 * fixedR), keplerianShifted.partialPV.getPosition(),
703 1, nonKeplerianAcceleration);
704
705
706 return new EquinoctialOrbit(new TimeStampedPVCoordinates(keplerianShifted.getDate(),
707 fixedP, fixedV, fixedA),
708 keplerianShifted.getFrame(), keplerianShifted.getMu());
709
710 } else {
711
712 return keplerianShifted;
713 }
714
715 }
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737 public EquinoctialOrbit interpolate(final AbsoluteDate date, final Stream<Orbit> sample) {
738
739
740 final List<Orbit> list = sample.collect(Collectors.toList());
741 boolean useDerivatives = true;
742 for (final Orbit orbit : list) {
743 useDerivatives = useDerivatives && orbit.hasDerivatives();
744 }
745
746
747 final HermiteInterpolator interpolator = new HermiteInterpolator();
748
749
750 AbsoluteDate previousDate = null;
751 double previousLm = Double.NaN;
752 for (final Orbit orbit : list) {
753 final EquinoctialOrbit equi = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);
754 final double continuousLm;
755 if (previousDate == null) {
756 continuousLm = equi.getLM();
757 } else {
758 final double dt = equi.getDate().durationFrom(previousDate);
759 final double keplerLm = previousLm + equi.getKeplerianMeanMotion() * dt;
760 continuousLm = MathUtils.normalizeAngle(equi.getLM(), keplerLm);
761 }
762 previousDate = equi.getDate();
763 previousLm = continuousLm;
764 if (useDerivatives) {
765 interpolator.addSamplePoint(equi.getDate().durationFrom(date),
766 new double[] {
767 equi.getA(),
768 equi.getEquinoctialEx(),
769 equi.getEquinoctialEy(),
770 equi.getHx(),
771 equi.getHy(),
772 continuousLm
773 },
774 new double[] {
775 equi.getADot(),
776 equi.getEquinoctialExDot(),
777 equi.getEquinoctialEyDot(),
778 equi.getHxDot(),
779 equi.getHyDot(),
780 equi.getLMDot()
781 });
782 } else {
783 interpolator.addSamplePoint(equi.getDate().durationFrom(date),
784 new double[] {
785 equi.getA(),
786 equi.getEquinoctialEx(),
787 equi.getEquinoctialEy(),
788 equi.getHx(),
789 equi.getHy(),
790 continuousLm
791 });
792 }
793 }
794
795
796 final double[][] interpolated = interpolator.derivatives(0.0, 1);
797
798
799 return new EquinoctialOrbit(interpolated[0][0], interpolated[0][1], interpolated[0][2],
800 interpolated[0][3], interpolated[0][4], interpolated[0][5],
801 interpolated[1][0], interpolated[1][1], interpolated[1][2],
802 interpolated[1][3], interpolated[1][4], interpolated[1][5],
803 PositionAngle.MEAN, getFrame(), date, getMu());
804
805 }
806
807
808 protected double[][] computeJacobianMeanWrtCartesian() {
809
810 final double[][] jacobian = new double[6][6];
811
812
813 computePVWithoutA();
814 final Vector3D position = partialPV.getPosition();
815 final Vector3D velocity = partialPV.getVelocity();
816 final double r2 = position.getNormSq();
817 final double r = FastMath.sqrt(r2);
818 final double r3 = r * r2;
819
820 final double mu = getMu();
821 final double sqrtMuA = FastMath.sqrt(a * mu);
822 final double a2 = a * a;
823
824 final double e2 = ex * ex + ey * ey;
825 final double oMe2 = 1 - e2;
826 final double epsilon = FastMath.sqrt(oMe2);
827 final double beta = 1 / (1 + epsilon);
828 final double ratio = epsilon * beta;
829
830 final double hx2 = hx * hx;
831 final double hy2 = hy * hy;
832 final double hxhy = hx * hy;
833
834
835 final Vector3D f = new Vector3D(1 - hy2 + hx2, 2 * hxhy, -2 * hy).normalize();
836 final Vector3D g = new Vector3D(2 * hxhy, 1 + hy2 - hx2, 2 * hx).normalize();
837 final Vector3D w = Vector3D.crossProduct(position, velocity).normalize();
838
839
840 final double x = Vector3D.dotProduct(position, f);
841 final double y = Vector3D.dotProduct(position, g);
842 final double xDot = Vector3D.dotProduct(velocity, f);
843 final double yDot = Vector3D.dotProduct(velocity, g);
844
845
846 final double c1 = a / (sqrtMuA * epsilon);
847 final double c2 = a * sqrtMuA * beta / r3;
848 final double c3 = sqrtMuA / (r3 * epsilon);
849 final Vector3D drDotSdEx = new Vector3D( c1 * xDot * yDot - c2 * ey * x - c3 * x * y, f,
850 -c1 * xDot * xDot - c2 * ey * y + c3 * x * x, g);
851
852
853 final Vector3D drDotSdEy = new Vector3D( c1 * yDot * yDot + c2 * ex * x - c3 * y * y, f,
854 -c1 * xDot * yDot + c2 * ex * y + c3 * x * y, g);
855
856
857 final Vector3D vectorAR = new Vector3D(2 * a2 / r3, position);
858 final Vector3D vectorARDot = new Vector3D(2 * a2 / mu, velocity);
859 fillHalfRow(1, vectorAR, jacobian[0], 0);
860 fillHalfRow(1, vectorARDot, jacobian[0], 3);
861
862
863 final double d1 = -a * ratio / r3;
864 final double d2 = (hy * xDot - hx * yDot) / (sqrtMuA * epsilon);
865 final double d3 = (hx * y - hy * x) / sqrtMuA;
866 final Vector3D vectorExRDot =
867 new Vector3D((2 * x * yDot - xDot * y) / mu, g, -y * yDot / mu, f, -ey * d3 / epsilon, w);
868 fillHalfRow(ex * d1, position, -ey * d2, w, epsilon / sqrtMuA, drDotSdEy, jacobian[1], 0);
869 fillHalfRow(1, vectorExRDot, jacobian[1], 3);
870
871
872 final Vector3D vectorEyRDot =
873 new Vector3D((2 * xDot * y - x * yDot) / mu, f, -x * xDot / mu, g, ex * d3 / epsilon, w);
874 fillHalfRow(ey * d1, position, ex * d2, w, -epsilon / sqrtMuA, drDotSdEx, jacobian[2], 0);
875 fillHalfRow(1, vectorEyRDot, jacobian[2], 3);
876
877
878 final double h = (1 + hx2 + hy2) / (2 * sqrtMuA * epsilon);
879 fillHalfRow(-h * xDot, w, jacobian[3], 0);
880 fillHalfRow( h * x, w, jacobian[3], 3);
881
882
883 fillHalfRow(-h * yDot, w, jacobian[4], 0);
884 fillHalfRow( h * y, w, jacobian[4], 3);
885
886
887 final double l = -ratio / sqrtMuA;
888 fillHalfRow(-1 / sqrtMuA, velocity, d2, w, l * ex, drDotSdEx, l * ey, drDotSdEy, jacobian[5], 0);
889 fillHalfRow(-2 / sqrtMuA, position, ex * beta, vectorEyRDot, -ey * beta, vectorExRDot, d3, w, jacobian[5], 3);
890
891 return jacobian;
892
893 }
894
895
896 protected double[][] computeJacobianEccentricWrtCartesian() {
897
898
899 final double[][] jacobian = computeJacobianMeanWrtCartesian();
900
901
902
903
904
905 final double le = getLE();
906 final double cosLe = FastMath.cos(le);
907 final double sinLe = FastMath.sin(le);
908 final double aOr = 1 / (1 - ex * cosLe - ey * sinLe);
909
910
911 final double[] rowEx = jacobian[1];
912 final double[] rowEy = jacobian[2];
913 final double[] rowL = jacobian[5];
914 for (int j = 0; j < 6; ++j) {
915 rowL[j] = aOr * (rowL[j] + sinLe * rowEx[j] - cosLe * rowEy[j]);
916 }
917
918 return jacobian;
919
920 }
921
922
923 protected double[][] computeJacobianTrueWrtCartesian() {
924
925
926 final double[][] jacobian = computeJacobianEccentricWrtCartesian();
927
928
929
930
931
932
933
934
935
936
937
938
939
940 final double le = getLE();
941 final double cosLe = FastMath.cos(le);
942 final double sinLe = FastMath.sin(le);
943 final double eSinE = ex * sinLe - ey * cosLe;
944 final double ecosE = ex * cosLe + ey * sinLe;
945 final double e2 = ex * ex + ey * ey;
946 final double epsilon = FastMath.sqrt(1 - e2);
947 final double onePeps = 1 + epsilon;
948 final double d = onePeps - ecosE;
949 final double cT = (d * d + eSinE * eSinE) / 2;
950 final double cE = ecosE * onePeps - e2;
951 final double cX = ex * eSinE / epsilon - ey + sinLe * onePeps;
952 final double cY = ey * eSinE / epsilon + ex - cosLe * onePeps;
953 final double factorLe = (cT + cE) / cT;
954 final double factorEx = cX / cT;
955 final double factorEy = cY / cT;
956
957
958 final double[] rowEx = jacobian[1];
959 final double[] rowEy = jacobian[2];
960 final double[] rowL = jacobian[5];
961 for (int j = 0; j < 6; ++j) {
962 rowL[j] = factorLe * rowL[j] + factorEx * rowEx[j] + factorEy * rowEy[j];
963 }
964
965 return jacobian;
966
967 }
968
969
970 public void addKeplerContribution(final PositionAngle type, final double gm,
971 final double[] pDot) {
972 final double oMe2;
973 final double ksi;
974 final double n = FastMath.sqrt(gm / a) / a;
975 switch (type) {
976 case MEAN :
977 pDot[5] += n;
978 break;
979 case ECCENTRIC :
980 oMe2 = 1 - ex * ex - ey * ey;
981 ksi = 1 + ex * FastMath.cos(lv) + ey * FastMath.sin(lv);
982 pDot[5] += n * ksi / oMe2;
983 break;
984 case TRUE :
985 oMe2 = 1 - ex * ex - ey * ey;
986 ksi = 1 + ex * FastMath.cos(lv) + ey * FastMath.sin(lv);
987 pDot[5] += n * ksi * ksi / (oMe2 * FastMath.sqrt(oMe2));
988 break;
989 default :
990 throw new OrekitInternalError(null);
991 }
992 }
993
994
995
996
997 public String toString() {
998 return new StringBuffer().append("equinoctial parameters: ").append('{').
999 append("a: ").append(a).
1000 append("; ex: ").append(ex).append("; ey: ").append(ey).
1001 append("; hx: ").append(hx).append("; hy: ").append(hy).
1002 append("; lv: ").append(FastMath.toDegrees(lv)).
1003 append(";}").toString();
1004 }
1005
1006
1007
1008
1009 private Object writeReplace() {
1010 return new DTO(this);
1011 }
1012
1013
1014 private static class DTO implements Serializable {
1015
1016
1017 private static final long serialVersionUID = 20170414L;
1018
1019
1020 private double[] d;
1021
1022
1023 private final Frame frame;
1024
1025
1026
1027
1028 private DTO(final EquinoctialOrbit orbit) {
1029
1030 final TimeStampedPVCoordinates pv = orbit.getPVCoordinates();
1031
1032
1033 final double epoch = FastMath.floor(pv.getDate().durationFrom(AbsoluteDate.J2000_EPOCH));
1034 final double offset = pv.getDate().durationFrom(AbsoluteDate.J2000_EPOCH.shiftedBy(epoch));
1035
1036 if (orbit.hasDerivatives()) {
1037
1038 this.d = new double[] {
1039 epoch, offset, orbit.getMu(),
1040 orbit.a, orbit.ex, orbit.ey,
1041 orbit.hx, orbit.hy, orbit.lv,
1042 orbit.aDot, orbit.exDot, orbit.eyDot,
1043 orbit.hxDot, orbit.hyDot, orbit.lvDot
1044 };
1045 } else {
1046
1047 this.d = new double[] {
1048 epoch, offset, orbit.getMu(),
1049 orbit.a, orbit.ex, orbit.ey,
1050 orbit.hx, orbit.hy, orbit.lv
1051 };
1052 }
1053
1054 this.frame = orbit.getFrame();
1055
1056 }
1057
1058
1059
1060
1061 private Object readResolve() {
1062 if (d.length >= 15) {
1063
1064 return new EquinoctialOrbit(d[ 3], d[ 4], d[ 5], d[ 6], d[ 7], d[ 8],
1065 d[ 9], d[10], d[11], d[12], d[13], d[14],
1066 PositionAngle.TRUE,
1067 frame, AbsoluteDate.J2000_EPOCH.shiftedBy(d[0]).shiftedBy(d[1]),
1068 d[2]);
1069 } else {
1070
1071 return new EquinoctialOrbit(d[ 3], d[ 4], d[ 5], d[ 6], d[ 7], d[ 8], PositionAngle.TRUE,
1072 frame, AbsoluteDate.J2000_EPOCH.shiftedBy(d[0]).shiftedBy(d[1]),
1073 d[2]);
1074 }
1075 }
1076
1077 }
1078
1079 }