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.differentiation.DSFactory;
22 import org.hipparchus.analysis.differentiation.DerivativeStructure;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.hipparchus.util.Decimal64Field;
26 import org.hipparchus.util.FastMath;
27 import org.hipparchus.util.Precision;
28 import org.junit.Assert;
29 import org.junit.Before;
30 import org.junit.BeforeClass;
31 import org.junit.Test;
32 import org.orekit.Utils;
33 import org.orekit.attitudes.Attitude;
34 import org.orekit.bodies.FieldGeodeticPoint;
35 import org.orekit.bodies.GeodeticPoint;
36 import org.orekit.bodies.OneAxisEllipsoid;
37 import org.orekit.errors.OrekitException;
38 import org.orekit.estimation.measurements.GroundStation;
39 import org.orekit.frames.Frame;
40 import org.orekit.frames.FramesFactory;
41 import org.orekit.frames.TopocentricFrame;
42 import org.orekit.orbits.FieldKeplerianOrbit;
43 import org.orekit.orbits.FieldOrbit;
44 import org.orekit.orbits.Orbit;
45 import org.orekit.orbits.OrbitType;
46 import org.orekit.orbits.PositionAngle;
47 import org.orekit.propagation.FieldSpacecraftState;
48 import org.orekit.propagation.SpacecraftState;
49 import org.orekit.propagation.numerical.NumericalPropagator;
50 import org.orekit.time.AbsoluteDate;
51 import org.orekit.time.FieldAbsoluteDate;
52 import org.orekit.time.TimeScalesFactory;
53 import org.orekit.utils.Constants;
54 import org.orekit.utils.IERSConventions;
55
56 public class FieldMendesPavlisModelTest {
57
58 private static double epsilon = 1e-6;
59
60 @BeforeClass
61 public static void setUpGlobal() {
62 Utils.setDataRoot("atmosphere");
63 }
64
65 @Before
66 public void setUp() throws OrekitException {
67 Utils.setDataRoot("regular-data:potential/shm-format");
68 }
69
70 @Test
71 public void testZenithDelay() {
72 doTestZenithDelay(Decimal64Field.getInstance());
73 }
74
75 private <T extends CalculusFieldElement<T>> void doTestZenithDelay(final Field<T> field) {
76 final T zero = field.getZero();
77
78
79
80
81
82
83
84
85
86
87
88
89
90 final double latitude = FastMath.toRadians(30.67166667);
91 final double longitude = FastMath.toRadians(-104.0250);
92 final double height = 2010.344;
93 final double pressure = 798.4188;
94 final double temperature = 300.15;
95 final double humidity = 0.4;
96 final double lambda = 0.532;
97 final FieldGeodeticPoint<T> point = new FieldGeodeticPoint<>(zero.add(latitude), zero.add(longitude), zero.add(height));
98
99
100 final double expectedHydroDelay = 1.932992;
101
102 final double expectedWetDelay = 0.223375e-2;
103
104 final double expectedDelay = 1.935226;
105
106 final double precision = 4.0e-6;
107
108 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2009, 8, 12, TimeScalesFactory.getUTC());
109
110 final MendesPavlisModel model = new MendesPavlisModel(temperature, pressure,
111 humidity, lambda);
112
113 final T[] computedDelay = model.computeZenithDelay(point, model.getParameters(field), date);
114
115 Assert.assertEquals(expectedHydroDelay, computedDelay[0].getReal(), precision);
116 Assert.assertEquals(expectedWetDelay, computedDelay[1].getReal(), precision);
117 Assert.assertEquals(expectedDelay, computedDelay[0].getReal() + computedDelay[1].getReal(), precision);
118
119 }
120
121 @Test
122 public void testMappingFactors() {
123 doTestMappingFactors(Decimal64Field.getInstance());
124 }
125
126 private <T extends CalculusFieldElement<T>> void doTestMappingFactors(final Field<T> field) {
127 final T zero = field.getZero();
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field, 2009, 8, 12, TimeScalesFactory.getUTC());
143
144 final double latitude = FastMath.toRadians(30.67166667);
145 final double longitude = FastMath.toRadians(-104.0250);
146 final double height = 2075;
147 final double pressure = 798.4188;
148 final double temperature = 300.15;
149 final double humidity = 0.4;
150 final double lambda = 0.532;
151 final FieldGeodeticPoint<T> point = new FieldGeodeticPoint<>(zero.add(latitude), zero.add(longitude), zero.add(height));
152
153 final double elevation = FastMath.toRadians(15.0);
154
155 final double expectedMapping = 3.80024367;
156
157
158 final MendesPavlisModel model = new MendesPavlisModel(temperature, pressure,
159 humidity, lambda);
160
161 final T[] computedMapping = model.mappingFactors(zero.add(elevation), point, date);
162
163 Assert.assertEquals(expectedMapping, computedMapping[0].getReal(), 5.0e-8);
164 Assert.assertEquals(expectedMapping, computedMapping[1].getReal(), 5.0e-8);
165 }
166
167 @Test
168 public void testDelay() {
169 doTestDelay(Decimal64Field.getInstance());
170 }
171
172 private <T extends CalculusFieldElement<T>> void doTestDelay(final Field<T> field) {
173 final T zero = field.getZero();
174 final double elevation = 10d;
175 final double height = 100d;
176 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field);
177 final FieldGeodeticPoint<T> point = new FieldGeodeticPoint<>(zero.add(FastMath.toRadians(45.0)), zero.add(FastMath.toRadians(45.0)), zero.add(height));
178 MendesPavlisModel model = MendesPavlisModel.getStandardModel(0.6943);
179 final T path = model.pathDelay(zero.add(FastMath.toRadians(elevation)), point, model.getParameters(field), date);
180 Assert.assertTrue(Precision.compareTo(path.getReal(), 20d, epsilon) < 0);
181 Assert.assertTrue(Precision.compareTo(path.getReal(), 0d, epsilon) > 0);
182 }
183
184 @Test
185 public void testFixedHeight() {
186 doTestFixedHeight(Decimal64Field.getInstance());
187 }
188
189 private <T extends CalculusFieldElement<T>> void doTestFixedHeight(final Field<T> field) {
190 final T zero = field.getZero();
191 final FieldAbsoluteDate<T> date = new FieldAbsoluteDate<>(field);
192 final FieldGeodeticPoint<T> point = new FieldGeodeticPoint<>(zero.add(FastMath.toRadians(45.0)), zero.add(FastMath.toRadians(45.0)), zero.add(350.0));
193 MendesPavlisModel model = MendesPavlisModel.getStandardModel(0.6943);
194 T lastDelay = zero.add(Double.MAX_VALUE);
195
196 for (double elev = 10d; elev < 90d; elev += 8d) {
197 final T delay = model.pathDelay(zero.add(FastMath.toRadians(elev)), point, model.getParameters(field), date);
198 Assert.assertTrue(Precision.compareTo(delay.getReal(), lastDelay.getReal(), epsilon) < 0);
199 lastDelay = delay;
200 }
201 }
202
203 @Test
204 public void testDelayStateDerivatives() {
205
206
207 final double latitude = FastMath.toRadians(45.0);
208 final double longitude = FastMath.toRadians(45.0);
209 final double height = 0.0;
210 final GeodeticPoint point = new GeodeticPoint(latitude, longitude, height);
211
212 final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
213 Constants.WGS84_EARTH_FLATTENING,
214 FramesFactory.getITRF(IERSConventions.IERS_2010, true));
215
216 final TopocentricFrame baseFrame = new TopocentricFrame(earth, point, "topo");
217
218
219 final GroundStation station = new GroundStation(baseFrame);
220
221
222 final MendesPavlisModel model = MendesPavlisModel.getStandardModel(0.65);
223
224
225 final DSFactory factory = new DSFactory(6, 1);
226 final DerivativeStructure a0 = factory.variable(0, 24464560.0);
227 final DerivativeStructure e0 = factory.variable(1, 0.05);
228 final DerivativeStructure i0 = factory.variable(2, 0.122138);
229 final DerivativeStructure pa0 = factory.variable(3, 3.10686);
230 final DerivativeStructure raan0 = factory.variable(4, 1.00681);
231 final DerivativeStructure anomaly0 = factory.variable(5, 0.048363);
232 final Field<DerivativeStructure> field = a0.getField();
233 final DerivativeStructure zero = field.getZero();
234
235
236 final FieldAbsoluteDate<DerivativeStructure> dsDate = new FieldAbsoluteDate<>(field);
237
238 final Frame frame = FramesFactory.getEME2000();
239 final FieldOrbit<DerivativeStructure> dsOrbit = new FieldKeplerianOrbit<>(a0, e0, i0, pa0, raan0, anomaly0,
240 PositionAngle.MEAN, frame,
241 dsDate, zero.add(3.9860047e14));
242
243 final FieldSpacecraftState<DerivativeStructure> dsState = new FieldSpacecraftState<>(dsOrbit);
244
245
246 final FieldVector3D<DerivativeStructure> position = dsState.getPVCoordinates().getPosition();
247 final DerivativeStructure dsElevation = baseFrame.getElevation(position, frame, dsDate);
248
249
250 final FieldGeodeticPoint<DerivativeStructure> dsPoint = new FieldGeodeticPoint<>(zero.add(latitude), zero.add(longitude), zero.add(height));
251 final DerivativeStructure delay = model.pathDelay(dsElevation, dsPoint, model.getParameters(field), dsDate);
252
253 final double[] compDeriv = delay.getAllDerivatives();
254
255
256 final Orbit orbit = dsOrbit.toOrbit();
257 final SpacecraftState state = dsState.toSpacecraftState();
258
259
260 final double[][] refDeriv = new double[1][6];
261 final OrbitType orbitType = OrbitType.KEPLERIAN;
262 final PositionAngle angleType = PositionAngle.MEAN;
263 double dP = 0.001;
264 double[] steps = NumericalPropagator.tolerances(1000000 * dP, orbit, orbitType)[0];
265 for (int i = 0; i < 6; i++) {
266 SpacecraftState stateM4 = shiftState(state, orbitType, angleType, -4 * steps[i], i);
267 final Vector3D positionM4 = stateM4.getPVCoordinates().getPosition();
268 final double elevationM4 = station.getBaseFrame().getElevation(positionM4, stateM4.getFrame(), stateM4.getDate());
269 double delayM4 = model.pathDelay(elevationM4, point, model.getParameters(), stateM4.getDate());
270
271 SpacecraftState stateM3 = shiftState(state, orbitType, angleType, -3 * steps[i], i);
272 final Vector3D positionM3 = stateM3.getPVCoordinates().getPosition();
273 final double elevationM3 = station.getBaseFrame().getElevation(positionM3, stateM3.getFrame(), stateM3.getDate());
274 double delayM3 = model.pathDelay(elevationM3, point, model.getParameters(), stateM3.getDate());
275
276 SpacecraftState stateM2 = shiftState(state, orbitType, angleType, -2 * steps[i], i);
277 final Vector3D positionM2 = stateM2.getPVCoordinates().getPosition();
278 final double elevationM2 = station.getBaseFrame().getElevation(positionM2, stateM2.getFrame(), stateM2.getDate());
279 double delayM2 = model.pathDelay(elevationM2, point, model.getParameters(), stateM2.getDate());
280
281 SpacecraftState stateM1 = shiftState(state, orbitType, angleType, -1 * steps[i], i);
282 final Vector3D positionM1 = stateM1.getPVCoordinates().getPosition();
283 final double elevationM1 = station.getBaseFrame().getElevation(positionM1, stateM1.getFrame(), stateM1.getDate());
284 double delayM1 = model.pathDelay(elevationM1, point, model.getParameters(), stateM1.getDate());
285
286 SpacecraftState stateP1 = shiftState(state, orbitType, angleType, 1 * steps[i], i);
287 final Vector3D positionP1 = stateP1.getPVCoordinates().getPosition();
288 final double elevationP1 = station.getBaseFrame().getElevation(positionP1, stateP1.getFrame(), stateP1.getDate());
289 double delayP1 = model.pathDelay(elevationP1, point, model.getParameters(), stateP1.getDate());
290
291 SpacecraftState stateP2 = shiftState(state, orbitType, angleType, 2 * steps[i], i);
292 final Vector3D positionP2 = stateP2.getPVCoordinates().getPosition();
293 final double elevationP2 = station.getBaseFrame().getElevation(positionP2, stateP2.getFrame(), stateP2.getDate());
294 double delayP2 = model.pathDelay(elevationP2, point, model.getParameters(), stateP2.getDate());
295
296 SpacecraftState stateP3 = shiftState(state, orbitType, angleType, 3 * steps[i], i);
297 final Vector3D positionP3 = stateP3.getPVCoordinates().getPosition();
298 final double elevationP3 = station.getBaseFrame().getElevation(positionP3, stateP3.getFrame(), stateP3.getDate());
299 double delayP3 = model.pathDelay(elevationP3, point, model.getParameters(), stateP3.getDate());
300
301 SpacecraftState stateP4 = shiftState(state, orbitType, angleType, 4 * steps[i], i);
302 final Vector3D positionP4 = stateP4.getPVCoordinates().getPosition();
303 final double elevationP4 = station.getBaseFrame().getElevation(positionP4, stateP4.getFrame(), stateP4.getDate());
304 double delayP4 = model.pathDelay(elevationP4, point, model.getParameters(), stateP4.getDate());
305
306 fillJacobianColumn(refDeriv, i, orbitType, angleType, steps[i],
307 delayM4, delayM3, delayM2, delayM1,
308 delayP1, delayP2, delayP3, delayP4);
309 }
310
311 for (int i = 0; i < 6; i++) {
312 Assert.assertEquals(compDeriv[i + 1], refDeriv[0][i], 2.0e-11);
313 }
314 }
315
316 private void fillJacobianColumn(double[][] jacobian, int column,
317 OrbitType orbitType, PositionAngle angleType, double h,
318 double sM4h, double sM3h,
319 double sM2h, double sM1h,
320 double sP1h, double sP2h,
321 double sP3h, double sP4h) {
322 for (int i = 0; i < jacobian.length; ++i) {
323 jacobian[i][column] = ( -3 * (sP4h - sM4h) +
324 32 * (sP3h - sM3h) -
325 168 * (sP2h - sM2h) +
326 672 * (sP1h - sM1h)) / (840 * h);
327 }
328 }
329
330 private SpacecraftState shiftState(SpacecraftState state, OrbitType orbitType, PositionAngle angleType,
331 double delta, int column) {
332
333 double[][] array = stateToArray(state, orbitType, angleType, true);
334 array[0][column] += delta;
335
336 return arrayToState(array, orbitType, angleType, state.getFrame(), state.getDate(),
337 state.getMu(), state.getAttitude());
338
339 }
340
341 private double[][] stateToArray(SpacecraftState state, OrbitType orbitType, PositionAngle angleType,
342 boolean withMass) {
343 double[][] array = new double[2][withMass ? 7 : 6];
344 orbitType.mapOrbitToArray(state.getOrbit(), angleType, array[0], array[1]);
345 if (withMass) {
346 array[0][6] = state.getMass();
347 }
348 return array;
349 }
350
351 private SpacecraftState arrayToState(double[][] array, OrbitType orbitType, PositionAngle angleType,
352 Frame frame, AbsoluteDate date, double mu,
353 Attitude attitude) {
354 Orbit orbit = orbitType.mapArrayToOrbit(array[0], array[1], angleType, date, mu, frame);
355 return (array.length > 6) ?
356 new SpacecraftState(orbit, attitude) :
357 new SpacecraftState(orbit, attitude, array[0][6]);
358 }
359
360 }