1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.models.earth.troposphere;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.util.FastMath;
22 import org.hipparchus.util.FieldSinCos;
23 import org.hipparchus.util.MathArrays;
24 import org.hipparchus.util.MathUtils;
25 import org.hipparchus.util.SinCos;
26 import org.orekit.annotation.DefaultDataContext;
27 import org.orekit.bodies.FieldGeodeticPoint;
28 import org.orekit.bodies.GeodeticPoint;
29 import org.orekit.data.DataContext;
30 import org.orekit.time.AbsoluteDate;
31 import org.orekit.time.FieldAbsoluteDate;
32 import org.orekit.time.TimeScale;
33 import org.orekit.utils.FieldLegendrePolynomials;
34 import org.orekit.utils.FieldTrackingCoordinates;
35 import org.orekit.utils.LegendrePolynomials;
36 import org.orekit.utils.TrackingCoordinates;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class GlobalMappingFunctionModel implements TroposphereMappingFunction {
60
61
62 private static final double FACTOR = 1.0e-5;
63
64
65 private final TimeScale utc;
66
67
68
69
70
71
72
73 @DefaultDataContext
74 public GlobalMappingFunctionModel() {
75 this(DataContext.getDefault().getTimeScales().getUTC());
76 }
77
78
79
80
81
82 public GlobalMappingFunctionModel(final TimeScale utc) {
83 this.utc = utc;
84 }
85
86
87 @Override
88 public double[] mappingFactors(final TrackingCoordinates trackingCoordinates,
89 final GeodeticPoint point,
90 final AbsoluteDate date) {
91
92
93 final double bh = 0.0029;
94 final double c0h = 0.062;
95 final double c10h;
96 final double c11h;
97 final double psi;
98
99
100 final double latitude = point.getLatitude();
101 final double longitude = point.getLongitude();
102
103 if (FastMath.sin(latitude) > 0) {
104
105 c10h = 0.001;
106 c11h = 0.005;
107 psi = 0.0;
108 } else {
109
110 c10h = 0.002;
111 c11h = 0.007;
112 psi = FastMath.PI;
113 }
114
115 double t0 = 28;
116 if (latitude < 0) {
117
118 t0 += 183;
119 }
120 final double coef = psi + ((date.getDayOfYear(utc) + 1 - t0) / 365.25) * MathUtils.TWO_PI;
121 final double ch = c0h + ((FastMath.cos(coef) + 1) * (c11h / 2.0) + c10h) * (1.0 - FastMath.cos(latitude));
122
123
124 final double bw = 0.00146;
125 final double cw = 0.04391;
126
127
128
129
130 final int degree = 9;
131 final int order = 9;
132 final LegendrePolynomials p = new LegendrePolynomials(degree, order, FastMath.sin(latitude));
133
134 double a0Hydro = 0.;
135 double amplHydro = 0.;
136 double a0Wet = 0.;
137 double amplWet = 0.;
138 final ABCoefficients abCoef = new ABCoefficients();
139 int j = 0;
140 for (int n = 0; n <= 9; n++) {
141 for (int m = 0; m <= n; m++) {
142
143 final SinCos sc = FastMath.sinCos(m * longitude);
144
145 a0Hydro = a0Hydro + (abCoef.getAHMean(j) * p.getPnm(n, m) * sc.cos() +
146 abCoef.getBHMean(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
147
148 a0Wet = a0Wet + (abCoef.getAWMean(j) * p.getPnm(n, m) * sc.cos() +
149 abCoef.getBWMean(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
150
151 amplHydro = amplHydro + (abCoef.getAHAmplitude(j) * p.getPnm(n, m) * sc.cos() +
152 abCoef.getBHAmplitude(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
153
154 amplWet = amplWet + (abCoef.getAWAmplitude(j) * p.getPnm(n, m) * sc.cos() +
155 abCoef.getBWAmplitude(j) * p.getPnm(n, m) * sc.sin()) * FACTOR;
156
157 j = j + 1;
158 }
159 }
160
161
162 final double ah = a0Hydro + amplHydro * FastMath.cos(coef - psi);
163 final double aw = a0Wet + amplWet * FastMath.cos(coef - psi);
164
165 final double[] function = new double[2];
166 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch,
167 trackingCoordinates.getElevation());
168 function[1] = TroposphericModelUtils.mappingFunction(aw, bw, cw,
169 trackingCoordinates.getElevation());
170
171
172 final double correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
173 point.getAltitude());
174 function[0] = function[0] + correction;
175
176 return function;
177 }
178
179
180 @Override
181 public <T extends CalculusFieldElement<T>> T[] mappingFactors(final FieldTrackingCoordinates<T> trackingCoordinates,
182 final FieldGeodeticPoint<T> point,
183 final FieldAbsoluteDate<T> date) {
184
185 final Field<T> field = date.getField();
186 final T zero = field.getZero();
187
188
189 final T bh = zero.newInstance(0.0029);
190 final T c0h = zero.newInstance(0.062);
191 final T c10h;
192 final T c11h;
193 final T psi;
194
195
196 final T latitude = point.getLatitude();
197 final T longitude = point.getLongitude();
198
199
200 if (FastMath.sin(latitude.getReal()) > 0) {
201 c10h = zero.newInstance(0.001);
202 c11h = zero.newInstance(0.005);
203 psi = zero;
204 } else {
205 c10h = zero.newInstance(0.002);
206 c11h = zero.newInstance(0.007);
207 psi = zero.getPi();
208 }
209
210 double t0 = 28;
211 if (latitude.getReal() < 0) {
212
213 t0 += 183;
214 }
215 final T coef = psi.add(date.getDayOfYear(utc).add(1 - t0).divide(365.25).multiply(MathUtils.TWO_PI));
216 final T ch = c11h.divide(2.0).multiply(FastMath.cos(coef).add(1.0)).add(c10h).multiply(FastMath.cos(latitude).negate().add(1.0)).add(c0h);
217
218
219 final T bw = zero.newInstance(0.00146);
220 final T cw = zero.newInstance(0.04391);
221
222
223
224
225 final int degree = 9;
226 final int order = 9;
227 final FieldLegendrePolynomials<T> p = new FieldLegendrePolynomials<>(degree, order, FastMath.sin(latitude));
228
229 T a0Hydro = zero;
230 T amplHydro = zero;
231 T a0Wet = zero;
232 T amplWet = zero;
233 final ABCoefficients abCoef = new ABCoefficients();
234 int j = 0;
235 for (int n = 0; n <= 9; n++) {
236 for (int m = 0; m <= n; m++) {
237
238 final FieldSinCos<T> sc = FastMath.sinCos(longitude.multiply(m));
239
240
241 a0Hydro = a0Hydro.add(p.getPnm(n, m).multiply(abCoef.getAHMean(j)).multiply(sc.cos()).
242 add(p.getPnm(n, m).multiply(abCoef.getBHMean(j)).multiply(sc.sin())).
243 multiply(FACTOR));
244
245 a0Wet = a0Wet.add(p.getPnm(n, m).multiply(abCoef.getAWMean(j)).multiply(sc.cos()).
246 add(p.getPnm(n, m).multiply(abCoef.getBWMean(j)).multiply(sc.sin())).
247 multiply(FACTOR));
248
249 amplHydro = amplHydro.add(p.getPnm(n, m).multiply(abCoef.getAHAmplitude(j)).multiply(sc.cos()).
250 add(p.getPnm(n, m).multiply(abCoef.getBHAmplitude(j)).multiply(sc.sin())).
251 multiply(FACTOR));
252
253 amplWet = amplWet.add(p.getPnm(n, m).multiply(abCoef.getAWAmplitude(j)).multiply(sc.cos()).
254 add(p.getPnm(n, m).multiply(abCoef.getBWAmplitude(j)).multiply(sc.sin())).
255 multiply(FACTOR));
256
257 j = j + 1;
258 }
259 }
260
261
262 final T ah = a0Hydro.add(amplHydro.multiply(FastMath.cos(coef.subtract(psi))));
263 final T aw = a0Wet.add(amplWet.multiply(FastMath.cos(coef.subtract(psi))));
264
265 final T[] function = MathArrays.buildArray(field, 2);
266 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch,
267 trackingCoordinates.getElevation());
268 function[1] = TroposphericModelUtils.mappingFunction(aw, bw, cw,
269 trackingCoordinates.getElevation());
270
271
272 final T correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
273 point.getAltitude(),
274 field);
275 function[0] = function[0].add(correction);
276
277 return function;
278 }
279
280 private static class ABCoefficients {
281
282
283 private static final double[] AH_MEAN = {
284 1.2517e02,
285 8.503e-01,
286 6.936e-02,
287 -6.760e+00,
288 1.771e-01,
289 1.130e-02,
290 5.963e-01,
291 1.808e-02,
292 2.801e-03,
293 -1.414e-03,
294 -1.212e+00,
295 9.300e-02,
296 3.683e-03,
297 1.095e-03,
298 4.671e-05,
299 3.959e-01,
300 -3.867e-02,
301 5.413e-03,
302 -5.289e-04,
303 3.229e-04,
304 2.067e-05,
305 3.000e-01,
306 2.031e-02,
307 5.900e-03,
308 4.573e-04,
309 -7.619e-05,
310 2.327e-06,
311 3.845e-06,
312 1.182e-01,
313 1.158e-02,
314 5.445e-03,
315 6.219e-05,
316 4.204e-06,
317 -2.093e-06,
318 1.540e-07,
319 -4.280e-08,
320 -4.751e-01,
321 -3.490e-02,
322 1.758e-03,
323 4.019e-04,
324 -2.799e-06,
325 -1.287e-06,
326 5.468e-07,
327 7.580e-08,
328 -6.300e-09,
329 -1.160e-01,
330 8.301e-03,
331 8.771e-04,
332 9.955e-05,
333 -1.718e-06,
334 -2.012e-06,
335 1.170e-08,
336 1.790e-08,
337 -1.300e-09,
338 1.000e-10
339 };
340
341
342 private static final double[] BH_MEAN = {
343 0.000e+00,
344 0.000e+00,
345 3.249e-02,
346 0.000e+00,
347 3.324e-02,
348 1.850e-02,
349 0.000e+00,
350 -1.115e-01,
351 2.519e-02,
352 4.923e-03,
353 0.000e+00,
354 2.737e-02,
355 1.595e-02,
356 -7.332e-04,
357 1.933e-04,
358 0.000e+00,
359 -4.796e-02,
360 6.381e-03,
361 -1.599e-04,
362 -3.685e-04,
363 1.815e-05,
364 0.000e+00,
365 7.033e-02,
366 2.426e-03,
367 -1.111e-03,
368 -1.357e-04,
369 -7.828e-06,
370 2.547e-06,
371 0.000e+00,
372 5.779e-03,
373 3.133e-03,
374 -5.312e-04,
375 -2.028e-05,
376 2.323e-07,
377 -9.100e-08,
378 -1.650e-08,
379 0.000e+00,
380 3.688e-02,
381 -8.638e-04,
382 -8.514e-05,
383 -2.828e-05,
384 5.403e-07,
385 4.390e-07,
386 1.350e-08,
387 1.800e-09,
388 0.000e+00,
389 -2.736e-02,
390 -2.977e-04,
391 8.113e-05,
392 2.329e-07,
393 8.451e-07,
394 4.490e-08,
395 -8.100e-09,
396 -1.500e-09,
397 2.000e-10
398 };
399
400
401 private static final double[] AH_AMPL = {
402 -2.738e-01,
403 -2.837e+00,
404 1.298e-02,
405 -3.588e-01,
406 2.413e-02,
407 3.427e-02,
408 -7.624e-01,
409 7.272e-02,
410 2.160e-02,
411 -3.385e-03,
412 4.424e-01,
413 3.722e-02,
414 2.195e-02,
415 -1.503e-03,
416 2.426e-04,
417 3.013e-01,
418 5.762e-02,
419 1.019e-02,
420 -4.476e-04,
421 6.790e-05,
422 3.227e-05,
423 3.123e-01,
424 -3.535e-02,
425 4.840e-03,
426 3.025e-06,
427 -4.363e-05,
428 2.854e-07,
429 -1.286e-06,
430 -6.725e-01,
431 -3.730e-02,
432 8.964e-04,
433 1.399e-04,
434 -3.990e-06,
435 7.431e-06,
436 -2.796e-07,
437 -1.601e-07,
438 4.068e-02,
439 -1.352e-02,
440 7.282e-04,
441 9.594e-05,
442 2.070e-06,
443 -9.620e-08,
444 -2.742e-07,
445 -6.370e-08,
446 -6.300e-09,
447 8.625e-02,
448 -5.971e-03,
449 4.705e-04,
450 2.335e-05,
451 4.226e-06,
452 2.475e-07,
453 -8.850e-08,
454 -3.600e-08,
455 -2.900e-09,
456 0.000e+00
457 };
458
459
460 private static final double[] BH_AMPL = {
461 0.000e+00,
462 0.000e+00,
463 -1.136e-01,
464 0.000e+00,
465 -1.868e-01,
466 -1.399e-02,
467 0.000e+00,
468 -1.043e-01,
469 1.175e-02,
470 -2.240e-03,
471 0.000e+00,
472 -3.222e-02,
473 1.333e-02,
474 -2.647e-03,
475 -2.316e-05,
476 0.000e+00,
477 5.339e-02,
478 1.107e-02,
479 -3.116e-03,
480 -1.079e-04,
481 -1.299e-05,
482 0.000e+00,
483 4.861e-03,
484 8.891e-03,
485 -6.448e-04,
486 -1.279e-05,
487 6.358e-06,
488 -1.417e-07,
489 0.000e+00,
490 3.041e-02,
491 1.150e-03,
492 -8.743e-04,
493 -2.781e-05,
494 6.367e-07,
495 -1.140e-08,
496 -4.200e-08,
497 0.000e+00,
498 -2.982e-02,
499 -3.000e-03,
500 1.394e-05,
501 -3.290e-05,
502 -1.705e-07,
503 7.440e-08,
504 2.720e-08,
505 -6.600e-09,
506 0.000e+00,
507 1.236e-02,
508 -9.981e-04,
509 -3.792e-05,
510 -1.355e-05,
511 1.162e-06,
512 -1.789e-07,
513 1.470e-08,
514 -2.400e-09,
515 -4.000e-10
516 };
517
518
519 private static final double[] AW_MEAN = {
520 5.640e+01,
521 1.555e+00,
522 -1.011e+00,
523 -3.975e+00,
524 3.171e-02,
525 1.065e-01,
526 6.175e-01,
527 1.376e-01,
528 4.229e-02,
529 3.028e-03,
530 1.688e+00,
531 -1.692e-01,
532 5.478e-02,
533 2.473e-02,
534 6.059e-04,
535 2.278e+00,
536 6.614e-03,
537 -3.505e-04,
538 -6.697e-03,
539 8.402e-04,
540 7.033e-04,
541 -3.236e+00,
542 2.184e-01,
543 -4.611e-02,
544 -1.613e-02,
545 -1.604e-03,
546 5.420e-05,
547 7.922e-05,
548 -2.711e-01,
549 -4.406e-01,
550 -3.376e-02,
551 -2.801e-03,
552 -4.090e-04,
553 -2.056e-05,
554 6.894e-06,
555 2.317e-06,
556 1.941e+00,
557 -2.562e-01,
558 1.598e-02,
559 5.449e-03,
560 3.544e-04,
561 1.148e-05,
562 7.503e-06,
563 -5.667e-07,
564 -3.660e-08,
565 8.683e-01,
566 -5.931e-02,
567 -1.864e-03,
568 -1.277e-04,
569 2.029e-04,
570 1.269e-05,
571 1.629e-06,
572 9.660e-08,
573 -1.015e-07,
574 -5.000e-10
575 };
576
577
578 private static final double[] BW_MEAN = {
579 0.000e+00,
580 0.000e+00,
581 2.592e-01,
582 0.000e+00,
583 2.974e-02,
584 -5.471e-01,
585 0.000e+00,
586 -5.926e-01,
587 -1.030e-01,
588 -1.567e-02,
589 0.000e+00,
590 1.710e-01,
591 9.025e-02,
592 2.689e-02,
593 2.243e-03,
594 0.000e+00,
595 3.439e-01,
596 2.402e-02,
597 5.410e-03,
598 1.601e-03,
599 9.669e-05,
600 0.000e+00,
601 9.502e-02,
602 -3.063e-02,
603 -1.055e-03,
604 -1.067e-04,
605 -1.130e-04,
606 2.124e-05,
607 0.000e+00,
608 -3.129e-01,
609 8.463e-03,
610 2.253e-04,
611 7.413e-05,
612 -9.376e-05,
613 -1.606e-06,
614 2.060e-06,
615 0.000e+00,
616 2.739e-01,
617 1.167e-03,
618 -2.246e-05,
619 -1.287e-04,
620 -2.438e-05,
621 -7.561e-07,
622 1.158e-06,
623 4.950e-08,
624 0.000e+00,
625 -1.344e-01,
626 5.342e-03,
627 3.775e-04,
628 -6.756e-05,
629 -1.686e-06,
630 -1.184e-06,
631 2.768e-07,
632 2.730e-08,
633 5.700e-09
634 };
635
636
637 private static final double[] AW_AMPL = {
638 1.023e-01,
639 -2.695e+00,
640 3.417e-01,
641 -1.405e-01,
642 3.175e-01,
643 2.116e-01,
644 3.536e+00,
645 -1.505e-01,
646 -1.660e-02,
647 2.967e-02,
648 3.819e-01,
649 -1.695e-01,
650 -7.444e-02,
651 7.409e-03,
652 -6.262e-03,
653 -1.836e+00,
654 -1.759e-02,
655 -6.256e-02,
656 -2.371e-03,
657 7.947e-04,
658 1.501e-04,
659 -8.603e-01,
660 -1.360e-01,
661 -3.629e-02,
662 -3.706e-03,
663 -2.976e-04,
664 1.857e-05,
665 3.021e-05,
666 2.248e+00,
667 -1.178e-01,
668 1.255e-02,
669 1.134e-03,
670 -2.161e-04,
671 -5.817e-06,
672 8.836e-07,
673 -1.769e-07,
674 7.313e-01,
675 -1.188e-01,
676 1.145e-02,
677 1.011e-03,
678 1.083e-04,
679 2.570e-06,
680 -2.140e-06,
681 -5.710e-08,
682 2.000e-08,
683 -1.632e+00,
684 -6.948e-03,
685 -3.893e-03,
686 8.592e-04,
687 7.577e-05,
688 4.539e-06,
689 -3.852e-07,
690 -2.213e-07,
691 -1.370e-08,
692 5.800e-09
693 };
694
695
696 private static final double[] BW_AMPL = {
697 0.000e+00,
698 0.000e+00,
699 -8.865e-02,
700 0.000e+00,
701 -4.309e-01,
702 6.340e-02,
703 0.000e+00,
704 1.162e-01,
705 6.176e-02,
706 -4.234e-03,
707 0.000e+00,
708 2.530e-01,
709 4.017e-02,
710 -6.204e-03,
711 4.977e-03,
712 0.000e+00,
713 -1.737e-01,
714 -5.638e-03,
715 1.488e-04,
716 4.857e-04,
717 -1.809e-04,
718 0.000e+00,
719 -1.514e-01,
720 -1.685e-02,
721 5.333e-03,
722 -7.611e-05,
723 2.394e-05,
724 8.195e-06,
725 0.000e+00,
726 9.326e-02,
727 -1.275e-02,
728 -3.071e-04,
729 5.374e-05,
730 -3.391e-05,
731 -7.436e-06,
732 6.747e-07,
733 0.000e+00,
734 -8.637e-02,
735 -3.807e-03,
736 -6.833e-04,
737 -3.861e-05,
738 -2.268e-05,
739 1.454e-06,
740 3.860e-07,
741 -1.068e-07,
742 0.000e+00,
743 -2.658e-02,
744 -1.947e-03,
745 7.131e-04,
746 -3.506e-05,
747 1.885e-07,
748 5.792e-07,
749 3.990e-08,
750 2.000e-08,
751 -5.700e-09
752 };
753
754
755 ABCoefficients() {
756
757 }
758
759
760
761
762
763 public double getAHMean(final int index) {
764 return AH_MEAN[index];
765 }
766
767
768
769
770
771 public double getBHMean(final int index) {
772 return BH_MEAN[index];
773 }
774
775
776
777
778
779 public double getAWMean(final int index) {
780 return AW_MEAN[index];
781 }
782
783
784
785
786
787 public double getBWMean(final int index) {
788 return BW_MEAN[index];
789 }
790
791
792
793
794
795 public double getAHAmplitude(final int index) {
796 return AH_AMPL[index];
797 }
798
799
800
801
802
803 public double getBHAmplitude(final int index) {
804 return BH_AMPL[index];
805 }
806
807
808
809
810
811 public double getAWAmplitude(final int index) {
812 return AW_AMPL[index];
813 }
814
815
816
817
818
819 public double getBWAmplitude(final int index) {
820 return BW_AMPL[index];
821 }
822 }
823 }