EngAlmanac.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: EngAlmanac.cpp 3184 2012-07-01 13:11:07Z yanweignss $"
00002 
00003 
00004 
00005 //============================================================================
00006 //
00007 //  This file is part of GPSTk, the GPS Toolkit.
00008 //
00009 //  The GPSTk is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU Lesser General Public License as published
00011 //  by the Free Software Foundation; either version 2.1 of the License, or
00012 //  any later version.
00013 //
00014 //  The GPSTk is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //  GNU Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with GPSTk; if not, write to the Free Software Foundation,
00021 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00022 //  
00023 //  Copyright 2004, The University of Texas at Austin
00024 //
00025 //============================================================================
00026 
00027 //============================================================================
00028 //
00029 //This software developed by Applied Research Laboratories at the University of
00030 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00031 //Department of Defense. The U.S. Government retains all rights to use,
00032 //duplicate, distribute, disclose, or release this software. 
00033 //
00034 //Pursuant to DoD Directive 523024 
00035 //
00036 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00037 //                           release, distribution is unlimited.
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 // This is a macro in order to retain useful location information in the exc
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          // check tlm preamble, subframe id and format #
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                /* Page with Orbital Elements */
00119                /*check PRN */
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:  /*  Page with Satellite health information 1-24 */
00141             for (int i=1; i <=24; i++)
00142                health[i] = static_cast<char>( ficked[7 + i] );
00143                // manually crack the t_oa and WNa
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                /* ignore page becase no data for our structure */
00152             return true;
00153 
00154          case 8: /* Page with UTC and ionosphere parameters */
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:  /* Page with Health for 25-32 and AS/SV config */
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:/* Page with Special Message */
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                // never reached, see if statement prior to this switch
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          // return value of the ecc for the given PRN
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          // return value of the iOffset for the given PRN
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          // return value of OMEGAdot for the given PRN
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          // return value of SV_health for the given PRN
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          // return value of Ahalf for the given PRN
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          // return value of A for the given PRN
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          // return value of OMEGA0 for the given PRN
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          // return value of w for the given PRN
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          // return value of M0 for the given PRN
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          // return value of the af0 for the given PRN
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          // return value of af1 for the given PRN
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          // return value of the Toa for the given PRN
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          // return value of the xmit_time for the given PRN
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          // return value of the orbit elm. for the given PRN
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          // return value of the orbit elm. for the given PRN
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    } // end of dump()
00563 
00564    std::ostream& operator<<(std::ostream& s, const EngAlmanac& alm)
00565    {
00566       alm.dump(s);
00567       return s;
00568    }
00569    
00570 } // namespace

Generated on Sat May 25 03:31:08 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1