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.Field;
20 import org.hipparchus.CalculusFieldElement;
21 import org.hipparchus.analysis.UnivariateFunction;
22 import org.hipparchus.analysis.interpolation.LinearInterpolator;
23 import org.hipparchus.util.FastMath;
24 import org.hipparchus.util.MathArrays;
25 import org.orekit.annotation.DefaultDataContext;
26 import org.orekit.bodies.FieldGeodeticPoint;
27 import org.orekit.bodies.GeodeticPoint;
28 import org.orekit.data.DataContext;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.FieldAbsoluteDate;
31 import org.orekit.time.TimeScale;
32 import org.orekit.utils.FieldTrackingCoordinates;
33 import org.orekit.utils.TrackingCoordinates;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class NiellMappingFunctionModel implements TroposphereMappingFunction {
50
51
52 private static final double[] VALUES_FOR_AH_AVERAGE = {
53 1.2769934e-3, 1.2683230e-3, 1.2465397e-3, 1.2196049e-3, 1.2045996e-3
54 };
55
56
57 private static final double[] VALUES_FOR_BH_AVERAGE = {
58 2.9153695e-3, 2.9152299e-3, 2.9288445e-3, 2.9022565e-3, 2.9024912e-3
59 };
60
61
62 private static final double[] VALUES_FOR_CH_AVERAGE = {
63 62.610505e-3, 62.837393e-3, 63.721774e-3, 63.824265e-3, 64.258455e-3
64 };
65
66
67 private static final double[] VALUES_FOR_AH_AMPLITUDE = {
68 0.0, 1.2709626e-5, 2.6523662e-5, 3.4000452e-5, 4.1202191e-5
69 };
70
71
72 private static final double[] VALUES_FOR_BH_AMPLITUDE = {
73 0.0, 2.1414979e-5, 3.0160779e-5, 7.2562722e-5, 11.723375e-5
74 };
75
76
77 private static final double[] VALUES_FOR_CH_AMPLITUDE = {
78 0.0, 9.0128400e-5, 4.3497037e-5, 84.795348e-5, 170.37206e-5
79 };
80
81
82 private static final double[] VALUES_FOR_AW = {
83 5.8021897e-4, 5.6794847e-4, 5.8118019e-4, 5.9727542e-4, 6.1641693e-4
84 };
85
86
87 private static final double[] VALUES_FOR_BW = {
88 1.4275268e-3, 1.5138625e-3, 1.4572752e-3, 1.5007428e-3, 1.7599082e-3
89 };
90
91
92 private static final double[] VALUES_FOR_CW = {
93 4.3472961e-2, 4.6729510e-2, 4.3908931e-2, 4.4626982e-2, 5.4736038e-2
94 };
95
96
97 private static final double[] LATITUDE_VALUES = {
98 FastMath.toRadians(15.0), FastMath.toRadians(30.0), FastMath.toRadians(45.0), FastMath.toRadians(60.0), FastMath.toRadians(75.0),
99 };
100
101
102 private final UnivariateFunction ahAverageFunction;
103
104
105 private final UnivariateFunction bhAverageFunction;
106
107
108 private final UnivariateFunction chAverageFunction;
109
110
111 private final UnivariateFunction ahAmplitudeFunction;
112
113
114 private final UnivariateFunction bhAmplitudeFunction;
115
116
117 private final UnivariateFunction chAmplitudeFunction;
118
119
120 private final UnivariateFunction awFunction;
121
122
123 private final UnivariateFunction bwFunction;
124
125
126 private final UnivariateFunction cwFunction;
127
128
129 private final TimeScale utc;
130
131
132
133
134
135
136
137 @DefaultDataContext
138 public NiellMappingFunctionModel() {
139 this(DataContext.getDefault().getTimeScales().getUTC());
140 }
141
142
143
144
145
146 public NiellMappingFunctionModel(final TimeScale utc) {
147 this.utc = utc;
148
149 this.ahAverageFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_AH_AVERAGE);
150 this.bhAverageFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_BH_AVERAGE);
151 this.chAverageFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_CH_AVERAGE);
152 this.ahAmplitudeFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_AH_AMPLITUDE);
153 this.bhAmplitudeFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_BH_AMPLITUDE);
154 this.chAmplitudeFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_CH_AMPLITUDE);
155
156
157 this.awFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_AW);
158 this.bwFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_BW);
159 this.cwFunction = new LinearInterpolator().interpolate(LATITUDE_VALUES, VALUES_FOR_CW);
160 }
161
162
163 @Override
164 public double[] mappingFactors(final TrackingCoordinates trackingCoordinates, final GeodeticPoint point,
165 final AbsoluteDate date) {
166
167
168 double t0 = 28;
169 if (point.getLatitude() < 0) {
170
171 t0 += 183;
172 }
173 final double coef = 2 * FastMath.PI * ((date.getDayOfYear(utc) - t0) / 365.25);
174 final double cosCoef = FastMath.cos(coef);
175
176
177 double absLatidude = FastMath.abs(point.getLatitude());
178
179 absLatidude = FastMath.max(FastMath.toRadians(15.0), absLatidude);
180
181 absLatidude = FastMath.min(FastMath.toRadians(75.0), absLatidude);
182 final double ah = ahAverageFunction.value(absLatidude) - ahAmplitudeFunction.value(absLatidude) * cosCoef;
183 final double bh = bhAverageFunction.value(absLatidude) - bhAmplitudeFunction.value(absLatidude) * cosCoef;
184 final double ch = chAverageFunction.value(absLatidude) - chAmplitudeFunction.value(absLatidude) * cosCoef;
185
186 final double[] function = new double[2];
187
188
189 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch, trackingCoordinates.getElevation());
190
191
192 function[1] = TroposphericModelUtils.mappingFunction(awFunction.value(absLatidude),
193 bwFunction.value(absLatidude),
194 cwFunction.value(absLatidude),
195 trackingCoordinates.getElevation());
196
197
198 final double correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
199 point.getAltitude());
200 function[0] = function[0] + correction;
201
202 return function;
203 }
204
205
206 @Override
207 public <T extends CalculusFieldElement<T>> T[] mappingFactors(final FieldTrackingCoordinates<T> trackingCoordinates,
208 final FieldGeodeticPoint<T> point,
209 final FieldAbsoluteDate<T> date) {
210 final Field<T> field = date.getField();
211 final T zero = field.getZero();
212
213
214 double t0 = 28;
215 if (point.getLatitude().getReal() < 0) {
216
217 t0 += 183;
218 }
219 final T coef = zero.getPi().multiply(2.0).multiply((date.getDayOfYear(utc).subtract(t0)).divide(365.25));
220 final T cosCoef = FastMath.cos(coef);
221
222
223 double absLatidude = FastMath.abs(point.getLatitude().getReal());
224
225 absLatidude = FastMath.max(FastMath.toRadians(15.0), absLatidude);
226
227 absLatidude = FastMath.min(FastMath.toRadians(75.0), absLatidude);
228 final T ah = cosCoef.multiply(ahAmplitudeFunction.value(absLatidude)).negate().add(ahAverageFunction.value(absLatidude));
229 final T bh = cosCoef.multiply(bhAmplitudeFunction.value(absLatidude)).negate().add(bhAverageFunction.value(absLatidude));
230 final T ch = cosCoef.multiply(chAmplitudeFunction.value(absLatidude)).negate().add(chAverageFunction.value(absLatidude));
231
232 final T[] function = MathArrays.buildArray(field, 2);
233
234
235 function[0] = TroposphericModelUtils.mappingFunction(ah, bh, ch,
236 trackingCoordinates.getElevation());
237
238
239 function[1] = TroposphericModelUtils.mappingFunction(zero.newInstance(awFunction.value(absLatidude)), zero.newInstance(bwFunction.value(absLatidude)),
240 zero.newInstance(cwFunction.value(absLatidude)), trackingCoordinates.getElevation());
241
242
243 final T correction = TroposphericModelUtils.computeHeightCorrection(trackingCoordinates.getElevation(),
244 point.getAltitude(),
245 field);
246 function[0] = function[0].add(correction);
247
248 return function;
249 }
250
251 }