1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements;
18
19 import java.util.List;
20
21 import org.hipparchus.geometry.euclidean.threed.Vector3D;
22 import org.hipparchus.stat.descriptive.StreamingStatistics;
23 import org.hipparchus.stat.descriptive.rank.Median;
24 import org.hipparchus.util.FastMath;
25 import org.junit.jupiter.api.Assertions;
26 import org.junit.jupiter.api.Test;
27 import org.orekit.estimation.Context;
28 import org.orekit.estimation.EstimationTestUtils;
29 import org.orekit.orbits.OrbitType;
30 import org.orekit.orbits.PositionAngleType;
31 import org.orekit.propagation.Propagator;
32 import org.orekit.propagation.SpacecraftState;
33 import org.orekit.propagation.conversion.NumericalPropagatorBuilder;
34 import org.orekit.time.AbsoluteDate;
35 import org.orekit.utils.Differentiation;
36 import org.orekit.utils.ParameterDriver;
37 import org.orekit.utils.ParameterFunction;
38
39 class AngularAzElTest {
40
41
42
43
44 @Test
45 void testValues() {
46
47 Context context = EstimationTestUtils.eccentricContext("regular-data:potential:tides");
48
49 final NumericalPropagatorBuilder propagatorBuilder =
50 context.createBuilder(OrbitType.EQUINOCTIAL, PositionAngleType.TRUE, false,
51 1.0e-6, 60.0, 0.001);
52
53
54 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
55 propagatorBuilder);
56 final List<ObservedMeasurement<?>> measurements =
57 EstimationTestUtils.createMeasurements(propagator,
58 new AngularAzElMeasurementCreator(context),
59 0.25, 3.0, 600.0);
60
61 propagator.clearStepHandlers();
62
63
64 final StreamingStatistics azDiffStat = new StreamingStatistics();
65 final StreamingStatistics elDiffStat = new StreamingStatistics();
66
67 for (final ObservedMeasurement<?> measurement : measurements) {
68
69
70 final AbsoluteDate datemeas = measurement.getDate();
71 SpacecraftState state = propagator.propagate(datemeas);
72
73
74 final EstimatedMeasurementBase<?> estimated = measurement.estimateWithoutDerivatives(new SpacecraftState[] { state });
75
76
77 azDiffStat.addValue(FastMath.abs(estimated.getEstimatedValue()[0] - measurement.getObservedValue()[0]));
78 elDiffStat.addValue(FastMath.abs(estimated.getEstimatedValue()[1] - measurement.getObservedValue()[1]));
79 }
80
81
82 Assertions.assertEquals(0.0, azDiffStat.getMean(), 6.9e-9);
83 Assertions.assertEquals(0.0, azDiffStat.getStandardDeviation(), 7.2e-9);
84 Assertions.assertEquals(0.0, elDiffStat.getMean(), 5.4e-9);
85 Assertions.assertEquals(0.0, elDiffStat.getStandardDeviation(), 3.3e-9);
86
87
88 Assertions.assertEquals(AngularAzEl.MEASUREMENT_TYPE, measurements.get(0).getMeasurementType());
89 }
90
91
92
93
94 @Test
95 void testStateDerivatives() {
96
97 Context context = EstimationTestUtils.geoStationnaryContext("regular-data:potential:tides");
98
99 final NumericalPropagatorBuilder propagatorBuilder =
100 context.createBuilder(OrbitType.EQUINOCTIAL, PositionAngleType.TRUE, false,
101 1.0e-6, 60.0, 0.001);
102
103
104 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
105 propagatorBuilder);
106 final List<ObservedMeasurement<?>> measurements =
107 EstimationTestUtils.createMeasurements(propagator,
108 new AngularAzElMeasurementCreator(context),
109 0.25, 3.0, 600.0);
110
111 propagator.clearStepHandlers();
112
113
114 double[] AzerrorsP = new double[3 * measurements.size()];
115 double[] AzerrorsV = new double[3 * measurements.size()];
116 double[] ElerrorsP = new double[3 * measurements.size()];
117 double[] ElerrorsV = new double[3 * measurements.size()];
118 int AzindexP = 0;
119 int AzindexV = 0;
120 int ElindexP = 0;
121 int ElindexV = 0;
122
123 for (final ObservedMeasurement<?> measurement : measurements) {
124
125
126 final GroundStation stationParameter = ((AngularAzEl) measurement).getStation();
127
128
129
130
131
132
133
134
135 final AbsoluteDate datemeas = measurement.getDate();
136 SpacecraftState state = propagator.propagate(datemeas);
137 final Vector3D stationP = stationParameter.getOffsetToInertial(state.getFrame(), datemeas, false).transformPosition(Vector3D.ZERO);
138 final double meanDelay = AbstractMeasurement.signalTimeOfFlightAdjustableEmitter(state.getPVCoordinates(), stationP,
139 datemeas, state.getFrame());
140
141 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
142 state = propagator.propagate(date);
143 final EstimatedMeasurement<?> estimated = measurement.estimate(0, 0, new SpacecraftState[] { state });
144 Assertions.assertEquals(2, estimated.getParticipants().length);
145 final double[][] jacobian = estimated.getStateDerivatives(0);
146
147
148 final double[][] finiteDifferencesJacobian =
149 Differentiation.differentiate(state1 ->
150 measurement.
151 estimateWithoutDerivatives(new SpacecraftState[] { state1 }).
152 getEstimatedValue(),
153 measurement.getDimension(),
154 propagator.getAttitudeProvider(),
155 OrbitType.CARTESIAN,
156 PositionAngleType.TRUE, 250.0, 4).
157 value(state);
158
159 Assertions.assertEquals(finiteDifferencesJacobian.length, jacobian.length);
160 Assertions.assertEquals(finiteDifferencesJacobian[0].length, jacobian[0].length);
161
162 final double smallest = FastMath.ulp((double) 1.0);
163
164 for (int i = 0; i < jacobian.length; ++i) {
165 for (int j = 0; j < jacobian[i].length; ++j) {
166 double relativeError = FastMath.abs((finiteDifferencesJacobian[i][j] - jacobian[i][j]) /
167 finiteDifferencesJacobian[i][j]);
168
169 if ((FastMath.sqrt(finiteDifferencesJacobian[i][j]) < smallest) && (FastMath.sqrt(jacobian[i][j]) < smallest) ){
170 relativeError = 0.0;
171 }
172
173 if (j < 3) {
174 if (i == 0) {
175 AzerrorsP[AzindexP++] = relativeError;
176 } else {
177 ElerrorsP[ElindexP++] = relativeError;
178 }
179 } else {
180 if (i == 0) {
181 AzerrorsV[AzindexV++] = relativeError;
182 } else {
183 ElerrorsV[ElindexV++] = relativeError;
184 }
185 }
186 }
187 }
188 }
189
190
191 Assertions.assertEquals(0.0, new Median().evaluate(AzerrorsP), 1.2e-10);
192 Assertions.assertEquals(0.0, new Median().evaluate(AzerrorsV), 6.1e-5);
193
194
195 Assertions.assertEquals(0.0, new Median().evaluate(ElerrorsP), 7.5e-11);
196 Assertions.assertEquals(0.0, new Median().evaluate(ElerrorsV), 2.3e-5);
197 }
198
199
200
201
202 @Test
203 void testParameterDerivatives() {
204
205 Context context = EstimationTestUtils.geoStationnaryContext("regular-data:potential:tides");
206
207 final NumericalPropagatorBuilder propagatorBuilder =
208 context.createBuilder(OrbitType.EQUINOCTIAL, PositionAngleType.TRUE, false,
209 1.0e-6, 60.0, 0.001);
210
211
212 for (final GroundStation station : context.stations) {
213 station.getClockOffsetDriver().setSelected(true);
214 station.getEastOffsetDriver().setSelected(true);
215 station.getNorthOffsetDriver().setSelected(true);
216 station.getZenithOffsetDriver().setSelected(true);
217 }
218 final Propagator propagator = EstimationTestUtils.createPropagator(context.initialOrbit,
219 propagatorBuilder);
220 final List<ObservedMeasurement<?>> measurements =
221 EstimationTestUtils.createMeasurements(propagator,
222 new AngularAzElMeasurementCreator(context),
223 0.25, 3.0, 600.0);
224 propagator.clearStepHandlers();
225
226 for (final ObservedMeasurement<?> measurement : measurements) {
227
228
229 final GroundStation stationParameter = ((AngularAzEl) measurement).getStation();
230
231
232
233
234
235
236
237
238 final AbsoluteDate datemeas = measurement.getDate();
239 final SpacecraftState stateini = propagator.propagate(datemeas);
240 final Vector3D stationP = stationParameter.getOffsetToInertial(stateini.getFrame(), datemeas, false).transformPosition(Vector3D.ZERO);
241 final double meanDelay = AbstractMeasurement.signalTimeOfFlightAdjustableEmitter(stateini.getPVCoordinates(), stationP,
242 datemeas, stateini.getFrame());
243
244 final AbsoluteDate date = measurement.getDate().shiftedBy(-0.75 * meanDelay);
245 final SpacecraftState state = propagator.propagate(date);
246 final ParameterDriver[] drivers = new ParameterDriver[] {
247 stationParameter.getEastOffsetDriver(),
248 stationParameter.getNorthOffsetDriver(),
249 stationParameter.getZenithOffsetDriver()
250 };
251 for (int i = 0; i < 3; ++i) {
252 final double[] gradient = measurement.estimate(0, 0, new SpacecraftState[] { state }).getParameterDerivatives(drivers[i]);
253 Assertions.assertEquals(2, measurement.getDimension());
254 Assertions.assertEquals(2, gradient.length);
255
256 for (final int k : new int[] {0, 1}) {
257 final ParameterFunction dMkdP =
258 Differentiation.differentiate(new ParameterFunction() {
259
260 @Override
261 public double value(final ParameterDriver parameterDriver, AbsoluteDate date) {
262 return measurement.
263 estimateWithoutDerivatives(new SpacecraftState[] { state }).
264 getEstimatedValue()[k];
265 }
266 }, 3, 50.0 * drivers[i].getScale());
267 final double ref = dMkdP.value(drivers[i], date);
268
269 if (ref > 1.e-12) {
270 Assertions.assertEquals(ref, gradient[k], 3e-10 * FastMath.abs(ref));
271 }
272 }
273 }
274 }
275 }
276 }
277