00001 #pragma ident "$Id: EngAlmanac.cpp 3184 2012-07-01 13:11:07Z yanweignss $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00051 #include "gps_constants.hpp"
00052 #include "CommonTime.hpp"
00053 #include "EngAlmanac.hpp"
00054
00055 using namespace std;
00056 using namespace gpstk;
00057
00058
00059 #define CHECK_SV_HERE(itty, prn) \
00060 if (itty == almPRN.end()) \
00061 { \
00062 SVNotPresentException \
00063 exc("Attempt to get data from EngAlmanac from a SV that is not" \
00064 " present."); \
00065 GPSTK_THROW(exc); \
00066 }
00067
00068 namespace gpstk
00069 {
00070 EngAlmanac :: EngAlmanac()
00071 throw()
00072 {
00073 for (int n = 0; n < 4; n++)
00074 {
00075 alpha[n] = beta[n] = 0.0;
00076 }
00077
00078 A0 = A1 = dt_ls = dt_lsf = 0.0;
00079
00080 t_ot = t_oa = 0;
00081
00082 wn_t = wn_lsf = 0;
00083
00084 alm_wk = 0;
00085
00086 dn = 0;
00087
00088 haveUTC = false;
00089 }
00090
00091 bool EngAlmanac::addSubframe(const long subframe[10],
00092 const int gpsWeek)
00093 throw(InvalidParameter)
00094 {
00095 double ficked[60];
00096
00097 if (!subframeConvert(subframe, gpsWeek, ficked))
00098 return false;
00099
00100 short pat = getSubframePattern(subframe);
00101
00102
00103 if ((ficked[0] != 0x8b) || ((ficked[4] != 4) && (ficked [4] != 5))
00104 || (pat < 4) || (pat > 10))
00105 {
00106 InvalidParameter
00107 exc("EngAlmanac::addSubframe: Not a valid almanac page.");
00108 GPSTK_THROW(exc);
00109 }
00110
00111 short svid = (subframe[3] >> 22) & 0x3F;
00112 short sfid = (subframe[2] >> 8) & 0x7;
00113 long tow = ((subframe[2] >> 13) & 0x1ffff) * 6;
00114
00115 switch(pat)
00116 {
00117 case 4:
00118
00119
00120 if ((ficked[19] < 0) || (ficked[19] > MAX_PRN_GPS))
00121 {
00122 InvalidParameter exc("EngAlmanac::addSubframe, PRN out of range "
00123 + StringUtils::asString(ficked[19]));
00124 GPSTK_THROW(exc);
00125 }
00126 {
00127 int prn = static_cast<short>( ficked[19] );
00128 if (prn) {
00129 SatID sat(prn,SatID::systemGPS);
00130 almPRN[sat] = AlmOrbit(prn, ficked[7], ficked[9], ficked[10],
00131 ficked[12], ficked[13], ficked[14],
00132 ficked[15], ficked[16], ficked[17],
00133 static_cast<long>( ficked[8] ),
00134 static_cast<long>( ficked[2] ), gpsWeek,
00135 static_cast<short>( ficked[11] ));
00136 }
00137 }
00138 break;
00139
00140 case 5:
00141 for (int i=1; i <=24; i++)
00142 health[i] = static_cast<char>( ficked[7 + i] );
00143
00144 t_oa = ((subframe[2] >> 14) & 0xFF) * 4096;
00145 convert8bit(gpsWeek, &ficked[7]);
00146 alm_wk = static_cast<int>(ficked[7]);
00147 break;
00148
00149 case 6:
00150 case 7:
00151
00152 return true;
00153
00154 case 8:
00155 alpha[0] = ficked[7];
00156 alpha[1] = ficked[8];
00157 alpha[2] = ficked[9];
00158 alpha[3] = ficked[10];
00159 beta[0] = ficked[11];
00160 beta[1] = ficked[12];
00161 beta[2] = ficked[13];
00162 beta[3] = ficked[14];
00163 A0 = ficked[15];
00164 A1 = ficked[16];
00165 dt_ls = ficked[19];
00166 t_ot = static_cast<long>( ficked[17] );
00167 wn_t = static_cast<int>( ficked[18] );
00168 wn_lsf = static_cast<int>( ficked[20] );
00169 dn = static_cast<char>( ficked[21] );
00170 dt_lsf = ficked[22];
00171 haveUTC = true;
00172 break;
00173
00174 case 9:
00175 for (int i=1; i<=MAX_PRN_GPS; i++)
00176 SV_config[i] = static_cast<char>( ficked[6 + i] );
00177
00178 for (int i=25; i<=MAX_PRN_GPS; i++)
00179 health[i] = static_cast<char>( ficked[14 + i] );
00180 break;
00181
00182 case 10:
00183 special_msg = "";
00184 for (int i=0; i<22; i++)
00185 special_msg += static_cast<char>( ficked[7 + i] );
00186 break;
00187
00188 default:
00189
00190 break;
00191 }
00192 return true;
00193 }
00194
00195 double EngAlmanac::getEcc(SatID sat) const
00196 throw(EngAlmanac::SVNotPresentException)
00197 {
00198 AlmOrbits::const_iterator i = almPRN.find(sat);
00199 CHECK_SV_HERE(i, sat);
00200
00201
00202 return (*i).second.ecc;
00203 }
00204
00205 double EngAlmanac::getIOffset(SatID sat) const
00206 throw(EngAlmanac::SVNotPresentException)
00207 {
00208 AlmOrbits::const_iterator i = almPRN.find(sat);
00209 CHECK_SV_HERE(i, sat);
00210
00211
00212 return (*i).second.i_offset;
00213 }
00214
00215 double EngAlmanac::getOmegadot(SatID sat) const
00216 throw(EngAlmanac::SVNotPresentException)
00217 {
00218
00219 AlmOrbits::const_iterator i = almPRN.find(sat);
00220 CHECK_SV_HERE(i, sat);
00221
00222
00223 return (*i).second.OMEGAdot;
00224 }
00225
00226 short EngAlmanac::get6bitHealth(SatID sat) const
00227 throw(EngAlmanac::SVNotPresentException)
00228 {
00229 SVBitsMap::const_iterator i = health.find(sat.id);
00230 if (i == health.end())
00231 {
00232 SVNotPresentException svnpe("SV health not present for PRN " +
00233 StringUtils::asString(sat.id));
00234 GPSTK_THROW(svnpe);
00235 }
00236
00237 return i->second;
00238 }
00239
00240 short EngAlmanac::getSVHealth(SatID sat) const
00241 throw(EngAlmanac::SVNotPresentException)
00242 {
00243 AlmOrbits::const_iterator i = almPRN.find(sat);
00244 CHECK_SV_HERE(i, sat);
00245
00246
00247 return (*i).second.SV_health;
00248 }
00249
00250 short EngAlmanac::getSVConfig(SatID sat) const
00251 throw(EngAlmanac::SVNotPresentException)
00252 {
00253 SVBitsMap::const_iterator i = SV_config.find(sat.id);
00254 if (i == SV_config.end())
00255 {
00256 SVNotPresentException svnpe("SV Configuration not present for PRN " +
00257 StringUtils::asString(sat.id));
00258 GPSTK_THROW(svnpe);
00259 }
00260
00261 return i->second;
00262 }
00263
00264 double EngAlmanac::getAhalf(SatID sat) const
00265 throw(EngAlmanac::SVNotPresentException)
00266 {
00267 AlmOrbits::const_iterator i = almPRN.find(sat);
00268 CHECK_SV_HERE(i, sat);
00269
00270
00271 return (*i).second.Ahalf;
00272 }
00273
00274 double EngAlmanac::getA(SatID sat) const
00275 throw(EngAlmanac::SVNotPresentException)
00276 {
00277 AlmOrbits::const_iterator i = almPRN.find(sat);
00278 CHECK_SV_HERE(i, sat);
00279
00280
00281 return (*i).second.Ahalf * (*i).second.Ahalf;
00282 }
00283
00284 double EngAlmanac::getOmega0(SatID sat) const
00285 throw(EngAlmanac::SVNotPresentException)
00286 {
00287
00288 AlmOrbits::const_iterator i = almPRN.find(sat);
00289 CHECK_SV_HERE(i, sat);
00290
00291
00292 return (*i).second.OMEGA0;
00293 }
00294
00295 double EngAlmanac::getW(SatID sat) const
00296 throw(EngAlmanac::SVNotPresentException)
00297 {
00298 AlmOrbits::const_iterator i = almPRN.find(sat);
00299 CHECK_SV_HERE(i, sat);
00300
00301
00302 return (*i).second.w;
00303 }
00304
00305 double EngAlmanac::getM0(SatID sat) const
00306 throw(EngAlmanac::SVNotPresentException)
00307 {
00308 AlmOrbits::const_iterator i = almPRN.find(sat);
00309 CHECK_SV_HERE(i, sat);
00310
00311
00312 return (*i).second.M0;
00313 }
00314
00315 double EngAlmanac::getAf0(SatID sat) const
00316 throw(EngAlmanac::SVNotPresentException)
00317 {
00318 AlmOrbits::const_iterator i = almPRN.find(sat);
00319 CHECK_SV_HERE(i, sat);
00320
00321
00322 return (*i).second.AF0;
00323 }
00324
00325
00326 double EngAlmanac::getAf1(SatID sat) const
00327 throw(EngAlmanac::SVNotPresentException)
00328 {
00329 AlmOrbits::const_iterator i = almPRN.find(sat);
00330 CHECK_SV_HERE(i, sat);
00331
00332
00333 return (*i).second.AF1;
00334 }
00335
00336
00337 double EngAlmanac::getToa() const throw()
00338 {
00339 return static_cast<double>( t_oa );
00340 }
00341
00342 double EngAlmanac::getToa(SatID sat) const
00343 throw(EngAlmanac::SVNotPresentException)
00344 {
00345 AlmOrbits::const_iterator i = almPRN.find(sat);
00346 CHECK_SV_HERE(i, sat);
00347
00348
00349 return static_cast<double>( (*i).second.Toa );
00350 }
00351
00352
00353 double EngAlmanac::getXmitTime(SatID sat) const
00354 throw(EngAlmanac::SVNotPresentException)
00355 {
00356 AlmOrbits::const_iterator i = almPRN.find(sat);
00357 CHECK_SV_HERE(i, sat);
00358
00359
00360 return static_cast<double>( (*i).second.xmit_time );
00361 }
00362
00363
00364 short EngAlmanac::getFullWeek(SatID sat) const
00365 throw(EngAlmanac::SVNotPresentException)
00366 {
00367 AlmOrbits::const_iterator i = almPRN.find(sat);
00368 CHECK_SV_HERE(i, sat);
00369
00370 return (*i).second.getFullWeek();
00371 }
00372
00373 void EngAlmanac::getIon(double a[4], double b[4]) const
00374 throw(InvalidRequest)
00375 {
00376 if (!haveUTC)
00377 {
00378 InvalidRequest
00379 exc("UTC offset (subframe 4, page 18) is not present.");
00380 GPSTK_THROW(exc);
00381 }
00382 for (int n = 0; n < 4; n++)
00383 {
00384 a[n] = alpha[n];
00385 b[n] = beta[n];
00386 }
00387 }
00388
00389 void EngAlmanac::getUTC(double& a0, double& a1, double& deltaTLS,
00390 long& tot, int& WNt, int& WNLSF,
00391 int& DN, double& deltaTLSF) const
00392 throw(InvalidRequest)
00393 {
00394 if (!haveUTC)
00395 {
00396 InvalidRequest
00397 exc("UTC offset (subframe 4, page 18) is not present.");
00398 GPSTK_THROW(exc);
00399 }
00400 a0 = A0;
00401 a1 = A1;
00402 deltaTLS = dt_ls;
00403 tot = t_ot;
00404 WNt = wn_t;
00405 WNLSF = wn_lsf;
00406 DN = static_cast<int>( dn );
00407 deltaTLSF = dt_lsf;
00408 }
00409
00410 short EngAlmanac::getAlmWeek() const throw()
00411 {
00412 return alm_wk;
00413 }
00414
00415 AlmOrbit EngAlmanac::getAlmOrbElem(SatID sat) const
00416 throw(EngAlmanac::SVNotPresentException)
00417 {
00418 AlmOrbits::const_iterator i = almPRN.find(sat);
00419 CHECK_SV_HERE(i, sat);
00420
00421
00422 return (*i).second;
00423 }
00424
00425 Xvt EngAlmanac::svXvt(SatID sat, const CommonTime& t) const
00426 throw(EngAlmanac::SVNotPresentException)
00427 {
00428 AlmOrbits::const_iterator i = almPRN.find(sat);
00429 CHECK_SV_HERE(i, sat);
00430
00431
00432 return (*i).second.svXvt(t);
00433 }
00434
00435 bool EngAlmanac::isData(SatID sat) const throw()
00436 {
00437 return (almPRN.find(sat) != almPRN.end());
00438 }
00439
00440 string int2bin(unsigned int v, int len=8)
00441 {
00442 string s;
00443 for (int i = 0; i < len; i++)
00444 {
00445 if (v & 1)
00446 s = "1" + s;
00447 else
00448 s = "0" + s;
00449 v = v >> 1;
00450 }
00451 return s;
00452 }
00453
00454
00455 bool EngAlmanac::check(ostream& s) const
00456 {
00457 bool good = false;
00458
00459 if (!haveUTC)
00460 s << "UTC offset (subframe 4, page 18) is not present." << endl;
00461
00462 double p51Toa=getToa();
00463 for (int prn=1; prn<=32; prn++)
00464 {
00465 try
00466 {
00467 double svToa = getToa(gpstk::SatID(prn, SatID::systemGPS));
00468 if (svToa != p51Toa)
00469 {
00470 s << "Toa mis-match on prn " << prn
00471 << " page 51 Toa=" << p51Toa
00472 << ", SV Toa=" << svToa << endl;
00473 good = false;
00474 }
00475 }
00476 catch (SVNotPresentException& e)
00477 {
00478 cout << "No page for prn " << prn << endl;
00479 }
00480 }
00481 return good;
00482 }
00483
00484
00485 void EngAlmanac::dump(ostream& s, bool checkFlag) const
00486 {
00487 ios::fmtflags oldFlags = s.flags();
00488
00489 s.fill(' ');
00490
00491 s << "****************************************************************"
00492 << "***************" << endl
00493 << "Broadcast Almanac (Engineering Units)" << endl
00494 << endl;
00495
00496 s << endl << " Iono Parameters" << endl << endl;
00497 s << "Alpha: " << scientific << setprecision(6);
00498 for (int i=0; i<4; i++)
00499 s << setw(13) << alpha[i] << " ";
00500 s << " various" << endl;
00501 s << " Beta: " << fixed << setprecision(1);
00502 for (int i=0; i<4; i++)
00503 s << setw(13) << beta[i] << " ";
00504 s << " various" << endl;
00505
00506 s << endl << " UTC Paramters" << endl << endl;
00507 s << scientific << setprecision(8)
00508 << "A0: " << setw(15) << A0 << " sec" << endl
00509 << "A1: " << setw(15) << A1 << " sec/sec" << endl
00510 << fixed << setprecision(1)
00511 << "dt_ls: " << setw(15) << dt_ls << " sec" << endl
00512 << "t_ot: " << setw(15) << t_ot << " sec" << endl
00513 << "wn_t: " << setw(15) << wn_t << " week" << endl
00514 << "wn_lsf " << setw(15) << wn_lsf << " week" << endl
00515 << "dn: " << setw(15) << (int)dn << " days" << endl
00516 << "dt_lsf: " << setw(15) << dt_lsf << " sec" << endl;
00517
00518 s << endl << " Orbit Parameters" << endl << endl;
00519 for (AlmOrbits::const_iterator i = almPRN.begin(); i != almPRN.end(); i++)
00520 s<< scientific << (*i).second;
00521
00522 s << endl << " Special Message" << endl << endl;
00523 StringUtils::hexDumpData(s, special_msg);
00524
00525
00526 s << endl << " Page 25 Health, AS, & SV config" << endl << endl;
00527
00528 s << "Toa: " << setfill(' ') << setw(8) << t_oa
00529 << ", week: " << setw(5) << alm_wk << endl << endl
00530 << "PRN health AS cfg PRN health AS cfg" << endl;
00531 string bits[33];
00532
00533 for (SVBitsMap::const_iterator i = health.begin(); i != health.end(); i++)
00534 {
00535 int prn = i->first;
00536 if (prn >= 1 && prn <= 32)
00537 bits[prn] = int2bin(i->second, 6);
00538 }
00539
00540 for (SVBitsMap::const_iterator i = SV_config.begin(); i != SV_config.end(); i++)
00541 {
00542 int prn = i->first;
00543 if (prn >= 1 && prn <= 32)
00544 {
00545 bits[prn] += " " + int2bin(i->second, 4);
00546 bits[prn].insert(9, " ");
00547 }
00548 }
00549
00550 for (int i=1; i<=16; i++)
00551 s << setw(2) << i << " " << bits[i] << " "
00552 << setw(2) << i+16 << " " << bits[i+16] << endl;
00553
00554 s << endl;
00555
00556 if (checkFlag)
00557 check(s);
00558
00559 s << endl;
00560
00561 s.flags(oldFlags);
00562 }
00563
00564 std::ostream& operator<<(std::ostream& s, const EngAlmanac& alm)
00565 {
00566 alm.dump(s);
00567 return s;
00568 }
00569
00570 }