1 //============================================================================== 2 // 3 // This file is part of GPSTk, the GPS Toolkit. 4 // 5 // The GPSTk is free software; you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published 7 // by the Free Software Foundation; either version 3.0 of the License, or 8 // any later version. 9 // 10 // The GPSTk is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public 16 // License along with GPSTk; if not, write to the Free Software Foundation, 17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 18 // 19 // This software was developed by Applied Research Laboratories at the 20 // University of Texas at Austin. 21 // Copyright 2004-2020, The Board of Regents of The University of Texas System 22 // 23 //============================================================================== 24 25 //============================================================================== 26 // 27 // This software was developed by Applied Research Laboratories at the 28 // University of Texas at Austin, under contract to an agency or agencies 29 // within the U.S. Department of Defense. The U.S. Government retains all 30 // rights to use, duplicate, distribute, disclose, or release this software. 31 // 32 // Pursuant to DoD Directive 523024 33 // 34 // DISTRIBUTION STATEMENT A: This software has been approved for public 35 // release, distribution is unlimited. 36 // 37 //============================================================================== 38 39 /** 40 * @file Rinex3ObsHeader.hpp 41 * Encapsulate header of Rinex observation file, including I/O 42 */ 43 44 #ifndef GPSTK_RINEX3OBSHEADER_HPP 45 #define GPSTK_RINEX3OBSHEADER_HPP 46 47 #include <vector> 48 #include <list> 49 #include <map> 50 #include <set> 51 #include <iostream> 52 #include <iomanip> 53 54 #include "CivilTime.hpp" 55 #include "FFStream.hpp" 56 #include "Rinex3ObsBase.hpp" 57 #include "Triple.hpp" 58 #include "RinexSatID.hpp" 59 #include "RinexObsID.hpp" 60 61 62 namespace gpstk 63 { 64 65 /// @ingroup FileHandling 66 //@{ 67 68 /** @page rinobshead RINEX OBS header implementation 69 * 70 * For each header line type, the following are listed in the 71 * table below: 72 * 1. The label 73 * 2. Its usage in RINEX 2 74 * 3. Its usage in RINEX 3 75 * 4. The name for validity checking and header variable 76 * storage (see below) 77 * 5. Variables (data members) storing the header information 78 * 79 * | Header Field | v2 | v3 | Name | Variables | 80 * | :------------------- | :-- | :-- | :---------------- | :---------------- | 81 * | RINEX VERSION / TYPE | req | req | Version | version | 82 * | ^ | ^ | ^ | ^ | fileType | 83 * | ^ | ^ | ^ | ^ | fileSys | 84 * | ^ | ^ | ^ | ^ | fileSysSat | 85 * | ^ | ^ | ^ | ^ | preserveVerType | 86 * | PGM / RUN BY / DATE | req | req | RunBy | fileProgram | 87 * | ^ | ^ | ^ | ^ | fileAgency | 88 * | ^ | ^ | ^ | ^ | date | 89 * | ^ | ^ | ^ | ^ | preserveDate | 90 * | COMMENT | opt | opt | Comment | commentList | 91 * | MARKER NAME | req | opt | MarkerName | markerName | 92 * | MARKER NUMBER | opt | opt | MarkerNumber | markerNumber | 93 * | MARKER TYPE | - | req | MarkerType | markerType | 94 * | OBSERVER / AGENCY | req | req | Observer | observer | 95 * | ^ | ^ | ^ | ^ | agency | 96 * | REC # / TYPE / VERS | req | req | Receiver | recNo | 97 * | ^ | ^ | ^ | ^ | recType | 98 * | ^ | ^ | ^ | ^ | recVers | 99 * | ANT # / TYPE | req | req | AntennaType | antNo | 100 * | ^ | ^ | ^ | ^ | antType | 101 * | APPROX POSITION XYZ | req | req | AntennaPosition | antennaPosition | 102 * | ANTENNA: DELTA H/E/N | req | req | AntennaDeltaHEN | antennaDeltaHEN | 103 * | ANTENNA: DELTA X/Y/Z | - | opt | AntennaDeltaXYZ | antennaDeltaXYZ | 104 * | ANTENNA: PHASECENTER | - | opt | AntennaPhaseCtr | antennaSatSys | 105 * | ^ | ^ | ^ | ^ | antennaObsCode | 106 * | ^ | ^ | ^ | ^ | antennaPhaseCtr | 107 * | ANTENNA: B.SIGHT XYZ | - | opt | AntennaBsightXYZ | antennaBsightXYZ | 108 * | ANTENNA: ZERODIR AZI | - | opt | AntennaZeroDirAzi | antennaZeroDirAzi | 109 * | ANTENNA: ZERODIR XYZ | - | opt | AntennaZeroDirXYZ | antennaZeroDirXYZ | 110 * | CENTER OF MASS: XYZ | - | opt | CenterOfMass | centerOfMass | 111 * | # / TYPES OF OBSERV | req | n/a | NumObs | | 112 * | SYS / # / OBS TYPES | n/a | req | SystemNumObs | mapObsTypes | 113 * | WAVELENGTH FACT L1/2 | opt | - | WaveFact | wavelengthFactor | 114 * | ^ | ^ | ^ | ^ | extraWaveFactList | 115 * | SIGNAL STRENGTH UNIT | - | opt | SigStrengthUnit | sigStrengthUnit | 116 * | INTERVAL | opt | opt | Interval | interval | 117 * | TIME OF FIRST OBS | req | req | FirstTime | firstObs | 118 * | TIME OF LAST OBS | opt | opt | LastTime | lastObs | 119 * | RCV CLOCK OFFS APPL | opt | opt | ReceiverOffset | receiverOffset | 120 * | SYS / DCBS APPLIED | - | opt | SystemDCBSapplied | infoDCBS | 121 * | SYS / PCVS APPLIED | - | opt | SystemPCVSapplied | infoPCVS | 122 * | SYS / SCALE FACTOR | - | opt | SystemScaleFac | sysSfacMap | 123 * | SYS / PHASE SHIFT | - | req | SystemPhaseShift | sysPhaseShift | 124 * | GLONASS SLOT / FRQ # | - | req | GlonassSlotFreqNo | glonassFreqNo | 125 * | GLONASS COD/PHS/BIS | - | req | GlonassCodPhsBias | glonassCodPhsBias | 126 * | LEAP SECONDS | opt | opt | LeapSeconds | leapSeconds | 127 * | # OF SATELLITES | opt | opt | NumSats | numSVs | 128 * | PRN / # OF OBS | opt | opt | PrnObs | numObsForSat | 129 * | END OF HEADER | req | req | EoH (header only) | - | 130 * 131 * The "Name" column in the above table is used for both 132 * validity flags and header strings. For the header strings, 133 * prepend "hs", e.g. "hsVersion" will give you the header field 134 * label. For validity flags, prepend valid, 135 * e.g. "validVersion" would indicate the presence of the "RINEX 136 * VERSION / TYPE" header record. 137 */ 138 139 /** 140 * This class models the header for a RINEX 3 Observation File. 141 * @sa gpstk::Rinex3ObsData and gpstk::Rinex3ObsStream. 142 * @sa rinex_obs_test.cpp and rinex_obs_read_write.cpp for examples. 143 * 144 * RINEX 2 is also supported. 145 * 146 * @warning This class makes no attempt to apply or remove any 147 * of the phase shifts when converting between RINEX and other 148 * observation types. This can lead to invalid RINEX OBS data. 149 * Either use RINEX 3.00 which does not require the 150 * SYS / PHASE SHIFT header field, or apply the corrections 151 * appropriately when performing conversions. 152 */ 153 class Rinex3ObsHeader : public Rinex3ObsBase 154 { 155 public: 156 157 /// A Simple Constructor. 158 Rinex3ObsHeader(); 159 160 /** Clear (empty out) header, setting all data members to 161 * default values */ 162 void clear(); 163 164 /// @name RINEX observation file header formatting strings 165 ///@{ 166 static const std::string hsVersion; ///< RINEX VERSION / TYPE 167 static const std::string hsRunBy; ///< PGM / RUN BY / DATE 168 static const std::string hsComment; ///< COMMENT 169 static const std::string hsMarkerName; ///< MARKER NAME 170 static const std::string hsMarkerNumber; ///< MARKER NUMBER 171 static const std::string hsMarkerType; ///< MARKER TYPE 172 static const std::string hsObserver; ///< OBSERVER / AGENCY 173 static const std::string hsReceiver; ///< REC # / TYPE / VERS 174 static const std::string hsAntennaType; ///< ANT # / TYPE 175 static const std::string hsAntennaPosition; ///< APPROX POSITION XYZ 176 static const std::string hsAntennaDeltaHEN; ///< ANTENNA: DELTA H/E/N 177 static const std::string hsAntennaDeltaXYZ; ///< ANTENNA: DELTA X/Y/Z 178 static const std::string hsAntennaPhaseCtr; ///< ANTENNA: PHASECENTER 179 static const std::string hsAntennaBsightXYZ; ///< ANTENNA: B.SIGHT XYZ 180 static const std::string hsAntennaZeroDirAzi; ///< ANTENNA: ZERODIR AZI 181 static const std::string hsAntennaZeroDirXYZ; ///< ANTENNA: ZERODIR XYZ 182 static const std::string hsCenterOfMass; ///< CENTER OF MASS: XYZ 183 static const std::string hsNumObs; ///< # / TYPES OF OBSERV 184 static const std::string hsSystemNumObs; ///< SYS / # / OBS TYPES 185 static const std::string hsWaveFact; ///< WAVELENGTH FACT L1/2 186 static const std::string hsSigStrengthUnit; ///< SIGNAL STRENGTH UNIT 187 static const std::string hsInterval; ///< INTERVAL 188 static const std::string hsFirstTime; ///< TIME OF FIRST OBS 189 static const std::string hsLastTime; ///< TIME OF LAST OBS 190 static const std::string hsReceiverOffset; ///< RCV CLOCK OFFS APPL 191 static const std::string hsSystemDCBSapplied; ///< SYS / DCBS APPLIED 192 static const std::string hsSystemPCVSapplied; ///< SYS / PCVS APPLIED 193 static const std::string hsSystemScaleFac; ///< SYS / SCALE FACTOR 194 static const std::string hsSystemPhaseShift; ///< SYS / PHASE SHIFT 195 static const std::string hsGlonassSlotFreqNo; ///< GLONASS SLOT / FRQ # 196 static const std::string hsGlonassCodPhsBias; ///< GLONASS COD/PHS/BIS 197 static const std::string hsLeapSeconds; ///< LEAP SECONDS 198 static const std::string hsNumSats; ///< # OF SATELLITES 199 static const std::string hsPrnObs; ///< PRN / # OF OBS 200 static const std::string hsEoH; ///< END OF HEADER 201 ///@} 202 203 /** Validity bits for the RINEX Observation Header - please 204 * keep ordered as strings above */ 205 enum Field 206 { 207 validInvalid = 0, ///< Not a valid field 208 validVersion, ///< RINEX VERSION / TYPE 209 validFirst = validVersion, ///< Used fore testing only 210 validRunBy, ///< PGM / RUN BY / DATE 211 validComment, ///< COMMENT 212 validMarkerName, ///< MARKER NAME 213 validMarkerNumber, ///< MARKER NUMBER 214 validMarkerType, ///< MARKER TYPE 215 validObserver, ///< OBSERVER / AGENCY 216 validReceiver, ///< REC # / TYPE / VERS 217 validAntennaType, ///< ANT # / TYPE 218 validAntennaPosition, ///< APPROX POSITION XYZ 219 validAntennaDeltaHEN, ///< ANTENNA: DELTA H/E/N 220 validAntennaDeltaXYZ, ///< ANTENNA: DELTA X/Y/Z 221 validAntennaPhaseCtr, ///< ANTENNA: PHASECENTER 222 validAntennaBsightXYZ, ///< ANTENNA: B.SIGHT XYZ 223 validAntennaZeroDirAzi, ///< ANTENNA: ZERODIR AZI 224 validAntennaZeroDirXYZ, ///< ANTENNA: ZERODIR XYZ 225 validCenterOfMass, ///< CENTER OF MASS: XYZ 226 validNumObs, ///< # / TYPES OF OBSERV 227 validSystemNumObs, ///< SYS / # / OBS TYPES 228 validWaveFact, ///< WAVELENGTH FACT L1/2 229 validSigStrengthUnit, ///< SIGNAL STRENGTH UNIT 230 validInterval, ///< INTERVAL 231 validFirstTime, ///< TIME OF FIRST OBS 232 validLastTime, ///< TIME OF LAST OBS 233 validReceiverOffset, ///< RCV CLOCK OFFS APPL 234 validSystemDCBSapplied, ///< SYSTEM DCBS APPLIED 235 validSystemPCVSapplied, ///< SYSTEM PCVS APPLIED 236 validSystemScaleFac, ///< SYSTEM SCALE FACTOR 237 validSystemPhaseShift, ///< SYS / PHASE SHIFT 238 validGlonassSlotFreqNo, ///< GLONASS SLOT / FRQ # 239 validGlonassCodPhsBias, ///< GLONASS COD/PHS/BIS 240 validLeapSeconds, ///< LEAP SECONDS 241 validNumSats, ///< # OF SATELLITES 242 validPrnObs, ///< PRN / # OF OBS 243 validLast ///< Used for testing only. 244 }; 245 246 /** RINEX 3 DCBS/PCVS info (for differential code bias and 247 * phase center variations corr.) */ 248 class Rinex3CorrInfo 249 { 250 public: 251 std::string satSys; ///< 1-char SV system (G/R/E/S) 252 std::string name; ///< program name used to apply corrections 253 std::string source; ///< source of corrections (URL) 254 }; 255 256 /// RINEX 2 extra "WAVELENGTH FACT" lines 257 class ExtraWaveFact 258 { 259 public: 260 /// List of Sats with this wavelength factor 261 std::vector<SatID> satList; 262 /// vector of wavelength factor values 263 short wavelengthFactor[2]; 264 /// Setter method for convenience of python bindings setWavelengthFactor(short wf1,short wf2)265 ExtraWaveFact& setWavelengthFactor(short wf1, short wf2) 266 { 267 wavelengthFactor[0] = wf1; 268 wavelengthFactor[1] = wf2; 269 return *this; 270 } 271 /** Getter method for convenience of python bindings. 272 * @note I decided to implement two methods instead of a 273 * single method that took a parameter that required 274 * sanity check so as to avoid having to do the sanity 275 * check and exception handling. */ getWavelengthFactor1()276 short getWavelengthFactor1() 277 { return wavelengthFactor[0]; } 278 /// @copydoc getWavelengthFactor1 getWavelengthFactor2()279 short getWavelengthFactor2() 280 { return wavelengthFactor[1]; } 281 }; 282 283 /// Commonly used vector of strings 284 typedef std::vector<std::string> StringVec; 285 /// Simple vector of ints 286 typedef std::vector<int> IntVec; 287 /// Type used to count the number of observations for each observable. 288 typedef std::map<RinexSatID, IntVec> PRNNumObsMap; 289 /** Scale Factor corrections for observations 290 * map <ObsType, ScaleFactor> */ 291 typedef std::map<RinexObsID, int> ScaleFacMap; 292 /** Per-system scale factor corrections. 293 * Satellite system map of scale factor maps 294 * <(G/R/E/S), <Rinex3ObsType, scalefactor>> */ 295 typedef std::map<std::string, ScaleFacMap> SysScaleFacMap; 296 /// Vector of obervables 297 typedef std::vector<RinexObsID> RinexObsVec; 298 /** Map system to observables 299 * map <sys char, vec<ObsID> >; 300 * NB defines data vec in ObsData */ 301 typedef std::map<std::string, RinexObsVec> RinexObsMap; 302 /// @todo document me 303 typedef std::map<std::string, RinexObsID> ObsIDMap; 304 /// @todo document me 305 typedef std::map<std::string, ObsIDMap> VersionObsMap; 306 /// Map satellite ID to phase shift 307 typedef std::map<RinexSatID, double> SVPhsShftMap; 308 /// Map observation type to sv-phase shift map 309 typedef std::map<RinexObsID, SVPhsShftMap> ObsPhsShftMap; 310 /// Map system to observation type phase shift map 311 typedef std::map<std::string, ObsPhsShftMap> SysPhsShftMap; 312 /// Map GLONASS SV ID to frequency number 313 typedef std::map<RinexSatID, int> GLOFreqNumMap; 314 /// Map GLONASS SV observable to code phase bias 315 typedef std::map<RinexObsID, double> GLOCodPhsBias; 316 /// Map SysChar + R2 Obs Type to Obs ID 317 typedef std::map<std::string,std::string> DisAmbMap; 318 /// Corrections (e.g. code bias) vector 319 typedef std::vector<Rinex3CorrInfo> CorrVec; 320 /// Vector of wavelength factors 321 typedef std::vector<ExtraWaveFact> FactorVector; 322 typedef std::set<Field> FieldSet; 323 324 class Fields 325 { 326 public: 327 Fields() = default; Fields(const FieldSet & fields)328 Fields(const FieldSet& fields) 329 : fieldsSet(fields) 330 {} 331 /// Compare field sets. operator ==(const Fields & rhs) const332 bool operator==(const Fields& rhs) const 333 { return fieldsSet == rhs.fieldsSet; } 334 /// Return true if the set of fields differs between this and rhs. operator !=(const Fields & rhs) const335 bool operator!=(const Fields& rhs) const 336 { return !(fieldsSet == rhs.fieldsSet); } 337 /// Set a specific field. set(Field f)338 Fields& set(Field f) 339 { fieldsSet.insert(f); return *this; } 340 /// Clear a specific field. clear(Field f)341 Fields& clear(Field f) 342 { fieldsSet.erase(f); return *this; } 343 /// Return true if the specific field is set (preferred to operator&). isSet(Field f) const344 bool isSet(Field f) const 345 { return fieldsSet.count(f) > 0; } 346 /// Clear all set fields. clear()347 void clear() 348 { fieldsSet.clear(); } 349 /// Return true if fieldsSet is empty, false otherwise. empty() const350 bool empty() const 351 { return fieldsSet.empty(); } 352 /** Backwards compatibility method for code still implemented 353 * around bit flags. 354 */ 355 Fields operator&(const Fields& rhs) const; 356 /** Backwards compatibility method for code still implemented 357 * around bit flags. 358 */ 359 Fields operator|(const Fields& rhs) const; 360 /** Backwards compatibility method for code still implemented 361 * around bit flags. 362 * @deprecated Please use isSet() instead. */ 363 Field operator&(Field rhs) const; 364 /** Alias for set() for backwards compatibility. 365 * @deprecated Please use set() instead. */ operator |=(Field rhs)366 Fields& operator|=(Field rhs) 367 { return set(rhs); } 368 /** Alias for clear(Field) 369 * @deprecated Please use clear(Field) instead. */ operator ^=(Field rhs)370 Fields& operator^=(Field rhs) 371 { return clear(rhs); } 372 /** Determine if a header is valid. 373 * @note This object is assumed to be a set of required 374 * fields. Generally you would call this method on one of 375 * the allValid2, etc. static objects defined above. 376 * @see isValid(double,const Fields&) 377 * @code{.cpp} 378 * if (Fields::allValid2.isValid(flags)) 379 * @endcode 380 * @param[in] present The set of flags present in an existing 381 * header to be compared with this set of required flags. 382 * @return true If all the fields in fieldsSet are also 383 * contained in present.fieldsSet. 384 */ 385 bool isValid(const Fields& present) const; 386 /** Determine if a header is valid. 387 * @param[in] version The RINEX version being validated. 388 * @param[in] present The set of flags present in an existing 389 * header to be compared with this set of required flags. 390 * @return true If all the fields in the fieldsSet value 391 * appropriate for the specified version are also contained 392 * in present.fieldsSet. 393 */ isValid(double version,const Fields & present)394 static bool isValid(double version, const Fields& present) 395 { return getRequired(version).isValid(present); } 396 /** Add descriptive information to an exception about which 397 * header fields are missing. This object is assumed to be 398 * the set of header fields that are expected. 399 * @param[in] valid The set of present header fields. 400 * @param[out] exc The exception to add descriptive text to. 401 * @post exc will have text entries added to it for each of 402 * the missing header fields, i.e. each field set in 403 * allValid that is not set in valid. 404 */ 405 void describeMissing(const Fields& valid, Exception& exc); 406 /** Get a reference to the set of required header fields for 407 * a given RINEX version. */ 408 static Fields getRequired(double version); 409 410 /// All the header fields set in this object. 411 FieldSet fieldsSet; 412 }; 413 414 static const Fields allValid2, allValid30, allValid301, allValid302, 415 allValid303; 416 417 /** Storage for R2 <-> R3 conversion of obstypes during 418 * reallyGet/Put Vector of strings containing ver 2 obs types 419 * (e.g. "C1" "L2") defined in reallyGet; also defined in 420 * PrepareVer2Write() from R3 ObsIDs */ 421 StringVec R2ObsTypes; 422 423 /** map between RINEX ver 3 ObsIDs and ver 2 obstypes for 424 * each system: reallyPut */ 425 VersionObsMap mapSysR2toR3ObsID; 426 427 /** map Sys + R2ot to their ObsID origins*/ 428 DisAmbMap R2DisambiguityMap; 429 430 431 double version; ///< RINEX 3 version/type 432 std::string fileType; ///< RINEX 3 file type 433 /// file sys char: RinexSatID system OR Mixed 434 std::string fileSys; 435 /** If false, the file type and system will be re-generated 436 * in the gpstk preferred format when writing the header, 437 * otherwise the strings fileType fileSys will be written 438 * unaltered */ 439 bool preserveVerType; 440 SatID fileSysSat; ///< fileSys as a SatID 441 std::string fileProgram; ///< program used to generate file 442 std::string fileAgency; ///< who ran program 443 std::string date; ///< when program was run 444 /** If false, the current system time will be used when 445 * writing the header, otherwise the value in date will be 446 * used. */ 447 bool preserveDate; 448 StringVec commentList; ///< comments in header 449 std::string markerName; ///< MARKER NAME 450 std::string markerNumber; ///< MARKER NUMBER 451 std::string markerType; ///< MARKER TYPE 452 std::string observer; ///< who collected the data 453 std::string agency; ///< observer's agency 454 std::string recNo; ///< receiver number 455 std::string recType; ///< receiver type 456 std::string recVers; ///< receiver version 457 std::string antNo; ///< antenna number 458 std::string antType; ///< antenna type 459 gpstk::Triple antennaPosition; ///< APPROX POSITION XYZ 460 gpstk::Triple antennaDeltaHEN; ///< ANTENNA: DELTA H/E/N 461 gpstk::Triple antennaDeltaXYZ; ///< ANTENNA: DELTA X/Y/Z 462 std::string antennaSatSys; ///< ANTENNA P.CTR BLOCK: SAT SYS 463 std::string antennaObsCode; ///< ANTENNA P.CTR BLOCK: OBS CODE 464 gpstk::Triple antennaPhaseCtr; ///< ANTENNA P.CTR BLOCK: PCTR POS 465 gpstk::Triple antennaBsightXYZ; ///< ANTENNA B.SIGHT XYZ 466 double antennaZeroDirAzi; ///< ANTENNA ZERODIR AZI 467 gpstk::Triple antennaZeroDirXYZ; ///< ANTENNA ZERODIR XYZ 468 gpstk::Triple centerOfMass; ///< vehicle CENTER OF MASS: XYZ 469 RinexObsMap mapObsTypes; ///< SYS / # / OBS TYPES 470 short wavelengthFactor[2]; ///< WAVELENGTH FACT (system-wide) 471 FactorVector extraWaveFactList; ///< WAVELENGTH FACT (per SV) 472 std::string sigStrengthUnit; ///< SIGNAL STRENGTH UNIT 473 double interval; ///< INTERVAL 474 CivilTime firstObs; ///< TIME OF FIRST OBS 475 CivilTime lastObs; ///< TIME OF LAST OBS 476 int receiverOffset; ///< RCV CLOCK OFFS APPL 477 CorrVec infoDCBS; ///< DCBS INFO 478 CorrVec infoPCVS; ///< PCVS INFO 479 SysScaleFacMap sysSfacMap; ///< SYS / SCALE FACTOR 480 SysPhsShftMap sysPhaseShift; ///< SYS / PHASE SHIFT 481 GLOFreqNumMap glonassFreqNo; ///< GLONASS SLOT / FRQ # 482 GLOCodPhsBias glonassCodPhsBias; ///< GLONASS COD/PHS/BIS 483 int leapSeconds; ///< LEAP SECONDS 484 short numSVs; ///< # OF SATELLITES 485 PRNNumObsMap numObsForSat; ///< PRN / # OF OBS 486 487 488 /// number & types of observations R2 only 489 ///@bug this is being used but is not actually being filled 490 RinexObsVec obsTypeList; 491 492 /// bits set when header rec.s present & valid 493 Fields valid; 494 /// true if found END OF HEADER 495 bool validEoH; 496 /// Map P to Y code observations in RINEX 2 files 497 bool PisY; 498 499 /// Used to help debug this class 500 static int debug; 501 502 /// Destructor ~Rinex3ObsHeader()503 virtual ~Rinex3ObsHeader() 504 {} 505 506 // The next four lines comprise our common interface. 507 508 /// Rinex3ObsHeader is a "header" so this function always 509 /// returns true. isHeader() const510 virtual bool isHeader() const 511 { return true; } 512 513 /** This is a debug output function which provides a lot of 514 * detail about the header contents, based on the value of \a 515 * version (RINEX format version). 516 */ dump(std::ostream & s) const517 virtual void dump(std::ostream& s) const 518 { dump(s, version); } 519 520 /** This is a debug output function which provides a lot of 521 * detail about the header contents for a specified RINEX 522 * format version. 523 * @param[in] dumpVersion The RINEX format version to use 524 * when dumping the contents of this header. Potentially 525 * affects the representation of obs IDs, as well as which 526 * header fields are printed. 527 */ 528 void dump(std::ostream& s, double dumpVersion) const; 529 530 /** This method returns the numerical index of a given observation 531 * 532 * @param[in] type String representing the observation type. 533 * @throw InvalidRequest 534 */ 535 virtual std::size_t getObsIndex(const std::string& type ) const; 536 537 /** This method returns the numerical index of a given observation 538 * 539 * @param[in] sys GNSS system character for the obs 540 * @param[in] obsID RinexObsID of the observation 541 * @throw InvalidRequest 542 */ 543 virtual std::size_t getObsIndex(const std::string& sys, 544 const RinexObsID& obsID ) const; 545 546 /** Parse a single header record, and modify valid 547 * accordingly. Used by reallyGetRecord for both 548 * Rinex3ObsHeader and Rinex3ObsData. 549 * @throw FFStreamError 550 */ 551 void parseHeaderRecord(std::string& line); 552 553 /** Compute number of valid header records that 554 * writeHeaderRecords() will write */ 555 int numberHeaderRecordsToBeWritten(void) const throw(); 556 557 /** Write all valid header records to the given stream. Used 558 * by reallyPutRecord for both Rinex3ObsHeader and 559 * Rinex3ObsData. 560 * @throw FFStreamError 561 * @throw StringUtils::StringException 562 */ 563 void writeHeaderRecords(FFStream& s) const; 564 565 /// Return boolean : is this a valid Rinex header? isValid() const566 bool isValid() const 567 { return (validEoH && Fields::isValid(version, valid)); } 568 569 /** Compute map of obs types for use in writing version 2 570 * header and data */ 571 void prepareVer2Write(void); 572 573 /** Compare this header with another. 574 * @param[in] right the header to compare this with. 575 * @param[out] diffs The header strings/identifiers that are 576 * different between this and right. 577 * @param[in] inclExclList a list of header strings to be ignored 578 * or used when making the comparison (e.g. "RINEX VERSION / TYPE"). 579 * @param[in] incl When true, only header lines listed in 580 * inclExclList will be compared. When false, differences in 581 * header lines in inclExclList will be ignored. 582 * @return true if this and right match given the 583 * included/excluded headers. */ 584 bool compare(const Rinex3ObsHeader& right, 585 StringVec& diffs, 586 const StringVec& inclExclList, 587 bool incl = false); 588 589 /// Return the RINEX header label for the given field enumeration. 590 static std::string asString(Field b); 591 /// Convert a RINEX header field label string into its matching enum. 592 static Field asField(const std::string& s); 593 594 /// Setter method for convenience of python bindings setWavelengthFactor(short wf1,short wf2)595 Rinex3ObsHeader& setWavelengthFactor(short wf1, short wf2) 596 { 597 wavelengthFactor[0] = wf1; 598 wavelengthFactor[1] = wf2; 599 return *this; 600 } 601 /// @copydoc ExtraWaveFact::getWavelengthFactor1() getWavelengthFactor1()602 short getWavelengthFactor1() 603 { return wavelengthFactor[0]; } 604 /// @copydoc ExtraWaveFact::getWavelengthFactor1() getWavelengthFactor2()605 short getWavelengthFactor2() 606 { return wavelengthFactor[1]; } 607 608 protected: 609 610 611 /** outputs this record to the stream correctly formatted. 612 * @throw std::exception 613 * @throw FFStreamError 614 * @throw StringUtils::StringException 615 */ 616 virtual void reallyPutRecord(FFStream& s) const; 617 618 /** This function retrieves the RINEX Header from the given FFStream. 619 * If an stream error is encountered, the stream is reset to its 620 * original position and its fail-bit is set. 621 * @throw std::exception 622 * @throw StringException when a StringUtils function fails 623 * @throw FFStreamError when exceptions(failbit) is set and 624 * a read or formatting error occurs. This also resets the 625 * stream to its pre-read position. */ 626 virtual void reallyGetRecord(FFStream& s); 627 628 629 /** Helper methods 630 * The conversion between RINEX v2.11 to RINEX v3 observation 631 * type is fraught with system-specific idiosyncracies. These 632 * methods read the list of v2.11 obs types stored in R2ObsTypes 633 * and attempt to build a corresponding list of v3 observation 634 * types where appropriate. 635 * @throw FFStreamError */ 636 std::vector<RinexObsID> mapR2ObsToR3Obs_G(); 637 std::vector<RinexObsID> mapR2ObsToR3Obs_R(); 638 std::vector<RinexObsID> mapR2ObsToR3Obs_E(); 639 std::vector<RinexObsID> mapR2ObsToR3Obs_S(); 640 641 /** Because of how pseudo-observables are handled, we need 642 * this function to remap the contents of mapObsTypes such 643 * that ionospheric delay and channel pseudo-observables get 644 * the treatment they need. */ 645 void remapObsTypes(RinexObsMap& remapped, 646 std::map<std::string,unsigned>& obsCount) 647 const; 648 649 friend class Rinex3ObsData; 650 651 652 private: 653 654 /** Converts the daytime \a dt into a Rinex Obs time 655 * string for the header */ 656 std::string writeTime(const CivilTime& civtime) const; 657 658 /** This function sets the time for this header. 659 * It looks at \a line to obtain the needed information. */ 660 CivilTime parseTime(const std::string& line) const; 661 662 /// save ObsID for cont. "PHASE SHIFT" R3.01 663 RinexObsID sysPhaseShiftObsID; 664 /// save the syschar while reading ScaleFactor 665 std::string satSysTemp; 666 /// recall the prev sat. sys for continuation lines. 667 std::string satSysPrev; 668 /// save OBS # / TYPES and Sys / SCALE FACTOR for continuation lines. 669 int numObs; 670 /// recall the prev # obs for cont. lines 671 int numObsPrev; 672 /// save PRN while reading PRN/OBS cont. lines 673 RinexSatID lastPRN; 674 /// Scale factor holding data for continuation lines. 675 int factor, factorPrev; 676 677 }; // end class Rinex3ObsHeader 678 679 std::ostream& operator<<(std::ostream& s, const Rinex3ObsHeader::Fields& v); 680 681 //@} 682 683 } // namespace 684 685 #endif // GPSTK_RINEX3OBSHEADER_HPP 686