RinexObsHeader.cpp
Go to the documentation of this file.
1 //==============================================================================
2 //
3 // This file is part of GNSSTk, the ARL:UT GNSS Toolkit.
4 //
5 // The GNSSTk 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 GNSSTk 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 GNSSTk; 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-2022, 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 
44 #include "StringUtils.hpp"
45 #include "RinexObsHeader.hpp"
46 #include "RinexObsStream.hpp"
47 #include "CivilTime.hpp"
48 #include "SystemTime.hpp"
49 
50 using namespace std;
51 using namespace gnsstk::StringUtils;
52 
53 namespace gnsstk
54 {
55  const string RinexObsHeader::versionString = "RINEX VERSION / TYPE";
56  const string RinexObsHeader::runByString = "PGM / RUN BY / DATE";
57  const string RinexObsHeader::commentString = "COMMENT";
58  const string RinexObsHeader::markerNameString = "MARKER NAME";
59  const string RinexObsHeader::markerNumberString = "MARKER NUMBER";
60  const string RinexObsHeader::observerString = "OBSERVER / AGENCY";
61  const string RinexObsHeader::receiverString = "REC # / TYPE / VERS";
62  const string RinexObsHeader::antennaTypeString = "ANT # / TYPE";
63  const string RinexObsHeader::antennaPositionString = "APPROX POSITION XYZ";
64  const string RinexObsHeader::antennaOffsetString = "ANTENNA: DELTA H/E/N";
65  const string RinexObsHeader::waveFactString = "WAVELENGTH FACT L1/2";
66  const string RinexObsHeader::numObsString = "# / TYPES OF OBSERV";
67  const string RinexObsHeader::intervalString = "INTERVAL";
68  const string RinexObsHeader::firstTimeString = "TIME OF FIRST OBS";
69  const string RinexObsHeader::lastTimeString = "TIME OF LAST OBS";
70  const string RinexObsHeader::receiverOffsetString = "RCV CLOCK OFFS APPL";
71  const string RinexObsHeader::leapSecondsString = "LEAP SECONDS";
72  const string RinexObsHeader::numSatsString = "# OF SATELLITES";
73  const string RinexObsHeader::prnObsString = "PRN / # OF OBS";
74  const string RinexObsHeader::endOfHeader = "END OF HEADER";
75 
76  const unsigned int RinexObsType::C1depend=0x01;
77  const unsigned int RinexObsType::L1depend=0x02;
78  const unsigned int RinexObsType::L2depend=0x04;
79  const unsigned int RinexObsType::P1depend=0x08;
80  const unsigned int RinexObsType::P2depend=0x10;
81  const unsigned int RinexObsType::EPdepend=0x20;
82  const unsigned int RinexObsType::PSdepend=0x40;
83 
84  const RinexObsType RinexObsHeader::UN("UN", "Unknown or Invalid", "unknown", 0);
85  const RinexObsType RinexObsHeader::L1("L1", "L1 Carrier Phase", "L1 cycles",
86  RinexObsType::L1depend);
87  const RinexObsType RinexObsHeader::L2("L2", "L2 Carrier Phase", "L2 cycles",
88  RinexObsType::L2depend);
89  const RinexObsType RinexObsHeader::C1("C1", "C/A-code pseudorange", "meters",
90  RinexObsType::C1depend);
91  const RinexObsType RinexObsHeader::C2("C2", "L2C-code pseudorange", "meters", 0);
92  const RinexObsType RinexObsHeader::P1("P1", "Pcode L1 pseudorange", "meters",
93  RinexObsType::P1depend);
94  const RinexObsType RinexObsHeader::P2("P2", "Pcode L2 pseudorange", "meters",
95  RinexObsType::P2depend);
96  const RinexObsType RinexObsHeader::D1("D1", "Doppler Frequency L1", "Hz", 0);
97  const RinexObsType RinexObsHeader::D2("D2", "Doppler Frequency L2", "Hz", 0);
98  const RinexObsType RinexObsHeader::S1("S1", "Signal-to-Noise L1", "dB-Hz", 0);
99  const RinexObsType RinexObsHeader::S2("S2", "Signal-to-Noise L2", "dB-Hz", 0);
100  const RinexObsType RinexObsHeader::T1("T1", "Transit 150 MHz", "meters", 0);
101  const RinexObsType RinexObsHeader::T2("T2", "Transit 400 MHz", "meters", 0);
102  // v 2.11
103  const RinexObsType RinexObsHeader::C5("C5", "L5C-code pseudorange", "meters", 0);
104  const RinexObsType RinexObsHeader::L5("L5", "L5 Carrier Phase", "L5 cycles", 0);
105  const RinexObsType RinexObsHeader::D5("D5", "Doppler Frequency L5", "Hz", 0);
106  const RinexObsType RinexObsHeader::S5("S5", "Signal-to-Noise L5", "dB-Hz", 0);
107  // Galileo only
108  const RinexObsType RinexObsHeader::C6("C6", "E6-code pseudorange", "meters", 0);
109  const RinexObsType RinexObsHeader::L6("L6", "E6 Carrier Phase", "L6 cycles", 0);
110  const RinexObsType RinexObsHeader::D6("D6", "Doppler Frequency E6", "Hz", 0);
111  const RinexObsType RinexObsHeader::S6("S6", "Signal-to-Noise E6", "dB-Hz", 0);
112 
113  const RinexObsType RinexObsHeader::C7("C7", "E5b-code pseudorange", "meters", 0);
114  const RinexObsType RinexObsHeader::L7("L7", "E5b Carrier Phase", "L7 cycles", 0);
115  const RinexObsType RinexObsHeader::D7("D7", "Doppler Frequency E5b", "Hz", 0);
116  const RinexObsType RinexObsHeader::S7("S7", "Signal-to-Noise E5b", "dB-Hz", 0);
117 
118  const RinexObsType RinexObsHeader::C8("C8", "E5a+b-code pseudorange", "meters", 0);
119  const RinexObsType RinexObsHeader::L8("L8", "E5a+b Carrier Phase", "L8 cycles", 0);
120  const RinexObsType RinexObsHeader::D8("D8", "Doppler Frequency E5a+b","Hz", 0);
121  const RinexObsType RinexObsHeader::S8("S8", "Signal-to-Noise E5a+b", "dB-Hz", 0);
122 
124  {
125  RinexObsHeader::UN,
127  RinexObsHeader::C1, RinexObsHeader::C2,
129  RinexObsHeader::D1, RinexObsHeader::D2,
130  RinexObsHeader::S1, RinexObsHeader::S2,
131  RinexObsHeader::T1, RinexObsHeader::T2,
132  RinexObsHeader::C5, RinexObsHeader::L5, RinexObsHeader::D5, RinexObsHeader::S5,
133  RinexObsHeader::C6, RinexObsHeader::L6, RinexObsHeader::D6, RinexObsHeader::S6,
134  RinexObsHeader::C7, RinexObsHeader::L7, RinexObsHeader::D7, RinexObsHeader::S7,
135  RinexObsHeader::C8, RinexObsHeader::L8, RinexObsHeader::D8, RinexObsHeader::S8
136  };
137 
138  // Warning: the size of the above sot array needs to be put
139  // in this initializer.
140  const std::vector<RinexObsType> RinexObsHeader::StandardRinexObsTypes(sot,sot+29);
141 
142  std::vector<RinexObsType> RinexObsHeader::RegisteredRinexObsTypes
143  = RinexObsHeader::StandardRinexObsTypes;
144 
145  void RinexObsHeader::reallyPutRecord(FFStream& ffs) const
146  {
147  RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
148 
149  strm.header = *this;
150 
151  unsigned long allValid = 0;
152  if (version == 2.0) allValid = allValid20;
153  else if (version == 2.1) allValid = allValid21;
154  else if (version == 2.11) allValid = allValid211;
155  else
156  {
157  FFStreamError err("Unknown RINEX version: " + asString(version,2));
158  err.addText("Make sure to set the version correctly.");
159  GNSSTK_THROW(err);
160  }
161 
162  if ((valid & allValid) != allValid)
163  {
164  FFStreamError err("Incomplete or invalid header.");
165  err.addText("Make sure you set all header valid bits for all of the available data.");
166  GNSSTK_THROW(err);
167  }
168 
169  try
170  {
171  WriteHeaderRecords(strm);
172  }
173  catch(FFStreamError& e)
174  {
175  GNSSTK_RETHROW(e);
176  }
177  catch(StringException& e)
178  {
179  GNSSTK_RETHROW(e);
180  }
181 
182  } // end RinexObsHeader::reallyPutRecord
183 
184 
185  // this function computes the number of valid header records which WriteHeaderRecords will write
186  int RinexObsHeader::NumberHeaderRecordsToBeWritten(void) const noexcept
187  {
188  int n=0;
189  if(valid & RinexObsHeader::versionValid) n++;
190  if(valid & RinexObsHeader::runByValid) n++;
191  if(valid & RinexObsHeader::markerNameValid) n++;
192  if(valid & RinexObsHeader::observerValid) n++;
193  if(valid & RinexObsHeader::receiverValid) n++;
194  if(valid & RinexObsHeader::antennaTypeValid) n++;
195  if(valid & RinexObsHeader::antennaPositionValid) n++;
196  if(valid & RinexObsHeader::antennaOffsetValid) n++;
197  if(valid & RinexObsHeader::waveFactValid) {
198  n++;
199  if(extraWaveFactList.size()) n += 1 + (extraWaveFactList.size()-1)/7;
200  }
201  if(valid & RinexObsHeader::obsTypeValid) n += 1 + (obsTypeList.size()-1)/9;
202  if(valid & RinexObsHeader::intervalValid) n++;
203  if(valid & RinexObsHeader::firstTimeValid) n++;
204  if(valid & RinexObsHeader::lastTimeValid) n++;
205  if(valid & RinexObsHeader::markerNumberValid) n++;
206  if(valid & RinexObsHeader::receiverOffsetValid) n++;
207  if(valid & RinexObsHeader::leapSecondsValid) n++;
208  if(valid & RinexObsHeader::commentValid) n += commentList.size();
209  if(valid & RinexObsHeader::numSatsValid) n++;
210  if(valid & RinexObsHeader::prnObsValid)
211  n += numObsForSat.size() * (1+numObsForSat.begin()->second.size()/9);
212  if(valid & RinexObsHeader::endValid) n++;
213  return n;
214  }
215 
216  // this function writes all valid header records
217  void RinexObsHeader::WriteHeaderRecords(FFStream& ffs) const
218  {
219  RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
220  string line;
221  if (valid & versionValid)
222  {
223  line = rightJustify(asString(version,2), 9);
224  line += string(11, ' ');
225  if ((fileType[0] != 'O') && (fileType[0] != 'o'))
226  {
227  FFStreamError err("This isn't a Rinex Observation file: " +
228  fileType.substr(0,1));
229  GNSSTK_THROW(err);
230  }
231 
232  if (system.system == SatelliteSystem::Unknown)
233  {
234  FFStreamError err("Invalid satellite system");
235  GNSSTK_THROW(err);
236  }
237 
238  line += leftJustify(string("Observation"), 20);
239  std::string str;
240  str = system.systemChar();
241  str = str + " (" + system.systemString() + ")";
242  line += leftJustify(str, 20);
243  line += versionString;
244  strm << line << endl;
245  strm.lineNumber++;
246  }
247  if (valid & runByValid)
248  {
249  line = leftJustify(fileProgram,20);
250  line += leftJustify(fileAgency,20);
251  CommonTime dt;
252  SystemTime sysTime;
253  string dat = (static_cast<CivilTime>(sysTime)).printf("%04Y%02m%02d %02H%02M%02S %P");
254  line += leftJustify(dat, 20);
255  line += runByString;
256  strm << line << endl;
257  strm.lineNumber++;
258  }
259  if (valid & markerNameValid)
260  {
261  line = leftJustify(markerName, 60);
262  line += markerNameString;
263  strm << line << endl;
264  strm.lineNumber++;
265  }
266  if (valid & observerValid)
267  {
268  line = leftJustify(observer, 20);
269  line += leftJustify(agency, 40);
270  line += observerString;
271  strm << line << endl;
272  strm.lineNumber++;
273  }
274  if (valid & receiverValid)
275  {
276  line = leftJustify(recNo, 20);
277  line += leftJustify(recType, 20);
278  line += leftJustify(recVers, 20);
279  line += receiverString;
280  strm << line << endl;
281  strm.lineNumber++;
282  }
283  if (valid & antennaTypeValid)
284  {
285  line = leftJustify(antNo, 20);
286  line += leftJustify(antType, 20);
287  line += string(20, ' ');
288  line += antennaTypeString;
289  strm << line << endl;
290  strm.lineNumber++;
291  }
292  if (valid & antennaPositionValid)
293  {
294  line = rightJustify(asString(antennaPosition[0], 4), 14);
295  line += rightJustify(asString(antennaPosition[1], 4), 14);
296  line += rightJustify(asString(antennaPosition[2], 4), 14);
297  line += string(18, ' ');
298  line += antennaPositionString;
299  strm << line << endl;
300  strm.lineNumber++;
301  }
302  if (valid & antennaOffsetValid)
303  {
304  line = rightJustify(asString(antennaOffset[0], 4), 14);
305  line += rightJustify(asString(antennaOffset[1], 4), 14);
306  line += rightJustify(asString(antennaOffset[2], 4), 14);
307  line += string(18, ' ');
308  line += antennaOffsetString;
309  strm << line << endl;
310  strm.lineNumber++;
311  }
312  if (valid & waveFactValid)
313  {
314  line = rightJustify(asString<short>(wavelengthFactor[0]),6);
315  line += rightJustify(asString<short>(wavelengthFactor[1]),6);
316  line += string(48, ' ');
317  line += waveFactString;
318  strm << line << endl;
319  strm.lineNumber++;
320 
321  // handle continuation lines
322  if (!extraWaveFactList.empty())
323  {
324  vector<ExtraWaveFact>::const_iterator itr = extraWaveFactList.begin();
325 
326  while (itr != extraWaveFactList.end())
327  {
328  const int maxSatsPerLine = 7;
329  short satsWritten = 0, satsLeft = (*itr).satList.size(), satsThisLine;
330  vector<SatID>::const_iterator vecItr = (*itr).satList.begin();
331 
332  while ((vecItr != (*itr).satList.end())) {
333  if(satsWritten == 0) {
334  line = rightJustify(asString<short>((*itr).wavelengthFactor[0]),6);
335  line += rightJustify(asString<short>((*itr).wavelengthFactor[1]),6);
336  satsThisLine = (satsLeft > maxSatsPerLine ? maxSatsPerLine : satsLeft);
337  line += rightJustify(asString<short>(satsThisLine),6);
338  }
339  try {
340  line += string(3, ' ') + RinexSatID(*vecItr).toString();
341  }
342  catch (Exception& e) {
343  FFStreamError ffse(e);
344  GNSSTK_THROW(ffse);
345  }
346  satsWritten++;
347  satsLeft--;
348  if(satsWritten==maxSatsPerLine || satsLeft==0) { // output a complete line
349  line += string(60 - line.size(), ' ');
350  line += waveFactString;
351  strm << line << endl;
352  strm.lineNumber++;
353  satsWritten = 0;
354  }
355  vecItr++;
356  }
357  itr++;
358  }
359  }
360  }
361  if (valid & obsTypeValid)
362  {
363  const int maxObsPerLine = 9;
364  int obsWritten = 0;
365  line = ""; // make sure the line contents are reset.
366 
367  vector<RinexObsType>::const_iterator itr = obsTypeList.begin();
368 
369  while (itr != obsTypeList.end())
370  {
371  // the first line needs to have the # of obs
372  if (obsWritten == 0)
373  line = rightJustify(asString(obsTypeList.size()), 6);
374  // if you hit 9, write out the line and start a new one
375  else if ((obsWritten % maxObsPerLine) == 0)
376  {
377  line += numObsString;
378  strm << line << endl;
379  strm.lineNumber++;
380  line = string(6, ' ');
381  }
382  line += rightJustify(convertObsType(*itr), 6);
383  obsWritten++;
384  itr++;
385  }
386  line += string(60 - line.size(), ' ');
387  line += numObsString;
388  strm << line << endl;
389  strm.lineNumber++;
390  }
391  if (valid & intervalValid)
392  {
393  line = rightJustify(asString(interval, 3), 10);
394  line += string(50, ' ');
395  line += intervalString;
396  strm << line << endl;
397  strm.lineNumber++;
398  }
399  if (valid & firstTimeValid)
400  {
401  line = writeTime(firstObs);
402  line += string(48-line.size(),' ');
403  if(firstSystem.system == SatelliteSystem::GPS) line += "GPS";
404  if(firstSystem.system == SatelliteSystem::Glonass) line += "GLO";
405  if(firstSystem.system == SatelliteSystem::Galileo) line += "GAL";
406  line += string(60 - line.size(), ' ');
407  line += firstTimeString;
408  strm << line << endl;
409  strm.lineNumber++;
410  }
411  if (valid & lastTimeValid)
412  {
413  line = writeTime(lastObs);
414  line += string(48-line.size(),' ');
415  if(lastSystem.system == SatelliteSystem::GPS) line += "GPS";
416  if(lastSystem.system == SatelliteSystem::Glonass) line += "GLO";
417  if(lastSystem.system == SatelliteSystem::Galileo) line += "GAL";
418  line += string(60 - line.size(), ' ');
419  line += lastTimeString;
420  strm << line << endl;
421  strm.lineNumber++;
422  }
423  if (valid & markerNumberValid)
424  {
425  line = leftJustify(markerNumber, 20);
426  line += string(40, ' ');
427  line += markerNumberString;
428  strm << line << endl;
429  strm.lineNumber++;
430  }
431  if (valid & receiverOffsetValid)
432  {
433  line = rightJustify(asString(receiverOffset),6);
434  line += string(54, ' ');
435  line += receiverOffsetString;
436  strm << line << endl;
437  strm.lineNumber++;
438  }
439  if (valid & leapSecondsValid)
440  {
441  line = rightJustify(asString(leapSeconds),6);
442  line += string(54, ' ');
443  line += leapSecondsString;
444  strm << line << endl;
445  strm.lineNumber++;
446  }
447  if (valid & commentValid)
448  {
449  vector<string>::const_iterator itr = commentList.begin();
450  while (itr != commentList.end())
451  {
452  line = leftJustify((*itr), 60);
453  line += commentString;
454  strm << line << endl;
455  strm.lineNumber++;
456  itr++;
457  }
458  }
459  if (valid & numSatsValid)
460  {
461  line = rightJustify(asString(numSVs), 6);
462  line += string(54, ' ');
463  line += numSatsString;
464  strm << line << endl;
465  strm.lineNumber++;
466  }
467  if (valid & prnObsValid)
468  {
469  const int maxObsPerLine = 9;
470  map<SatID, vector<int> >::const_iterator itr = numObsForSat.begin();
471  while (itr != numObsForSat.end())
472  {
473  int numObsWritten = 0;
474 
475  vector<int>::const_iterator vecItr = (*itr).second.begin();
476  while (vecItr != (*itr).second.end())
477  {
478  if (numObsWritten == 0)
479  {
480  try {
481  RinexSatID prn((*itr).first);
482  line = string(3, ' ') + prn.toString();
483  }
484  catch (Exception& e) {
485  FFStreamError ffse(e);
486  GNSSTK_RETHROW(ffse);
487  }
488  }
489  else if ((numObsWritten % maxObsPerLine) == 0)
490  {
491  line += prnObsString;
492  strm << line << endl;
493  strm.lineNumber++;
494  line = string(6, ' ');
495  }
496  line += rightJustify(asString(*vecItr), 6);
497  ++vecItr;
498  ++numObsWritten;
499  }
500  line += string(60 - line.size(), ' ');
501  line += prnObsString;
502  strm << line << endl;
503  strm.lineNumber++;
504  itr++;
505  }
506  }
507  if (valid & endValid)
508  {
509  line = string(60, ' ');
510  line += endOfHeader;
511  strm << line << endl;
512  strm.lineNumber++;
513  }
514  } // end RinexObsHeader::WriteHeaderRecords()
515 
516 
517  // this function parses a single header record
518  void RinexObsHeader::ParseHeaderRecord(string& line)
519  {
520  string label(line, 60, 20);
521 
522  if (label == versionString)
523  {
524  version = asDouble(line.substr(0,20));
525 // cout << "R2ObsHeader:ParseHeaderRecord:version = " << version << endl;
526  fileType = strip(line.substr(20, 20));
527  if ( (fileType[0] != 'O') &&
528  (fileType[0] != 'o'))
529  {
530  FFStreamError e("This isn't a Rinex Obs file");
531  GNSSTK_THROW(e);
532  }
533  string system_str = strip(line.substr(40, 20));
534  try {
535  system.fromString(system_str);
536  }
537  catch (Exception& e)
538  {
539  FFStreamError ffse("Input satellite system is unsupported: " + system_str);
540  GNSSTK_THROW(ffse);
541  }
542  valid |= versionValid;
543  }
544  else if (label == runByString )
545  {
546  fileProgram = strip(line.substr(0, 20));
547  fileAgency = strip(line.substr(20, 20));
548  date = strip(line.substr(40, 20));
549  valid |= runByValid;
550  }
551  else if (label == commentString)
552  {
553  string s = strip(line.substr(0, 60));
554  commentList.push_back(s);
555  valid |= commentValid;
556  }
557  else if (label == markerNameString)
558  {
559  markerName = strip(line.substr(0,60));
560  valid |= markerNameValid;
561  }
562  else if (label == markerNumberString)
563  {
564  markerNumber = strip(line.substr(0,20));
565  valid |= markerNumberValid;
566  }
567  else if (label == observerString)
568  {
569  observer = strip(line.substr(0,20));
570  agency = strip(line.substr(20,40));
571  valid |= observerValid;
572  }
573  else if (label == receiverString)
574  {
575  recNo = strip(line.substr(0, 20));
576  recType = strip(line.substr(20,20));
577  recVers = strip(line.substr(40,20));
578  valid |= receiverValid;
579  }
580  else if (label ==antennaTypeString)
581  {
582  antNo = strip(line.substr(0, 20));
583  antType = strip(line.substr(20, 20));
584  valid |= antennaTypeValid;
585  }
586  else if (label == antennaPositionString)
587  {
588  antennaPosition[0] = asDouble(line.substr(0, 14));
589  antennaPosition[1] = asDouble(line.substr(14, 14));
590  antennaPosition[2] = asDouble(line.substr(28, 14));
591  valid |= antennaPositionValid;
592  }
593  else if (label == antennaOffsetString)
594  {
595  antennaOffset[0] = asDouble(line.substr(0, 14));
596  antennaOffset[1] = asDouble(line.substr(14, 14));
597  antennaOffset[2] = asDouble(line.substr(28, 14));
598  valid |= antennaOffsetValid;
599  }
600  else if (label == waveFactString)
601  {
602  // first time reading this
603  if (! (valid & waveFactValid))
604  {
605  wavelengthFactor[0] = asInt(line.substr(0,6));
606  wavelengthFactor[1] = asInt(line.substr(6,6));
607  valid |= waveFactValid;
608  }
609  // additional wave fact lines
610  else
611  {
612  const int maxSatsPerLine = 7;
613  int Nsats;
614  ExtraWaveFact ewf;
615  ewf.wavelengthFactor[0] = asInt(line.substr(0,6));
616  ewf.wavelengthFactor[1] = asInt(line.substr(6,6));
617  Nsats = asInt(line.substr(12,6));
618 
619  if (Nsats > maxSatsPerLine) // > not >=
620  {
621  FFStreamError e("Invalid number of Sats for " + waveFactString);
622  GNSSTK_THROW(e);
623  }
624 
625  for (int i = 0; i < Nsats; i++)
626  {
627  try {
628  RinexSatID prn(line.substr(21+i*6,3));
629  ewf.satList.push_back(prn);
630  }
631  catch (Exception& e){
632  FFStreamError ffse(e);
633  GNSSTK_RETHROW(ffse);
634  }
635  }
636 
637  extraWaveFactList.push_back(ewf);
638  }
639  }
640  else if (label == numObsString)
641  {
642  const int maxObsPerLine = 9;
643  // process the first line
644  if (! (valid & obsTypeValid))
645  {
646  numObs = asInt(line.substr(0,6));
647 
648  for (int i = 0; (i < numObs) && (i < maxObsPerLine); i++)
649  {
650  int position = i * 6 + 6 + 4;
651  RinexObsType rt = convertObsType(line.substr(position,2));
652  obsTypeList.push_back(rt);
653  }
654  valid |= obsTypeValid;
655  }
656  // process continuation lines
657  else
658  {
659  for (int j=0, i=obsTypeList.size();
660  (i < numObs) && (j < maxObsPerLine); i++)
661  {
662  int position = (i % maxObsPerLine) * 6 + 6 + 4;
663  RinexObsType rt = convertObsType(line.substr(position,2));
664  obsTypeList.push_back(rt);
665  j++;
666  }
667  }
668  }
669  else if (label == intervalString)
670  {
671  interval = asDouble(line.substr(0, 10));
672  valid |= intervalValid;
673  }
674  else if (label == firstTimeString)
675  {
676  firstObs = parseTime(line);
677  firstSystem.system = SatelliteSystem::GPS;
678  if(line.substr(48,3)=="GLO") firstSystem.system=SatelliteSystem::Glonass;
679  if(line.substr(48,3)=="GAL") firstSystem.system=SatelliteSystem::Galileo;
680  valid |= firstTimeValid;
681  }
682  else if (label == lastTimeString)
683  {
684  lastObs = parseTime(line);
685  lastSystem.system = SatelliteSystem::GPS;
686  if(line.substr(48,3)=="GLO") lastSystem.system=SatelliteSystem::Glonass;
687  if(line.substr(48,3)=="GAL") lastSystem.system=SatelliteSystem::Galileo;
688  valid |= lastTimeValid;
689  }
690  else if (label == receiverOffsetString)
691  {
692  receiverOffset = asInt(line.substr(0,6));
693  valid |= receiverOffsetValid;
694  }
695  else if (label == leapSecondsString)
696  {
697  leapSeconds = asInt(line.substr(0,6));
698  valid |= leapSecondsValid;
699  }
700  else if (label == numSatsString)
701  {
702  numSVs = asInt(line.substr(0,6)) ;
703  valid |= numSatsValid;
704  }
705  else if (label == prnObsString)
706  {
707  const int maxObsPerLine = 9;
708  // continuation lines... you have to know what PRN
709  // this is continuing for, hence lastPRN
710  if ((lastPRN.id != -1) &&
711  (numObsForSat[lastPRN].size() != obsTypeList.size()))
712  {
713  for(int i = numObsForSat[lastPRN].size();
714  (i < int(obsTypeList.size())) &&
715  ( (i % maxObsPerLine) < maxObsPerLine); i++)
716  {
717  numObsForSat[lastPRN].push_back(asInt(line.substr((i%maxObsPerLine)*6+6,6)));
718  }
719  }
720  else
721  {
722  try {
723  lastPRN.fromString(line.substr(3,3));
724  }
725  catch (Exception& e) {
726  FFStreamError ffse(e);
727  GNSSTK_RETHROW(ffse);
728  }
729  vector<int> numObsList;
730  for(int i = 0;
731  (i < int(obsTypeList.size())) && (i < maxObsPerLine); i++)
732  {
733  numObsList.push_back(asInt(line.substr(i*6+6,6)));
734  }
735 
736  numObsForSat[lastPRN] = numObsList;
737  }
738  valid |= prnObsValid;
739  }
740  else if (label == endOfHeader)
741  {
742  valid |= endValid;
743  }
744  else
745  {
746  FFStreamError e("Unidentified label: " + label);
747  GNSSTK_THROW(e);
748  }
749  } // end of RinexObsHeader::ParseHeaderRecord(string& line)
750 
751 
752  // This function parses the entire header from the given stream
753  void RinexObsHeader::reallyGetRecord(FFStream& ffs)
754  {
755  RinexObsStream& strm = dynamic_cast<RinexObsStream&>(ffs);
756 
757  // if already read, just return
758  if (strm.headerRead == true)
759  return;
760 
761  // since we're reading a new header, we need to reinitialize
762  // all our list structures. all the other objects should be ok.
763  // this also applies if we threw an exception the first time we read
764  // the header and are now re-reading it. some of these could be full
765  // and we need to empty them.
766  commentList.clear();
767  wavelengthFactor[0] = wavelengthFactor[1] = 1;
768  extraWaveFactList.clear();
769  obsTypeList.clear();
770  numObsForSat.clear();
771  valid = 0;
772  numObs = 0;
773  lastPRN.id = -1;
774 
775  string line;
776 
777  while (!(valid & endValid))
778  {
779  strm.formattedGetLine(line);
781 
782  if (line.length()==0)
783  {
784  FFStreamError e("No data read");
785  GNSSTK_THROW(e);
786  }
787  else if (line.length()<60 || line.length()>80)
788  {
789  FFStreamError e("Invalid line length");
790  GNSSTK_THROW(e);
791  }
792 
793  try
794  {
795  ParseHeaderRecord(line);
796  }
797  catch(FFStreamError& e)
798  {
799  GNSSTK_RETHROW(e);
800  }
801 
802  } // end while(not end of header)
803 
804  unsigned long allValid;
805  if (version == 2.0) allValid = allValid20;
806  else if (version == 2.1) allValid = allValid21;
807  else if (version == 2.11) allValid = allValid211;
808  else
809  {
810  FFStreamError e("Unknown or unsupported RINEX version " +
811  asString(version));
812  GNSSTK_THROW(e);
813  }
814 
815  if ( (allValid & valid) != allValid)
816  {
817  FFStreamError e("Incomplete or invalid header");
818  GNSSTK_THROW(e);
819  }
820 
821  // If we get here, we should have reached the end of header line
822  strm.header = *this;
823  strm.headerRead = true;
824 
825  } // end of reallyGetRecord()
826 
827 
828 
830  RinexObsHeader::convertObsType(const std::string& oneObs)
831  {
832  RinexObsType ot(RegisteredRinexObsTypes[0]); // Unknown type
833  for(size_t i=0; i<RegisteredRinexObsTypes.size(); i++) {
834  if(RegisteredRinexObsTypes[i].type == oneObs) {
835  ot = RegisteredRinexObsTypes[i];
836  break;
837  }
838  //FFStreamError e("Bad obs type: " + oneObs);
839  //GNSSTK_THROW(e);
840  }
841  return ot;
842  }
843  string
844  RinexObsHeader::convertObsType(const RinexObsType& oneObs)
845  {
846  return oneObs.type;
847  }
848 
849 
850  CommonTime RinexObsHeader::parseTime(const string& line) const
851  {
852  int year, month, day, hour, min;
853  double sec;
854 
855  year = asInt( line.substr(0, 6 ));
856  month = asInt( line.substr(6, 6 ));
857  day = asInt( line.substr(12, 6 ));
858  hour = asInt( line.substr(18, 6 ));
859  min = asInt( line.substr(24, 6 ));
860  sec = asDouble(line.substr(30, 13));
861  return CivilTime(year, month, day, hour, min, sec).convertToCommonTime();
862  }
863 
864  string RinexObsHeader::writeTime(const CommonTime& dt) const
865  {
866  string line;
867  CivilTime civTime(dt);
868  line = rightJustify(asString<short>(civTime.year), 6);
869  line += rightJustify(asString<short>(civTime.month), 6);
870  line += rightJustify(asString<short>(civTime.day), 6);
871  line += rightJustify(asString<short>(civTime.hour), 6);
872  line += rightJustify(asString<short>(civTime.minute), 6);
873  line += rightJustify(asString(civTime.second, 7), 13);
874  return line;
875  }
876 
877  void RinexObsHeader::dump(ostream& s) const
878  {
879  size_t i,j;
880  s << "---------------------------------- REQUIRED ----------------------------------\n";
881  string str;
882  str = system.systemChar();
883  str = str + " (" + system.systemString() + ")";
884  s << "Rinex Version " << fixed << setw(5) << setprecision(2) << version
885  << ", File type " << fileType << ", System " << str << ".\n";
886  s << "Prgm: " << fileProgram << ", Run: " << date << ", By: " << fileAgency << endl;
887  s << "Marker name: " << markerName << ".\n";
888  s << "Obs'r : " << observer << ", Agency: " << agency << endl;
889  s << "Rec#: " << recNo << ", Type: " << recType << ", Vers: " << recVers << endl;
890  s << "Antenna # : " << antNo << ", Type : " << antType << endl;
891  s << "Position (XYZ,m) : " << setprecision(4) << antennaPosition << ".\n";
892  s << "Antenna offset (ENU,m) : " << setprecision(4) << antennaOffset << ".\n";
893  s << "Wavelength factors (default) L1:" << wavelengthFactor[0]
894  << ", L2: " << wavelengthFactor[1] << ".\n";
895  for(i=0; i<extraWaveFactList.size(); i++) {
896  s << "Wavelength factors (extra) L1:"
897  << extraWaveFactList[i].wavelengthFactor[0]
898  << ", L2: " << extraWaveFactList[i].wavelengthFactor[1]
899  << ", for Sats";
900  for(j=0; j<extraWaveFactList[i].satList.size(); j++)
901  s << " " << extraWaveFactList[i].satList[j];
902  s << endl;
903  }
904  s << "Observation types (" << obsTypeList.size() << ") :\n";
905  for(i=0; i<obsTypeList.size(); i++)
906  s << " Type #" << i << " = "
907  << gnsstk::RinexObsHeader::convertObsType(obsTypeList[i])
908  << " " << obsTypeList[i].description
909  << " (" << obsTypeList[i].units << ")." << endl;
910  s << "Time of first obs " << (static_cast<CivilTime>(firstObs)).printf("%04Y/%02m/%02d %02H:%02M:%010.7f")
911  << " " << (firstSystem.system==SatelliteSystem::Glonass ? "GLO" :
912  (firstSystem.system==SatelliteSystem::Galileo ? "GAL" : "GPS")) << endl;
913  s << "(This header is ";
914  if((valid & allValid211) == allValid211) s << "VALID 2.11";
915  else if((valid & allValid21) == allValid21) s << "VALID 2.1";
916  else if((valid & allValid20) == allValid20) s << "VALID 2.0";
917  else s << "NOT VALID";
918  s << " Rinex.)\n";
919 
920  if(!(valid & versionValid)) s << " Version is NOT valid\n";
921  if(!(valid & runByValid)) s << " Run by is NOT valid\n";
922  if(!(valid & markerNameValid)) s << " Marker Name is NOT valid\n";
923  if(!(valid & observerValid)) s << " Observer is NOT valid\n";
924  if(!(valid & receiverValid)) s << " Receiver is NOT valid\n";
925  if(!(valid & antennaTypeValid)) s << " Antenna Type is NOT valid\n";
926  if(!(valid & antennaPositionValid)) s << " Ant Position is NOT valid\n";
927  if(!(valid & antennaOffsetValid)) s << " Antenna Offset is NOT valid\n";
928  if(!(valid & waveFactValid)) s << " Wavelength factor is NOT valid\n";
929  if(!(valid & obsTypeValid)) s << " Obs Type is NOT valid\n";
930  if(!(valid & firstTimeValid)) s << " First time is NOT valid\n";
931  if(!(valid & endValid)) s << " End is NOT valid\n";
932 
933  s << "---------------------------------- OPTIONAL ----------------------------------\n";
934  if(valid & markerNumberValid) s << "Marker number : " << markerNumber << endl;
935  if(valid & intervalValid) s << "Interval = "
936  << fixed << setw(7) << setprecision(3) << interval << endl;
937  if(valid & lastTimeValid) s << "Time of last obs "
938  << (static_cast<CivilTime>(lastObs)).printf("%04Y/%02m/%02d %02H:%02M:%010.7f")
939  << " " << (lastSystem.system==SatelliteSystem::Glonass ? "GLO":
940  (lastSystem.system==SatelliteSystem::Galileo ? "GAL" : "GPS")) << endl;
941  if(valid & leapSecondsValid) s << "Leap seconds: " << leapSeconds << endl;
942  if(valid & receiverOffsetValid) s << "Clock offset record is present and offsets "
943  << (receiverOffset?"ARE":"are NOT") << " applied." << endl;
944  if(valid & numSatsValid) s << "Number of Satellites with data : " << numSVs << endl;
945  if(valid & prnObsValid) {
946  s << "SAT ";
947  for(i=0; i<obsTypeList.size(); i++)
948  s << setw(7) << convertObsType(obsTypeList[i]);
949  s << endl;
950  map<SatID, vector<int> >::const_iterator sat_itr = numObsForSat.begin();
951  while (sat_itr != numObsForSat.end()) {
952  vector<int> obsvec=sat_itr->second;
953  s << " " << RinexSatID(sat_itr->first) << " ";
954  for(i=0; i<obsvec.size(); i++) s << " " << setw(6) << obsvec[i];
955  s << endl;
956  sat_itr++;
957  }
958  }
959  if(commentList.size() && !(valid & commentValid)) s << " Comment is NOT valid\n";
960  s << "Comments (" << commentList.size() << ") :\n";
961  for(i=0; i<commentList.size(); i++)
962  s << commentList[i] << endl;
963  s << "-------------------------------- END OF HEADER -------------------------------\n";
964  }
965 
966  // return 1 if type already defined,
967  // 0 if successful
968  // -1 if not successful - invalid input
969  int RegisterExtendedRinexObsType(string t, string d, string u, unsigned int dep)
970  {
971  if(t.empty()) return -1;
972  // throw if t="UN" ?
973  // check that it is not duplicated
974  for(size_t i=0; i<RinexObsHeader::RegisteredRinexObsTypes.size(); i++) {
975  if(RinexObsHeader::RegisteredRinexObsTypes[i].type == t) { return 1; }
976  }
977  RinexObsType ot;
978  if(t.size()>2) t.resize(2,' '); ot.type = stripTrailing(t);
979  if(d.size()>20) d.resize(20,' '); ot.description = stripTrailing(d);
980  if(u.size()>10) u.resize(10,' '); ot.units = stripTrailing(u);
981  ot.depend = dep;
982  RinexObsHeader::RegisteredRinexObsTypes.push_back(ot);
983  return 0;
984  }
985 
986  // Pretty print a list of standard Rinex observation types
988  {
989  s << "The list of standard Rinex obs types:\n";
990  s << " OT Description Units\n";
991  s << " -- -------------------- ---------\n";
992  for(size_t i=0; i<RinexObsHeader::StandardRinexObsTypes.size(); i++) {
993  string line;
994  line = string(" ")+RinexObsHeader::StandardRinexObsTypes[i].type;
995  line += leftJustify(string(" ")+RinexObsHeader::StandardRinexObsTypes[i].description,21);
996  line += leftJustify(string(" ")+RinexObsHeader::StandardRinexObsTypes[i].units,11);
997  s << line << endl;
998  }
999  }
1000 
1001  // Pretty print a list of registered extended Rinex observation types
1003  {
1004  s << "The list of available extended Rinex obs types:\n";
1005  s << " OT Description Units Required input (EP=ephemeris,PS=Rx Position)\n";
1006  s << " -- -------------------- --------- ------------------\n";
1007  for(size_t i=RinexObsHeader::StandardRinexObsTypes.size();
1008  i<RinexObsHeader::RegisteredRinexObsTypes.size(); i++) {
1009  string line;
1010  line = string(" ")+RinexObsHeader::RegisteredRinexObsTypes[i].type;
1011  line += leftJustify(string(" ")+RinexObsHeader::RegisteredRinexObsTypes[i].description,21);
1012  line += leftJustify(string(" ")+RinexObsHeader::RegisteredRinexObsTypes[i].units,11);
1013  for(int j=1; j<=6; j++) {
1014  if(j==3 || j==4) continue;
1015  if(RinexObsHeader::RegisteredRinexObsTypes[i].depend &
1016  RinexObsHeader::StandardRinexObsTypes[j].depend)
1017  line += string(" ")+RinexObsHeader::StandardRinexObsTypes[j].type;
1018  else line += string(" ");
1019  }
1020  if(RinexObsHeader::RegisteredRinexObsTypes[i].depend & RinexObsType::EPdepend)
1021  line += string(" EP"); else line += string(" ");
1022  if(RinexObsHeader::RegisteredRinexObsTypes[i].depend & RinexObsType::PSdepend)
1023  line += string(" PS"); else line += string(" ");
1024  s << line << endl;
1025  }
1026  }
1027 
1028 } // namespace gnsstk
gnsstk::RinexObsStream
Definition: RinexObsStream.hpp:67
gnsstk::ExtraWaveFact::wavelengthFactor
short wavelengthFactor[2]
vector of wavelength factor values
Definition: RinexObsHeader.hpp:97
gnsstk::dump
void dump(vector< SatPass > &SatPassList, ostream &os, bool rev, bool dbug)
Definition: SatPassUtilities.cpp:59
gnsstk::StringUtils::asInt
long asInt(const std::string &s)
Definition: StringUtils.hpp:713
gnsstk::RinexObsType::units
std::string units
10- char units (optional) e.g. "meters"
Definition: RinexObsHeader.hpp:71
example6.day
day
Definition: example6.py:66
gnsstk::ExtraWaveFact
RINEX 2 extra "WAVELENGTH FACT" lines.
Definition: RinexObsHeader.hpp:92
gnsstk::CivilTime::year
int year
Definition: CivilTime.hpp:198
L1
gnsstk::Matrix< double > L1
Definition: Matrix_LUDecomp_T.cpp:46
gnsstk::FFStream
Definition: FFStream.hpp:119
StringUtils.hpp
example6.year
year
Definition: example6.py:64
gnsstk::RinexObsType::depend
unsigned int depend
Definition: RinexObsHeader.hpp:72
example6.recNo
recNo
Definition: example6.py:29
example6.observer
observer
Definition: example6.py:25
gnsstk::FFTextStream::formattedGetLine
void formattedGetLine(std::string &line, const bool expectEOF=false)
Definition: FFTextStream.cpp:149
example6.antNo
antNo
Definition: example6.py:34
gnsstk::UnixTime::printf
virtual std::string printf(const std::string &fmt) const
Definition: UnixTime.cpp:105
gnsstk::DisplayStandardRinexObsTypes
void DisplayStandardRinexObsTypes(ostream &s)
Definition: RinexObsHeader.cpp:987
gnsstk::FFTextStream::lineNumber
unsigned int lineNumber
Definition: FFTextStream.hpp:98
example6.hour
hour
Definition: example6.py:67
RinexObsStream.hpp
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk::CivilTime::day
int day
Definition: CivilTime.hpp:200
example6.date
date
Definition: example6.py:18
example6.recType
recType
Definition: example6.py:30
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::RegisterExtendedRinexObsType
int RegisterExtendedRinexObsType(string t, string d, string u, unsigned int dep)
Definition: RinexObsHeader.cpp:969
P1
gnsstk::Matrix< double > P1
Definition: Matrix_LUDecomp_T.cpp:49
example6.antType
antType
Definition: example6.py:35
gnsstk::ExtraWaveFact::satList
std::vector< SatID > satList
List of Sats with this wavelength factor.
Definition: RinexObsHeader.hpp:95
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::StringUtils::stripTrailing
std::string & stripTrailing(std::string &s, const std::string &aString, std::string::size_type num=std::string::npos)
Definition: StringUtils.hpp:1453
gnsstk::CivilTime::convertToCommonTime
virtual CommonTime convertToCommonTime() const
Definition: CivilTime.cpp:75
example6.fileProgram
fileProgram
Definition: example6.py:17
gnsstk::RinexObsType::type
std::string type
2- char type e.g. L1, P2
Definition: RinexObsHeader.hpp:69
P2
gnsstk::Matrix< double > P2
Definition: Matrix_LUDecomp_T.cpp:49
example6.markerName
markerName
Definition: example6.py:22
SystemTime.hpp
gnsstk::DisplayExtendedRinexObsTypes
void DisplayExtendedRinexObsTypes(ostream &s)
Definition: RinexObsHeader.cpp:1002
example4.err
err
Definition: example4.py:126
gnsstk::RinexObsType
RINEX Observation Types.
Definition: RinexObsHeader.hpp:67
example6.agency
agency
Definition: example6.py:26
gnsstk::SystemTime
Definition: SystemTime.hpp:54
gnsstk::CommonTime
Definition: CommonTime.hpp:84
gnsstk::min
T min(const SparseMatrix< T > &SM)
Maximum element - return 0 if empty.
Definition: SparseMatrix.hpp:858
version
string version(string("2.4 9/23/15 rev"))
example6.valid
valid
Definition: example6.py:20
gnsstk::RinexObsHeader::convertObsType
static RinexObsType convertObsType(const std::string &oneObs)
Definition: RinexObsHeader.cpp:830
example6.firstObs
firstObs
Definition: example6.py:63
CivilTime.hpp
gnsstk::StringUtils::asDouble
double asDouble(const std::string &s)
Definition: StringUtils.hpp:705
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
example6.fileType
fileType
Definition: example6.py:15
example6.interval
interval
Definition: example6.py:75
gnsstk::CivilTime::minute
int minute
Definition: CivilTime.hpp:202
RinexObsHeader.hpp
gnsstk::CivilTime
Definition: CivilTime.hpp:55
gnsstk::StringUtils
Definition: IonexStoreStrategy.cpp:44
example6.recVers
recVers
Definition: example6.py:31
gnsstk::StringUtils::rightJustify
std::string & rightJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1557
gnsstk::RinexSatID::toString
std::string toString() const noexcept
Definition: RinexSatID.cpp:204
gnsstk::RinexSatID
Definition: RinexSatID.hpp:63
std
Definition: Angle.hpp:142
gnsstk::CivilTime::month
int month
Definition: CivilTime.hpp:199
example6.markerNumber
markerNumber
Definition: example6.py:72
example6.fileAgency
fileAgency
Definition: example6.py:19
gnsstk::sot
RinexObsType sot[29]
Definition: RinexObsHeader.cpp:123
gnsstk::CivilTime::second
double second
Definition: CivilTime.hpp:203
gnsstk::StringUtils::strip
std::string & strip(std::string &s, const std::string &aString, std::string::size_type num=std::string::npos)
Definition: StringUtils.hpp:1482
gnsstk::StringUtils::leftJustify
std::string & leftJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1582
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
example6.month
month
Definition: example6.py:65
example6.antennaPosition
antennaPosition
Definition: example6.py:39
gnsstk::RinexObsType::description
std::string description
20- char description (optional) e.g. "L1 pseudorange"
Definition: RinexObsHeader.hpp:70
gnsstk::RinexObsStream::header
RinexObsHeader header
The header for this file.
Definition: RinexObsStream.hpp:112
gnsstk::RinexObsStream::headerRead
bool headerRead
Whether or not the RinexObsHeader has been read.
Definition: RinexObsStream.hpp:109
L2
gnsstk::Matrix< double > L2
Definition: Matrix_LUDecomp_T.cpp:46
example6.numSVs
numSVs
Definition: example6.py:112
gnsstk::CivilTime::hour
int hour
Definition: CivilTime.hpp:201


gnsstk
Author(s):
autogenerated on Wed Oct 25 2023 02:40:41