1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.bodies;
18
19 import java.io.Serial;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.hipparchus.CalculusFieldElement;
24 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.FieldSinCos;
28 import org.hipparchus.util.SinCos;
29 import org.orekit.bodies.JPLEphemeridesLoader.EphemerisType;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.time.TimeScales;
33 import org.orekit.utils.Constants;
34
35
36
37
38
39
40
41
42
43
44
45
46 abstract class PredefinedIAUPoles implements IAUPole {
47
48
49 @Serial
50 private static final long serialVersionUID = 20200130L;
51
52
53 private final TimeScales timeScales;
54
55
56
57
58
59 private final boolean isGcrf;
60
61
62
63
64
65
66 PredefinedIAUPoles(final TimeScales timeScales) {
67 this(timeScales, false);
68 }
69
70
71
72
73
74
75
76
77
78 PredefinedIAUPoles(final TimeScales timeScales,
79 final boolean isGcrf) {
80 this.timeScales = timeScales;
81 this.isGcrf = isGcrf;
82 }
83
84
85 private static class Sun extends PredefinedIAUPoles {
86
87
88 @Serial
89 private static final long serialVersionUID = 20200130L;
90
91
92 private static final double W0 = 84.176;
93
94
95 private static final double W_DOT = 14.1844000;
96
97
98 private final Vector3D pole = new Vector3D(FastMath.toRadians(286.13),
99 FastMath.toRadians(63.87));
100
101
102
103
104
105
106 Sun(final TimeScales timeScales) {
107 super(timeScales);
108 }
109
110
111 public Vector3D getPole(final AbsoluteDate date) {
112 return pole;
113 }
114
115
116 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
117 return new FieldVector3D<>(date.getField(), pole);
118 }
119
120
121 public double getPrimeMeridianAngle(final AbsoluteDate date) {
122 return FastMath.toRadians(d(date) * W_DOT + W0);
123 }
124
125
126 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
127 return FastMath.toRadians(d(date).multiply(W_DOT).add(W0));
128 }
129
130 }
131
132
133 private static class Mercury extends PredefinedIAUPoles {
134
135
136 @Serial
137 private static final long serialVersionUID = 20200130L;
138
139
140 private static final double ALPHA_0 = 281.0097;
141
142
143 private static final double ALPHA_DOT = -0.0328;
144
145
146 private static final double DELTA_0 = 61.4143;
147
148
149 private static final double DELTA_DOT = -0.0049;
150
151
152 private static final double W_0 = 329.5469;
153
154
155 private static final double W_DOT = 6.1385025;
156
157
158 private static final double M1_COEFF = 0.00993822;
159
160
161 private static final double M2_COEFF = -0.00104581;
162
163
164 private static final double M3_COEFF = -0.00010280;
165
166
167 private static final double M4_COEFF = -0.00002364;
168
169
170 private static final double M5_COEFF = -0.00000532;
171
172
173 private static final double M1_0 = 174.791086;
174
175
176 private static final double M1_DOT = 4.092335;
177
178
179 private static final double M2_0 = 349.582171;
180
181
182 private static final double M2_DOT = 8.184670;
183
184
185 private static final double M3_0 = 164.373257;
186
187
188 private static final double M3_DOT = 12.277005;
189
190
191 private static final double M4_0 = 339.164343;
192
193
194 private static final double M4_DOT = 16.369340;
195
196
197 private static final double M5_0 = 153.955429;
198
199
200 private static final double M5_DOT = 20.461675;
201
202
203
204
205
206
207 Mercury(final TimeScales timeScales) {
208 super(timeScales);
209 }
210
211
212 public Vector3D getPole(final AbsoluteDate date) {
213 final double t = t(date);
214 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
215 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
216 }
217
218
219 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
220 final T t = t(date);
221 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
222 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
223 }
224
225
226 public double getPrimeMeridianAngle(final AbsoluteDate date) {
227 final double d = d(date);
228 return FastMath.toRadians(d(date) * W_DOT + W_0 +
229 FastMath.sin(FastMath.toRadians(d * M1_DOT + M1_0)) * M1_COEFF +
230 FastMath.sin(FastMath.toRadians(d * M2_DOT + M2_0)) * M2_COEFF +
231 FastMath.sin(FastMath.toRadians(d * M3_DOT + M3_0)) * M3_COEFF +
232 FastMath.sin(FastMath.toRadians(d * M4_DOT + M4_0)) * M4_COEFF +
233 FastMath.sin(FastMath.toRadians(d * M5_DOT + M5_0)) * M5_COEFF);
234 }
235
236
237 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
238 final T d = d(date);
239 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0).
240 add(FastMath.toRadians(d.multiply(M1_DOT).add(M1_0)).sin().multiply(M1_COEFF)).
241 add(FastMath.toRadians(d.multiply(M2_DOT).add(M2_0)).sin().multiply(M2_COEFF)).
242 add(FastMath.toRadians(d.multiply(M3_DOT).add(M3_0)).sin().multiply(M3_COEFF)).
243 add(FastMath.toRadians(d.multiply(M4_DOT).add(M4_0)).sin().multiply(M4_COEFF)).
244 add(FastMath.toRadians(d.multiply(M5_DOT).add(M5_0)).sin().multiply(M5_COEFF)));
245 }
246
247 }
248
249
250 private static class Venus extends PredefinedIAUPoles {
251
252
253 @Serial
254 private static final long serialVersionUID = 20200130L;
255
256
257 private static final double W_0 = 160.20;
258
259
260 private static final double W_DOT = -1.4813688;
261
262
263 private final Vector3D pole = new Vector3D(FastMath.toRadians(272.76),
264 FastMath.toRadians(67.16));
265
266
267
268
269
270
271 Venus(final TimeScales timeScales) {
272 super(timeScales);
273 }
274
275
276 public Vector3D getPole(final AbsoluteDate date) {
277 return pole;
278 }
279
280
281 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
282 return new FieldVector3D<>(date.getField(), pole);
283 }
284
285
286 public double getPrimeMeridianAngle(final AbsoluteDate date) {
287 return FastMath.toRadians(d(date) * W_DOT + W_0);
288 }
289
290
291 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
292 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
293 }
294
295 }
296
297
298 private static class Earth extends PredefinedIAUPoles {
299
300
301 @Serial
302 private static final long serialVersionUID = 20200130L;
303
304
305 private static final double ALPHA_0 = 0.00;
306
307
308 private static final double ALPHA_DOT = -0.641;
309
310
311 private static final double DELTA_0 = 90.00;
312
313
314 private static final double DELTA_DOT = -0.557;
315
316
317 private static final double W_0 = 190.147;
318
319
320 private static final double W_DOT = 360.9856235;
321
322
323
324
325
326
327 Earth(final TimeScales timeScales) {
328 super(timeScales);
329 }
330
331
332 public Vector3D getPole(final AbsoluteDate date) {
333 final double t = t(date);
334 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
335 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
336 }
337
338
339 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
340 final T t = t(date);
341 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
342 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
343 }
344
345
346 @Override
347 public Vector3D getNode(final AbsoluteDate date) {
348 final double t = t(date);
349 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 + 90.0),
350 0.0);
351 }
352
353
354 @Override
355 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
356 final T t = t(date);
357 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0 + 90.0)),
358 date.getField().getZero());
359 }
360
361
362 public double getPrimeMeridianAngle(final AbsoluteDate date) {
363 return FastMath.toRadians(d(date) * W_DOT + W_0);
364 }
365
366
367 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
368 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
369 }
370
371 }
372
373
374 private static class Moon extends PredefinedIAUPoles {
375
376
377 @Serial
378 private static final long serialVersionUID = 20200130L;
379
380
381 private static final double ALPHA_0 = 269.9949;
382
383
384 private static final double ALPHA_DOT = 0.0031;
385
386
387 private static final double DELTA_0 = 66.5392;
388
389
390 private static final double DELTA_DOT = 0.0130;
391
392
393 private static final double W_0 = 38.3213;
394
395
396 private static final double W_DOT = 13.17635815;
397
398
399 private static final double W_DOT_DOT = -1.4e-12;
400
401
402 private static final double E01_0 = 125.045;
403
404
405 private static final double E01_DOT = -0.0529921;
406
407
408 private static final double E01_SIN = -3.8787;
409
410
411 private static final double E01_COS = 1.5419;
412
413
414 private static final double E01_W_SIN = 3.5610;
415
416
417 private static final double E02_0 = 250.089;
418
419
420 private static final double E02_DOT = -0.1059842;
421
422
423 private static final double E02_SIN = -0.1204;
424
425
426 private static final double E02_COS = 0.0239;
427
428
429 private static final double E02_W_SIN = 0.1208;
430
431
432 private static final double E03_0 = 260.008;
433
434
435 private static final double E03_DOT = 13.0120009;
436
437
438 private static final double E03_SIN = 0.0700;
439
440
441 private static final double E03_COS = -0.0278;
442
443
444 private static final double E03_W_SIN = -0.0642;
445
446
447 private static final double E04_0 = 176.625;
448
449
450 private static final double E04_DOT = 13.3407154;
451
452
453 private static final double E04_SIN = -0.0172;
454
455
456 private static final double E04_COS = 0.0068;
457
458
459 private static final double E04_W_SIN = 0.0158;
460
461
462 private static final double E05_0 = 357.529;
463
464
465 private static final double E05_DOT = 0.9856003;
466
467
468 private static final double E05_W_SIN = 0.0252;
469
470
471 private static final double E06_0 = 311.589;
472
473
474 private static final double E06_DOT = 26.4057084;
475
476
477 private static final double E06_SIN = 0.0072;
478
479
480 private static final double E06_COS = -0.0029;
481
482
483 private static final double E06_W_SIN = -0.0066;
484
485
486 private static final double E07_0 = 134.963;
487
488
489 private static final double E07_DOT = 13.0649930;
490
491
492 private static final double E07_COS = 0.0009;
493
494
495 private static final double E07_W_SIN = -0.0047;
496
497
498 private static final double E08_0 = 276.617;
499
500
501 private static final double E08_DOT = 0.3287146;
502
503
504 private static final double E08_W_SIN = -0.0046;
505
506
507 private static final double E09_0 = 34.226;
508
509
510 private static final double E09_DOT = 1.7484877;
511
512
513 private static final double E09_W_SIN = 0.0028;
514
515
516 private static final double E10_0 = 15.134;
517
518
519 private static final double E10_DOT = -0.1589763;
520
521
522 private static final double E10_SIN = -0.0052;
523
524
525 private static final double E10_COS = 0.0008;
526
527
528 private static final double E10_W_SIN = 0.0052;
529
530
531 private static final double E11_0 = 119.743;
532
533
534 private static final double E11_DOT = 0.0036096;
535
536
537 private static final double E11_W_SIN = 0.0040;
538
539
540 private static final double E12_0 = 239.961;
541
542
543 private static final double E12_DOT = 0.1643573;
544
545
546 private static final double E12_W_SIN = 0.0019;
547
548
549 private static final double E13_0 = 25.053;
550
551
552 private static final double E13_DOT = 12.9590088;
553
554
555 private static final double E13_SIN = 0.0043;
556
557
558 private static final double E13_COS = -0.0009;
559
560
561 private static final double E13_W_SIN = -0.0044;
562
563
564
565
566
567
568 Moon(final TimeScales timeScales) {
569 super(timeScales);
570 }
571
572
573 public Vector3D getPole(final AbsoluteDate date) {
574 final double d = d(date);
575 final double t = t(date);
576
577 final SinCos scE01 = FastMath.sinCos(FastMath.toRadians(d * E01_DOT + E01_0));
578 final SinCos scE02 = FastMath.sinCos(FastMath.toRadians(d * E02_DOT + E02_0));
579 final SinCos scE03 = FastMath.sinCos(FastMath.toRadians(d * E03_DOT + E03_0));
580 final SinCos scE04 = FastMath.sinCos(FastMath.toRadians(d * E04_DOT + E04_0));
581 final SinCos scE06 = FastMath.sinCos(FastMath.toRadians(d * E06_DOT + E06_0));
582 final SinCos scE10 = FastMath.sinCos(FastMath.toRadians(d * E10_DOT + E10_0));
583 final SinCos scE13 = FastMath.sinCos(FastMath.toRadians(d * E13_DOT + E13_0));
584
585 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
586 scE01.sin() * E01_SIN +
587 scE02.sin() * E02_SIN +
588 scE03.sin() * E03_SIN +
589 scE04.sin() * E04_SIN +
590 scE06.sin() * E06_SIN +
591 scE10.sin() * E10_SIN +
592 scE13.sin() * E13_SIN),
593 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
594 scE01.cos() * E01_COS +
595 scE02.cos() * E02_COS +
596 scE03.cos() * E03_COS +
597 scE04.cos() * E04_COS +
598 scE06.cos() * E06_COS +
599 FastMath.cos(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_COS +
600 scE10.cos() * E10_COS +
601 scE13.cos() * E13_COS));
602 }
603
604
605 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
606 final T d = d(date);
607 final T t = t(date);
608
609 final FieldSinCos<T> scE01 = FastMath.sinCos(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)));
610 final FieldSinCos<T> scE02 = FastMath.sinCos(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)));
611 final FieldSinCos<T> scE03 = FastMath.sinCos(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)));
612 final FieldSinCos<T> scE04 = FastMath.sinCos(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)));
613 final FieldSinCos<T> scE06 = FastMath.sinCos(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)));
614 final FieldSinCos<T> scE10 = FastMath.sinCos(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)));
615 final FieldSinCos<T> scE13 = FastMath.sinCos(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)));
616
617 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
618 add(scE01.sin().multiply(E01_SIN)).
619 add(scE02.sin().multiply(E02_SIN)).
620 add(scE03.sin().multiply(E03_SIN)).
621 add(scE04.sin().multiply(E04_SIN)).
622 add(scE06.sin().multiply(E06_SIN)).
623 add(scE10.sin().multiply(E10_SIN)).
624 add(scE13.sin().multiply(E13_SIN))),
625 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
626 add(scE01.cos().multiply(E01_COS)).
627 add(scE02.cos().multiply(E02_COS)).
628 add(scE03.cos().multiply(E03_COS)).
629 add(scE04.cos().multiply(E04_COS)).
630 add(scE06.cos().multiply(E06_COS)).
631 add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).cos().multiply(E07_COS)).
632 add(scE10.cos().multiply(E10_COS)).
633 add(scE13.cos().multiply(E13_COS))));
634 }
635
636
637 public double getPrimeMeridianAngle(final AbsoluteDate date) {
638 final double d = d(date);
639
640 return FastMath.toRadians(d * (d * W_DOT_DOT + W_DOT) + W_0 +
641 FastMath.sin(FastMath.toRadians(d * E01_DOT + E01_0)) * E01_W_SIN +
642 FastMath.sin(FastMath.toRadians(d * E02_DOT + E02_0)) * E02_W_SIN +
643 FastMath.sin(FastMath.toRadians(d * E03_DOT + E03_0)) * E03_W_SIN +
644 FastMath.sin(FastMath.toRadians(d * E04_DOT + E04_0)) * E04_W_SIN +
645 FastMath.sin(FastMath.toRadians(d * E05_DOT + E05_0)) * E05_W_SIN +
646 FastMath.sin(FastMath.toRadians(d * E06_DOT + E06_0)) * E06_W_SIN +
647 FastMath.sin(FastMath.toRadians(d * E07_DOT + E07_0)) * E07_W_SIN +
648 FastMath.sin(FastMath.toRadians(d * E08_DOT + E08_0)) * E08_W_SIN +
649 FastMath.sin(FastMath.toRadians(d * E09_DOT + E09_0)) * E09_W_SIN +
650 FastMath.sin(FastMath.toRadians(d * E10_DOT + E10_0)) * E10_W_SIN +
651 FastMath.sin(FastMath.toRadians(d * E11_DOT + E11_0)) * E11_W_SIN +
652 FastMath.sin(FastMath.toRadians(d * E12_DOT + E12_0)) * E12_W_SIN +
653 FastMath.sin(FastMath.toRadians(d * E13_DOT + E13_0)) * E13_W_SIN);
654 }
655
656
657 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
658 final T d = d(date);
659 return FastMath.toRadians(d.multiply(d.multiply(W_DOT_DOT).add(W_DOT)).add(W_0).
660 add(FastMath.toRadians(d.multiply(E01_DOT).add(E01_0)).sin().multiply(E01_W_SIN)).
661 add(FastMath.toRadians(d.multiply(E02_DOT).add(E02_0)).sin().multiply(E02_W_SIN)).
662 add(FastMath.toRadians(d.multiply(E03_DOT).add(E03_0)).sin().multiply(E03_W_SIN)).
663 add(FastMath.toRadians(d.multiply(E04_DOT).add(E04_0)).sin().multiply(E04_W_SIN)).
664 add(FastMath.toRadians(d.multiply(E05_DOT).add(E05_0)).sin().multiply(E05_W_SIN)).
665 add(FastMath.toRadians(d.multiply(E06_DOT).add(E06_0)).sin().multiply(E06_W_SIN)).
666 add(FastMath.toRadians(d.multiply(E07_DOT).add(E07_0)).sin().multiply(E07_W_SIN)).
667 add(FastMath.toRadians(d.multiply(E08_DOT).add(E08_0)).sin().multiply(E08_W_SIN)).
668 add(FastMath.toRadians(d.multiply(E09_DOT).add(E09_0)).sin().multiply(E09_W_SIN)).
669 add(FastMath.toRadians(d.multiply(E10_DOT).add(E10_0)).sin().multiply(E10_W_SIN)).
670 add(FastMath.toRadians(d.multiply(E11_DOT).add(E11_0)).sin().multiply(E11_W_SIN)).
671 add(FastMath.toRadians(d.multiply(E12_DOT).add(E12_0)).sin().multiply(E12_W_SIN)).
672 add(FastMath.toRadians(d.multiply(E13_DOT).add(E13_0)).sin().multiply(E13_W_SIN)));
673 }
674
675 }
676
677
678 private static class Mars extends PredefinedIAUPoles {
679
680
681 @Serial
682 private static final long serialVersionUID = 20200130L;
683
684
685 private static final double ALPHA_0 = 317.68143;
686
687
688 private static final double ALPHA_DOT = -0.1061;
689
690
691 private static final double DELTA_0 = 52.88650;
692
693
694 private static final double DELTA_DOT = -0.0609;
695
696
697 private static final double W_0 = 176.630;
698
699
700 private static final double W_DOT = 350.89198226;
701
702
703
704
705
706
707 Mars(final TimeScales timeScales) {
708 super(timeScales);
709 }
710
711
712 public Vector3D getPole(final AbsoluteDate date) {
713 final double t = t(date);
714 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
715 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
716 }
717
718
719 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
720 final T t = t(date);
721 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
722 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
723 }
724
725
726 public double getPrimeMeridianAngle(final AbsoluteDate date) {
727 return FastMath.toRadians(d(date) * W_DOT + W_0);
728 }
729
730
731 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
732 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
733 }
734
735 }
736
737
738 private static class Jupiter extends PredefinedIAUPoles {
739
740
741 @Serial
742 private static final long serialVersionUID = 20200130L;
743
744
745 private static final double ALPHA_0 = 268.056595;
746
747
748 private static final double ALPHA_DOT = -0.006499;
749
750
751 private static final double DELTA_0 = 64.495303;
752
753
754 private static final double DELTA_DOT = 0.002413;
755
756
757 private static final double JA_0 = 99.360714;
758
759
760 private static final double JA_DOT = 4850.4046;
761
762
763 private static final double JA_SIN = 0.000117;
764
765
766 private static final double JA_COS = 0.000050;
767
768
769 private static final double JB_0 = 175.895369;
770
771
772 private static final double JB_DOT = 1191.9605;
773
774
775 private static final double JB_SIN = 0.000938;
776
777
778 private static final double JB_COS = 0.000404;
779
780
781 private static final double JC_0 = 300.323162;
782
783
784 private static final double JC_DOT = 262.5475;
785
786
787 private static final double JC_SIN = 0.001432;
788
789
790 private static final double JC_COS = 0.000617;
791
792
793 private static final double JD_0 = 114.012305;
794
795
796 private static final double JD_DOT = 6070.2476;
797
798
799 private static final double JD_SIN = 0.000030;
800
801
802 private static final double JD_COS = -0.000013;
803
804
805 private static final double JE_0 = 49.511251;
806
807
808 private static final double JE_DOT = 64.3000;
809
810
811 private static final double JE_SIN = 0.002150;
812
813
814 private static final double JE_COS = 0.000926;
815
816
817 private static final double W_0 = 284.95;
818
819
820 private static final double W_DOT = 870.5360000;
821
822
823
824
825
826
827 Jupiter(final TimeScales timeScales) {
828 super(timeScales);
829 }
830
831
832 public Vector3D getPole(final AbsoluteDate date) {
833
834 final double t = t(date);
835 final double ja = FastMath.toRadians(t * JA_DOT + JA_0);
836 final double jb = FastMath.toRadians(t * JB_DOT + JB_0);
837 final double jc = FastMath.toRadians(t * JC_DOT + JC_0);
838 final double jd = FastMath.toRadians(t * JD_DOT + JD_0);
839 final double je = FastMath.toRadians(t * JE_DOT + JE_0);
840
841 final SinCos scJa = FastMath.sinCos(ja);
842 final SinCos scJb = FastMath.sinCos(jb);
843 final SinCos scJc = FastMath.sinCos(jc);
844 final SinCos scJd = FastMath.sinCos(jd);
845 final SinCos scJe = FastMath.sinCos(je);
846
847 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0 +
848 scJa.sin() * JA_SIN +
849 scJb.sin() * JB_SIN +
850 scJc.sin() * JC_SIN +
851 scJd.sin() * JD_SIN +
852 scJe.sin() * JE_SIN),
853 FastMath.toRadians(t * DELTA_DOT + DELTA_0 +
854 scJa.cos() * JA_COS +
855 scJb.cos() * JB_COS +
856 scJc.cos() * JC_COS +
857 scJd.cos() * JD_COS +
858 scJe.cos() * JE_COS));
859 }
860
861
862 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
863
864 final T t = t(date);
865 final T ja = FastMath.toRadians(t.multiply(JA_DOT).add(JA_0));
866 final T jb = FastMath.toRadians(t.multiply(JB_DOT).add(JB_0));
867 final T jc = FastMath.toRadians(t.multiply(JC_DOT).add(JC_0));
868 final T jd = FastMath.toRadians(t.multiply(JD_DOT).add(JD_0));
869 final T je = FastMath.toRadians(t.multiply(JE_DOT).add(JE_0));
870
871 final FieldSinCos<T> scJa = FastMath.sinCos(ja);
872 final FieldSinCos<T> scJb = FastMath.sinCos(jb);
873 final FieldSinCos<T> scJc = FastMath.sinCos(jc);
874 final FieldSinCos<T> scJd = FastMath.sinCos(jd);
875 final FieldSinCos<T> scJe = FastMath.sinCos(je);
876
877 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0).
878 add(scJa.sin().multiply(JA_SIN)).
879 add(scJb.sin().multiply(JB_SIN)).
880 add(scJc.sin().multiply(JC_SIN)).
881 add(scJd.sin().multiply(JD_SIN)).
882 add(scJe.sin().multiply(JE_SIN))),
883 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0).
884 add(scJa.cos().multiply(JA_COS)).
885 add(scJb.cos().multiply(JB_COS)).
886 add(scJc.cos().multiply(JC_COS)).
887 add(scJd.cos().multiply(JD_COS)).
888 add(scJe.cos().multiply(JE_COS))));
889
890 }
891
892
893 public double getPrimeMeridianAngle(final AbsoluteDate date) {
894 return FastMath.toRadians(d(date) * W_DOT + W_0);
895 }
896
897
898 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
899 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
900 }
901
902 }
903
904
905 private static class Saturn extends PredefinedIAUPoles {
906
907
908 @Serial
909 private static final long serialVersionUID = 20200130L;
910
911
912 private static final double ALPHA_0 = 40.589;
913
914
915 private static final double ALPHA_DOT = -0.036;
916
917
918 private static final double DELTA_0 = 83.537;
919
920
921 private static final double DELTA_DOT = -0.004;
922
923
924 private static final double W_0 = 38.90;
925
926
927 private static final double W_DOT = 810.7939024;
928
929
930
931
932
933
934 Saturn(final TimeScales timeScales) {
935 super(timeScales);
936 }
937
938
939 public Vector3D getPole(final AbsoluteDate date) {
940 final double t = t(date);
941 return new Vector3D(FastMath.toRadians(t * ALPHA_DOT + ALPHA_0),
942 FastMath.toRadians(t * DELTA_DOT + DELTA_0));
943 }
944
945
946 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
947 final T t = t(date);
948 return new FieldVector3D<>(FastMath.toRadians(t.multiply(ALPHA_DOT).add(ALPHA_0)),
949 FastMath.toRadians(t.multiply(DELTA_DOT).add(DELTA_0)));
950 }
951
952
953 public double getPrimeMeridianAngle(final AbsoluteDate date) {
954 return FastMath.toRadians(d(date) * W_DOT + W_0);
955 }
956
957
958 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
959 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
960 }
961
962 }
963
964
965 private static class Uranus extends PredefinedIAUPoles {
966
967
968 @Serial
969 private static final long serialVersionUID = 20200130L;
970
971
972 private static final double W_0 = 203.81;
973
974
975 private static final double W_DOT = -501.1600928;
976
977
978 private final Vector3D pole = new Vector3D(FastMath.toRadians(257.311),
979 FastMath.toRadians(-15.175));
980
981
982
983
984
985
986 Uranus(final TimeScales timeScales) {
987 super(timeScales);
988 }
989
990
991 public Vector3D getPole(final AbsoluteDate date) {
992 return pole;
993 }
994
995
996 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
997 return new FieldVector3D<>(date.getField(), pole);
998 }
999
1000
1001 public double getPrimeMeridianAngle(final AbsoluteDate date) {
1002 return FastMath.toRadians(d(date) * W_DOT + W_0);
1003 }
1004
1005
1006 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1007 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
1008 }
1009
1010 }
1011
1012
1013 private static class Neptune extends PredefinedIAUPoles {
1014
1015
1016 @Serial
1017 private static final long serialVersionUID = 20200130L;
1018
1019
1020 private static final double ALPHA_0 = 299.36;
1021
1022
1023 private static final double ALPHA_SIN = 0.70;
1024
1025
1026 private static final double DELTA_0 = 43.46;
1027
1028
1029 private static final double DELTA_COS = -0.51;
1030
1031
1032 private static final double W_0 = 253.18;
1033
1034
1035 private static final double W_DOT = 536.3128492;
1036
1037
1038 private static final double W_SIN = -0.48;
1039
1040
1041 private static final double N_0 = 357.85;
1042
1043
1044 private static final double N_DOT = 52.316;
1045
1046
1047
1048
1049
1050
1051 Neptune(final TimeScales timeScales) {
1052 super(timeScales);
1053 }
1054
1055
1056 public Vector3D getPole(final AbsoluteDate date) {
1057 final double n = FastMath.toRadians(t(date) * N_DOT + N_0);
1058 final SinCos sc = FastMath.sinCos(n);
1059 return new Vector3D(FastMath.toRadians(sc.sin() * ALPHA_SIN + ALPHA_0),
1060 FastMath.toRadians(sc.cos() * DELTA_COS + DELTA_0));
1061 }
1062
1063
1064 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1065 final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
1066 final FieldSinCos<T> sc = FastMath.sinCos(n);
1067 return new FieldVector3D<>(FastMath.toRadians(sc.sin().multiply(ALPHA_SIN).add(ALPHA_0)),
1068 FastMath.toRadians(sc.cos().multiply(DELTA_COS).add(DELTA_0)));
1069 }
1070
1071
1072 public double getPrimeMeridianAngle(final AbsoluteDate date) {
1073 final double n = FastMath.toRadians(t(date) * N_DOT + N_0);
1074 return FastMath.toRadians(d(date) * W_DOT + FastMath.sin(n) * W_SIN + W_0);
1075 }
1076
1077
1078 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1079 final T n = FastMath.toRadians(t(date).multiply(N_DOT).add(N_0));
1080 return FastMath.toRadians(d(date).multiply(W_DOT).add(n.sin().multiply(W_SIN)).add(W_0));
1081 }
1082
1083 }
1084
1085
1086 private static class Pluto extends PredefinedIAUPoles {
1087
1088
1089 @Serial
1090 private static final long serialVersionUID = 20200130L;
1091
1092
1093 private static final double W_0 = 302.695;
1094
1095
1096 private static final double W_DOT = 56.3625225;
1097
1098
1099 private final Vector3D pole = new Vector3D(FastMath.toRadians(132.993),
1100 FastMath.toRadians(-6.163));
1101
1102
1103
1104
1105
1106
1107 Pluto(final TimeScales timeScales) {
1108 super(timeScales);
1109 }
1110
1111
1112 public Vector3D getPole(final AbsoluteDate date) {
1113 return pole;
1114 }
1115
1116
1117 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1118 return new FieldVector3D<>(date.getField(), pole);
1119 }
1120
1121
1122 public double getPrimeMeridianAngle(final AbsoluteDate date) {
1123 return FastMath.toRadians(d(date) * W_DOT + W_0);
1124 }
1125
1126
1127 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1128 return FastMath.toRadians(d(date).multiply(W_DOT).add(W_0));
1129 }
1130
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140 private static class GcrfAligned extends PredefinedIAUPoles {
1141
1142
1143 @Serial
1144 private static final long serialVersionUID = 20200130L;
1145
1146
1147
1148
1149
1150
1151 GcrfAligned(final TimeScales timeScales) {
1152 super(timeScales, true);
1153 }
1154
1155
1156 public Vector3D getPole(final AbsoluteDate date) {
1157 return Vector3D.PLUS_K;
1158 }
1159
1160
1161 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getPole(final FieldAbsoluteDate<T> date) {
1162 return FieldVector3D.getPlusK(date.getField());
1163 }
1164
1165
1166 @Override
1167 public Vector3D getNode(final AbsoluteDate date) {
1168 return Vector3D.PLUS_I;
1169 }
1170
1171
1172 @Override
1173 public <T extends CalculusFieldElement<T>> FieldVector3D<T> getNode(final FieldAbsoluteDate<T> date) {
1174 return FieldVector3D.getPlusI(date.getField());
1175 }
1176
1177
1178 public double getPrimeMeridianAngle(final AbsoluteDate date) {
1179 return 0;
1180 }
1181
1182
1183 public <T extends CalculusFieldElement<T>> T getPrimeMeridianAngle(final FieldAbsoluteDate<T> date) {
1184 return date.getField().getZero();
1185 }
1186
1187 }
1188
1189
1190
1191
1192
1193
1194
1195 public static PredefinedIAUPoles getIAUPole(final EphemerisType body,
1196 final TimeScales timeScales) {
1197
1198 return switch (body) {
1199 case SUN -> new Sun(timeScales);
1200 case MERCURY -> new Mercury(timeScales);
1201 case VENUS -> new Venus(timeScales);
1202 case EARTH -> new Earth(timeScales);
1203 case MOON -> new Moon(timeScales);
1204 case MARS -> new Mars(timeScales);
1205 case JUPITER -> new Jupiter(timeScales);
1206 case SATURN -> new Saturn(timeScales);
1207 case URANUS -> new Uranus(timeScales);
1208 case NEPTUNE -> new Neptune(timeScales);
1209 case PLUTO -> new Pluto(timeScales);
1210 default -> new GcrfAligned(timeScales);
1211 };
1212 }
1213
1214
1215
1216
1217
1218
1219
1220 static List<PredefinedIAUPoles> values(final TimeScales timeScales) {
1221 final List<PredefinedIAUPoles> values = new ArrayList<>(12);
1222 values.add(new Sun(timeScales));
1223 values.add(new Mercury(timeScales));
1224 values.add(new Venus(timeScales));
1225 values.add(new Earth(timeScales));
1226 values.add(new Moon(timeScales));
1227 values.add(new Mars(timeScales));
1228 values.add(new Jupiter(timeScales));
1229 values.add(new Saturn(timeScales));
1230 values.add(new Uranus(timeScales));
1231 values.add(new Neptune(timeScales));
1232 values.add(new Pluto(timeScales));
1233 values.add(new GcrfAligned(timeScales));
1234 return values;
1235 }
1236
1237
1238
1239
1240
1241 protected double t(final AbsoluteDate date) {
1242 return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
1243 Constants.JULIAN_CENTURY;
1244 }
1245
1246
1247
1248
1249
1250
1251 protected <T extends CalculusFieldElement<T>> T t(final FieldAbsoluteDate<T> date) {
1252 final FieldAbsoluteDate<T> j2000Epoch =
1253 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
1254 return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_CENTURY);
1255 }
1256
1257
1258
1259
1260
1261 protected double d(final AbsoluteDate date) {
1262 return date.offsetFrom(timeScales.getJ2000Epoch(), timeScales.getTDB()) /
1263 Constants.JULIAN_DAY;
1264 }
1265
1266
1267
1268
1269
1270
1271 protected <T extends CalculusFieldElement<T>> T d(final FieldAbsoluteDate<T> date) {
1272 final FieldAbsoluteDate<T> j2000Epoch =
1273 new FieldAbsoluteDate<>(date.getField(), timeScales.getJ2000Epoch());
1274 return date.offsetFrom(j2000Epoch, timeScales.getTDB()).divide(Constants.JULIAN_DAY);
1275 }
1276
1277 @Override
1278 public boolean isGcrfAligned() {
1279 return isGcrf;
1280 }
1281
1282 }