EngAlmanac.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 "gps_constants.hpp"
45 #include "CommonTime.hpp"
46 #include "EngAlmanac.hpp"
47 
48 using namespace std;
49 using namespace gnsstk;
50 
51 // This is a macro in order to retain useful location information in the exc
52 #define CHECK_SV_HERE(itty, prn) \
53 if (itty == almPRN.end()) \
54 { \
55  SVNotPresentException \
56  exc("Attempt to get data from EngAlmanac from a SV that is not" \
57  " present."); \
58  GNSSTK_THROW(exc); \
59 }
60 
61 namespace gnsstk
62 {
63  EngAlmanac :: EngAlmanac()
64  noexcept
65  {
66  for (int n = 0; n < 4; n++)
67  {
68  alpha[n] = beta[n] = 0.0;
69  }
70 
71  A0 = A1 = dt_ls = dt_lsf = 0.0;
72 
73  t_ot = t_oa = 0;
74 
75  wn_t = wn_lsf = 0;
76 
77  alm_wk = wn_a = 0;
78 
79  dn = 0;
80 
81  haveUTC = false;
82  }
83 
84  bool EngAlmanac::addSubframe(const long subframe[10],
85  const int gpsWeek)
86  {
87  uint32_t tinput[10];
88  for (int n=0;n<10;++n)
89  tinput[n] = static_cast<uint32_t>( subframe[n] );
90  return( addSubframe( tinput, static_cast<const short>( gpsWeek )));
91  }
92 
93  bool EngAlmanac::addSubframe(const uint32_t subframe[10],
94  const short gpsWeek)
95  {
96  double ficked[60];
97 
98  if (!subframeConvert(subframe, gpsWeek, ficked))
99  return false;
100 
101  short pat = getSubframePattern(subframe);
102 
103  // check tlm preamble, subframe id and format #
104  if ((ficked[0] != 0x8b) || ((ficked[4] != 4) && (ficked [4] != 5))
105  || (pat < 4) || (pat > 10))
106  {
107  InvalidParameter
108  exc("EngAlmanac::addSubframe: Not a valid almanac page.");
109  GNSSTK_THROW(exc);
110  }
111 
112  //short svid = (subframe[3] >> 22) & 0x3F;
113  //short sfid = (subframe[2] >> 8) & 0x7;
114  //long tow = ((subframe[2] >> 13) & 0x1ffff) * 6;
115 
116  switch(pat)
117  {
118  case 4:
119  /* Page with Orbital Elements */
120  /*check PRN */
121  if ((ficked[19] < 0) || (ficked[19] > MAX_PRN_GPS))
122  {
123  InvalidParameter exc("EngAlmanac::addSubframe, PRN out of range "
124  + StringUtils::asString(ficked[19]));
125  GNSSTK_THROW(exc);
126  }
127  {
128  int prn = static_cast<short>( ficked[19] );
129  if (prn) {
130  SatID sat(prn,SatelliteSystem::GPS);
131  almPRN[sat] = AlmOrbit(prn, ficked[7], ficked[9], ficked[10],
132  ficked[12], ficked[13], ficked[14],
133  ficked[15], ficked[16], ficked[17],
134  static_cast<long>( ficked[8] ),
135  static_cast<long>( ficked[2] ),
136  gpsWeek,
137  static_cast<short>( ficked[11] ));
138  }
139  }
140  break;
141 
142  case 5: /* Page with Satellite health information 1-24 */
143  for (int i=1; i <=24; i++)
144  health[i] = static_cast<char>( ficked[7 + i] );
145  // manually crack the t_oa and WNa
146  t_oa = ((subframe[2] >> 14) & 0xFF) * 4096;
147  wn_a = static_cast<int>(ficked[7]);
148  convert8bit(gpsWeek, &ficked[7]);
149  alm_wk = static_cast<int>(ficked[7]);
150  break;
151 
152  case 6:
153  case 7:
154  /* ignore page becase no data for our structure */
155  return true;
156 
157  case 8: /* Page with UTC and ionosphere parameters */
158  alpha[0] = ficked[7];
159  alpha[1] = ficked[8];
160  alpha[2] = ficked[9];
161  alpha[3] = ficked[10];
162  beta[0] = ficked[11];
163  beta[1] = ficked[12];
164  beta[2] = ficked[13];
165  beta[3] = ficked[14];
166  A0 = ficked[15];
167  A1 = ficked[16];
168  dt_ls = ficked[19];
169  t_ot = static_cast<long>( ficked[17] );
170  wn_t = static_cast<int>( ficked[18] );
171  wn_lsf = static_cast<int>( ficked[20] );
172  dn = static_cast<char>( ficked[21] );
173  dt_lsf = ficked[22];
174  haveUTC = true;
175  break;
176 
177  case 9: /* Page with Health for 25-32 and AS/SV config */
178  for (int i=1; i<=MAX_PRN_GPS; i++)
179  SV_config[i] = static_cast<char>( ficked[6 + i] );
180 
181  for (int i=25; i<=MAX_PRN_GPS; i++)
182  health[i] = static_cast<char>( ficked[14 + i] );
183  break;
184 
185  case 10:/* Page with Special Message */
186  special_msg = "";
187  for (int i=0; i<22; i++)
188  special_msg += static_cast<char>( ficked[7 + i] );
189  break;
190 
191  default:
192  // never reached, see if statement prior to this switch
193  break;
194  }
195  return true;
196  }
197 
198  double EngAlmanac::getEcc(SatID sat) const
199  {
200  AlmOrbits::const_iterator i = almPRN.find(sat);
201  CHECK_SV_HERE(i, sat);
202 
203  // return value of the ecc for the given PRN
204  return (*i).second.ecc;
205  }
206 
207  double EngAlmanac::getIOffset(SatID sat) const
208  {
209  AlmOrbits::const_iterator i = almPRN.find(sat);
210  CHECK_SV_HERE(i, sat);
211 
212  // return value of the iOffset for the given PRN
213  return (*i).second.i_offset;
214  }
215 
216  double EngAlmanac::getOmegadot(SatID sat) const
217  {
218 
219  AlmOrbits::const_iterator i = almPRN.find(sat);
220  CHECK_SV_HERE(i, sat);
221 
222  // return value of OMEGAdot for the given PRN
223  return (*i).second.OMEGAdot;
224  }
225 
226  short EngAlmanac::get6bitHealth(SatID sat) const
227  {
228  SVBitsMap::const_iterator i = health.find(sat.id);
229  if (i == health.end())
230  {
231  SVNotPresentException svnpe("SV health not present for PRN " +
233  GNSSTK_THROW(svnpe);
234  }
235 
236  return i->second;
237  }
238 
239  short EngAlmanac::getSVHealth(SatID sat) const
240  {
241  AlmOrbits::const_iterator i = almPRN.find(sat);
242  CHECK_SV_HERE(i, sat);
243 
244  // return value of SV_health for the given PRN
245  return (*i).second.SV_health;
246  }
247 
248  short EngAlmanac::getSVConfig(SatID sat) const
249  {
250  SVBitsMap::const_iterator i = SV_config.find(sat.id);
251  if (i == SV_config.end())
252  {
253  SVNotPresentException svnpe("SV Configuration not present for PRN " +
255  GNSSTK_THROW(svnpe);
256  }
257 
258  return i->second;
259  }
260 
261  double EngAlmanac::getAhalf(SatID sat) const
262  {
263  AlmOrbits::const_iterator i = almPRN.find(sat);
264  CHECK_SV_HERE(i, sat);
265 
266  // return value of Ahalf for the given PRN
267  return (*i).second.Ahalf;
268  }
269 
270  double EngAlmanac::getA(SatID sat) const
271  {
272  AlmOrbits::const_iterator i = almPRN.find(sat);
273  CHECK_SV_HERE(i, sat);
274 
275  // return value of A for the given PRN
276  return (*i).second.Ahalf * (*i).second.Ahalf;
277  }
278 
279  double EngAlmanac::getOmega0(SatID sat) const
280  {
281 
282  AlmOrbits::const_iterator i = almPRN.find(sat);
283  CHECK_SV_HERE(i, sat);
284 
285  // return value of OMEGA0 for the given PRN
286  return (*i).second.OMEGA0;
287  }
288 
289  double EngAlmanac::getW(SatID sat) const
290  {
291  AlmOrbits::const_iterator i = almPRN.find(sat);
292  CHECK_SV_HERE(i, sat);
293 
294  // return value of w for the given PRN
295  return (*i).second.w;
296  }
297 
298  double EngAlmanac::getM0(SatID sat) const
299  {
300  AlmOrbits::const_iterator i = almPRN.find(sat);
301  CHECK_SV_HERE(i, sat);
302 
303  // return value of M0 for the given PRN
304  return (*i).second.M0;
305  }
306 
307  double EngAlmanac::getAf0(SatID sat) const
308  {
309  AlmOrbits::const_iterator i = almPRN.find(sat);
310  CHECK_SV_HERE(i, sat);
311 
312  // return value of the af0 for the given PRN
313  return (*i).second.AF0;
314  }
315 
316 
317  double EngAlmanac::getAf1(SatID sat) const
318  {
319  AlmOrbits::const_iterator i = almPRN.find(sat);
320  CHECK_SV_HERE(i, sat);
321 
322  // return value of af1 for the given PRN
323  return (*i).second.AF1;
324  }
325 
326 
327  double EngAlmanac::getToa() const noexcept
328  {
329  return static_cast<double>( t_oa );
330  }
331 
332  double EngAlmanac::getToa(SatID sat) const
333  {
334  AlmOrbits::const_iterator i = almPRN.find(sat);
335  CHECK_SV_HERE(i, sat);
336 
337  // return value of the Toa for the given PRN
338  return static_cast<double>( (*i).second.Toa );
339  }
340 
341 
342  double EngAlmanac::getXmitTime(SatID sat) const
343  {
344  AlmOrbits::const_iterator i = almPRN.find(sat);
345  CHECK_SV_HERE(i, sat);
346 
347  // return value of the xmit_time for the given PRN
348  return static_cast<double>( (*i).second.xmit_time );
349  }
350 
351 
352  short EngAlmanac::getFullWeek(SatID sat) const
353  {
354  AlmOrbits::const_iterator i = almPRN.find(sat);
355  CHECK_SV_HERE(i, sat);
356 
357  return (*i).second.getFullWeek();
358  }
359 
360  void EngAlmanac::getIon(double a[4], double b[4]) const
361  {
362  if (!haveUTC)
363  {
364  InvalidRequest
365  exc("UTC offset (subframe 4, page 18) is not present.");
366  GNSSTK_THROW(exc);
367  }
368  for (int n = 0; n < 4; n++)
369  {
370  a[n] = alpha[n];
371  b[n] = beta[n];
372  }
373  }
374 
375  void EngAlmanac::getUTC(double& a0, double& a1, double& deltaTLS,
376  long& tot, int& WNt, int& WNLSF,
377  int& DN, double& deltaTLSF) const
378  {
379  if (!haveUTC)
380  {
381  InvalidRequest
382  exc("UTC offset (subframe 4, page 18) is not present.");
383  GNSSTK_THROW(exc);
384  }
385  a0 = A0;
386  a1 = A1;
387  deltaTLS = dt_ls;
388  tot = t_ot;
389  WNt = wn_t;
390  WNLSF = wn_lsf;
391  DN = static_cast<int>( dn );
392  deltaTLSF = dt_lsf;
393  }
394 
395  short EngAlmanac::getAlmWeek() const noexcept
396  {
397  return alm_wk;
398  }
399 
400  AlmOrbit EngAlmanac::getAlmOrbElem(SatID sat) const
401  {
402  AlmOrbits::const_iterator i = almPRN.find(sat);
403  CHECK_SV_HERE(i, sat);
404 
405  // return value of the orbit elm. for the given PRN
406  return (*i).second;
407  }
408 
409  Xvt EngAlmanac::svXvt(SatID sat, const CommonTime& t) const
410  {
411  AlmOrbits::const_iterator i = almPRN.find(sat);
412  CHECK_SV_HERE(i, sat);
413 
414  // return value of the orbit elm. for the given PRN
415  return (*i).second.svXvt(t);
416  }
417 
418  bool EngAlmanac::isData(SatID sat) const noexcept
419  {
420  return (almPRN.find(sat) != almPRN.end());
421  }
422 
423  string int2bin(unsigned int v, int len=8)
424  {
425  string s;
426  for (int i = 0; i < len; i++)
427  {
428  if (v & 1)
429  s = "1" + s;
430  else
431  s = "0" + s;
432  v = v >> 1;
433  }
434  return s;
435  }
436 
437 
438  bool EngAlmanac::check(ostream& s) const
439  {
440  bool good = false;
441 
442  if (!haveUTC)
443  s << "UTC offset (subframe 4, page 18) is not present." << endl;
444 
445  double p51Toa=getToa();
446  for (int prn=1; prn<=32; prn++)
447  {
448  try
449  {
450  double svToa = getToa(gnsstk::SatID(prn, SatelliteSystem::GPS));
451  if (svToa != p51Toa)
452  {
453  s << "Toa mis-match on prn " << prn
454  << " page 51 Toa=" << p51Toa
455  << ", SV Toa=" << svToa << endl;
456  good = false;
457  }
458  }
459  catch (SVNotPresentException& e)
460  {
461  cout << "No page for prn " << prn << endl;
462  }
463  }
464  return good;
465  }
466 
467 
468  void EngAlmanac::dump(ostream& s, bool checkFlag) const
469  {
470  ios::fmtflags oldFlags = s.flags();
471 
472  s.fill(' ');
473 
474  s << "****************************************************************"
475  << "***************" << endl
476  << "Broadcast Almanac (Engineering Units)" << endl
477  << endl;
478 
479  s << endl << " Iono Parameters" << endl << endl;
480  s << "Alpha: " << scientific << setprecision(6);
481  for (int i=0; i<4; i++)
482  s << setw(13) << alpha[i] << " ";
483  s << " various" << endl;
484  s << " Beta: " << fixed << setprecision(1);
485  for (int i=0; i<4; i++)
486  s << setw(13) << beta[i] << " ";
487  s << " various" << endl;
488 
489  s << endl << " UTC Paramters" << endl << endl;
490  s << scientific << setprecision(8)
491  << "A0: " << setw(15) << A0 << " sec" << endl
492  << "A1: " << setw(15) << A1 << " sec/sec" << endl
493  << fixed << setprecision(1)
494  << "dt_ls: " << setw(15) << dt_ls << " sec" << endl
495  << "t_ot: " << setw(15) << t_ot << " sec" << endl
496  << "wn_t: " << setw(15) << wn_t << " week" << endl
497  << "wn_lsf " << setw(15) << wn_lsf << " week" << endl
498  << "dn: " << setw(15) << (int)dn << " days" << endl
499  << "dt_lsf: " << setw(15) << dt_lsf << " sec" << endl;
500 
501  s << endl << " Orbit Parameters" << endl << endl;
502  for (AlmOrbits::const_iterator i = almPRN.begin(); i != almPRN.end(); i++)
503  s<< scientific << (*i).second;
504 
505  s << endl << " Special Message" << endl << endl;
506  StringUtils::hexDumpData(s, special_msg);
507 
508 
509  s << endl << " Page 25 Health, AS, & SV config" << endl << endl;
510 
511  s << "Toa: " << setfill(' ') << setw(8) << t_oa
512  << ", week: " << setw(5) << wn_a << " (" << alm_wk << ")" << endl
513  << endl
514  << "PRN health AS cfg PRN health AS cfg" << endl;
515  string bits[33];
516 
517  for (SVBitsMap::const_iterator i = health.begin(); i != health.end(); i++)
518  {
519  int prn = i->first;
520  if (prn >= 1 && prn <= 32)
521  bits[prn] = int2bin(i->second, 6);
522  }
523 
524  for (SVBitsMap::const_iterator i = SV_config.begin(); i != SV_config.end(); i++)
525  {
526  int prn = i->first;
527  if (prn >= 1 && prn <= 32)
528  {
529  bits[prn] += " " + int2bin(i->second, 4);
530  bits[prn].insert(9, " ");
531  }
532  }
533 
534  for (int i=1; i<=16; i++)
535  s << setw(2) << i << " " << bits[i] << " "
536  << setw(2) << i+16 << " " << bits[i+16] << endl;
537 
538  s << endl;
539 
540  if (checkFlag)
541  check(s);
542 
543  s << endl;
544 
545  s.flags(oldFlags);
546  } // end of dump()
547 
548  std::ostream& operator<<(std::ostream& s, const EngAlmanac& alm)
549  {
550  alm.dump(s);
551  return s;
552  }
553 
554 } // namespace
gnsstk::dump
void dump(vector< SatPass > &SatPassList, ostream &os, bool rev, bool dbug)
Definition: SatPassUtilities.cpp:59
gnsstk::SatID::id
int id
Satellite identifier, e.g. PRN.
Definition: SatID.hpp:154
const
#define const
Definition: getopt.c:43
gps_constants.hpp
EngAlmanac.hpp
gnsstk::SatID
Definition: SatID.hpp:89
gnsstk::StringUtils::asString
std::string asString(IonexStoreStrategy e)
Convert a IonexStoreStrategy to a whitespace-free string name.
Definition: IonexStoreStrategy.cpp:46
gnsstk
For Sinex::InputHistory.
Definition: BasicFramework.cpp:50
gnsstk::MAX_PRN_GPS
const long MAX_PRN_GPS
Definition: gps_constants.hpp:59
gnsstk::EngAlmanac
Definition: EngAlmanac.hpp:71
gnsstk::StringUtils::hexDumpData
void hexDumpData(const std::string &data, std::ostream &s, const HexDumpDataConfig &cfg)
Definition: StringUtils.cpp:62
gnsstk::CommonTime
Definition: CommonTime.hpp:84
gnsstk::Xvt
Definition: Xvt.hpp:60
gnsstk::beta
double beta(double x, double y)
Definition: SpecialFuncs.cpp:204
std::operator<<
std::ostream & operator<<(std::ostream &s, gnsstk::StringUtils::FFLead v)
Definition: FormattedDouble_T.cpp:44
gnsstk::int2bin
string int2bin(unsigned int v, int len=8)
Definition: EngAlmanac.cpp:423
CHECK_SV_HERE
#define CHECK_SV_HERE(itty, prn)
Definition: EngAlmanac.cpp:52
A1
static const int A1
Definition: DiscCorr.cpp:630
CommonTime.hpp
std
Definition: Angle.hpp:142
GNSSTK_THROW
#define GNSSTK_THROW(exc)
Definition: Exception.hpp:366
gnsstk::EngAlmanac::dump
void dump(std::ostream &s=std::cout, bool checkFlag=true) const
Definition: EngAlmanac.cpp:468
gnsstk::AlmOrbit
Definition: AlmOrbit.hpp:59


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