SP3Header.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 "SP3Stream.hpp"
46 #include "SP3Header.hpp"
47 #include "CivilTime.hpp"
48 #include "MJD.hpp"
49 #include "GPSWeekSecond.hpp"
50 
51 #define debug false
52 
53 namespace gnsstk
54 {
55  using namespace StringUtils;
56  using namespace std;
57 
59  {
60  SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);
61 
62  string line;
63  strm.formattedGetLine(line);
64  if(debug) std::cout << "SP3 Header Line 1 " << line << std::endl;
65 
66  if (line[0]=='#' && line[1]!='#') // line 1
67  {
68  // version character
69  if(line[1] == 'a') version = SP3a;
70  else if(line[1] == 'b') version = SP3b;
71  else if(line[1] == 'c') version = SP3c;
72  else if(line[1] == 'd') version = SP3d;
73  else {
74  FFStreamError e("Unknown version of SP3: " + line.substr(0,3));
75  GNSSTK_THROW(e);
76  }
77 
78  // are V records present?
79  if(line[2] == 'V') containsVelocity = true;
80  else containsVelocity = false;
81 
82  // parse the rest of the line
83  int year = asInt(line.substr(3,4));
84  int month = asInt(line.substr(8,2));
85  int dom = asInt(line.substr(11,2));
86  int hour = asInt(line.substr(14,2));
87  int minute = asInt(line.substr(17,2));
88  double second = asInt(line.substr(20,10));
89  try {
91  }
92  catch (gnsstk::Exception& e) {
93  FFStreamError fe("Invalid time:" + string(1, line[0]));
94  GNSSTK_THROW(fe);
95  }
96  numberOfEpochs = asInt(line.substr(32,7));
97  dataUsed = line.substr(40,5);
98  coordSystem = line.substr(46,5);
99  orbitType = line.substr(52,3);
100  agency = line.substr(56,4);
101  }
102  else
103  {
104  FFStreamError e("Unknown label in line 1: " + line.substr(0,2));
105  GNSSTK_THROW(e);
106  }
107 
108  strm.formattedGetLine(line);
109  if(debug) std::cout << "SP3 Header Line 2 " << line << std::endl;
110  if (line[0]=='#' && line[1]=='#') // line 2
111  {
112  epochInterval = asDouble(line.substr(24,14));
113  }
114  else
115  {
116  FFStreamError e("Unknown label in line 2: " + line.substr(0,2));
117  GNSSTK_THROW(e);
118  }
119 
120  int i, index;
121  int numSVs(0), readSVs(0);
122 
123  // the map stores them sorted, so use svsAsWritten to determine
124  // which SV each accuracy corresponds to.
125  vector<SP3SatID> svsAsWritten;
126  SP3SatID sat;
127 
128  //Count lines for use in SP3d
129  int lineCount = 2;
130  int svLineCount = 0;
131  bool done = false;
132 
133  // read in the SV list
134  while(!done)
135  {
136  strm.formattedGetLine(line);
137  lineCount++;
138  if(debug) std::cout << "SP3 Header Line " << lineCount << " " << line << std::endl;
139  if (line[0]=='+' && line[1]=='+')
140  {
141  done=true;
142  strm.lastLine=line;
143  }
144  else
145  {
146  if (line[0]=='+')
147  {
148  svLineCount++;
149  // get the total number of svs on line 3
150  if (svLineCount == 1)
151  {
152  numSVs = asInt(line.substr(3,3));
153  svsAsWritten.resize(numSVs);
154  }
155  for(index = 9; index < 60; index += 3)
156  {
157  if (readSVs < numSVs)
158  {
159  try {
160  sat = SP3SatID(line.substr(index,3));
161  }
162  catch (Exception& e) {
163  FFStreamError ffse(e);
164  GNSSTK_THROW(ffse);
165  }
166  svsAsWritten[readSVs] = sat;
167  satList[sat] = 0;
168  readSVs++;
169  }
170  }
171  }
172  else
173  {
178  FFStreamError e("Unknown 1st char: "
179  //in line " + asString(i) + ": "
180  + string(1, line[0]));
181  GNSSTK_THROW(e);
182  }
183  }
184  }
185 
186  readSVs = 0;
187 
188  // read in the accuracy.
189  for (i = 0; i < svLineCount; i++) // lines 8-12
190  {
191  if (i==0)
192  {
193  line=strm.lastLine;
194  }
195  else
196  {
197  strm.formattedGetLine(line);
198  lineCount++;
199  }
200 
201  if(debug) std::cout << "SP3 Header Line " << lineCount << " " << line << std::endl;
202  if ((line[0]=='+') && (line[1]=='+'))
203  {
204  for(index = 9; index < 60; index += 3)
205  {
206  if (readSVs < numSVs)
207  {
208  satList[svsAsWritten[readSVs]] = asInt(line.substr(index,3));
209  readSVs++;
210  }
211  }
212  }
213  else
214  {
215  FFStreamError e("Unknown label in line " + asString(i) + ": "
216  + line.substr(0,2));
217  GNSSTK_THROW(e);
218  }
219  }
220 
221  strm.formattedGetLine(line);
222  lineCount++;
223  if(debug) std::cout << "SP3 Header Line %c1 " << line << std::endl;
224  if (version == SP3b || version == SP3c || version == SP3d) {
225  if(line[0]=='%' && line[1]=='c')
226  {
227  // file system
228  system.fromString(line.substr(3,2));
229 
230  // time system
231  string ts = upperCase(line.substr(9,3));
232  timeSystem = gnsstk::StringUtils::asTimeSystem(ts);
233  }
234  else
235  {
236  FFStreamError e("Unknown label in line %c1: " + line.substr(0,2));
237  GNSSTK_THROW(e);
238  }
239  }
240  else if (version == SP3a)
241  {
242  // standard for SP3a says "All times referred to in this
243  // document are GPS times".
244  timeSystem = gnsstk::TimeSystem::GPS;
245  }
246  // make sure header time is in the right time system
247  time.setTimeSystem(timeSystem);
248 
249  strm.formattedGetLine(line);
250  lineCount++;
251  if(debug) std::cout << "SP3 Header Line %c2 " << line << std::endl;
252 
253  strm.formattedGetLine(line);
254  lineCount++;
255  if(debug) std::cout << "SP3 Header Line %f1 " << line << std::endl;
256  if (version == SP3c || version == SP3d) {
257  if (line[0]=='%' && line[1]=='f')
258  {
259  basePV = asDouble(line.substr(3,10));
260  baseClk = asDouble(line.substr(14,12));
261  }
262  else
263  {
264  FFStreamError e("Unknown label in line %f1: " + line.substr(0,2));
265  GNSSTK_THROW(e);
266  }
267  }
268 
269  strm.formattedGetLine(line);
270  lineCount++;
271  if(debug) std::cout << "SP3 Header Line %f2 " << line << std::endl;
272 
273  // read in 2 unused %i lines // lines 17,18
274  for(i = 0; i <= 1; i++) {
275  strm.formattedGetLine(line);
276  lineCount++;
277  if(debug) std::cout << "SP3 Header Line %i " << line << std::endl;
278  }
279 
280  // read in comment lines
281  comments.clear();
282  done=false;
283  while(!done) // lines 19-22
284  {
285  strm.formattedGetLine(line);
286  lineCount++;
287  if(line[0]=='/' && line[1]=='*')
288  {
289  if(debug) std::cout << "SP3 Header Line " << i << " " << line << std::endl;
290  // strip the first 3 characters
291  line.erase(0, 3);
292  // and add to the comment vector
293  comments.push_back(line);
294  }
295  else
296  {
297  done=true;
298  strm.lastLine=line;
299  }
300  }
301 
302  // save the header, for use later when reading SP3Data records
303  strm.header = *this;
304 
305  } // end SP3Header::reallyGetRecord()
306 
307 
309  {
310  try {
311  SP3Stream& strm = dynamic_cast<SP3Stream&>(ffs);
312  int i,k;
313  long j;
314  string line;
315  SP3SatID SVid;
316  bool isVerA = (version == SP3a);
317  bool isVerB = (version == SP3b);
318  bool isVerC = (version == SP3c);
319  bool isVerD = (version == SP3d);
320 
321  // line 1
322  CivilTime civTime(time);
323  line = "#";
324  line += versionChar();
325  line += (containsVelocity ? "V" : "P");
326  line += civTime.printf("%4Y %2m %2d %2H %2M");
327  line += " " + rightJustify(civTime.printf("%.8f"),11);
328  line += " " + rightJustify(asString(numberOfEpochs),7);
329  line += " " + rightJustify(dataUsed,5);
330  line += " " + rightJustify(coordSystem,5);
331  line += " " + rightJustify(orbitType,3);
332  line += " " + rightJustify(agency,4);
333  strm << line << endl;
334  strm.lineNumber++;
335 
336  // line 2
337  GPSWeekSecond gpsWS(time);
338  line = "##";
339  line += rightJustify(gpsWS.printf("%F"),5);
340  line += rightJustify(gpsWS.printf("%15.8g"),16);
341  line += " " + rightJustify(asString(epochInterval,8),14);
342  line += " " + (static_cast<MJD>(time)).printf("%5.0Q");
343  line += " " + rightJustify(asString(time.getSecondOfDay()/86400.,13),15);
344  strm << line << endl;
345  strm.lineNumber++;
346 
347  //SV lines and SV Accuracy lines
348  //Map<SV,accuracy flag> (all SVs in data)
349  std::map<SP3SatID, short>::const_iterator it;
350  if (isVerD)
351  {
352  int totalLines = satList.size()/17;
353  if (satList.size()%17 != 0) totalLines++;
354  int numberOfLines = 2*totalLines;
355  if (numberOfLines < 10){
356  numberOfLines = 10;
357  }
358  int linesInSec = numberOfLines/2;
359  for(i=1;i<=numberOfLines;i++){
360  if (i==1) line = "+ " + rightJustify(asString(satList.size()),3) + " ";
361  else if ( i < linesInSec+1) line = "+ ";
362  else line = "++ ";
363  k=0;
364  if(i==1 || i==linesInSec+1)
365  {
366  it = satList.begin();
367  }
368  while(k<17)
369  {
370  if (it != satList.end())
371  {
372  if (i < linesInSec+1)
373  {
374  SVid = it->first;
375  j=-1;
376  }
377  else
378  {
379  j = it->second;
380  }
381  it++;
382  }
383  else
384  {
385  j=0;
386  }
387  if(j==-1)
388  {
389  try{
390  line += rightJustify(SP3SatID(SVid).toString(),3);
391  }
392  catch(Exception& e)
393  {
394  FFStreamError ffse(e);
395  GNSSTK_THROW(ffse);
396  }
397  }
398  else
399  {
400  line += rightJustify(asString(j),3);
401  }
402  k++;
403  }
404  strm << line << endl;
405  strm.lineNumber++;
406  }
407  }
408  else
409  {
410  for(i=3; i<=12; i++) { // loop over the lines
411  if(i==3) line = "+ " + rightJustify(asString(satList.size()),2) + " ";
412  else if(i < 8) line = "+ ";
413  else line = "++ ";
414  k = 0;
415  if(i == 3 || i == 8) // start the iteration
416  it = satList.begin();
417  while(k < 17) { // there are 17 per line
418  if(it != satList.end()) {
419  if(i < 8) { // lines 3-7 - sat id
420  if(!isVerA) {
421  // a satellite in version b or c -> let j be -1 to mark it
422  SVid = it->first;
423  j = -1;
424  }
425  else j = it->first.id;
426  }
427  else // lines 8-12 - accuracy
428  j = it->second;
429  it++;
430  }
431  else j=0; // no more
432 
433  if(j == -1) // sat version b or c
434  try {
435  line += rightJustify(SP3SatID(SVid).toString(),3);
436  }
437  catch (Exception& e)
438  {
439  FFStreamError ffse(e);
440  GNSSTK_THROW(ffse);
441  }
442  else // sat version a, accuracy, or 0
443  line += rightJustify(asString(j),3);
444  k++;
445  }
446  strm << line << endl;
447  strm.lineNumber++;
448  }
449  }
450 
451  // line 13
452  string ft("cc");
453  if(!isVerA)
454  {
455  ft[0] = system.systemChar();
456  ft[1] = ' ';
457  }
458  if(isVerB)
459  {
460  if(timeSystem != TimeSystem::GPS && timeSystem != TimeSystem::UTC)
461  {
462  FFStreamError ffse("Time system must be GPS or UTC");
463  GNSSTK_THROW(ffse);
464  }
465  }
466  if(isVerC || isVerD)
467  {
468  if(timeSystem != TimeSystem::GPS && timeSystem != TimeSystem::GLO &&
469  timeSystem != TimeSystem::GAL && timeSystem != TimeSystem::TAI &&
470  timeSystem != TimeSystem::UTC && timeSystem != TimeSystem::QZS )
471  {
472  FFStreamError ffse("Time system must be GPS, GLO, GAL, TAI, UTC, or QZS");
473  GNSSTK_THROW(ffse);
474  }
475  }
476  strm << "%c " << ft << " cc"
477  << " " << (isVerA ? "ccc" : timeSystemString())
478  << " ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc" << endl;
479  strm.lineNumber++;
480 
481  // line 14
482  strm << "%c cc cc ccc ccc cccc cccc cccc cccc ccccc ccccc ccccc ccccc" << endl;
483 
484  // line 15
485  strm << "%f "
486  << ((isVerC || isVerD) ? rightJustify(asString(basePV,7),10) : " 0.0000000")
487  << " "
488  << ((isVerC || isVerD) ? rightJustify(asString(baseClk,9),12) : " 0.000000000")
489  << " 0.00000000000 0.000000000000000" << endl;
490  strm.lineNumber++;
491 
492  // lines 16-18
493  strm << "%f 0.0000000 0.000000000 0.00000000000 0.000000000000000" << endl;
494  strm.lineNumber++;
495  strm << "%i 0 0 0 0 0 0 0 0 0" << endl;
496  strm.lineNumber++;
497  strm << "%i 0 0 0 0 0 0 0 0 0" << endl;
498  strm.lineNumber++;
499 
500  // Comment lines
501  //std::vector<std::string> comments; ///< vector of 4 comment lines
502  bool done=false;
503  j=0;
504  int linesOfComments = 4;
505  if ((int)comments.size() > linesOfComments){
506  linesOfComments = (int)comments.size();
507  }
508  while (!done) {
509  line = "/* ";
510  if(isVerD){
511  if(j < (int)comments.size()) line += leftJustify(comments[j],77);
512  else line += string(77,'C');
513  }
514  else{
515  if(j < (int)comments.size()) line += leftJustify(comments[j],57);
516  else line += string(57,'C');
517  }
518  j++;
519  if(j==linesOfComments){
520  done=true;
521  }
522  strm << line << endl;
523  strm.lineNumber++;
524  }
525 
526  // save header for use with SP3Data::reallyPut
527  strm.header = *this;
528  }
529  catch(Exception& e) { GNSSTK_RETHROW(e); }
530  catch(std::exception& e) { Exception g(e.what()); GNSSTK_THROW(g); }
531  }
532 
533 
534  void SP3Header::dump(ostream& s) const noexcept
535  {
536  s << "SP3 Header: version " << versionString() << " containing ";
537  if(containsVelocity) s << "positions and velocities.";
538  else s << "positions only.";
539  CivilTime ct(time);
540  s << endl;
541  s << " Time tag : " << ct.printf("%4Y/%02m/%02d %2H:%02M:%02S") << endl;
542  s << " Timespacing is " << epochInterval
543  << " sec, and the number of epochs is " << numberOfEpochs << endl;
544  s << " Data used as input : " << dataUsed << endl;
545  s << " Coordinate system : " << coordSystem << endl;
546  s << " Orbit estimate type : " << orbitType << endl;
547  s << " Agency : " << agency << endl;
548  if(version == SP3c) {
549  s << " File type: '" << system.systemChar() << "' which is "
550  << system.systemString() << endl;
551  s << " Time System: " << timeSystemString() << endl;
552  s << " Base for Pos/Vel =" << fixed << setw(10) << setprecision(7)
553  << basePV << endl;
554  s << " Base for Clk/Rate =" << setw(12) << setprecision(9)
555  << baseClk << endl;
556  }
557 
558  s << " List of satellite PRN/accuracy (" << satList.size() << " total) :\n";
559  int i=0;
560  std::map<SP3SatID,short>::const_iterator it=satList.begin();
561  while(it != satList.end()) {
562  s << " " << it->first << "/" << it->second;
563  if(!(++i % 8)) s << endl;
564  it++;
565  }
566  if(i % 8) s << endl;
567 
568  s << " Comments:\n";
569  for(size_t j=0; j<comments.size(); j++) s << " " << comments[j] << endl;
570 
571  s << "End of SP3 header" << endl;
572 
573  } // end SP3Header::dump()
574 
575 } // namespace
gnsstk::StringUtils::upperCase
std::string & upperCase(std::string &s)
Definition: StringUtils.hpp:2117
gnsstk::StringUtils::asInt
long asInt(const std::string &s)
Definition: StringUtils.hpp:713
SP3Header.hpp
gnsstk::SatID::id
int id
Satellite identifier, e.g. PRN.
Definition: SatID.hpp:154
gnsstk::FFStream
Definition: FFStream.hpp:119
StringUtils.hpp
example6.year
year
Definition: example6.py:64
gnsstk::TimeSystem::TAI
@ TAI
International Atomic Time.
gnsstk::FFTextStream::formattedGetLine
void formattedGetLine(std::string &line, const bool expectEOF=false)
Definition: FFTextStream.cpp:149
gnsstk::SP3Header::reallyGetRecord
virtual void reallyGetRecord(FFStream &s)
Definition: SP3Header.cpp:58
gnsstk::SP3Stream::header
SP3Header header
SP3Header for this file.
Definition: SP3Stream.hpp:88
gnsstk::FFTextStream::lineNumber
unsigned int lineNumber
Definition: FFTextStream.hpp:98
example6.hour
hour
Definition: example6.py:67
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
example6.minute
minute
Definition: example6.py:68
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
MJD.hpp
gnsstk::GPSWeekSecond
Definition: GPSWeekSecond.hpp:56
gnsstk::SP3Header::reallyPutRecord
virtual void reallyPutRecord(FFStream &s) const
Definition: SP3Header.cpp:308
gnsstk::Exception
Definition: Exception.hpp:151
example6.second
second
Definition: example6.py:69
gnsstk::StringUtils::asTimeSystem
TimeSystem asTimeSystem(const std::string &s)
Convert a string representation of TimeSystem to an enum.
Definition: TimeSystem.cpp:324
gnsstk::TimeSystem::QZS
@ QZS
QZSS system Time.
gnsstk::TimeSystem::GAL
@ GAL
Galileo system time.
example4.time
time
Definition: example4.py:103
gnsstk::CivilTime::printf
virtual std::string printf(const std::string &fmt) const
Definition: CivilTime.cpp:111
gnsstk::SP3Stream
Definition: SP3Stream.hpp:61
example6.agency
agency
Definition: example6.py:26
version
string version(string("2.4 9/23/15 rev"))
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
gnsstk::TimeSystem::GLO
@ GLO
GLONASS system time (aka UTC(SU))
gnsstk::TimeSystem::UTC
@ UTC
Coordinated Universal Time (e.g., from NTP)
gnsstk::CivilTime
Definition: CivilTime.hpp:55
gnsstk::StringUtils::rightJustify
std::string & rightJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1557
GPSWeekSecond.hpp
gnsstk::TimeSystem::GPS
@ GPS
GPS system time.
std
Definition: Angle.hpp:142
gnsstk::GPSWeekSecond::printf
virtual std::string printf(const std::string &fmt) const
Definition: GPSWeekSecond.hpp:145
SP3Stream.hpp
gnsstk::MJD
Definition: MJD.hpp:54
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
gnsstk::SP3SatID
Definition: SP3SatID.hpp:63
example6.month
month
Definition: example6.py:65
gnsstk::SP3Stream::lastLine
std::string lastLine
Last line read, perhaps not yet processed.
Definition: SP3Stream.hpp:92
debug
#define debug
Definition: SP3Header.cpp:51
gnsstk::SP3Header::dump
virtual void dump(std::ostream &s=std::cout) const noexcept
Dump contents to an ostream.
Definition: SP3Header.cpp:534
example6.numSVs
numSVs
Definition: example6.py:112


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