RinexObsID.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 "RinexObsID.hpp"
45 #include "RinexSatID.hpp"
46 #include "StringUtils.hpp"
47 #include "Rinex3ObsHeader.hpp"
48 
49 namespace gnsstk
50 {
51 
52  // string containing the system characters for all valid RINEX systems.
53  std::string RinexObsID::validRinexSystems("GRESCJI");
54 
55  // maps between 1-char and 3-char system id
56  std::map<std::string, std::string> RinexObsID::map1to3sys {
57  { "G", "GPS" },
58  { "R", "GLO" },
59  { "E", "GAL" },
60  { "S", "GEO" },
61  { "C", "BDS" },
62  { "J", "QZS" },
63  { "I", "IRN" }
64  };
65 
66  std::map<std::string, std::string> RinexObsID::map3to1sys {
67  { "GPS", "G" },
68  { "GLO", "R" },
69  { "GAL", "E" },
70  { "GEO", "S" },
71  { "BDS", "C" },
72  { "QZS", "J" },
73  { "IRN", "I" }
74  };
75 
76  // string containing the frequency digits for all valid RINEX systems.
77  std::string RinexObsID::validRinexFrequencies("123456789");
78 
80 
82  : ObsID()
83  {
84  // Note that the choice of tracking code for L1, L2, S1, S2
85  // are arbitrary since they are ambiguous in the rinex 2
86  // specifications
87  // L1 -> L1P; P1 -> C1P; C1 -> C1C; S1 -> S1P; D1 -> D1P
88  if (rot == RinexObsHeader::L1)
89  {
93  }
94  else if (rot == RinexObsHeader::P1)
95  {
99  }
100  else if (rot == RinexObsHeader::C1)
101  {
105  }
106  else if (rot == RinexObsHeader::S1)
107  {
111  }
112  else if (rot == RinexObsHeader::D1)
113  {
117  }
118  // L2 -> L2P; P2 -> C2P; C2 -> C2X; S2 -> S2P; D2 -> D2P
119  else if (rot == RinexObsHeader::L2)
120  {
124  }
125  else if (rot == RinexObsHeader::P2)
126  {
130  }
131  else if (rot == RinexObsHeader::C2)
132  {
136  }
137  else if (rot == RinexObsHeader::S2)
138  {
142  }
143  else if (rot == RinexObsHeader::D2)
144  {
148  }
149  }
150 
151  // Represent this object using the Rinex3 notation
152  std::string RinexObsID::asString(double version) const
153  {
154  char buff[4];
155 
156  buff[0] = ot2char[type];
157  buff[1] = cb2char[band];
158  buff[2] = tc2char[code];
159  if ((fabs(version - 3.02) < 0.005) && (band == CarrierBand::B1) &&
161  (code == TrackingCode::B1IQ)))
162  {
163  // kludge for RINEX 3.02 BDS codes
164  buff[1] = '1';
165  }
166  // special cases.
168  {
169  buff[2] = ' ';
170  }
171  else if (type == ObservationType::Channel)
172  {
173  buff[1] = '1';
174  buff[2] = ' ';
175  }
176  buff[3] = 0;
177  return std::string(buff);
178  }
179 
180  namespace StringUtils
181  {
182  // convert this object to a string representation
183  std::string asString(const RinexObsID& p)
184  {
185  return p.asString();
186  }
187  }
188 
189  // RINEX 3.03 document, section 5.1
190  // GPS
191  // L1 C,S,L,X,P,W,Y,M,N(but not C1N) G 1 CSLXPWYMN (but not C1N)
192  // L2 C,D,S,L,X,P,W,Y,M,N(but not C2N) G 2 CDSLXPWYMN (but not C1N)
193  // L5 I,Q,X G 5 IQX
194  // GLO
195  // G1 C,P R 1 CP
196  // G2 C,P R 2 CP
197  // GAL
198  // E1 A,B,C,X,Z E 1 ABCXZ
199  // E5a I,Q,X E 5 IQX
200  // E5b I,Q,X E 7 IQX
201  // E5ab I,Q,X E 8 IQX
202  // E6 A,B,C,X,Z E 6 ABCXZ
203  // SBAS
204  // L1 C S 1 C
205  // L5 I,Q,X S 5 IQX
206  // BDS
207  // B1 I,Q,X C 1 IQX
208  // B2 I,Q,X C 7 IQX
209  // B3 I,Q,X C 6 IQX
210  // QZSS
211  // L1 C,S,L,X,Z J 1 CSLXZ
212  // L2 S,L,X J 2 SLX
213  // L5 I,Q,X J 5 IQX
214  // L6 S,L,X J 6 SLX
215  // IRNSS
216  // L5 A,B,C,X I 5 ABCX
217  // L9 A,B,C,X I 9 ABCX
218 
219  // Determine if the given ObsID is valid. If the input string is 3
220  // characters long, the system is assumed to be GPS. If this string is 4
221  // characters long, the first character is the system designator as
222  // described in the Rinex 3 specification.
223  bool isValidRinexObsID(const std::string& strID)
224  {
225  int i(static_cast<int>(strID.length())-3);
226  if(i < 0 || i > 1)
227  {
228  return false;
229  }
230 
231  char sys;
232  std::string id;
233 
234  if(i == 1)
235  {
236  sys = strID[0];
237  id = strID.substr(1);
238  return isValidRinexObsID(id,sys);
239  }
240 
241  // test all RINEX systems
242  std::string syss(RinexObsID::validRinexSystems);
243  for(size_t j=0; j<syss.size(); j++)
244  {
245  if(isValidRinexObsID(strID,syss[j]))
246  {
247  return true;
248  }
249  }
250 
251  return false;
252  }
253 
254  // Determine if the given ObsID is valid, for the given system
255  bool isValidRinexObsID(const std::string& strID, const char sys)
256  {
257  if(strID.length() != 3)
258  {
259  return false;
260  }
261  char ot(strID[0]);
262  char cb(strID[1]);
263  char tc(strID[2]);
264  const std::string &codes(RinexObsID::validRinexTrackingCodes[sys][cb]);
265  if(ot == ' ' || ot == '-')
266  {
267  return false;
268  }
269  if (RinexObsID::char2ot.find(ot) == RinexObsID::char2ot.end())
270  {
271  return false;
272  }
273  if(codes.find(std::string(1,tc)) == std::string::npos)
274  {
275  return false;
276  }
277  // special cases for iono and channel num
278  if (ot == 'I' && ((tc != ' ') || (cb < '1') || (cb > '9')))
279  {
280  return false;
281  }
282  if (ot == 'X' && ((tc != ' ') || (cb != '1')))
283  {
284  return false;
285  }
286  if (((codes == "* ") || (codes == " *")) && (ot == 'I'))
287  {
288  // channel num must always be "band" 1, but if the system
289  // doesn't have any actual data on "1" band, we don't want
290  // to accidentally say that we can get iono delay data for
291  // a band that isn't valid for the system.
292  return false;
293  }
294  if(sys == 'G' && ot == 'C' && tc == 'N') // the one exception
295  {
296  return false;
297  }
298 
299  return true;
300  }
301 
302  std::ostream& RinexObsID::dumpCheck(std::ostream& s)
303  {
304  try {
305  const std::string types("CLDS");
306  std::map<char,std::string>::const_iterator it;
307 
308  for(size_t i=0; i<RinexObsID::validRinexSystems.size(); i++) {
309  char csys = RinexObsID::validRinexSystems[i];
310  std::string sys = RinexObsID::validRinexSystems.substr(i,1);
311  RinexSatID sat(sys);
312  std::string system(sat.systemString());
313 
314  s << "System " << sys << " = " << system << ", frequencies ";
315  for(it = RinexObsID::validRinexTrackingCodes[sys[0]].begin();
316  it != RinexObsID::validRinexTrackingCodes[sys[0]].end(); ++it)
317  s << it->first;
318  s << std::endl;
319 
320  for(it = RinexObsID::validRinexTrackingCodes[sys[0]].begin();
321  it != RinexObsID::validRinexTrackingCodes[sys[0]].end(); ++it)
322  {
323  s << " " << system << "(" << sys << "), freq " << it->first
324  << ", codes '" << it->second << "'" << std::endl;
325  std::string codes(it->second), str;
326  for(size_t j=0; j<codes.size(); ++j) {
327  std::ostringstream oss1;
328  for(size_t k=0; k<types.size(); ++k) {
329  str = std::string(1,types[k]) + std::string(1,it->first)
330  + std::string(1,codes[j]);
331  std::ostringstream oss;
332  if(!isValidRinexObsID(str,csys))
333  oss << str << " " << "-INVALID-";
334  else
335  {
336  RinexObsID robsid(sys+str,
338  oss << str << " " << robsid;
339  }
340  oss1 << " " << StringUtils::leftJustify(oss.str(),34);
341  }
342  s << StringUtils::stripTrailing(oss1.str()) << std::endl;
343  }
344  }
345  }
346  }
347  catch(Exception& e) {
348  s << "Exception: " << e.what() << std::endl;
349  GNSSTK_RETHROW(e);
350  }
351 
352  return s;
353  }
354 
355  bool RinexObsID ::
356  equalIndex(const RinexObsID& right)
357  const
358  {
359  if (type != right.type)
360  return false;
362  {
363  // only check band for ionospheric delay.
364  return band == right.band;
365  }
367  {
368  // There's only one channel type pseudo-observable
369  return true;
370  }
371  // use the default for everything else
372  return operator==(right);
373  }
374 
375  // This is used to register a new RinexObsID & Rinex 3
376  // identifier. The syntax for the Rinex 3 identifier is the
377  // same as for the RinexObsID constructor. If there are spaces
378  // in the provided identifier, they are ignored
380  newID(const std::string& strID, const std::string& desc)
381  {
382  if (char2ot.count(strID[0]) &&
383  char2cb.count(strID[1]) &&
384  char2tc.count(strID[2]))
385  {
386  GNSSTK_THROW(InvalidParameter("Identifier " + strID +
387  " already defined."));
388  }
389 
390  return idCreator(strID, desc);
391  }
392 
393 
395  idCreator(const std::string& strID, const std::string& desc)
396  {
397  char ot = strID[0];
399  if (!char2ot.count(ot))
400  {
401  type = (ObservationType)otDesc.size();
402  otDesc[type] = desc;
403  char2ot[ot] = type;
404  ot2char[type] = ot;
405  }
406  else
407  type = char2ot[ot];
408 
409  char cb = strID[1];
411  if (!char2cb.count(cb))
412  {
413  band = (CarrierBand)cbDesc.size();
414  cbDesc[band] = desc;
415  char2cb[cb] = band;
416  cb2char[band] = cb;
417  }
418  else
419  band = char2cb[cb];
420 
421  char tc = strID[2];
423  if (!char2tc.count(tc))
424  {
425  code = (TrackingCode) tcDesc.size();
426  tcDesc[code] = desc;
427  char2tc[tc] = code;
428  tc2char[code] = tc;
429  }
430  else
431  code = char2tc[tc];
432 
433  return RinexObsID(type, band, code);
434  }
435 
436 
437  std::string RinexObsID ::
439  {
440  std::string rv;
441  for (const auto i : char2ot)
442  {
443  rv += i.first;
444  }
445  return rv;
446  }
447 
448 
449  std::string RinexObsID ::
451  {
452  std::string rv;
453  for (const auto i : char2cb)
454  {
455  rv += i.first;
456  }
457  return rv;
458  }
459 
460 
461  std::string RinexObsID ::
463  {
464  std::string rv;
465  for (const auto i : char2tc)
466  {
467  rv += i.first;
468  }
469  return rv;
470  }
471 
472 } // end namespace
gnsstk::TrackingCode::B1Q
@ B1Q
BeiDou B1 Q code.
gnsstk::RinexObsHeader::D1
static const GNSSTK_EXPORT RinexObsType D1
Definition: RinexObsHeader.hpp:219
gnsstk::RinexObsHeader::L1
static const GNSSTK_EXPORT RinexObsType L1
Definition: RinexObsHeader.hpp:213
gnsstk::RinexObsID::asString
std::string asString() const
Definition: RinexObsID.hpp:190
gnsstk::RinexObsID::RinexObsID
RinexObsID()
empty constructor, creates an invalid object
Definition: RinexObsID.hpp:106
gnsstk::RinexObsID::dumpCheck
static std::ostream & dumpCheck(std::ostream &s)
Definition: RinexObsID.cpp:302
gnsstk::RinexObsHeader::S1
static const GNSSTK_EXPORT RinexObsType S1
Definition: RinexObsHeader.hpp:221
gnsstk::RinexObsID::char2ot
static GNSSTK_EXPORT std::map< char, ObservationType > char2ot
Definition: RinexObsID.hpp:285
gnsstk::isValidRinexObsID
bool isValidRinexObsID(const std::string &strID)
Definition: RinexObsID.cpp:223
StringUtils.hpp
gnsstk::RinexSatID::systemString
std::string systemString() const noexcept
Definition: RinexSatID.cpp:82
gnsstk::ObservationType::Phase
@ Phase
accumulated phase, in cycles
gnsstk::CarrierBand
CarrierBand
Definition: CarrierBand.hpp:54
gnsstk::Exception::what
std::string what() const
Dump to a string.
Definition: Exception.cpp:193
gnsstk::RinexObsID::getTCChars
static std::string getTCChars()
Definition: RinexObsID.cpp:462
gnsstk::RinexObsHeader::P1
static const GNSSTK_EXPORT RinexObsType P1
Definition: RinexObsHeader.hpp:217
gnsstk::ObsID::tcDesc
static GNSSTK_EXPORT std::map< TrackingCode, std::string > tcDesc
These strings are for forming a somewhat verbose description.
Definition: ObsID.hpp:216
gnsstk::ObservationType::Channel
@ Channel
Channel number.
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk::ObsID::band
CarrierBand band
Definition: ObsID.hpp:200
gnsstk::Rinex3ObsBase::currentVersion
static const GNSSTK_EXPORT double currentVersion
Definition: Rinex3ObsBase.hpp:72
gnsstk::RinexObsID::map3to1sys
static GNSSTK_EXPORT std::map< std::string, std::string > map3to1sys
Definition: RinexObsID.hpp:267
gnsstk::RinexObsID::getCBChars
static std::string getCBChars()
Definition: RinexObsID.cpp:450
gnsstk::ObservationType::SNR
@ SNR
Signal strength, in dB-Hz.
gnsstk::RinexObsID::map1to3sys
static GNSSTK_EXPORT std::map< std::string, std::string > map1to3sys
Definition: RinexObsID.hpp:266
gnsstk::ObservationType::Range
@ Range
pseudorange, in meters
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::CarrierBand::L2
@ L2
GPS L2, QZSS L2.
gnsstk::RinexObsID::validRinexSystems
static GNSSTK_EXPORT std::string validRinexSystems
This string contains the system characters for all RINEX systems.
Definition: RinexObsID.hpp:262
gnsstk::Exception
Definition: Exception.hpp:151
gnsstk::RinexObsID::validRinexTrackingCodes
static GNSSTK_EXPORT std::map< char, std::map< char, std::string > > validRinexTrackingCodes
Definition: RinexObsID.hpp:281
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::TrackingCode::CA
@ CA
Legacy GPS civil code.
gnsstk::RinexObsID::validRinexFrequencies
static GNSSTK_EXPORT std::string validRinexFrequencies
Definition: RinexObsID.hpp:271
gnsstk::CarrierBand::B1
@ B1
BeiDou B1.
gnsstk::ObsID
Definition: ObsID.hpp:82
RinexObsID.hpp
gnsstk::RinexObsType
RINEX Observation Types.
Definition: RinexObsHeader.hpp:67
gnsstk::TrackingCode::L2CML
@ L2CML
Modernized GPS L2 civil M+L combined tracking.
Rinex3ObsHeader.hpp
gnsstk::ObsID::operator==
virtual bool operator==(const ObsID &right) const
Equality requires all fields to be the same.
Definition: ObsID.cpp:71
gnsstk::TrackingCode::B1I
@ B1I
BeiDou B1 I code.
gnsstk::RinexObsHeader::L2
static const GNSSTK_EXPORT RinexObsType L2
Definition: RinexObsHeader.hpp:214
gnsstk::RinexObsID::equalIndex
bool equalIndex(const RinexObsID &right) const
Definition: RinexObsID.cpp:356
version
string version(string("2.4 9/23/15 rev"))
gnsstk::ObsID::code
TrackingCode code
Definition: ObsID.hpp:201
gnsstk::CarrierBand::L1
@ L1
GPS L1, Galileo E1, SBAS L1, QZSS L1, BeiDou L1.
gnsstk::TrackingCode::B1IQ
@ B1IQ
BeiDou B1 I+Q code.
gnsstk::RinexObsID
Definition: RinexObsID.hpp:102
gnsstk::RinexObsID::getOTChars
static std::string getOTChars()
Definition: RinexObsID.cpp:438
gnsstk::RinexObsID::char2tc
static GNSSTK_EXPORT std::map< char, TrackingCode > char2tc
Definition: RinexObsID.hpp:287
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
gnsstk::TrackingCode::P
@ P
Legacy GPS precise code.
gnsstk::ObsID::otDesc
static GNSSTK_EXPORT std::map< ObservationType, std::string > otDesc
Definition: ObsID.hpp:218
gnsstk::RinexObsID::idCreator
static RinexObsID idCreator(const std::string &id, const std::string &desc="")
Definition: RinexObsID.cpp:395
gnsstk::RinexObsID::tc2char
static GNSSTK_EXPORT std::map< TrackingCode, char > tc2char
Definition: RinexObsID.hpp:290
gnsstk::RinexObsID::char2cb
static GNSSTK_EXPORT std::map< char, CarrierBand > char2cb
Definition: RinexObsID.hpp:286
gnsstk::RinexObsHeader::P2
static const GNSSTK_EXPORT RinexObsType P2
Definition: RinexObsHeader.hpp:218
gnsstk::RinexObsID::cb2char
static GNSSTK_EXPORT std::map< CarrierBand, char > cb2char
Definition: RinexObsID.hpp:289
gnsstk::ObsID::type
ObservationType type
Definition: ObsID.hpp:199
gnsstk::TrackingCode
TrackingCode
Definition: TrackingCode.hpp:64
gnsstk::RinexSatID
Definition: RinexSatID.hpp:63
gnsstk::RinexObsHeader::D2
static const GNSSTK_EXPORT RinexObsType D2
Definition: RinexObsHeader.hpp:220
gnsstk::ObservationType::Doppler
@ Doppler
Doppler, in Hz.
gnsstk::RinexObsID::ot2char
static GNSSTK_EXPORT std::map< ObservationType, char > ot2char
Definition: RinexObsID.hpp:288
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
RinexSatID.hpp
gnsstk::RinexObsID::newID
static RinexObsID newID(const std::string &id, const std::string &desc="")
Definition: RinexObsID.cpp:380
gnsstk::ObservationType::Iono
@ Iono
Ionospheric delay.
gnsstk::RinexObsHeader::S2
static const GNSSTK_EXPORT RinexObsType S2
Definition: RinexObsHeader.hpp:222
gnsstk::ObsID::cbDesc
static GNSSTK_EXPORT std::map< CarrierBand, std::string > cbDesc
Definition: ObsID.hpp:217
gnsstk::RinexObsHeader::C2
static const GNSSTK_EXPORT RinexObsType C2
Definition: RinexObsHeader.hpp:216
gnsstk::RinexObsHeader::C1
static const GNSSTK_EXPORT RinexObsType C1
Definition: RinexObsHeader.hpp:215
gnsstk::ObservationType
ObservationType
The type of observation, mostly used by ObsID.
Definition: ObservationType.hpp:55


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