1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.estimation.measurements.gnss;
18
19 import java.io.IOException;
20 import java.security.NoSuchAlgorithmException;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import org.junit.jupiter.api.Assertions;
25 import org.junit.jupiter.api.BeforeEach;
26 import org.junit.jupiter.api.Test;
27 import org.orekit.Utils;
28 import org.orekit.data.DataSource;
29 import org.orekit.errors.OrekitException;
30 import org.orekit.errors.OrekitMessages;
31 import org.orekit.files.rinex.observation.ObservationData;
32 import org.orekit.files.rinex.observation.ObservationDataSet;
33 import org.orekit.files.rinex.observation.RinexObservationParser;
34 import org.orekit.gnss.Frequency;
35 import org.orekit.gnss.MeasurementType;
36 import org.orekit.gnss.ObservationType;
37 import org.orekit.gnss.SatInSystem;
38 import org.orekit.gnss.SatelliteSystem;
39 import org.orekit.utils.Constants;
40
41 public class MeasurementCombinationFactoryTest {
42
43
44 private static double eps = 1.0e-4;
45
46
47 private ObservationData obs1;
48
49
50 private SatelliteSystem system;
51
52
53 private ObservationDataSet dataSetRinex2;
54
55
56 private ObservationDataSet dataSetRinex3;
57
58 @BeforeEach
59 public void setUp() throws NoSuchAlgorithmException, IOException {
60 Utils.setDataRoot("gnss");
61 RinexObservationParser parser = new RinexObservationParser();
62
63
64 obs1 = new ObservationData(ObservationType.L1, 2.25E7, 0, 0);
65
66
67 final String name2 = "rinex/truncate-sbch0440.16o";
68 List<ObservationDataSet> parsed2 = parser.parse(new DataSource(name2,
69 () -> Utils.class.getClassLoader().getResourceAsStream(name2))).
70 getObservationDataSets();
71 dataSetRinex2 = parsed2.get(0);
72
73
74 final String name3 = "rinex/aaaa0000.00o";
75 List<ObservationDataSet> parsed3 = parser.parse(new DataSource(name3,
76 () -> Utils.class.getClassLoader().getResourceAsStream(name3))).
77 getObservationDataSets();
78 dataSetRinex3 = parsed3.get(1);
79
80
81 system = dataSetRinex2.getSatellite().getSystem();
82 }
83
84 @Test
85 public void testEmptyDataSetGeometryFree() {
86 doTestEmptyDataSet(MeasurementCombinationFactory.getGeometryFreeCombination(system));
87 }
88
89 @Test
90 public void testEmptyDataSetIonoFree() {
91 doTestEmptyDataSet(MeasurementCombinationFactory.getIonosphereFreeCombination(system));
92 }
93
94 @Test
95 public void testEmptyDataSetWideLane() {
96 doTestEmptyDataSet(MeasurementCombinationFactory.getWideLaneCombination(system));
97 }
98
99 @Test
100 public void testEmptyDataSetNarrowLane() {
101 doTestEmptyDataSet(MeasurementCombinationFactory.getNarrowLaneCombination(system));
102 }
103
104 @Test
105 public void testEmptyDataSetMelbourneWubbena() {
106 doTestEmptyDataSet(MeasurementCombinationFactory.getMelbourneWubbenaCombination(system));
107 }
108
109 @Test
110 public void testEmptyDataSetPhaseMinusCode() {
111 doTestEmptyDataSet(MeasurementCombinationFactory.getPhaseMinusCodeCombination(system));
112 }
113
114 @Test
115 public void testEmptyDataSetGRAPHIC() {
116 doTestEmptyDataSet(MeasurementCombinationFactory.getGRAPHICCombination(system));
117 }
118
119
120
121
122 private void doTestEmptyDataSet(final MeasurementCombination combination) {
123
124 final ObservationDataSet emptyDataSet = new ObservationDataSet(new SatInSystem(dataSetRinex2.getSatellite().getSystem(),
125 dataSetRinex2.getSatellite()
126 .getPRN()),
127 dataSetRinex2.getDate(), 0, dataSetRinex2.getRcvrClkOffset(),
128 new ArrayList<ObservationData>());
129
130 final CombinedObservationDataSet combinedData = combination.combine(emptyDataSet);
131 Assertions.assertEquals(0, combinedData.getObservationData().size());
132 }
133
134 @Test
135 public void testExceptionsGeometryFree() {
136 doTestExceptionsDualFrequency(MeasurementCombinationFactory.getGeometryFreeCombination(system));
137 }
138
139 @Test
140 public void testExceptionsIonoFree() {
141 doTestExceptionsDualFrequency(MeasurementCombinationFactory.getIonosphereFreeCombination(system));
142 }
143
144 @Test
145 public void testExceptionsWideLane() {
146 doTestExceptionsDualFrequency(MeasurementCombinationFactory.getWideLaneCombination(system));
147 }
148
149 @Test
150 public void testExceptionsNarrowLane() {
151 doTestExceptionsDualFrequency(MeasurementCombinationFactory.getNarrowLaneCombination(system));
152 }
153
154 @Test
155 public void testExceptionsPhaseMinusCode() {
156 doTestExceptionsSingleFrequency(MeasurementCombinationFactory.getPhaseMinusCodeCombination(system));
157 }
158
159 @Test
160 public void testExceptionsGRAPHIC() {
161 doTestExceptionsSingleFrequency(MeasurementCombinationFactory.getGRAPHICCombination(system));
162 }
163
164 private void doTestExceptionsSingleFrequency(final AbstractSingleFrequencyCombination combination) {
165
166 try {
167 final ObservationData observation = new ObservationData(ObservationType.L5, 12345678.0, 0, 0);
168 combination.combine(obs1, observation);
169 Assertions.fail("an exception should have been thrown");
170 } catch (OrekitException oe) {
171 Assertions.assertEquals(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS, oe.getSpecifier());
172 }
173
174
175 try {
176 final ObservationData observation = new ObservationData(ObservationType.L1, 12345678.0, 0, 0);
177 combination.combine(obs1, observation);
178 Assertions.fail("an exception should have been thrown");
179 } catch (OrekitException oe) {
180 Assertions.assertEquals(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS, oe.getSpecifier());
181 }
182 }
183
184
185
186
187 private void doTestExceptionsDualFrequency(final AbstractDualFrequencyCombination combination) {
188
189 try {
190 final ObservationData observation = new ObservationData(ObservationType.L1, 12345678.0, 0, 0);
191 combination.combine(obs1, observation);
192 Assertions.fail("an exception should have been thrown");
193 } catch (OrekitException oe) {
194 Assertions.assertEquals(OrekitMessages.INCOMPATIBLE_FREQUENCIES_FOR_COMBINATION_OF_MEASUREMENTS, oe.getSpecifier());
195 }
196
197
198 try {
199 final ObservationData observation = new ObservationData(ObservationType.D2, 12345678.0, 0, 0);
200 combination.combine(obs1, observation);
201 Assertions.fail("an exception should have been thrown");
202 } catch (OrekitException oe) {
203 Assertions.assertEquals(OrekitMessages.INVALID_MEASUREMENT_TYPES_FOR_COMBINATION_OF_MEASUREMENTS, oe.getSpecifier());
204 }
205 }
206
207 @Test
208 public void testRinex2GeometryFree() {
209 doTestRinexDualFrequency(MeasurementCombinationFactory.getGeometryFreeCombination(system),
210 CombinationType.GEOMETRY_FREE, 6.953, 27534453.519,0.0, Double.NaN, 2, 2);
211 }
212
213 @Test
214 public void testRinex2IonoFree() {
215 doTestRinexDualFrequency(MeasurementCombinationFactory.getIonosphereFreeCombination(system),
216 CombinationType.IONO_FREE, 23732467.5026, 3772223175.669, 0.0, 4658 * Frequency.F0, 2, 2);
217 }
218
219 @Test
220 public void testRinex2WideLane() {
221 doTestRinexDualFrequency(MeasurementCombinationFactory.getWideLaneCombination(system),
222 CombinationType.WIDE_LANE, 23732453.7100, 27534453.519, 0.0, 34 * Frequency.F0, 2, 2);
223 }
224
225 @Test
226 public void testRinex2NarrowLane() {
227 doTestRinexDualFrequency(MeasurementCombinationFactory.getNarrowLaneCombination(system),
228 CombinationType.NARROW_LANE, 23732481.2951, 221895659.955, 0.0, 274 * Frequency.F0, 2, 2);
229 }
230
231 @Test
232 public void testRinex2MelbourneWubbena() {
233 doTestRinexDualFrequency(MeasurementCombinationFactory.getMelbourneWubbenaCombination(system),
234 CombinationType.MELBOURNE_WUBBENA, 0.0, 0.0, 3801972.2239, 34 * Frequency.F0, 1, 2);
235 }
236
237 @Test
238 public void testRinex2PhaseMinusCode() {
239 doTestRinex2SingleFrequency(MeasurementCombinationFactory.getPhaseMinusCodeCombination(system),
240 CombinationType.PHASE_MINUS_CODE, 73448118.300);
241 }
242
243 @Test
244 public void testRinex2GRAPHIC() {
245 doTestRinex2SingleFrequency(MeasurementCombinationFactory.getGRAPHICCombination(system),
246 CombinationType.GRAPHIC, 60456544.068);
247 }
248
249 private void doTestRinex2SingleFrequency(final MeasurementCombination combination, final CombinationType type,
250 final double expectedL2P2) {
251
252 final CombinedObservationDataSet combinedDataSet = combination.combine(dataSetRinex2);
253 checkCombinedDataSet(combinedDataSet, 1);
254 Assertions.assertEquals(type.getName(), combination.getName());
255
256 final List<CombinedObservationData> data = combinedDataSet.getObservationData();
257
258 Assertions.assertEquals(expectedL2P2, data.get(0).getValue(), eps);
259 Assertions.assertEquals(120 * Frequency.F0, data.get(0).getCombinedMHzFrequency(), eps);
260 }
261
262 @Test
263 public void testRinex3GeometryFree() {
264 doTestRinexDualFrequency(MeasurementCombinationFactory.getGeometryFreeCombination(system),
265 CombinationType.GEOMETRY_FREE, 2.187, 3821708.096, 0.0, Double.NaN, 2, 3);
266 }
267
268 @Test
269 public void testRinex3IonoFree() {
270 doTestRinexDualFrequency(MeasurementCombinationFactory.getIonosphereFreeCombination(system),
271 CombinationType.IONO_FREE, 22399214.1934, 179620369.206, 0.0, 235 * Frequency.F0, 2, 3);
272 }
273
274 @Test
275 public void testRinex3WideLane() {
276 doTestRinexDualFrequency(MeasurementCombinationFactory.getWideLaneCombination(system),
277 CombinationType.WIDE_LANE, 22399239.8790, 3821708.096, 0.0, 5 * Frequency.F0, 2, 3);
278 }
279
280 @Test
281 public void testRinex3NarrowLane() {
282 doTestRinexDualFrequency(MeasurementCombinationFactory.getNarrowLaneCombination(system),
283 CombinationType.NARROW_LANE, 22399188.5078, 179620457.900, 0.0, 235 * Frequency.F0, 2, 3);
284 }
285
286 @Test
287 public void testRinex3MelbourneWubbena() {
288 doTestRinexDualFrequency(MeasurementCombinationFactory.getMelbourneWubbenaCombination(system),
289 CombinationType.MELBOURNE_WUBBENA, 0.0, 0.0, -18577480.4117, 5 * Frequency.F0, 1, 3);
290 }
291
292 @Test
293 public void testRinex3PhaseMinusCode() {
294 doTestRinex3SingleFrequency(MeasurementCombinationFactory.getPhaseMinusCodeCombination(system),
295 CombinationType.PHASE_MINUS_CODE, 95309391.697, 69321899.401,
296 69321893.420, 65500187.511);
297 }
298
299 @Test
300 public void testRinex3GRAPHIC() {
301 doTestRinex3SingleFrequency(MeasurementCombinationFactory.getGRAPHICCombination(system),
302 CombinationType.GRAPHIC, 70053877.7315, 57060139.2905,
303 57060136.2880, 55149281.1465);
304 }
305
306 private void doTestRinex3SingleFrequency(final MeasurementCombination combination, final CombinationType type,
307 final double expected1C, final double expected2W,
308 final double expected2X, final double expected5X) {
309
310 final CombinedObservationDataSet combinedDataSet = combination.combine(dataSetRinex3);
311 Assertions.assertEquals(type.getName(), combination.getName());
312
313 final List<CombinedObservationData> data = combinedDataSet.getObservationData();
314
315 Assertions.assertEquals(expected1C, data.get(0).getValue(), eps);
316 Assertions.assertEquals(154 * Frequency.F0, data.get(0).getCombinedMHzFrequency(), eps);
317
318 Assertions.assertEquals(expected2W, data.get(1).getValue(), eps);
319 Assertions.assertEquals(120 * Frequency.F0, data.get(1).getCombinedMHzFrequency(), eps);
320
321 Assertions.assertEquals(expected2X, data.get(2).getValue(), eps);
322 Assertions.assertEquals(120 * Frequency.F0, data.get(1).getCombinedMHzFrequency(), eps);
323
324 Assertions.assertEquals(expected5X, data.get(3).getValue(), eps);
325 Assertions.assertEquals(115 * Frequency.F0, data.get(3).getCombinedMHzFrequency(), eps);
326 }
327
328
329
330
331 private void doTestRinexDualFrequency(final MeasurementCombination combination, final CombinationType expectedType,
332 final double expectedRangeValue, final double expectedPhaseValue, final double expectedRangePhase,
333 final double expectedFrequency, final int expectedSize, final int rinexVersion) {
334
335
336 final CombinedObservationDataSet combinedDataSet;
337 if (rinexVersion == 2) {
338 combinedDataSet = combination.combine(dataSetRinex2);
339 checkCombinedDataSet(combinedDataSet, expectedSize);
340 } else {
341 combinedDataSet = combination.combine(dataSetRinex3);
342 Assertions.assertEquals(expectedSize, combinedDataSet.getObservationData().size());
343 }
344
345 Assertions.assertEquals(expectedType.getName(), combination.getName());
346
347
348 for (CombinedObservationData cod : combinedDataSet.getObservationData()) {
349
350 if (cod.getMeasurementType() == MeasurementType.CARRIER_PHASE) {
351
352 Assertions.assertEquals(expectedPhaseValue, cod.getValue(), eps);
353 Assertions.assertEquals(expectedFrequency, cod.getCombinedMHzFrequency(), eps);
354 Assertions.assertEquals(expectedType, cod.getCombinationType());
355
356 } else if (cod.getMeasurementType() == MeasurementType.PSEUDO_RANGE) {
357
358 Assertions.assertEquals(expectedRangeValue, cod.getValue(), eps);
359 Assertions.assertEquals(expectedFrequency, cod.getCombinedMHzFrequency(), eps);
360 Assertions.assertEquals(expectedType, cod.getCombinationType());
361
362 } else if (cod.getMeasurementType() == MeasurementType.COMBINED_RANGE_PHASE) {
363
364 Assertions.assertEquals(expectedRangePhase, cod.getValue(), eps);
365 Assertions.assertEquals(expectedFrequency, cod.getCombinedMHzFrequency(), eps);
366 Assertions.assertEquals(expectedType, cod.getCombinationType());
367
368 }
369
370 }
371 }
372
373 private void checkCombinedDataSet(final CombinedObservationDataSet combinedDataSet,
374 final int expectedSize) {
375
376 Assertions.assertEquals(expectedSize, combinedDataSet.getObservationData().size());
377
378 Assertions.assertEquals(30, combinedDataSet.getPrnNumber());
379 Assertions.assertEquals(SatelliteSystem.GPS, combinedDataSet.getSatelliteSystem());
380
381 Assertions.assertEquals(0.0, combinedDataSet.getRcvrClkOffset(), eps);
382
383 Assertions.assertEquals("2016-02-13T00:49:43.000Z", combinedDataSet.getDate().toString());
384 }
385
386 @Test
387 public void testIssue746() {
388
389
390
391
392
393 final ObservationData obs1 = new ObservationData(ObservationType.L1, 1.17452520667E8, 0, 0);
394 final ObservationData obs2 = new ObservationData(ObservationType.L2, 9.1521434853E7, 0, 0);
395
396
397 final IonosphereFreeCombination ionoFree = MeasurementCombinationFactory.getIonosphereFreeCombination(SatelliteSystem.GPS);
398 final CombinedObservationData combined = ionoFree.combine(obs1, obs2);
399
400
401 final double wavelength = Constants.SPEED_OF_LIGHT / (combined.getCombinedMHzFrequency() * 1.0e6);
402 final double combineValueMeters = combined.getValue() * wavelength;
403
404
405 Assertions.assertEquals(22350475.245, combineValueMeters, 0.001);
406
407 }
408
409 }