1 /* Copyright 2002-2026 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.files.rinex.observation;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24
25 import org.hipparchus.geometry.euclidean.threed.Vector3D;
26 import org.hipparchus.geometry.euclidean.twod.Vector2D;
27 import org.orekit.files.rinex.section.Label;
28 import org.orekit.files.rinex.section.RinexClockObsBaseHeader;
29 import org.orekit.files.rinex.utils.ParsingUtils;
30 import org.orekit.files.rinex.utils.RinexFileType;
31 import org.orekit.gnss.SatInSystem;
32 import org.orekit.gnss.SatelliteSystem;
33 import org.orekit.time.AbsoluteDate;
34 import org.orekit.time.TimeScales;
35
36 /** Container for Rinex observation file header.
37 * @since 9.2
38 */
39 public class RinexObservationHeader extends RinexClockObsBaseHeader {
40
41 /** Index of label in header lines. */
42 public static final int LABEL_INDEX = 60;
43
44 /** Name of the Antenna Marker. */
45 private String markerName;
46
47 /** Number of Antenna marker. */
48 private String markerNumber;
49
50 /** Type of Antenna marker. */
51 private String markerType;
52
53 /** Name of Observer. */
54 private String observerName;
55
56 /** Name of Agency. */
57 private String agencyName;
58
59 /** Antenna Number. */
60 private String antennaNumber;
61
62 /** Antenna Type. */
63 private String antennaType;
64
65 /** Approximate Marker Position (WGS84). */
66 private Vector3D approxPos;
67
68 /** Antenna Height. */
69 private double antennaHeight;
70
71 /** Eccentricities of antenna center. */
72 private Vector2D eccentricities;
73
74 /** Position of antenna reference point for antenna on vehicle. */
75 private Vector3D antRefPoint;
76
77 /** Satellite system for average phasecenter position.
78 * @since 12.0
79 */
80 private SatelliteSystem phaseCenterSystem;
81
82 /** Observation code of the average phasecenter position w/r to antenna reference point. */
83 private String observationCode;
84
85 /** Antenna phasecenter.
86 * North/East/Up (fixed station) or X/Y/Z in body fixed system (vehicle). */
87 private Vector3D antennaPhaseCenter;
88
89 /** Antenna B.Sight.
90 * Direction of the “vertical” antenna axis towards the GNSS satellites. */
91 private Vector3D antennaBSight;
92
93 /** Azimuth of the zero direction of a fixed antenna (degrees, from north). */
94 private double antennaAzimuth;
95
96 /** Zero direction of antenna. */
97 private Vector3D antennaZeroDirection;
98
99 /** Current center of mass (X,Y,Z, meters) of vehicle in body fixed coordinate system. */
100 private Vector3D centerMass;
101
102 /** Unit of the carrier to noise ratio observables Snn (if present) DBHZ: S/N given in dbHz. */
103 private String signalStrengthUnit;
104
105 /** Observation interval in seconds. */
106 private double interval;
107
108 /** Time of First observation record. */
109 private AbsoluteDate tFirstObs;
110
111 /** Time of last observation record. */
112 private AbsoluteDate tLastObs;
113
114 /** Flag for application of real time-derived receiver clock offset.
115 * @since 12.1
116 */
117 private boolean clockOffsetApplied;
118
119 /** List of phase shift correction used to generate phases consistent w/r to cycle shifts. */
120 private final List<PhaseShiftCorrection> phaseShiftCorrections;
121
122 /** List of scale factor corrections. */
123 private final Map<SatelliteSystem, List<ScaleFactorCorrection>> scaleFactorCorrections;
124
125 /** List of GLONASS satellite-channel associations.
126 * @since 12.0
127 */
128 private final List<GlonassSatelliteChannel> glonassChannels;
129
130 /** Number of satellites.
131 * @since 12.0
132 */
133 private int nbSat;
134
135 /** Number of observations per satellite.
136 * @since 12.0
137 */
138 private final Map<SatInSystem, Map<String, Integer>> nbObsPerSat;
139
140 /** Code phase bias correction for GLONASS C1C signal.
141 * @since 12.0
142 */
143 private double c1cCodePhaseBias;
144
145 /** Code phase bias correction for GLONASS C1P signal.
146 * @since 12.0
147 */
148 private double c1pCodePhaseBias;
149
150 /** Code phase bias correction for GLONASS C2C signal.
151 * @since 12.0
152 */
153 private double c2cCodePhaseBias;
154
155 /** Code phase bias correction for GLONASS C2P signal.
156 * @since 12.0
157 */
158 private double c2pCodePhaseBias;
159
160 /** Simple constructor.
161 */
162 public RinexObservationHeader() {
163 super(RinexFileType.OBSERVATION);
164 antennaAzimuth = Double.NaN;
165 antennaHeight = Double.NaN;
166 eccentricities = Vector2D.ZERO;
167 clockOffsetApplied = false;
168 nbSat = -1;
169 interval = Double.NaN;
170 phaseShiftCorrections = new ArrayList<>();
171 scaleFactorCorrections = new HashMap<>();
172 glonassChannels = new ArrayList<>();
173 nbObsPerSat = new HashMap<>();
174 tLastObs = AbsoluteDate.FUTURE_INFINITY;
175 c1cCodePhaseBias = Double.NaN;
176 c1pCodePhaseBias = Double.NaN;
177 c2cCodePhaseBias = Double.NaN;
178 c2pCodePhaseBias = Double.NaN;
179 }
180
181 /** {@inheritDoc} */
182 @Override
183 public SatelliteSystem parseSatelliteSystem(final String line, final SatelliteSystem defaultSatelliteSystem) {
184 // for observation files, the satellite system is in column 40, and empty defaults to GPS
185 return SatelliteSystem.parseSatelliteSystem(line.substring(40, 41), defaultSatelliteSystem);
186 }
187
188 /** {@inheritDoc} */
189 @Override
190 public void parseProgramRunByDate(final String line, final TimeScales timeScales) {
191 parseProgramRunByDate(ParsingUtils.parseString(line, 0, 20),
192 ParsingUtils.parseString(line, 20, 20),
193 ParsingUtils.parseString(line, 40, 20),
194 timeScales);
195 }
196
197 /** Set name of the antenna marker.
198 * @param markerName name of the antenna marker
199 */
200 public void setMarkerName(final String markerName) {
201 this.markerName = markerName;
202 }
203
204 /** Get name of the antenna marker.
205 * @return name of the antenna marker
206 */
207 public String getMarkerName() {
208 return markerName;
209 }
210
211 /** Set number of the antenna marker.
212 * @param markerNumber number of the antenna marker
213 */
214 public void setMarkerNumber(final String markerNumber) {
215 this.markerNumber = markerNumber;
216 }
217
218 /** Get number of the antenna marker.
219 * @return number of the antenna marker
220 */
221 public String getMarkerNumber() {
222 return markerNumber;
223 }
224
225 /** Set name of the observer.
226 * @param observerName name of the observer
227 */
228 public void setObserverName(final String observerName) {
229 this.observerName = observerName;
230 }
231
232 /** Get name of the observer.
233 * @return name of the observer
234 */
235 public String getObserverName() {
236 return observerName;
237 }
238
239 /**
240 * Setter for the agency name.
241 * @param agencyName the agency name to set
242 */
243 public void setAgencyName(final String agencyName) {
244 this.agencyName = agencyName;
245 }
246
247 /** Get name of the agency.
248 * @return name of the agency
249 */
250 public String getAgencyName() {
251 return agencyName;
252 }
253
254 /** Set the number of the antenna.
255 * @param antennaNumber number of the antenna
256 */
257 public void setAntennaNumber(final String antennaNumber) {
258 this.antennaNumber = antennaNumber;
259 }
260
261 /** Get the number of the antenna.
262 * @return number of the antenna
263 */
264 public String getAntennaNumber() {
265 return antennaNumber;
266 }
267
268 /** Set the type of the antenna.
269 * @param antennaType type of the antenna
270 */
271 public void setAntennaType(final String antennaType) {
272 this.antennaType = antennaType;
273 }
274
275 /** Get the type of the antenna.
276 * @return type of the antenna
277 */
278 public String getAntennaType() {
279 return antennaType;
280 }
281
282 /** Set the Approximate Marker Position.
283 * @param approxPos Approximate Marker Position
284 */
285 public void setApproxPos(final Vector3D approxPos) {
286 this.approxPos = approxPos;
287 }
288
289 /** Get the Approximate Marker Position.
290 * @return Approximate Marker Position
291 */
292 public Vector3D getApproxPos() {
293 return approxPos;
294 }
295
296 /** Set the antenna height.
297 * @param antennaHeight height of the antenna
298 */
299 public void setAntennaHeight(final double antennaHeight) {
300 this.antennaHeight = antennaHeight;
301 }
302
303 /** Get the antenna height.
304 * @return height of the antenna
305 */
306 public double getAntennaHeight() {
307 return antennaHeight;
308 }
309
310 /** Set the eccentricities of antenna center.
311 * @param eccentricities Eccentricities of antenna center
312 */
313 public void setEccentricities(final Vector2D eccentricities) {
314 this.eccentricities = eccentricities;
315 }
316
317 /** Get the eccentricities of antenna center.
318 * @return Eccentricities of antenna center
319 */
320 public Vector2D getEccentricities() {
321 return eccentricities;
322 }
323
324 /** Set the application flag for realtime-derived receiver clock offset.
325 * @param clockOffsetApplied application flag for realtime-derived receiver clock offset
326 * @since 12.1
327 */
328 public void setClockOffsetApplied(final boolean clockOffsetApplied) {
329 this.clockOffsetApplied = clockOffsetApplied;
330 }
331
332 /** Get the application flag for realtime-derived receiver clock offset.
333 * @return application flag for realtime-derived receiver clock offset
334 * @since 12.1
335 */
336 public boolean getClockOffsetApplied() {
337 return clockOffsetApplied;
338 }
339
340 /** Set the observation interval in seconds.
341 * @param interval Observation interval in seconds
342 */
343 public void setInterval(final double interval) {
344 this.interval = interval;
345 }
346
347 /** Get the observation interval in seconds.
348 * @return Observation interval in seconds
349 */
350 public double getInterval() {
351 return interval;
352 }
353
354 /** Set the time of First observation record.
355 * @param firstObs Time of First observation record
356 */
357 public void setTFirstObs(final AbsoluteDate firstObs) {
358 this.tFirstObs = firstObs;
359 }
360
361 /** Get the time of First observation record.
362 * @return Time of First observation record
363 */
364 public AbsoluteDate getTFirstObs() {
365 return tFirstObs;
366 }
367
368 /** Set the time of last observation record.
369 * @param lastObs Time of last observation record
370 */
371 public void setTLastObs(final AbsoluteDate lastObs) {
372 this.tLastObs = lastObs;
373 }
374
375 /** Get the time of last observation record.
376 * @return Time of last observation record
377 */
378 public AbsoluteDate getTLastObs() {
379 return tLastObs;
380 }
381
382 /** Set type of the antenna marker.
383 * @param markerType type of the antenna marker
384 */
385 public void setMarkerType(final String markerType) {
386 this.markerType = markerType;
387 }
388
389 /** Get type of the antenna marker.
390 * @return type of the antenna marker
391 */
392 public String getMarkerType() {
393 return markerType;
394 }
395
396 /** Set the position of antenna reference point for antenna on vehicle.
397 * @param refPoint Position of antenna reference point for antenna on vehicle
398 */
399 public void setAntennaReferencePoint(final Vector3D refPoint) {
400 this.antRefPoint = refPoint;
401 }
402
403 /** Get the position of antenna reference point for antenna on vehicle.
404 * @return Position of antenna reference point for antenna on vehicle
405 */
406 public Vector3D getAntennaReferencePoint() {
407 return antRefPoint;
408 }
409
410 /** Set satellite system for average phase center.
411 * @param phaseCenterSystem satellite system for average phase center
412 * @since 12.0
413 */
414 public void setPhaseCenterSystem(final SatelliteSystem phaseCenterSystem) {
415 this.phaseCenterSystem = phaseCenterSystem;
416 }
417
418 /** Get satellite system for average phase center.
419 * @return satellite system for average phase center
420 * @since 12.0
421 */
422 public SatelliteSystem getPhaseCenterSystem() {
423 return phaseCenterSystem;
424 }
425
426 /** Set the observation code of the average phasecenter position w/r to antenna reference point.
427 * @param observationCode Observation code of the average phasecenter position w/r to antenna reference point
428 */
429 public void setObservationCode(final String observationCode) {
430 this.observationCode = observationCode;
431 }
432
433 /** Get the observation code of the average phasecenter position w/r to antenna reference point.
434 * @return Observation code of the average phasecenter position w/r to antenna reference point
435 */
436 public String getObservationCode() {
437 return observationCode;
438 }
439
440 /** Set the antenna phasecenter.
441 * @param antennaPhaseCenter Antenna phasecenter
442 */
443 public void setAntennaPhaseCenter(final Vector3D antennaPhaseCenter) {
444 this.antennaPhaseCenter = antennaPhaseCenter;
445 }
446
447 /** Get the antenna phasecenter.
448 * @return Antenna phasecenter
449 */
450 public Vector3D getAntennaPhaseCenter() {
451 return antennaPhaseCenter;
452 }
453
454 /** Set the antenna B.Sight.
455 * @param antennaBSight Antenna B.Sight
456 */
457 public void setAntennaBSight(final Vector3D antennaBSight) {
458 this.antennaBSight = antennaBSight;
459 }
460
461 /** Get the antenna B.Sight.
462 * @return Antenna B.Sight
463 */
464 public Vector3D getAntennaBSight() {
465 return antennaBSight;
466 }
467
468 /** Set the azimuth of the zero direction of a fixed antenna.
469 * @param antennaAzimuth Azimuth of the zero direction of a fixed antenna
470 */
471 public void setAntennaAzimuth(final double antennaAzimuth) {
472 this.antennaAzimuth = antennaAzimuth;
473 }
474
475 /** Get the azimuth of the zero direction of a fixed antenna.
476 * @return Azimuth of the zero direction of a fixed antenna
477 */
478 public double getAntennaAzimuth() {
479 return antennaAzimuth;
480 }
481
482 /** Set the zero direction of antenna.
483 * @param antennaZeroDirection Zero direction of antenna
484 */
485 public void setAntennaZeroDirection(final Vector3D antennaZeroDirection) {
486 this.antennaZeroDirection = antennaZeroDirection;
487 }
488
489 /** Get the zero direction of antenna.
490 * @return Zero direction of antenna
491 */
492 public Vector3D getAntennaZeroDirection() {
493 return antennaZeroDirection;
494 }
495
496 /** Set the current center of mass of vehicle in body fixed coordinate system.
497 * @param centerMass Current center of mass of vehicle in body fixed coordinate system
498 */
499 public void setCenterMass(final Vector3D centerMass) {
500 this.centerMass = centerMass;
501 }
502
503 /** Get the current center of mass of vehicle in body fixed coordinate system.
504 * @return Current center of mass of vehicle in body fixed coordinate system
505 */
506 public Vector3D getCenterMass() {
507 return centerMass;
508 }
509
510 /** Set the unit of the carrier to noise ratio observables.
511 * @param signalStrengthUnit Unit of the carrier to noise ratio observables
512 */
513 public void setSignalStrengthUnit(final String signalStrengthUnit) {
514 this.signalStrengthUnit = signalStrengthUnit;
515 }
516
517 /** Get the unit of the carrier to noise ratio observables.
518 * @return Unit of the carrier to noise ratio observables
519 */
520 public String getSignalStrengthUnit() {
521 return signalStrengthUnit;
522 }
523
524 /** Add phase shift correction used to generate phases consistent w/r to cycle shifts.
525 * @param phaseShiftCorrection phase shift correction used to generate phases consistent w/r to cycle shifts
526 */
527 public void addPhaseShiftCorrection(final PhaseShiftCorrection phaseShiftCorrection) {
528 phaseShiftCorrections.add(phaseShiftCorrection);
529 }
530
531 /** Get the list of phase shift correction used to generate phases consistent w/r to cycle shifts.
532 * @return List of phase shift correction used to generate phases consistent w/r to cycle shifts
533 */
534 public List<PhaseShiftCorrection> getPhaseShiftCorrections() {
535 return Collections.unmodifiableList(phaseShiftCorrections);
536 }
537
538 /** Add scale factor correction.
539 * @param satelliteSystem system to which this scaling factor applies
540 * @param scaleFactorCorrection scale factor correction
541 */
542 public void addScaleFactorCorrection(final SatelliteSystem satelliteSystem, final ScaleFactorCorrection scaleFactorCorrection) {
543 final List<ScaleFactorCorrection> sfc;
544 synchronized (scaleFactorCorrections) {
545 sfc = scaleFactorCorrections.computeIfAbsent(satelliteSystem, k -> new ArrayList<>());
546 }
547 sfc.add(scaleFactorCorrection);
548 }
549
550 /** Get the list of scale factor correction.
551 * @param satelliteSystem system to which this scaling factor applies
552 * @return List of scale factor correction
553 */
554 public List<ScaleFactorCorrection> getScaleFactorCorrections(final SatelliteSystem satelliteSystem) {
555 final List<ScaleFactorCorrection> sfc = scaleFactorCorrections.get(satelliteSystem);
556 return sfc == null ? Collections.emptyList() : Collections.unmodifiableList(sfc);
557 }
558
559 /** Add GLONASS satellite/channel association.
560 * @param glonassChannel GLONASS satellite/channel association
561 * @since 12.0
562 */
563 public void addGlonassChannel(final GlonassSatelliteChannel glonassChannel) {
564 glonassChannels.add(glonassChannel);
565 }
566
567 /** Get the list of GLONASS satellite/channel associations.
568 * @return List of GLONASS satellite/channel associations
569 * @since 12.0
570 */
571 public List<GlonassSatelliteChannel> getGlonassChannels() {
572 return Collections.unmodifiableList(glonassChannels);
573 }
574
575 /** Set number of satellites.
576 * @param nbSat number of satellites
577 * @since 12.0
578 */
579 public void setNbSat(final int nbSat) {
580 this.nbSat = nbSat;
581 }
582
583 /** Get number of satellites.
584 * @return number of satellites
585 * @since 12.0
586 */
587 public int getNbSat() {
588 return nbSat;
589 }
590
591 /** Set number of observations for a satellite.
592 * @param sat satellite
593 * @param type observation type
594 * @param nbObs number of observations of this type for this satellite
595 * @since 12.0
596 */
597 public void setNbObsPerSatellite(final SatInSystem sat, final String type, final int nbObs) {
598 final Map<String, Integer> satNbObs;
599 synchronized (nbObsPerSat) {
600 satNbObs = nbObsPerSat.computeIfAbsent(sat, k -> new HashMap<>());
601 }
602 satNbObs.put(type, nbObs);
603 }
604
605 /** Get an unmodifiable view of the map of number of observations per satellites.
606 * @return unmodifiable view of the map of number of observations per satellites
607 * @since 12.0
608 */
609 public Map<SatInSystem, Map<String, Integer>> getNbObsPerSat() {
610 return Collections.unmodifiableMap(nbObsPerSat);
611 }
612
613 /** Set the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1C} signal.
614 * @param c1cCodePhaseBias code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1C} signal
615 * @since 12.0
616 */
617 public void setC1cCodePhaseBias(final double c1cCodePhaseBias) {
618 this.c1cCodePhaseBias = c1cCodePhaseBias;
619 }
620
621 /** Get the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1C} signal.
622 * @return code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1C} signal
623 * @since 12.0
624 */
625 public double getC1cCodePhaseBias() {
626 return c1cCodePhaseBias;
627 }
628
629 /** Set the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1P} signal.
630 * @param c1pCodePhaseBias code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1P} signal
631 * @since 12.0
632 */
633 public void setC1pCodePhaseBias(final double c1pCodePhaseBias) {
634 this.c1pCodePhaseBias = c1pCodePhaseBias;
635 }
636
637 /** Get the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1P} signal.
638 * @return code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C1P} signal
639 * @since 12.0
640 */
641 public double getC1pCodePhaseBias() {
642 return c1pCodePhaseBias;
643 }
644
645 /** Set the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2C} signal.
646 * @param c2cCodePhaseBias code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2C} signal
647 * @since 12.0
648 */
649 public void setC2cCodePhaseBias(final double c2cCodePhaseBias) {
650 this.c2cCodePhaseBias = c2cCodePhaseBias;
651 }
652
653 /** Get the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2C} signal.
654 * @return code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2C} signal
655 * @since 12.0
656 */
657 public double getC2cCodePhaseBias() {
658 return c2cCodePhaseBias;
659 }
660
661 /** Set the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2P} signal.
662 * @param c2pCodePhaseBias code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2P} signal
663 * @since 12.0
664 */
665 public void setC2pCodePhaseBias(final double c2pCodePhaseBias) {
666 this.c2pCodePhaseBias = c2pCodePhaseBias;
667 }
668
669 /** Get the code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2P} signal.
670 * @return code phase bias correction for GLONASS {@link org.orekit.gnss.PredefinedObservationType#C2P} signal
671 * @since 12.0
672 */
673 public double getC2pCodePhaseBias() {
674 return c2pCodePhaseBias;
675 }
676
677 /** {@inheritDoc} */
678 @Override
679 public void checkType(final String line, final String name) {
680 checkType(line, 20, name);
681 }
682
683 /** {@inheritDoc} */
684 @Override
685 public int getLabelIndex() {
686 return LABEL_INDEX;
687 }
688
689 /** {@inheritDoc} */
690 @Override
691 public boolean matchFound(final Label label, final String line) {
692 final int max = getLabelIndex();
693 return line.length() >= max && label.matches(line.substring(max).trim());
694 }
695
696 }