AntexData.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 
45 #include "AntexData.hpp"
46 #include "AntexStream.hpp"
47 #include "CivilTime.hpp"
48 #include "GNSSconstants.hpp"
49 #include "MJD.hpp"
50 #include "RinexObsID.hpp"
51 #include "StringUtils.hpp"
52 #include "TimeString.hpp"
53 
54 using namespace gnsstk::StringUtils;
55 using namespace std;
56 
57 namespace gnsstk
58 {
59  const string AntexData::startAntennaString = "START OF ANTENNA";
60  const string AntexData::typeSerNumString = "TYPE / SERIAL NO";
61  const string AntexData::methodString = "METH / BY / # / DATE";
62  const string AntexData::daziString = "DAZI";
63  const string AntexData::zenithString = "ZEN1 / ZEN2 / DZEN";
64  const string AntexData::numFreqString = "# OF FREQUENCIES";
65  const string AntexData::validFromString = "VALID FROM";
66  const string AntexData::validUntilString = "VALID UNTIL";
67  const string AntexData::sinexCodeString = "SINEX CODE";
68  const string AntexData::dataCommentString = "COMMENT";
69  const string AntexData::startFreqString = "START OF FREQUENCY";
70  const string AntexData::neuFreqString = "NORTH / EAST / UP";
71  const string AntexData::endOfFreqString = "END OF FREQUENCY";
72  const string AntexData::startFreqRMSString = "START OF FREQ RMS";
73  const string AntexData::neuFreqRMSString =
74  "NORTH / EAST / UP"; // NB duplicate!
75  const string AntexData::endOfFreqRMSString = "END OF FREQ RMS";
76  const string AntexData::endOfAntennaString = "END OF ANTENNA";
77 
78  /* NB. this dimension must be updated with the list
79  in IGS file rcvr_ant.tab. See that file for
80  additional information.
81  Number of types that are used for satellites */
82 
83  // vector of type strings that identify satellites; must be kept updated.
87  const vector<string> AntexData::SatelliteTypes =
88  {
89  "BEIDOU-2G",
90  "BEIDOU-2I",
91  "BEIDOU-2M",
92  "BEIDOU-3I",
93  "BEIDOU-3SI-CAST",
94  "BEIDOU-3SI-SECM",
95  "BEIDOU-3SM-CAST",
96  "BEIDOU-3SM-SECM",
97  "BEIDOU-3M-CAST",
98  "BEIDOU-3M-SECM",
99  "BEIDOU-3G-CAST",
100  "BLOCK I",
101  "BLOCK II",
102  "BLOCK IIA",
103  "BLOCK IIR-A",
104  "BLOCK IIR-B",
105  "BLOCK IIR-M",
106  "BLOCK IIF",
107  "BLOCK IIIA",
108  "GALILEO-0A",
109  "GALILEO-0B",
110  "GALILEO-1",
111  "GALILEO-2",
112  "GLONASS",
113  "GLONASS-M",
114  "GLONASS-M+",
115  "GLONASS-K1",
116  "GLONASS-K2",
117  "IRNSS-1GEO",
118  "IRNSS-1IGSO",
119  "QZSS",
120  "QZSS-2I",
121  "QZSS-2G"
122  };
123 
124  // ----------------------------------------------------------------------------
126  {
127  if (!isValid())
128  {
129  return false;
130  }
132  (!(valid & validFromValid) && !(valid & validUntilValid)))
133  {
134  return true;
135  }
136  if ((valid & validFromValid) && time < validFrom)
137  {
138  return false;
139  }
140  if ((valid & validUntilValid) && time > validUntil)
141  {
142  return false;
143  }
144 
145  return true;
146  }
147 
148  // ----------------------------------------------------------------------------
149  // Generate a name from type and serial number
150  string AntexData::name() const
151  {
152  if (!isValid())
153  {
154  return string("invalid");
155  }
156  if (isRxAntenna)
157  {
158  return (type);
159  }
160  else
161  { // must distinguish name with PRN and start time
162  MJD mt(validFrom);
163  return (type + string("/") + serialNo + string("/") +
164  asString(mt.mjd, 2));
165  }
166  }
167 
168  // ----------------------------------------------------------------------------
169  double AntexData::getTotalPhaseCenterOffset(const string& freq,
170  double azim,
171  double elev_nadir) const
172  {
173  try
174  {
175  // these do all the checking and throwing
176  double pcv = getPhaseCenterVariation(freq, azim, elev_nadir);
177  Triple pco = getPhaseCenterOffset(freq);
178 
179  double elev = elev_nadir;
180  if (!isRxAntenna) // satellite : elev_nadir is 'nadir' angle:
181  {
182  elev = 90. - elev_nadir; // from Z axis toward XY plane.
183  }
184 
185  double cosel = ::cos(elev * DEG_TO_RAD);
186  double sinel = ::sin(elev * DEG_TO_RAD);
187  double cosaz = ::cos(azim * DEG_TO_RAD);
188  double sinaz = ::sin(azim * DEG_TO_RAD);
189 
190  // see doc for class AntexData for signs, etc
191  return (-pcv + pco[0] * cosel * cosaz + pco[1] * cosel * sinaz +
192  pco[2] * sinel);
193  }
194  catch (Exception& e)
195  {
196  GNSSTK_RETHROW(e);
197  }
198  }
199 
200  /* Access the PCO (only) values in the antenna coordinate system
201  (This does NOT include the phase center variations, which should
202  be computed using getPhaseCenterVariation() and added to the PCOs to get
203  the total phase center offset).
204  */
205  Triple AntexData::getPhaseCenterOffset(const string& freq) const
206  {
207  if (!isValid())
208  {
209  gnsstk::Exception e("Invalid AntexData object");
210  GNSSTK_THROW(e);
211  }
212 
213  // get the antennaPCOandPCVData for this frequency
214  map<string, antennaPCOandPCVData>::const_iterator it =
215  freqPCVmap.find(freq);
216  if (it == freqPCVmap.end())
217  {
219  "Frequency " + freq +
220  " not found! System not supported or data corrupted.");
221  GNSSTK_THROW(e);
222  }
223  // const antennaPCOandPCVData& antpco = it->second;
224 
225  Triple retval;
226  for (int i = 0; i < 3; i++)
227  retval[i] = it->second.PCOvalue[i];
228 
229  return retval;
230  }
231 
232  /* Compute the phase center variation (only) at the given azimuth and
233  elevation (receiver) or nadir (satellite) angles */
234  double AntexData::getPhaseCenterVariation(const string& freq,
235  double azimuth,
236  double elev_nadir) const
237  {
238  if (!isValid())
239  {
240  Exception e("Invalid AntexData object");
241  GNSSTK_THROW(e);
242  }
243  if (elev_nadir < 0.0 || elev_nadir > 90.0)
244  {
245  Exception e("Invalid elevation/nadir angle");
246  GNSSTK_THROW(e);
247  }
248 
249  double retpco, azim, zen;
250  zen = elev_nadir; // satellite: elev_nadir is a zenith (nadir) angle
251  if (isRxAntenna) // receiver: elev_nadir is an elevation
252  {
253  zen = 90. - elev_nadir;
254  }
255 
256  /* ensure azim is within range
257  LOG(INFO) << "PCV:0 " << fixed << setprecision(2) <<azimuth<<
258  ","<<elev_nadir; */
259  azim = azimuth;
260  while (azim < 0.0)
261  azim += 360.0;
262  while (azim >= 360.0)
263  azim -= 360.0;
264 
265  /* find four points bracketing the point (azim,zen)
266  zen
267  ^
268  zn_hi | 0 1 have pco at 0,1,2,3
269  | x have (azim,zen) at x, want retpco at x
270  zn_lo | 2 3
271  |----------> azim
272  az_lo az_hi
273 
274  find bracketing azims within the map, then find bracketing zeniths and
275  PCOs
276  */
277  double az_lo, az_hi, zn_lo, zn_hi, pco[4];
278  map<double, zenOffsetMap>::const_iterator jt_lo, jt_hi;
279 
280  map<string, antennaPCOandPCVData>::const_iterator it;
281  it = freqPCVmap.find(freq);
282  if (it == freqPCVmap.end())
283  {
284  Exception e("Frequency " + freq +
285  " not found! System not supported or data corrupted.");
286  GNSSTK_THROW(e);
287  }
288 
289  const antennaPCOandPCVData &antpco = it->second;
290  const azimZenMap &azzenmap = antpco.PCVvalue; // map<double, zenOffsetMap>
291 
292  if (!antpco.hasAzimuth)
293  {
294  // LOG(INFO) << "No azim"; az_lo = az_hi = azim;
295  jt_hi = azzenmap.begin(); // this will be only entry, with az == -1
296  }
297  else
298  {
299  // LOG(INFO) << "Look for " << azim << " in azzenmap";
300  jt_hi = azzenmap.find(azim); // find() returns end() unless exact match
301  }
302 
303  // either azimuth is not there, or there is an exact match in azimuth
304  if (jt_hi != azzenmap.end())
305  {
306  // LOG(INFO) << "Found azim " << fixed << setprecision(2) <<
307  // jt_hi->first; az_lo = az_hi = azim;
308  const zenOffsetMap &zenoffmap = jt_hi->second; // map<double,double>
309  // bracket zenith angle
310  evaluateZenithMap(zen, zenoffmap, zn_lo, zn_hi, pco[2], pco[0]);
311  if (zn_lo == zn_hi) // exact match in zenith angle
312  {
313  retpco = pco[0]; // TD use fabs(diff) < tolerance ?
314  }
315  else // linear interpolation in zenith angle
316  {
317  retpco = (pco[0] * (zen - zn_lo) + pco[2] * (zn_hi - zen)) /
318  (zn_hi - zn_lo);
319  }
320  }
321 
322  else
323  { // must bracket in azimuth
324  /* lower_bound() returns first value >= azim (but == case handled
325  above) */
326  jt_lo = jt_hi = azzenmap.lower_bound(azim);
327 
328  if (jt_lo == azzenmap.end())
329  { // beyond the last value
330  jt_lo--; // last value
331  az_lo = jt_lo->first;
332  jt_hi = azzenmap.begin(); // wrap around to beginning
333  az_hi = jt_hi->first + 360.;
334  // LOG(INFO) << "Beyond high";
335  }
336  else if (jt_hi == azzenmap.begin())
337  { // before the first value
338  az_hi = jt_hi->first;
339  (jt_lo = azzenmap.end())--; // wrap around to end
340  az_lo = jt_lo->first - 360.;
341  // LOG(INFO) << "Before low";
342  }
343  else
344  { // azim is bracketed
345  az_hi = jt_hi->first;
346  jt_lo--;
347  az_lo = jt_lo->first;
348  // LOG(INFO) << "Bracket";
349  }
350 
351  // get zenith angles and pcos at upper and lower azimuths
352  evaluateZenithMap(zen, jt_hi->second, zn_lo, zn_hi, pco[3], pco[1]);
353  evaluateZenithMap(zen, jt_lo->second, zn_lo, zn_hi, pco[2], pco[0]);
354 
355  // interpolation
356  if (zn_hi == zn_lo)
357  {
358  // zen exact match, linear interpolate in azimuth
359  retpco = (pco[2] * (az_hi - azim) + pco[3] * (azim - az_lo)) /
360  (az_hi - az_lo);
361  // LOG(INFO) << "Exact match";
362  }
363  else
364  {
365  // bi-linear interpolation
366  retpco = (pco[0] * (az_hi - azim) * (zen - zn_lo) +
367  pco[1] * (azim - az_lo) * (zen - zn_lo) +
368  pco[2] * (az_hi - azim) * (zn_hi - zen) +
369  pco[3] * (azim - az_lo) * (zn_hi - zen)) /
370  ((az_hi - az_lo) * (zn_hi - zn_lo));
371  }
372  }
373 
374  // do not change the sign; just interpolate the map
375  return retpco;
376  }
377 
378  void AntexData::dump(ostream& s, int detail) const
379  {
380  map<string, antennaPCOandPCVData>::const_iterator it;
381  map<double, zenOffsetMap>::const_iterator jt;
382  map<double, double>::const_iterator kt;
383 
384  s << "Antenna Type/SN: [" << name() << "]";
385  if (isRxAntenna)
386  {
387  s << " (Receiver)" << endl;
388  }
389  else
390  {
391  if (PRN != -1 || SVN != -1)
392  {
393  s << " (" << RinexObsID::map1to3sys[string(1, systemChar)];
394  if (PRN != -1)
395  {
396  s << string(" PRN ") + asString(PRN);
397  }
398  if (SVN != -1)
399  {
400  s << string(" SVN ") + asString(SVN);
401  }
402  s << ")";
403  }
404  s << " code " << satCode << ", COSPAR " << cospar << endl;
405  }
406 
407  if (detail <= 0)
408  {
409  return;
410  }
411 
412  s << "Method: " << method << " Agency: " << agency
413  << " #Cal.Ant.s: " << noAntCalibrated << " Date: " << date << endl;
414  if (azimDelta > 0.0)
415  {
416  s << "Azimuth dependence, delta azimuth = " << fixed << setprecision(1)
417  << azimDelta << endl;
418  }
419  else
420  {
421  s << "No azimuth dependence" << endl;
422  }
423  s << "Elevation dependence: from " << fixed << setprecision(1)
424  << zenRange[0] << " to " << zenRange[1] << " in steps of "
425  << zenRange[2] << " degrees." << endl;
426  s << "Frequencies stored (" << nFreq << "): ";
427 
428  for (it = freqPCVmap.begin(); it != freqPCVmap.end(); ++it)
429  s << " " << it->first;
430  s << endl;
431  s << "Valid FROM "
432  << (validFrom == CommonTime::BEGINNING_OF_TIME
433  ? " (all time) "
434  : printTime(validFrom, "%02m/%02d/%04Y %02H:%02M:%.7s"))
435  << " TO "
436  << (validUntil == CommonTime::END_OF_TIME
437  ? " (all time) "
438  : printTime(validUntil, "%02m/%02d/%04Y %02H:%02M:%.7s"))
439  << endl;
440  if (!sinexCode.empty())
441  {
442  s << "SINEX code: " << sinexCode << endl;
443  }
444  for (size_t i = 0; i < commentList.size(); i++)
445  {
446  // if(i==0) s << "Comments:\n";
447  s << "Comment " << setw(2) << i + 1 << ": " << commentList[i] << endl;
448  }
449 
450  if (detail == 1)
451  {
452  for (it = freqPCVmap.begin(); it != freqPCVmap.end(); it++)
453  {
454  const antennaPCOandPCVData &antpco = it->second;
455  s << "PCO ("
456  << (isRxAntenna ? "NEU from antenna reference position"
457  : "body XYZ from center-of-mass")
458  << ") (mm):"
459  << " (freq " << it->first << ") " << fixed << setprecision(2)
460  << setw(10) << antpco.PCOvalue[0] << ", " << setw(10)
461  << antpco.PCOvalue[1] << ", " << setw(10) << antpco.PCOvalue[2]
462  << endl;
463  }
464  return;
465  }
466 
467  // loop over frequency
468  for (it = freqPCVmap.begin(); it != freqPCVmap.end(); it++)
469  {
470  s << "Offset values for frequency: " << it->first << " ("
471  << (it->second.hasAzimuth ? "has" : "does not have") << " azimuths)"
472  << endl;
473  const antennaPCOandPCVData &antpco = it->second;
474 
475  // PCOs
476  s << " PCO ("
477  << (isRxAntenna ? "NEU from antenna reference position"
478  : "body XYZ from center-of-mass")
479  << ") (mm):" << fixed << setprecision(2) << setw(10)
480  << antpco.PCOvalue[0] << ", " << setw(10) << antpco.PCOvalue[1]
481  << ", " << setw(10) << antpco.PCOvalue[2] << endl;
482 
483  // RMS PCOs
484  if (valid & neuFreqRMSValid)
485  {
486  s << " RMS PCO ("
487  << (isRxAntenna ? "NEU from antenna reference position"
488  : "body XYZ from center-of-mass")
489  << " (mm):" << fixed << setprecision(2) << setw(10)
490  << antpco.PCOrms[0] << ", " << setw(10) << antpco.PCOrms[1]
491  << ", " << setw(10) << antpco.PCOrms[2] << endl;
492  }
493 
494  // PCV array(s)
495  const azimZenMap &azel = antpco.PCVvalue;
496  s << fixed << setprecision(2);
497  // header line
498  jt = azel.begin();
499  const zenOffsetMap &zenoffmap = jt->second;
500  s << " PCVs follow, one azimuth per row: AZ(deg) { PCVs(EL)(mm) .. "
501  ".. }\n";
502  s << " EL(deg)";
503  for (kt = zenoffmap.begin(); kt != zenoffmap.end(); kt++)
504  s << setw(8) << kt->first;
505  s << endl;
506  // data values
507  for (jt = azel.begin(); jt != azel.end(); jt++)
508  {
509  double azimuth = jt->first;
510  const zenOffsetMap &zenoffmap = jt->second;
511  if (azimuth == -1.0)
512  {
513  s << " (NOAZI)";
514  }
515  else
516  {
517  s << setw(9) << azimuth;
518  }
519  for (kt = zenoffmap.begin(); kt != zenoffmap.end(); kt++)
520  s << setw(8) << kt->second;
521  s << endl;
522  }
523  } // end loop over frequency
524  }
525 
526  // ----------------------------------------------------------------------------
527  // protected routines
528 
529  /* Find zenith angles bracketing the input zenith angle within the given map,
530  and the corresponding PCOs.
531  */
533  const zenOffsetMap& eomap, double& zen_lo,
534  double& zen_hi, double& pco_lo,
535  double& pco_hi) const
536  {
537  map<double, double>::const_iterator kt;
538 
539  // find() returns end() unless there is an exact match
540  kt = eomap.find(zen);
541  if (kt != eomap.end())
542  { // exact match
543  zen_lo = zen_hi = zen;
544  pco_lo = pco_hi = kt->second;
545  return;
546  }
547 
548  // lower_bound() returns first value >= zen (but == case handled above)
549  kt = eomap.lower_bound(zen);
550 
551  // zen is above the last, or below the first value - just take that value
552  if (kt == eomap.end() || kt == eomap.begin())
553  {
554  if (kt == eomap.end())
555  {
556  kt--; // last value
557  }
558  zen_lo = zen_hi = zen;
559  pco_lo = pco_hi = kt->second;
560  return;
561  }
562 
563  // zen is bracketed
564  zen_hi = kt->first;
565  pco_hi = kt->second;
566  kt--;
567  zen_lo = kt->first;
568  pco_lo = kt->second;
569 
570  return;
571  }
572 
574  {
575  if (!isValid())
576  {
577  FFStreamError fse(string("Cannot write invalid AntexData"));
578  GNSSTK_THROW(fse);
579  }
580 
581  size_t i;
582  string line;
583  map<string, antennaPCOandPCVData>::const_iterator it;
584  map<double, zenOffsetMap>::const_iterator jt;
585  map<double, double>::const_iterator kt;
586  AntexStream &strm = dynamic_cast<AntexStream &>(ffs);
587 
588  line = rightJustify(leftJustify(startAntennaString, 20), 80);
589  strm << line << endl;
590  strm.lineNumber++;
591 
592  line = leftJustify(type, 20);
593  line += leftJustify(serialNo, 20);
594  line += leftJustify(satCode, 10);
595  line += leftJustify(cospar, 10);
596  line += typeSerNumString; //"TYPE / SERIAL NO";
597  strm << leftJustify(line, 80) << endl;
598  strm.lineNumber++;
599 
600  line = leftJustify(method, 20);
601  line += leftJustify(agency, 20);
602  line += leftJustify(rightJustify(asString(noAntCalibrated), 6), 10);
603  line += leftJustify(date, 10);
604  line += methodString; // "METH / BY / # / DATE";
605  strm << leftJustify(line, 80) << endl;
606  strm.lineNumber++;
607 
608  line = string(" ");
609  line += rightJustify(asString(azimDelta, 1), 6);
610  line = leftJustify(line, 60);
611  line += daziString; // "DAZI";
612  strm << leftJustify(line, 80) << endl;
613  strm.lineNumber++;
614 
615  line = string(" ");
616  line += rightJustify(asString(zenRange[0], 1), 6);
617  line += rightJustify(asString(zenRange[1], 1), 6);
618  line += rightJustify(asString(zenRange[2], 1), 6);
619  line = leftJustify(line, 60);
620  line += zenithString; // "ZEN1 / ZEN2 / DZEN";
621  strm << leftJustify(line, 80) << endl;
622  strm.lineNumber++;
623 
624  line = rightJustify(asString(nFreq), 6);
625  line = leftJustify(line, 60);
626  line += numFreqString; // "# OF FREQUENCIES";
627  strm << leftJustify(line, 80) << endl;
628  strm.lineNumber++;
629 
630  if (valid & validFromValid)
631  {
632  if (stringValidFrom.empty())
633  {
634  line = writeTime(validFrom);
635  }
636  else
637  {
638  line = stringValidFrom;
639  }
640  line = leftJustify(line, 60);
641  line += validFromString; // "VALID FROM";
642  strm << leftJustify(line, 80) << endl;
643  strm.lineNumber++;
644  }
645 
646  if (valid & validUntilValid)
647  {
648  if (stringValidUntil.empty())
649  {
650  line = writeTime(validUntil);
651  }
652  else
653  {
654  line = stringValidUntil;
655  }
656  line = leftJustify(line, 60);
657  line += validUntilString; // "VALID UNTIL";
658  strm << leftJustify(line, 80) << endl;
659  strm.lineNumber++;
660  }
661 
662  if (valid & sinexCodeValid)
663  {
664  line = leftJustify(rightJustify(sinexCode, 10), 60);
665  line += sinexCodeString; // "SINEX CODE";
666  strm << leftJustify(line, 80) << endl;
667  strm.lineNumber++;
668  }
669 
670  for (i = 0; i < commentList.size(); i++)
671  {
672  line = leftJustify(commentList[i], 60);
673  line += dataCommentString; // "COMMENT";
674  strm << leftJustify(line, 80) << endl;
675  strm.lineNumber++;
676  }
677 
678  // loop over frequency
679  string freqStr;
680  for (it = freqPCVmap.begin(); it != freqPCVmap.end(); it++)
681  {
682  const antennaPCOandPCVData &antpco = it->second;
683 
684  ostringstream oss;
685  freqStr = it->first;
686  line = string(" ");
687  line += freqStr;
688  line = leftJustify(line, 60);
689  line += startFreqString; // "START OF FREQUENCY";
690  strm << leftJustify(line, 80) << endl;
691  strm.lineNumber++;
692 
693  line = string();
694  for (i = 0; i < 3; i++)
695  line += rightJustify(asString(antpco.PCOvalue[i], 2), 10);
696  line = leftJustify(line, 60);
697  line += neuFreqString; // "NORTH / EAST / UP";
698  strm << leftJustify(line, 80) << endl;
699  strm.lineNumber++;
700 
701  // PCVs
702  const azimZenMap &azel = antpco.PCVvalue;
703  for (jt = azel.begin(); jt != azel.end(); jt++)
704  {
705  const zenOffsetMap &zenoffmap = jt->second;
706  if (antpco.hasAzimuth && jt->first > -1.0)
707  {
708  line = rightJustify(asString(jt->first, 1), 8);
709  }
710  else
711  {
712  line = string(" NOAZI");
713  }
714  for (kt = zenoffmap.begin(); kt != zenoffmap.end(); kt++)
715  {
716  line += rightJustify(asString(kt->second, 2), 8);
717  }
718  strm << line << endl;
719  strm.lineNumber++;
720  }
721 
722  line = string(" ");
723  line += freqStr;
724  line = leftJustify(line, 60);
725  line += endOfFreqString; // "END OF FREQUENCY";
726  strm << leftJustify(line, 80) << endl;
727  strm.lineNumber++;
728  }
729 
730  if (valid & (startFreqRMSValid | neuFreqRMSValid | endOfFreqRMSValid))
731  {
732  // loop over frequency again
733  for (it = freqPCVmap.begin(); it != freqPCVmap.end(); it++)
734  {
735  const antennaPCOandPCVData &antpco = it->second;
736  ostringstream oss;
737  freqStr = it->first;
738  line = string(" ");
739  line += freqStr;
740  line = leftJustify(line, 60);
741  line += startFreqRMSString; // "START OF FREQ RMS";
742  strm << leftJustify(line, 80) << endl;
743  strm.lineNumber++;
744 
745  line = string();
746  for (i = 0; i < 3; i++)
747  line += rightJustify(asString(antpco.PCOrms[i], 2), 10);
748  line = leftJustify(line, 60);
749  line += neuFreqRMSString; // "NORTH / EAST / UP";
750  strm << leftJustify(line, 80) << endl;
751  strm.lineNumber++;
752 
753  // PCVs
754  const azimZenMap &azel = antpco.PCVrms;
755  for (jt = azel.begin(); jt != azel.end(); jt++)
756  {
757  const zenOffsetMap &zenoffmap = jt->second;
758  if (antpco.hasAzimuth)
759  {
760  line = rightJustify(asString(jt->first, 1), 8);
761  }
762  else
763  {
764  line = string(" NOAZI");
765  }
766  for (kt = zenoffmap.begin(); kt != zenoffmap.end(); kt++)
767  {
768  line += rightJustify(asString(kt->second, 2), 8);
769  }
770  strm << line << endl;
771  strm.lineNumber++;
772  }
773 
774  line = string(" ");
775  line += freqStr;
776  line = leftJustify(line, 60);
777  line += endOfFreqRMSString; // "END OF FREQ RMS";
778  strm << leftJustify(line, 80) << endl;
779  strm.lineNumber++;
780  }
781  }
782 
783  line = rightJustify(leftJustify(endOfAntennaString, 20), 80);
784  strm << line << endl;
785  strm.lineNumber++;
786 
787  } // end AntexData::reallyPutRecord
788 
790  {
791  AntexStream &strm = dynamic_cast<AntexStream &>(ffs);
792 
793  // If the header hasn't been read, read it...
794  if (!strm.headerRead)
795  {
796  strm >> strm.header;
797  }
798 
799  // Clear out this object
800  AntexData ad;
801  *this = ad;
802 
803  string line;
804 
805  while (!(valid & endOfAntennaValid))
806  {
807  strm.formattedGetLine(line, true);
808  stripTrailing(line);
809 
810  if (line.length() == 0)
811  {
812  continue;
813  }
814 
815  try
816  {
817  ParseDataRecord(line);
818  }
819  catch (FFStreamError& e)
820  {
821  GNSSTK_THROW(e);
822  }
823  }
824 
825  } // end of reallyGetRecord()
826 
827  // ----------------------------------------------------------------------------
828  // private routines
829 
830  /* helper routine for ParseDataRecord
831  throw if valid contains test, i.e. !(test & valid) */
832  void AntexData::throwRecordOutOfOrder(unsigned long test, string& label)
833  {
834  if (test & valid)
835  {
836  FFStreamError fse(string("Records are out of order: detected at ") +
837  label);
838  GNSSTK_THROW(fse);
839  }
840  }
841 
842  // for reallyGetRecord
843  void AntexData::ParseDataRecord(string& line)
844  {
845  try
846  {
847  static bool hasAzim, foundRMS(false);
848  // static int freq;
849  static string freq;
850  string label(line, 60, 20);
851 
852  if (label == startAntennaString)
853  { // "START OF ANTENNA"
854  throwRecordOutOfOrder(typeSerNumValid, label);
855  valid |= startAntennaValid;
856  }
857  else if (label == typeSerNumString)
858  { // "TYPE / SERIAL NO"
859  throwRecordOutOfOrder(methodValid, label);
860  type = stripTrailing(stripLeading(line.substr(0, 20)));
861  // determine if satellite
862  isRxAntenna = true;
863  for (size_t i = 0; i < AntexData::SatelliteTypes.size(); i++)
864  if (type == AntexData::SatelliteTypes[i])
865  {
866  isRxAntenna = false;
867  break;
868  }
869  serialNo = stripTrailing(stripLeading(line.substr(20, 20)));
870  satCode = stripTrailing(stripLeading(line.substr(40, 10)));
871  cospar = stripTrailing(stripLeading(line.substr(50, 10)));
872  if (!isRxAntenna)
873  { // get the PRN and SVN numbers
874  if (serialNo.length() > 1)
875  {
876  PRN = asInt(serialNo.substr(1, 2));
877  }
878  else
879  {
880  PRN = -1;
881  }
882  if (satCode.length() > 1)
883  {
884  SVN = asInt(satCode.substr(1, 3));
885  }
886  else
887  {
888  SVN = -1;
889  }
890  systemChar = line[20];
891  }
892  valid |= typeSerNumValid;
893  }
894  else if (label == methodString)
895  { // "METH / BY / # / DATE"
896  throwRecordOutOfOrder(daziValid, label);
897  method = stripTrailing(stripLeading(line.substr(0, 20)));
898  agency = stripTrailing(stripLeading(line.substr(20, 20)));
899  noAntCalibrated = asInt(line.substr(40, 6));
900  date = stripTrailing(stripLeading(line.substr(50, 10)));
901  valid |= methodValid;
902  }
903  else if (label == daziString)
904  { // "DAZI"
905  throwRecordOutOfOrder(zenithValid, label);
906  azimDelta = asDouble(line.substr(2, 6));
907  if (azimDelta > 0.0)
908  {
909  hasAzim = true;
910  }
911  else
912  {
913  hasAzim = false;
914  }
915  valid |= daziValid;
916  }
917  else if (label == zenithString)
918  { // "ZEN1 / ZEN2 / DZEN"
919  throwRecordOutOfOrder(numFreqValid, label);
920  zenRange[0] = asDouble(line.substr(2, 6)); // NB. zenith angles
921  zenRange[1] = asDouble(line.substr(8, 6)); // not elevation angles
922  zenRange[2] = asDouble(line.substr(14, 6));
923  valid |= zenithValid;
924  }
925  else if (label == numFreqString)
926  { // "# OF FREQUENCIES"
927  throwRecordOutOfOrder(validFromValid | validUntilValid |
928  sinexCodeValid | dataCommentValid |
929  startFreqValid,
930  label);
931  nFreq = (unsigned int)(asInt(line.substr(0, 6)));
932  valid |= numFreqValid;
933  }
934  else if (label == validFromString)
935  { // "VALID FROM"
936  throwRecordOutOfOrder(validUntilValid | sinexCodeValid |
937  dataCommentValid | startFreqValid,
938  label);
939  stringValidFrom = line.substr(0, 43);
940  validFrom = parseTime(line);
941  valid |= validFromValid;
942  }
943  else if (label == validUntilString)
944  { // "VALID UNTIL"
945  throwRecordOutOfOrder(
946  sinexCodeValid | dataCommentValid | startFreqValid, label);
947  stringValidUntil = line.substr(0, 43);
948  validUntil = parseTime(line);
949  if (validUntil == CommonTime::BEGINNING_OF_TIME)
950  {
951  validUntil = CommonTime::END_OF_TIME;
952  }
953  valid |= validUntilValid;
954  }
955  else if (label == sinexCodeString)
956  { // "SINEX CODE"
957  throwRecordOutOfOrder(dataCommentValid | startFreqValid, label);
958  sinexCode = stripTrailing(stripLeading(line.substr(0, 10)));
959  valid |= sinexCodeValid;
960  }
961  else if (label == dataCommentString)
962  { // "COMMENT"
963  throwRecordOutOfOrder(startFreqValid, label);
964  string str = stripTrailing(line.substr(0, 60));
965  commentList.push_back(str);
966  valid |= dataCommentValid;
967  }
968  else if (label == startFreqString)
969  { // "START OF FREQUENCY"
970  foundRMS = false;
971  throwRecordOutOfOrder(startFreqRMSValid | neuFreqRMSValid |
972  endOfFreqRMSValid | endOfAntennaValid,
973  label);
974  freq = line.substr(3, 3);
975  valid |= startFreqValid;
976  }
977  else if (label == neuFreqString && !foundRMS)
978  { // "NORTH / EAST / UP"
979  // LOG(INFO) << "Found NORTH / EAST / UP";
980  throwRecordOutOfOrder(startFreqRMSValid | neuFreqRMSValid |
981  endOfFreqRMSValid | endOfAntennaValid,
982  label);
983  freqPCVmap[freq].PCOvalue[0] = asDouble(line.substr(0, 10));
984  freqPCVmap[freq].PCOvalue[1] = asDouble(line.substr(10, 10));
985  freqPCVmap[freq].PCOvalue[2] = asDouble(line.substr(20, 10));
986  valid |= neuFreqValid;
987  // set flag here
988  freqPCVmap[freq].hasAzimuth = hasAzim;
989  }
990  else if (label == endOfFreqString)
991  { // "END OF FREQUENCY"
992  throwRecordOutOfOrder(startFreqRMSValid | neuFreqRMSValid |
993  endOfFreqRMSValid | endOfAntennaValid,
994  label);
995  if (freq != line.substr(3, 3))
996  {
997  FFStreamError fse("START/END OF FREQ confused: " + freq +
998  " != " + line.substr(3, 3));
999  GNSSTK_THROW(fse);
1000  }
1001  valid |= endOfFreqValid;
1002  }
1003  else if (label == startFreqRMSString)
1004  { // "START OF FREQ RMS"
1005  foundRMS = true;
1006  // LOG(INFO) << "Found START OF FREQ RMS";
1007  throwRecordOutOfOrder(endOfAntennaValid, label);
1008  freq = line.substr(3, 3);
1009  valid |= startFreqRMSValid;
1010  }
1011  else if (label == neuFreqRMSString && foundRMS)
1012  { // "NORTH / EAST / UP"
1013  // LOG(INFO) << "Found NORTH / EAST / UP for RMS";
1014  throwRecordOutOfOrder(endOfAntennaValid, label);
1015  freqPCVmap[freq].PCOrms[0] = asDouble(line.substr(0, 10));
1016  freqPCVmap[freq].PCOrms[1] = asDouble(line.substr(10, 10));
1017  freqPCVmap[freq].PCOrms[2] = asDouble(line.substr(20, 10));
1018  valid |= neuFreqRMSValid;
1019  }
1020  else if (label == endOfFreqRMSString)
1021  { // "END OF FREQ RMS"
1022  foundRMS = false;
1023  throwRecordOutOfOrder(endOfAntennaValid, label);
1024  if (freq != line.substr(3, 3))
1025  {
1026  FFStreamError fse("START/END OF FREQ RMS confused: " + freq +
1027  " != " + line.substr(3, 3));
1028  GNSSTK_THROW(fse);
1029  }
1030  valid |= endOfFreqRMSValid;
1031  }
1032  else if (label == endOfAntennaString)
1033  { // "END OF ANTENNA"
1034  valid |= endOfAntennaValid;
1035  }
1036  else
1037  {
1038  // LOG(INFO) << "Found data record, valid is " << hex << valid;
1039  int i, n;
1040  string noazi = line.substr(3, 5);
1041  double azim = asDouble(line.substr(0, 8));
1042  if (!hasAzim && noazi != string("NOAZI"))
1043  {
1044  FFStreamError fse(
1045  "Invalid format; zero delta azimuth without NOAZI");
1046  GNSSTK_THROW(fse);
1047  }
1048 
1049  // NOAZI : data stored under azimuth = -1.0
1050  if (noazi == string("NOAZI"))
1051  {
1052  azim = -1.0;
1053  }
1054 
1055  n = line.length() / 8 - 1;
1056  if (n != 1 + int((zenRange[1] - zenRange[0]) / zenRange[2]))
1057  {
1058  FFStreamError fse(
1059  "Invalid format; wrong number of zenith/offset values");
1060  GNSSTK_THROW(fse);
1061  }
1062 
1063  // loop over values; format is 3x,a5,mf8.2
1064  for (i = 1; i <= n; i++)
1065  {
1066  double value = asDouble(line.substr(8 * i, 8));
1067  double zen = zenRange[0] + (i - 1) * zenRange[2];
1068  if (valid & neuFreqRMSValid)
1069  {
1070  freqPCVmap[freq].PCVrms[azim][zen] = value;
1071  }
1072  else if (valid & neuFreqValid)
1073  {
1074  freqPCVmap[freq].PCVvalue[azim][zen] = value;
1075  }
1076  }
1077 
1078  } // end if/else if/else on record type
1079 
1080  } // end try
1081  catch (FFStreamError& fse)
1082  {
1083  GNSSTK_RETHROW(fse);
1084  }
1085  } // end AntexData::ParseDataRecord
1086 
1087  CommonTime AntexData::parseTime(const string& line) const
1088  {
1089  try
1090  {
1091  // default value
1093 
1094  if (line.substr(0, 42) == string(42, ' '))
1095  {
1096  return time;
1097  }
1098 
1099  /* check if the spaces are in the right place - an easy
1100  way to check if there's corruption in the file
1101  --YYYY----MM----DD----HH----MMsssss.sssssss-----------------
1102  012345678901234567890123456789012345678901234567890123456789
1103  */
1104  if ((line.substr(0, 2) != string(2, ' ')) ||
1105  (line.substr(6, 4) != string(4, ' ')) ||
1106  (line.substr(12, 4) != string(4, ' ')) ||
1107  (line.substr(18, 4) != string(4, ' ')) ||
1108  (line.substr(24, 4) != string(4, ' ')) || (line[43] != ' '))
1109  {
1110  FFStreamError e("Invalid time format");
1111  GNSSTK_THROW(e);
1112  }
1113 
1114  // parse the time
1115  int year, month, day, hour, min;
1116  double sec;
1117 
1118  year = asInt(line.substr(2, 4));
1119  month = asInt(line.substr(10, 4));
1120  day = asInt(line.substr(16, 4));
1121  hour = asInt(line.substr(22, 4));
1122  min = asInt(line.substr(28, 4));
1123  sec = asDouble(line.substr(30, 13));
1124 
1125  time = CivilTime(year, month, day, hour, min, sec);
1126 
1127  return time;
1128  }
1129  // string exceptions for substr are caught here
1130  catch (std::exception& e)
1131  {
1132  FFStreamError err("std::exception: " + string(e.what()));
1133  GNSSTK_THROW(err);
1134  }
1135  catch (Exception& e)
1136  {
1137  string text;
1138  for (size_t i = 0; i < e.getTextCount(); i++)
1139  text += e.getText(i);
1140  FFStreamError err("Exception in parseTime(): " + text);
1141  GNSSTK_THROW(err);
1142  }
1143  }
1144 
1145  string AntexData::writeTime(const CommonTime& dt) const
1146  {
1148  {
1149  return string(43, ' ');
1150  }
1151 
1152  /* --YYYY----MM----DD----HH----MMsssss.sssssss-----------------
1153  012345678901234567890123456789012345678901234567890123456789 */
1154  string line;
1155  CivilTime civ(dt);
1156  line = string(2, ' ');
1157  line += rightJustify(asString<short>(civ.year), 4);
1158  line += string(4, ' ');
1159  line += rightJustify(asString<short>(civ.month), 2);
1160  line += string(4, ' ');
1161  line += rightJustify(asString<short>(civ.day), 2);
1162  line += string(4, ' ');
1163  line += rightJustify(asString<short>(civ.hour), 2);
1164  line += string(4, ' ');
1165  line += rightJustify(asString<short>(civ.minute), 2);
1166  line += rightJustify(asString(civ.second, 7), 13);
1167 
1168  return line;
1169  }
1170 
1171 } // namespace gnsstk
gnsstk::AntexData::ParseDataRecord
void ParseDataRecord(std::string &line)
Definition: AntexData.cpp:843
gnsstk::StringUtils::asInt
long asInt(const std::string &s)
Definition: StringUtils.hpp:713
gnsstk::AntexData::dump
virtual void dump(std::ostream &s, int detail=0) const
Definition: AntexData.cpp:378
example6.day
day
Definition: example6.py:66
gnsstk::AntexData::typeSerNumString
static const GNSSTK_EXPORT std::string typeSerNumString
"TYPE / SERIAL NO"
Definition: AntexData.hpp:129
gnsstk::CivilTime::year
int year
Definition: CivilTime.hpp:198
gnsstk::FFStream
Definition: FFStream.hpp:119
StringUtils.hpp
example6.year
year
Definition: example6.py:64
gnsstk::AntexData::neuFreqRMSString
static const GNSSTK_EXPORT std::string neuFreqRMSString
"NORTH / EAST / UP"
Definition: AntexData.hpp:155
gnsstk::AntexData::writeTime
std::string writeTime(const CommonTime &dt) const
Definition: AntexData.cpp:1145
gnsstk::AntexData::azimZenMap
std::map< double, zenOffsetMap > azimZenMap
Definition: AntexData.hpp:197
gnsstk::AntexData::validUntilString
static const GNSSTK_EXPORT std::string validUntilString
"VALID UNTIL"
Definition: AntexData.hpp:141
gnsstk::FFTextStream::formattedGetLine
void formattedGetLine(std::string &line, const bool expectEOF=false)
Definition: FFTextStream.cpp:149
gnsstk::AntexData::startFreqRMSString
static const GNSSTK_EXPORT std::string startFreqRMSString
"START OF FREQ RMS"
Definition: AntexData.hpp:153
gnsstk::AntexData::antennaPCOandPCVData::PCVvalue
azimZenMap PCVvalue
Definition: AntexData.hpp:222
gnsstk::AntexData::zenithString
static const GNSSTK_EXPORT std::string zenithString
"ZEN1 / ZEN2 / DZEN"
Definition: AntexData.hpp:135
gnsstk::AntexData::throwRecordOutOfOrder
void throwRecordOutOfOrder(unsigned long test, std::string &label)
Definition: AntexData.cpp:832
gnsstk::AntexData::getTotalPhaseCenterOffset
double getTotalPhaseCenterOffset(const std::string &freq, double azimuth, double elevation) const
Definition: AntexData.cpp:169
gnsstk::FFTextStream::lineNumber
unsigned int lineNumber
Definition: FFTextStream.hpp:98
gnsstk::AntexStream
This class reads an Antex files.
Definition: AntexStream.hpp:57
gnsstk::Exception::getTextCount
size_t getTextCount() const
Returns the number of text strings in the exception text stack.
Definition: Exception.cpp:152
example6.hour
hour
Definition: example6.py:67
gnsstk::AntexData::zenOffsetMap
std::map< double, double > zenOffsetMap
map from zenith angle (degrees) to PC offset (millimeters)
Definition: AntexData.hpp:192
gnsstk::AntexData::sinexCodeString
static const GNSSTK_EXPORT std::string sinexCodeString
"SINEX CODE"
Definition: AntexData.hpp:143
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
gnsstk::CommonTime::BEGINNING_OF_TIME
static const GNSSTK_EXPORT CommonTime BEGINNING_OF_TIME
earliest representable CommonTime
Definition: CommonTime.hpp:102
GNSSconstants.hpp
gnsstk::RinexObsID::map1to3sys
static GNSSTK_EXPORT std::map< std::string, std::string > map1to3sys
Definition: RinexObsID.hpp:266
gnsstk::Triple
Definition: Triple.hpp:68
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::StringUtils::stripLeading
std::string & stripLeading(std::string &s, const std::string &aString, std::string::size_type num=std::string::npos)
Definition: StringUtils.hpp:1426
MJD.hpp
std::sin
double sin(gnsstk::Angle x)
Definition: Angle.hpp:144
gnsstk::AntexData::parseTime
CommonTime parseTime(const std::string &line) const
Definition: AntexData.cpp:1087
gnsstk::Exception
Definition: Exception.hpp:151
AntexStream.hpp
gnsstk::AntexData::antennaPCOandPCVData::PCVrms
azimZenMap PCVrms
Definition: AntexData.hpp:222
gnsstk::AntexData::startAntennaString
static const GNSSTK_EXPORT std::string startAntennaString
"START OF ANTENNA"
Definition: AntexData.hpp:127
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::CommonTime::END_OF_TIME
static const GNSSTK_EXPORT CommonTime END_OF_TIME
latest representable CommonTime
Definition: CommonTime.hpp:104
gnsstk::Exception::getText
std::string getText(const size_t &index=0) const
Definition: Exception.cpp:139
gnsstk::AntexData::antennaPCOandPCVData::PCOvalue
double PCOvalue[3]
Definition: AntexData.hpp:210
gnsstk::AntexData::startFreqString
static const GNSSTK_EXPORT std::string startFreqString
"START OF FREQUENCY"
Definition: AntexData.hpp:147
gnsstk::AntexData
Definition: AntexData.hpp:120
gnsstk::AntexData::isValid
bool isValid() const
Convenience function returns true only if a valid object.
Definition: AntexData.hpp:311
example4.time
time
Definition: example4.py:103
gnsstk::AntexData::antennaPCOandPCVData::PCOrms
double PCOrms[3]
Definition: AntexData.hpp:210
gnsstk::AntexStream::headerRead
bool headerRead
Whether or not the AntexHeader has been read.
Definition: AntexStream.hpp:85
example4.err
err
Definition: example4.py:126
RinexObsID.hpp
example6.agency
agency
Definition: example6.py:26
gnsstk::CommonTime
Definition: CommonTime.hpp:84
gnsstk::min
T min(const SparseMatrix< T > &SM)
Maximum element - return 0 if empty.
Definition: SparseMatrix.hpp:858
gnsstk::AntexData::endOfAntennaString
static const GNSSTK_EXPORT std::string endOfAntennaString
"END OF ANTENNA"
Definition: AntexData.hpp:159
example6.valid
valid
Definition: example6.py:20
CivilTime.hpp
std::cos
double cos(gnsstk::Angle x)
Definition: Angle.hpp:146
gnsstk::StringUtils::asDouble
double asDouble(const std::string &s)
Definition: StringUtils.hpp:705
gnsstk::AntexData::evaluateZenithMap
void evaluateZenithMap(double zen, const zenOffsetMap &eomap, double &zen_lo, double &zen_hi, double &pco_lo, double &pco_hi) const
Definition: AntexData.cpp:532
GNSSTK_RETHROW
#define GNSSTK_RETHROW(exc)
Definition: Exception.hpp:369
AntexData.hpp
gnsstk::CivilTime::minute
int minute
Definition: CivilTime.hpp:202
gnsstk::AntexData::endOfFreqRMSString
static const GNSSTK_EXPORT std::string endOfFreqRMSString
"END OF FREQ RMS"
Definition: AntexData.hpp:157
gnsstk::MJD::mjd
long double mjd
Definition: MJD.hpp:169
gnsstk::AntexData::antennaPCOandPCVData::hasAzimuth
bool hasAzimuth
Definition: AntexData.hpp:214
gnsstk::CivilTime
Definition: CivilTime.hpp:55
gnsstk::AntexData::name
std::string name() const
Generate a name from type and serial number.
Definition: AntexData.cpp:150
gnsstk::StringUtils
Definition: IonexStoreStrategy.cpp:44
gnsstk::AntexData::numFreqString
static const GNSSTK_EXPORT std::string numFreqString
"# OF FREQUENCIES"
Definition: AntexData.hpp:137
gnsstk::StringUtils::rightJustify
std::string & rightJustify(std::string &s, const std::string::size_type length, const char pad=' ')
Definition: StringUtils.hpp:1557
gnsstk::AntexData::dataCommentString
static const GNSSTK_EXPORT std::string dataCommentString
"COMMENT"
Definition: AntexData.hpp:145
gnsstk::printTime
std::string printTime(const CommonTime &t, const std::string &fmt)
Definition: TimeString.cpp:64
gnsstk::AntexData::methodString
static const GNSSTK_EXPORT std::string methodString
"METH / BY / # / DATE"
Definition: AntexData.hpp:131
std
Definition: Angle.hpp:142
gnsstk::CivilTime::month
int month
Definition: CivilTime.hpp:199
gnsstk::AntexData::endOfFreqString
static const GNSSTK_EXPORT std::string endOfFreqString
"END OF FREQUENCY"
Definition: AntexData.hpp:151
gnsstk::CivilTime::second
double second
Definition: CivilTime.hpp:203
gnsstk::AntexData::getPhaseCenterOffset
Triple getPhaseCenterOffset(const std::string &freq) const
Definition: AntexData.cpp:205
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::AntexData::reallyPutRecord
virtual void reallyPutRecord(FFStream &s) const
Definition: AntexData.cpp:573
example6.month
month
Definition: example6.py:65
gnsstk::AntexData::getPhaseCenterVariation
double getPhaseCenterVariation(const std::string &freq, double azimuth, double elev_nadir) const
Definition: AntexData.cpp:234
gnsstk::AntexData::validFromString
static const GNSSTK_EXPORT std::string validFromString
"VALID FROM"
Definition: AntexData.hpp:139
gnsstk::AntexData::neuFreqString
static const GNSSTK_EXPORT std::string neuFreqString
"NORTH / EAST / UP"
Definition: AntexData.hpp:149
gnsstk::AntexStream::header
AntexHeader header
The header for this file.
Definition: AntexStream.hpp:88
gnsstk::AntexData::daziString
static const GNSSTK_EXPORT std::string daziString
"DAZI"
Definition: AntexData.hpp:133
gnsstk::AntexData::SatelliteTypes
static const GNSSTK_EXPORT std::vector< std::string > SatelliteTypes
Definition: AntexData.hpp:189
gnsstk::AntexData::antennaPCOandPCVData
Definition: AntexData.hpp:203
TimeString.hpp
gnsstk::CivilTime::hour
int hour
Definition: CivilTime.hpp:201
gnsstk::AntexData::reallyGetRecord
virtual void reallyGetRecord(FFStream &s)
Definition: AntexData.cpp:789
gnsstk::DEG_TO_RAD
static const double DEG_TO_RAD
Conversion Factor from degrees to radians (units: degrees^-1)
Definition: GNSSconstants.hpp:76


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