1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.sinex;
18
19 import org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.orekit.errors.OrekitException;
21 import org.orekit.errors.OrekitMessages;
22 import org.orekit.gnss.GnssSignal;
23 import org.orekit.gnss.SatInSystem;
24 import org.orekit.models.earth.displacement.PsdCorrection;
25 import org.orekit.time.AbsoluteDate;
26 import org.orekit.time.TimeScales;
27 import org.orekit.utils.TimeSpanMap;
28
29 import java.util.HashMap;
30 import java.util.Map;
31
32
33
34
35
36
37 public class SinexParseInfo extends ParseInfo<Sinex> {
38
39
40 private final Map<SatInSystem, Map<GnssSignal, Vector3D>> satellitesPhaseCenters;
41
42
43 private final Map<AntennaKey, Map<GnssSignal, Vector3D>> stationsPhaseCenters;
44
45
46 private final Map<String, Station> stations;
47
48
49 private final Map<AbsoluteDate, SinexEopEntry> eop;
50
51
52 private double px;
53
54
55 private double py;
56
57
58 private double pz;
59
60
61 private double vx;
62
63
64 private double vy;
65
66
67 private double vz;
68
69
70 private PsdCorrection.Axis axis;
71
72
73 private PsdCorrection.TimeEvolution evolution;
74
75
76 private double amplitude;
77
78
79 private double relaxationTime;
80
81
82 private final Map<GnssSignal, Vector3D> phaseCenters;
83
84
85
86
87 SinexParseInfo(final TimeScales timeScales) {
88 super(timeScales);
89 this.satellitesPhaseCenters = new HashMap<>();
90 this.stationsPhaseCenters = new HashMap<>();
91 this.stations = new HashMap<>();
92 this.eop = new HashMap<>();
93 this.phaseCenters = new HashMap<>();
94 }
95
96
97 @Override
98 void newSource(final String name) {
99 super.newSource(name);
100 resetPosition();
101 resetVelocity();
102 resetPsdCorrection();
103 }
104
105
106
107
108
109
110 void addSatellitePhaseCenter(final SatInSystem satInSystem, final GnssSignal signal, final Vector3D phaseCenter) {
111 satellitesPhaseCenters.
112 computeIfAbsent(satInSystem, s -> new HashMap<>()).
113 put(signal, phaseCenter);
114 }
115
116
117
118
119
120
121 void addStationPhaseCenter(final AntennaKey key, final Vector3D phaseCenter, final GnssSignal[] signals) {
122 phaseCenters.put(signals[phaseCenters.size()], phaseCenter);
123 if (phaseCenters.size() == signals.length) {
124
125 stationsPhaseCenters.computeIfAbsent(key, k -> new HashMap<>()).putAll(phaseCenters);
126 phaseCenters.clear();
127 }
128 }
129
130
131
132
133 void addStation(final Station station) {
134 stations.putIfAbsent(station.getSiteCode(), station);
135 }
136
137
138
139
140
141 Station getCurrentLineStation(final int index) {
142 return stations.get(parseString(index, 4));
143 }
144
145
146
147
148 AbsoluteDate getCurrentLineStartDate() {
149 return stringEpochToAbsoluteDate(parseString(16, 12), true);
150 }
151
152
153
154
155 AbsoluteDate getCurrentLineEndDate() {
156 return stringEpochToAbsoluteDate(parseString(29, 12), false);
157 }
158
159
160
161
162
163
164 void setPx(final double x, final Station station, final AbsoluteDate epoch) {
165 this.px = x;
166 finalizePositionIfComplete(station, epoch);
167 }
168
169
170
171
172
173
174 void setPy(final double y, final Station station, final AbsoluteDate epoch) {
175 this.py = y;
176 finalizePositionIfComplete(station, epoch);
177 }
178
179
180
181
182
183
184 void setPz(final double z, final Station station, final AbsoluteDate epoch) {
185 this.pz = z;
186 finalizePositionIfComplete(station, epoch);
187 }
188
189
190
191
192
193 private void finalizePositionIfComplete(final Station station, final AbsoluteDate epoch) {
194 if (!Double.isNaN(px + py + pz)) {
195
196 station.setEpoch(epoch);
197 station.setPosition(new Vector3D(px, py, pz));
198 resetPosition();
199 }
200 }
201
202
203
204 void resetPosition() {
205 px = Double.NaN;
206 py = Double.NaN;
207 pz = Double.NaN;
208 }
209
210
211
212
213
214 void setVx(final double x, final Station station) {
215 this.vx = x;
216 finalizeVelocityIfComplete(station);
217 }
218
219
220
221
222
223 void setVy(final double y, final Station station) {
224 this.vy = y;
225 finalizeVelocityIfComplete(station);
226 }
227
228
229
230
231
232 void setVz(final double z, final Station station) {
233 this.vz = z;
234 finalizeVelocityIfComplete(station);
235 }
236
237
238
239
240 private void finalizeVelocityIfComplete(final Station station) {
241 if (!Double.isNaN(vx + vy + vz)) {
242
243 station.setVelocity(new Vector3D(vx, vy, vz));
244 resetVelocity();
245 }
246 }
247
248
249
250 void resetVelocity() {
251 vx = Double.NaN;
252 vy = Double.NaN;
253 vz = Double.NaN;
254 }
255
256
257
258
259 void setAxis(final PsdCorrection.Axis axis) {
260 this.axis = axis;
261 }
262
263
264
265
266 void setEvolution(final PsdCorrection.TimeEvolution evolution) {
267 this.evolution = evolution;
268 }
269
270
271
272
273
274
275 void setAmplitude(final double correctionAmplitude, final Station station, final AbsoluteDate epoch) {
276 this.amplitude = correctionAmplitude;
277 finalizePsdCorrectionIfComplete(station, epoch);
278 }
279
280
281
282
283
284
285 void setRelaxationTime(final double correctionRelaxationTime,
286 final Station station, final AbsoluteDate epoch) {
287 this.relaxationTime = correctionRelaxationTime;
288 finalizePsdCorrectionIfComplete(station, epoch);
289 }
290
291
292
293
294
295 private void finalizePsdCorrectionIfComplete(final Station station, final AbsoluteDate epoch) {
296 if (!Double.isNaN(amplitude + relaxationTime)) {
297
298 final PsdCorrection correction = new PsdCorrection(axis, evolution, epoch, amplitude, relaxationTime);
299 station.addPsdCorrectionValidAfter(correction, epoch);
300 resetPsdCorrection();
301 }
302 }
303
304
305
306 private void resetPsdCorrection() {
307 axis = null;
308 evolution = null;
309 amplitude = Double.NaN;
310 relaxationTime = Double.NaN;
311 }
312
313
314
315
316
317 SinexEopEntry createEOPEntry(final AbsoluteDate date) {
318 return eop.computeIfAbsent(date, SinexEopEntry::new);
319 }
320
321
322 @Override
323 protected Sinex build() {
324
325
326 for (final Station station : stations.values()) {
327
328
329 final TimeSpanMap<Map<GnssSignal, Vector3D>> phaseCentersMap = station.getPhaseCentersMap();
330
331 if (station.getAntennaKeyTimeSpanMap().getSpansNumber() > 1) {
332 for (TimeSpanMap.Span<AntennaKey> keySpan = station.getAntennaKeyTimeSpanMap().getFirstNonNullSpan();
333 keySpan != null; keySpan = keySpan.next()) {
334
335
336 Map<GnssSignal, Vector3D> centers =
337 phaseCentersMap.get(AbsoluteDate.createMedian(keySpan.getStart(), keySpan.getEnd()));
338 if (centers == null) {
339
340 centers = new HashMap<>();
341 phaseCentersMap.addValidBetween(centers, keySpan.getStart(), keySpan.getEnd());
342 }
343
344 if (keySpan.getData() != null) {
345
346
347 AntennaKey closestKey = null;
348 for (final AntennaKey candidate : keySpan.getData().matchingCandidates()) {
349 if (stationsPhaseCenters.containsKey(candidate)) {
350 closestKey = candidate;
351 break;
352 }
353 }
354 if (closestKey == null) {
355 throw new OrekitException(OrekitMessages.UNKNOWN_GNSS_ANTENNA,
356 keySpan.getData().getName(),
357 keySpan.getData().getRadomeCode(),
358 keySpan.getData().getSerialNumber());
359 }
360
361
362 centers.putAll(stationsPhaseCenters.get(closestKey));
363
364 }
365
366 }
367 }
368
369 }
370
371 return new Sinex(getTimeScales(), getCreationDate(), getStartDate(), getEndDate(),
372 satellitesPhaseCenters, stations, eop);
373 }
374
375 }