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.util.Collection;
20
21 import org.apache.commons.math3.analysis.interpolation.HermiteInterpolator;
22 import org.apache.commons.math3.geometry.euclidean.threed.Vector3D;
23 import org.apache.commons.math3.util.FastMath;
24 import org.apache.commons.math3.util.MathUtils;
25 import org.orekit.errors.OrekitException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.frames.Frame;
28 import org.orekit.time.AbsoluteDate;
29 import org.orekit.utils.PVCoordinates;
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 public class EquinoctialOrbit extends Orbit {
71
72
73
74
75 @Deprecated
76 public static final int MEAN_LATITUDE_ARGUMENT = 0;
77
78
79
80
81 @Deprecated
82 public static final int ECCENTRIC_LATITUDE_ARGUMENT = 1;
83
84
85
86
87 @Deprecated
88 public static final int TRUE_LATITUDE_ARGUMENT = 2;
89
90
91 private static final long serialVersionUID = -2000712440570076839L;
92
93
94 private final double a;
95
96
97 private final double ex;
98
99
100 private final double ey;
101
102
103 private final double hx;
104
105
106 private final double hy;
107
108
109 private final double lv;
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127 public EquinoctialOrbit(final double a, final double ex, final double ey,
128 final double hx, final double hy,
129 final double l, final PositionAngle type,
130 final Frame frame, final AbsoluteDate date, final double mu)
131 throws IllegalArgumentException {
132 super(frame, date, mu);
133 if (ex * ex + ey * ey >= 1.0) {
134 throw OrekitException.createIllegalArgumentException(
135 OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS, getClass().getName());
136 }
137 this.a = a;
138 this.ex = ex;
139 this.ey = ey;
140 this.hx = hx;
141 this.hy = hy;
142
143 switch (type) {
144 case MEAN :
145 this.lv = eccentricToTrue(meanToEccentric(l));
146 break;
147 case ECCENTRIC :
148 this.lv = eccentricToTrue(l);
149 break;
150 case TRUE :
151 this.lv = l;
152 break;
153 default :
154 throw OrekitException.createInternalError(null);
155 }
156
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182 @Deprecated
183 public EquinoctialOrbit(final double a, final double ex, final double ey,
184 final double hx, final double hy,
185 final double l, final int type,
186 final Frame frame, final AbsoluteDate date, final double mu)
187 throws IllegalArgumentException {
188 super(frame, date, mu);
189 if (ex * ex + ey * ey >= 1.0) {
190 throw OrekitException.createIllegalArgumentException(
191 OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS, getClass().getName());
192 }
193 this.a = a;
194 this.ex = ex;
195 this.ey = ey;
196 this.hx = hx;
197 this.hy = hy;
198
199 switch (type) {
200 case MEAN_LATITUDE_ARGUMENT :
201 this.lv = eccentricToTrue(meanToEccentric(l));
202 break;
203 case ECCENTRIC_LATITUDE_ARGUMENT :
204 this.lv = eccentricToTrue(l);
205 break;
206 case TRUE_LATITUDE_ARGUMENT :
207 this.lv = l;
208 break;
209 default :
210 this.lv = Double.NaN;
211 throw OrekitException.createIllegalArgumentException(
212 OrekitMessages.ANGLE_TYPE_NOT_SUPPORTED,
213 "MEAN_LATITUDE_ARGUMENT", "ECCENTRIC_LATITUDE_ARGUMENT",
214 "TRUE_LATITUDE_ARGUMENT");
215 }
216
217 }
218
219
220
221
222
223
224
225
226
227
228 public EquinoctialOrbit(final PVCoordinates pvCoordinates, final Frame frame,
229 final AbsoluteDate date, final double mu)
230 throws IllegalArgumentException {
231 super(pvCoordinates, frame, date, mu);
232
233
234 final Vector3D pvP = pvCoordinates.getPosition();
235 final Vector3D pvV = pvCoordinates.getVelocity();
236 final double r = pvP.getNorm();
237 final double V2 = pvV.getNormSq();
238 final double rV2OnMu = r * V2 / mu;
239
240 if (rV2OnMu > 2) {
241 throw OrekitException.createIllegalArgumentException(
242 OrekitMessages.HYPERBOLIC_ORBIT_NOT_HANDLED_AS, getClass().getName());
243 }
244
245
246 final Vector3D w = pvCoordinates.getMomentum().normalize();
247 final double d = 1.0 / (1 + w.getZ());
248 hx = -d * w.getY();
249 hy = d * w.getX();
250
251
252 final double cLv = (pvP.getX() - d * pvP.getZ() * w.getX()) / r;
253 final double sLv = (pvP.getY() - d * pvP.getZ() * w.getY()) / r;
254 lv = FastMath.atan2(sLv, cLv);
255
256
257
258 a = r / (2 - rV2OnMu);
259
260
261 final double eSE = Vector3D.dotProduct(pvP, pvV) / FastMath.sqrt(mu * a);
262 final double eCE = rV2OnMu - 1;
263 final double e2 = eCE * eCE + eSE * eSE;
264 final double f = eCE - e2;
265 final double g = FastMath.sqrt(1 - e2) * eSE;
266 ex = a * (f * cLv + g * sLv) / r;
267 ey = a * (f * sLv - g * cLv) / r;
268
269 }
270
271
272
273
274 public EquinoctialOrbit(final Orbit op) {
275 super(op.getFrame(), op.getDate(), op.getMu());
276 a = op.getA();
277 ex = op.getEquinoctialEx();
278 ey = op.getEquinoctialEy();
279 hx = op.getHx();
280 hy = op.getHy();
281 lv = op.getLv();
282 }
283
284
285 public OrbitType getType() {
286 return OrbitType.EQUINOCTIAL;
287 }
288
289
290 public double getA() {
291 return a;
292 }
293
294
295 public double getEquinoctialEx() {
296 return ex;
297 }
298
299
300 public double getEquinoctialEy() {
301 return ey;
302 }
303
304
305 public double getHx() {
306 return hx;
307 }
308
309
310 public double getHy() {
311 return hy;
312 }
313
314
315
316
317
318 public double getL(final PositionAngle type) {
319 return (type == PositionAngle.MEAN) ? getLM() :
320 ((type == PositionAngle.ECCENTRIC) ? getLE() :
321 getLv());
322 }
323
324
325 public double getLv() {
326 return lv;
327 }
328
329
330 public double getLE() {
331 final double epsilon = FastMath.sqrt(1 - ex * ex - ey * ey);
332 final double cosLv = FastMath.cos(lv);
333 final double sinLv = FastMath.sin(lv);
334 final double num = ey * cosLv - ex * sinLv;
335 final double den = epsilon + 1 + ex * cosLv + ey * sinLv;
336 return lv + 2 * FastMath.atan(num / den);
337 }
338
339
340
341
342
343 private double eccentricToTrue(final double lE) {
344 final double epsilon = FastMath.sqrt(1 - ex * ex - ey * ey);
345 final double cosLE = FastMath.cos(lE);
346 final double sinLE = FastMath.sin(lE);
347 final double num = ex * sinLE - ey * cosLE;
348 final double den = epsilon + 1 - ex * cosLE - ey * sinLE;
349 return lE + 2 * FastMath.atan(num / den);
350 }
351
352
353 public double getLM() {
354 final double lE = getLE();
355 return lE - ex * FastMath.sin(lE) + ey * FastMath.cos(lE);
356 }
357
358
359
360
361
362 private double meanToEccentric(final double lM) {
363
364
365
366 double lE = lM;
367 double shift = 0.0;
368 double lEmlM = 0.0;
369 double cosLE = FastMath.cos(lE);
370 double sinLE = FastMath.sin(lE);
371 int iter = 0;
372 do {
373 final double f2 = ex * sinLE - ey * cosLE;
374 final double f1 = 1.0 - ex * cosLE - ey * sinLE;
375 final double f0 = lEmlM - f2;
376
377 final double f12 = 2.0 * f1;
378 shift = f0 * f12 / (f1 * f12 - f0 * f2);
379
380 lEmlM -= shift;
381 lE = lM + lEmlM;
382 cosLE = FastMath.cos(lE);
383 sinLE = FastMath.sin(lE);
384
385 } while ((++iter < 50) && (FastMath.abs(shift) > 1.0e-12));
386
387 return lE;
388
389 }
390
391
392 public double getE() {
393 return FastMath.sqrt(ex * ex + ey * ey);
394 }
395
396
397 public double getI() {
398 return 2 * FastMath.atan(FastMath.sqrt(hx * hx + hy * hy));
399 }
400
401
402 protected PVCoordinates initPVCoordinates() {
403
404
405 final double lE = getLE();
406
407
408 final double hx2 = hx * hx;
409 final double hy2 = hy * hy;
410 final double factH = 1. / (1 + hx2 + hy2);
411
412
413 final double ux = (1 + hx2 - hy2) * factH;
414 final double uy = 2 * hx * hy * factH;
415 final double uz = -2 * hy * factH;
416
417 final double vx = uy;
418 final double vy = (1 - hx2 + hy2) * factH;
419 final double vz = 2 * hx * factH;
420
421
422 final double exey = ex * ey;
423 final double ex2 = ex * ex;
424 final double ey2 = ey * ey;
425 final double e2 = ex2 + ey2;
426 final double eta = 1 + FastMath.sqrt(1 - e2);
427 final double beta = 1. / eta;
428
429
430 final double cLe = FastMath.cos(lE);
431 final double sLe = FastMath.sin(lE);
432 final double exCeyS = ex * cLe + ey * sLe;
433
434
435 final double x = a * ((1 - beta * ey2) * cLe + beta * exey * sLe - ex);
436 final double y = a * ((1 - beta * ex2) * sLe + beta * exey * cLe - ey);
437
438 final double factor = FastMath.sqrt(getMu() / a) / (1 - exCeyS);
439 final double xdot = factor * (-sLe + beta * ey * exCeyS);
440 final double ydot = factor * ( cLe - beta * ex * exCeyS);
441
442 final Vector3D position =
443 new Vector3D(x * ux + y * vx, x * uy + y * vy, x * uz + y * vz);
444 final Vector3D velocity =
445 new Vector3D(xdot * ux + ydot * vx, xdot * uy + ydot * vy, xdot * uz + ydot * vz);
446 return new PVCoordinates(position, velocity);
447
448 }
449
450
451 public EquinoctialOrbit shiftedBy(final double dt) {
452 return new EquinoctialOrbit(a, ex, ey, hx, hy,
453 getLM() + getKeplerianMeanMotion() * dt,
454 PositionAngle.MEAN, getFrame(),
455 getDate().shiftedBy(dt), getMu());
456 }
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478 public EquinoctialOrbit interpolate(final AbsoluteDate date, final Collection<Orbit> sample) {
479
480
481 final HermiteInterpolator interpolator = new HermiteInterpolator();
482
483
484 AbsoluteDate previousDate = null;
485 double previousLm = Double.NaN;
486 for (final Orbit orbit : sample) {
487 final EquinoctialOrbit equi = (EquinoctialOrbit) OrbitType.EQUINOCTIAL.convertType(orbit);
488 final double continuousLm;
489 if (previousDate == null) {
490 continuousLm = equi.getLM();
491 } else {
492 final double dt = equi.getDate().durationFrom(previousDate);
493 final double keplerLm = previousLm + equi.getKeplerianMeanMotion() * dt;
494 continuousLm = MathUtils.normalizeAngle(equi.getLM(), keplerLm);
495 }
496 previousDate = equi.getDate();
497 previousLm = continuousLm;
498 interpolator.addSamplePoint(equi.getDate().durationFrom(date),
499 new double[] {
500 equi.getA(),
501 equi.getEquinoctialEx(),
502 equi.getEquinoctialEy(),
503 equi.getHx(),
504 equi.getHy(),
505 continuousLm
506 });
507 }
508
509
510 final double[] interpolated = interpolator.value(0);
511
512
513 return new EquinoctialOrbit(interpolated[0], interpolated[1], interpolated[2],
514 interpolated[3], interpolated[4], interpolated[5],
515 PositionAngle.MEAN, getFrame(), date, getMu());
516
517 }
518
519
520 protected double[][] computeJacobianMeanWrtCartesian() {
521
522 final double[][] jacobian = new double[6][6];
523
524
525 final Vector3D position = getPVCoordinates().getPosition();
526 final Vector3D velocity = getPVCoordinates().getVelocity();
527 final double r2 = position.getNormSq();
528 final double r = FastMath.sqrt(r2);
529 final double r3 = r * r2;
530
531 final double mu = getMu();
532 final double sqrtMuA = FastMath.sqrt(a * mu);
533 final double a2 = a * a;
534
535 final double e2 = ex * ex + ey * ey;
536 final double oMe2 = 1 - e2;
537 final double epsilon = FastMath.sqrt(oMe2);
538 final double beta = 1 / (1 + epsilon);
539 final double ratio = epsilon * beta;
540
541 final double hx2 = hx * hx;
542 final double hy2 = hy * hy;
543 final double hxhy = hx * hy;
544
545
546 final Vector3D f = new Vector3D(1 - hy2 + hx2, 2 * hxhy, -2 * hy).normalize();
547 final Vector3D g = new Vector3D(2 * hxhy, 1 + hy2 - hx2, 2 * hx).normalize();
548 final Vector3D w = Vector3D.crossProduct(position, velocity).normalize();
549
550
551 final double x = Vector3D.dotProduct(position, f);
552 final double y = Vector3D.dotProduct(position, g);
553 final double xDot = Vector3D.dotProduct(velocity, f);
554 final double yDot = Vector3D.dotProduct(velocity, g);
555
556
557 final double c1 = a / (sqrtMuA * epsilon);
558 final double c2 = a * sqrtMuA * beta / r3;
559 final double c3 = sqrtMuA / (r3 * epsilon);
560 final Vector3D drDotSdEx = new Vector3D( c1 * xDot * yDot - c2 * ey * x - c3 * x * y, f,
561 -c1 * xDot * xDot - c2 * ey * y + c3 * x * x, g);
562
563
564 final Vector3D drDotSdEy = new Vector3D( c1 * yDot * yDot + c2 * ex * x - c3 * y * y, f,
565 -c1 * xDot * yDot + c2 * ex * y + c3 * x * y, g);
566
567
568 final Vector3D vectorAR = new Vector3D(2 * a2 / r3, position);
569 final Vector3D vectorARDot = new Vector3D(2 * a2 / mu, velocity);
570 fillHalfRow(1, vectorAR, jacobian[0], 0);
571 fillHalfRow(1, vectorARDot, jacobian[0], 3);
572
573
574 final double d1 = -a * ratio / r3;
575 final double d2 = (hy * xDot - hx * yDot) / (sqrtMuA * epsilon);
576 final double d3 = (hx * y - hy * x) / sqrtMuA;
577 final Vector3D vectorExRDot =
578 new Vector3D((2 * x * yDot - xDot * y) / mu, g, -y * yDot / mu, f, -ey * d3 / epsilon, w);
579 fillHalfRow(ex * d1, position, -ey * d2, w, epsilon / sqrtMuA, drDotSdEy, jacobian[1], 0);
580 fillHalfRow(1, vectorExRDot, jacobian[1], 3);
581
582
583 final Vector3D vectorEyRDot =
584 new Vector3D((2 * xDot * y - x * yDot) / mu, f, -x * xDot / mu, g, ex * d3 / epsilon, w);
585 fillHalfRow(ey * d1, position, ex * d2, w, -epsilon / sqrtMuA, drDotSdEx, jacobian[2], 0);
586 fillHalfRow(1, vectorEyRDot, jacobian[2], 3);
587
588
589 final double h = (1 + hx2 + hy2) / (2 * sqrtMuA * epsilon);
590 fillHalfRow(-h * xDot, w, jacobian[3], 0);
591 fillHalfRow( h * x, w, jacobian[3], 3);
592
593
594 fillHalfRow(-h * yDot, w, jacobian[4], 0);
595 fillHalfRow( h * y, w, jacobian[4], 3);
596
597
598 final double l = -ratio / sqrtMuA;
599 fillHalfRow(-1 / sqrtMuA, velocity, d2, w, l * ex, drDotSdEx, l * ey, drDotSdEy, jacobian[5], 0);
600 fillHalfRow(-2 / sqrtMuA, position, ex * beta, vectorEyRDot, -ey * beta, vectorExRDot, d3, w, jacobian[5], 3);
601
602 return jacobian;
603
604 }
605
606
607 protected double[][] computeJacobianEccentricWrtCartesian() {
608
609
610 final double[][] jacobian = computeJacobianMeanWrtCartesian();
611
612
613
614
615
616 final double le = getLE();
617 final double cosLe = FastMath.cos(le);
618 final double sinLe = FastMath.sin(le);
619 final double aOr = 1 / (1 - ex * cosLe - ey * sinLe);
620
621
622 final double[] rowEx = jacobian[1];
623 final double[] rowEy = jacobian[2];
624 final double[] rowL = jacobian[5];
625 for (int j = 0; j < 6; ++j) {
626 rowL[j] = aOr * (rowL[j] + sinLe * rowEx[j] - cosLe * rowEy[j]);
627 }
628
629 return jacobian;
630
631 }
632
633
634 protected double[][] computeJacobianTrueWrtCartesian() {
635
636
637 final double[][] jacobian = computeJacobianEccentricWrtCartesian();
638
639
640
641
642
643
644
645
646
647
648
649
650
651 final double le = getLE();
652 final double cosLe = FastMath.cos(le);
653 final double sinLe = FastMath.sin(le);
654 final double eSinE = ex * sinLe - ey * cosLe;
655 final double ecosE = ex * cosLe + ey * sinLe;
656 final double e2 = ex * ex + ey * ey;
657 final double epsilon = FastMath.sqrt(1 - e2);
658 final double onePeps = 1 + epsilon;
659 final double d = onePeps - ecosE;
660 final double cT = (d * d + eSinE * eSinE) / 2;
661 final double cE = ecosE * onePeps - e2;
662 final double cX = ex * eSinE / epsilon - ey + sinLe * onePeps;
663 final double cY = ey * eSinE / epsilon + ex - cosLe * onePeps;
664 final double factorLe = (cT + cE) / cT;
665 final double factorEx = cX / cT;
666 final double factorEy = cY / cT;
667
668
669 final double[] rowEx = jacobian[1];
670 final double[] rowEy = jacobian[2];
671 final double[] rowL = jacobian[5];
672 for (int j = 0; j < 6; ++j) {
673 rowL[j] = factorLe * rowL[j] + factorEx * rowEx[j] + factorEy * rowEy[j];
674 }
675
676 return jacobian;
677
678 }
679
680
681 public void addKeplerContribution(final PositionAngle type, final double gm,
682 final double[] pDot) {
683 final double oMe2;
684 final double ksi;
685 final double n = FastMath.sqrt(gm / a) / a;
686 switch (type) {
687 case MEAN :
688 pDot[5] += n;
689 break;
690 case ECCENTRIC :
691 oMe2 = 1 - ex * ex - ey * ey;
692 ksi = 1 + ex * FastMath.cos(lv) + ey * FastMath.sin(lv);
693 pDot[5] += n * ksi / oMe2;
694 break;
695 case TRUE :
696 oMe2 = 1 - ex * ex - ey * ey;
697 ksi = 1 + ex * FastMath.cos(lv) + ey * FastMath.sin(lv);
698 pDot[5] += n * ksi * ksi / (oMe2 * FastMath.sqrt(oMe2));
699 break;
700 default :
701 throw OrekitException.createInternalError(null);
702 }
703 }
704
705
706
707
708 public String toString() {
709 return new StringBuffer().append("equinoctial parameters: ").append('{').
710 append("a: ").append(a).
711 append("; ex: ").append(ex).append("; ey: ").append(ey).
712 append("; hx: ").append(hx).append("; hy: ").append(hy).
713 append("; lv: ").append(FastMath.toDegrees(lv)).
714 append(";}").toString();
715 }
716
717 }