CNAVEphemeris.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: CNAVEphemeris.cpp 3140 2012-06-18 15:03:02Z susancummins $"
00002 
00003 //============================================================================
00004 //
00005 //  This file is part of GPSTk, the GPS Toolkit.
00006 //
00007 //  The GPSTk is free software; you can redistribute it and/or modify
00008 //  it under the terms of the GNU Lesser General Public License as published
00009 //  by the Free Software Foundation; either version 2.1 of the License, or
00010 //  any later version.
00011 //
00012 //  The GPSTk is distributed in the hope that it will be useful,
00013 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 //  GNU Lesser General Public License for more details.
00016 //
00017 //  You should have received a copy of the GNU Lesser General Public
00018 //  License along with GPSTk; if not, write to the Free Software Foundation,
00019 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 
00025 //============================================================================
00026 //
00027 //This software developed by Applied Research Laboratories at the University of
00028 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00029 //Department of Defense. The U.S. Government retains all rights to use,
00030 //duplicate, distribute, disclose, or release this software. 
00031 //
00032 //Pursuant to DoD Directive 523024 
00033 //
00034 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00035 //                           release, distribution is unlimited.
00036 //
00037 //=============================================================================
00038 
00043 #include <iomanip>
00044 #include <cmath>
00045 #include <iostream>
00046 
00047 #include "StringUtils.hpp"
00048 #include "GNSSconstants.hpp"
00049 #include "MathBase.hpp"
00050 #include "GPSEllipsoid.hpp"
00051 #include "CNAVEphemeris.hpp"
00052 #include "GPS_URA.hpp"
00053 
00054 namespace gpstk
00055 {
00056    using namespace std;
00057 
00058    CNAVEphemeris::CNAVEphemeris()
00059       throw()
00060    {
00061       dataLoaded = false;
00062 
00063       satSys = "";
00064 
00065       PRNID = TOWWeek = L1Health = L2Health = L5Health =
00066       TOWCount[0] = TOWCount[1] = Alert[0] = Alert[1] = Top = 0;
00067 
00068    }
00069 
00070    void CNAVEphemeris::loadData( const std::string satSysArg, const ObsID obsIDArg, 
00071                                  const short PRNIDArg, const short AlertMsg10Arg, 
00072                                  const long TOWMsg10Arg, const short AlertMsg11Arg,
00073                                  const long TOWMsg11Arg, const short TOWWeekArg, 
00074                                  const long TopArg, const short URAoeArg,
00075                                            const short L1HealthArg, const short L2HealthArg, 
00076                                            const short L5HealthArg, const double ToeArg, 
00077                                       const double accuracyArg, const double CucArg, 
00078                                  const double CusArg, const double CrcArg, 
00079                                  const double CrsArg, const double CicArg, 
00080                                  const double CisArg, const double M0Arg, 
00081                                  const double dnArg, const double dndotArg,
00082                                            const double eccArg, const double deltaAArg, 
00083                                  const double AdotArg, const double OMEGA0Arg, 
00084                                  const double i0Arg, const double wArg, 
00085                                            const double deltaOMEGAdotArg, const double idotArg )
00086    {
00087       satSys        = satSysArg;
00088            obsID         = obsIDArg;
00089            PRNID         = PRNIDArg;
00090       Alert[0]      = AlertMsg10Arg;
00091       Alert[1]      = AlertMsg11Arg;
00092       TOWCount[0]   = TOWMsg10Arg;
00093       TOWCount[1]   = TOWMsg11Arg;
00094       TOWWeek       = TOWWeekArg;
00095       L1Health      = L1HealthArg;
00096       L2Health      = L2HealthArg;
00097       L5Health      = L5HealthArg;
00098       Top           = TopArg;
00099       short URAoe   = URAoeArg;
00100       double deltaA = deltaAArg;
00101       bool healthy  = false;
00102       if (obsIDArg.band == ObsID::cbL2 && L2Health == 0) healthy = true;
00103       if (obsIDArg.band == ObsID::cbL5 && L5Health == 0) healthy = true;
00104 
00105       double A             = A_REF_GPS + deltaA;
00106       double Ahalf         = SQRT(A);
00107       double deltaOMEGAdot = deltaOMEGAdotArg;
00108       double OMEGAdot      = OMEGADOT_REF_GPS + deltaOMEGAdot;
00109       satSys = "G";
00110       double timeDiff = ToeArg - TOWCount[0];
00111       short epochWeek = TOWWeek;
00112       if (timeDiff < -HALFWEEK) epochWeek++;
00113       else if (timeDiff > HALFWEEK) epochWeek--;
00114     
00115          // The observation ID has a type of navigation. The code type could
00116          // be L1, L2, or L5.
00117       ObsID obsID(ObsID::otNavMsg, obsIDArg.band, obsIDArg.code);
00118 
00119       long beginFitSOW = ((TOWCount[0])/7200)*7200;
00120       long endFitSOW   = beginFitSOW + 10800;
00121       short beginFitWk = TOWWeek;
00122       short endFitWk   = TOWWeek;
00123 
00124       CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
00125 
00126       if (endFitSOW >= FULLWEEK)
00127       {
00128          endFitSOW -= FULLWEEK;
00129          endFitWk++;
00130       }
00131       CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS); 
00132 
00133       CommonTime ToeCT = GPSWeekSecond(epochWeek, ToeArg, TimeSystem::GPS);
00134 
00135       orbit.loadData(satSys, obsID, PRNID, beginFit, endFit, ToeCT,
00136                      URAoe, healthy, CucArg, CusArg, CrcArg, CrsArg, CicArg,
00137                      CisArg, M0Arg, dnArg, dndotArg, eccArg, A, Ahalf, AdotArg, 
00138                                OMEGA0Arg, i0Arg, wArg, OMEGAdot, idotArg);
00139       dataLoaded  = true;   
00140    }
00141 
00142    void CNAVEphemeris::loadData( const ObsID obsIDArg, 
00143                                  const short PRNIDArg,
00144                                  const PackedNavBits message10,
00145                                  const PackedNavBits message11)
00146 
00147       throw( InvalidParameter)
00148    {
00149       obsID         = obsIDArg;
00150       PRNID         = PRNIDArg;
00151       satSys        = "G";
00152 
00153          // Message Type 10 data
00154       Alert[0]      = message10.asUnsignedLong(37, 1, 1);
00155       TOWCount[0]   = message10.asUnsignedLong(20, 17, 300);
00156       TOWWeek       = message10.asUnsignedLong(38, 13, 1);
00157       L1Health      = message10.asUnsignedLong(51, 1, 1);
00158       L2Health      = message10.asUnsignedLong(52, 1, 1);
00159       L5Health      = message10.asUnsignedLong(53, 1, 1);
00160       Top           = message10.asUnsignedLong(54, 11, 300);
00161       short URAoe   = message10.asLong(65, 5, 1);
00162       double Toe    = message10.asUnsignedLong(70, 11, 300);
00163       double deltaA = message10.asSignedDouble(81, 26, -9);
00164       double Adot   = message10.asSignedDouble(107, 25, -21);
00165       double dn     = message10.asDoubleSemiCircles(132, 17, -44);
00166       double dndot  = message10.asDoubleSemiCircles(149, 23, -57);
00167       double M0     = message10.asDoubleSemiCircles(172, 33, -32);
00168       double ecc    = message10.asUnsignedDouble(205, 33, -34);
00169       double w      = message10.asDoubleSemiCircles(238, 33, -32);
00170       
00171          // Message Type 11 data
00172       Alert[1]             = message11.asUnsignedLong(37, 1, 1);
00173       TOWCount[1]          = message11.asUnsignedLong(20, 17, 300);
00174       double OMEGA0        = message11.asDoubleSemiCircles(49, 33, -32);
00175       double i0            = message11.asDoubleSemiCircles(82, 33, -32);
00176       double deltaOMEGAdot = message11.asDoubleSemiCircles(115, 17, -44);
00177       double idot          = message11.asDoubleSemiCircles(132, 15, -44);
00178       double Cis           = message11.asSignedDouble(147, 16, -30);
00179       double Cic           = message11.asSignedDouble(163, 16, -30);
00180       double Crs           = message11.asSignedDouble(179, 24, -8);
00181       double Crc           = message11.asSignedDouble(203, 24, -8);
00182       double Cus           = message11.asSignedDouble(227, 21, -30);
00183       double Cuc           = message11.asSignedDouble(248, 21, -30);
00184 
00185       double A        = A_REF_GPS + deltaA;
00186       double Ahalf    = SQRT(A);
00187       double OMEGAdot = OMEGADOT_REF_GPS + deltaOMEGAdot;
00188 
00189       bool healthy = false;
00190       if (obsIDArg.band == ObsID::cbL2 && L2Health == 0) healthy = true;
00191       if (obsIDArg.band == ObsID::cbL5 && L5Health == 0) healthy = true;
00192 
00193       double timeDiff = Toe - TOWCount[0];
00194       short epochWeek = TOWWeek;
00195       if (timeDiff < -HALFWEEK) epochWeek++;
00196       else if (timeDiff > HALFWEEK) epochWeek--;
00197 
00198       long beginFitSOW = ((TOWCount[0])/7200)*7200;
00199       long endFitSOW   = beginFitSOW + 10800;
00200       short beginFitWk = TOWWeek;
00201       short endFitWk   = TOWWeek;
00202 
00203       CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
00204 
00205       if (endFitSOW >= FULLWEEK)
00206       {
00207          endFitSOW -= FULLWEEK;
00208          endFitWk++;
00209       }
00210       CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS); 
00211 
00212       CommonTime ToeCT = GPSWeekSecond(epochWeek, Toe, TimeSystem::GPS);
00213 
00214       orbit.loadData(satSys, obsID, PRNID, beginFit, endFit, ToeCT,
00215                      URAoe, healthy, Cuc, Cus, Crc, Crs, Cic, Cis, M0, dn,
00216                      dndot, ecc, A, Ahalf, Adot, OMEGA0, i0, w, OMEGAdot, idot);
00217       dataLoaded = true;
00218    }
00219 
00220    bool CNAVEphemeris::hasData() 
00221    {
00222       return(dataLoaded);
00223    }
00224             
00225     Xv CNAVEphemeris::svXv(const CommonTime& t) const
00226       throw( InvalidRequest )
00227    {
00228       if(!dataLoaded)
00229       {
00230          InvalidRequest exc("svXvt: Required data not stored.");
00231          GPSTK_THROW(exc);
00232       }
00233       Xv sv;
00234       Xv xv = orbit.svXv(t);
00235       sv.x = xv.x; // Position
00236       sv.v = xv.v; // Velocity
00237       return sv;
00238    }
00239 
00240    double CNAVEphemeris::svRelativity(const CommonTime& t) const
00241       throw( InvalidRequest )
00242    {
00243       if(!dataLoaded)
00244       {
00245          InvalidRequest exc("svRelativity(): Required data not stored.");
00246          GPSTK_THROW(exc);
00247       }
00248       return orbit.svRelativity(t);
00249    }
00250       
00251    CommonTime CNAVEphemeris::getTransmitTime() const
00252       throw(InvalidRequest)
00253    {
00254       if(!dataLoaded)
00255       {
00256          InvalidRequest exc("getTransmitTime: Required data not stored.");
00257          GPSTK_THROW(exc);
00258       }
00259       GPSWeekSecond gws(TOWWeek, TOWCount[0], TimeSystem::GPS);
00260       return (gws.convertToCommonTime());
00261    }
00262 
00263    CommonTime CNAVEphemeris::getTimeOfPrediction() const
00264       throw( InvalidRequest )
00265    {
00266       if(!dataLoaded)
00267       {
00268          InvalidRequest exc("getTimeOfPrediction(): Required data not stored.");
00269          GPSTK_THROW(exc);
00270       }
00271       short week(TOWWeek);
00272       if( Top - TOWCount[0] < -HALFWEEK)
00273       week++;
00274       else if ( Top - TOWCount[0] > HALFWEEK)
00275       week--;
00276       CommonTime toReturn;
00277       toReturn = GPSWeekSecond(week, Top, TimeSystem::GPS);
00278       return toReturn;
00279    }
00280 
00281    short CNAVEphemeris::getPRNID() const
00282       throw( InvalidRequest )
00283    {
00284       if(!dataLoaded)
00285       {
00286          InvalidRequest exc("getPRNID(): Required data not stored.");
00287          GPSTK_THROW(exc);
00288       }
00289       return PRNID;
00290    }
00291 
00292    short CNAVEphemeris::getAlert(short messageNum)  const
00293       throw( InvalidRequest, Exception )
00294    {
00295       if (!dataLoaded)
00296       {
00297          InvalidRequest exc("getAlert(): messageNum not stored.");
00298          GPSTK_THROW(exc);
00299       }
00300       if (messageNum == 10) return Alert[0];
00301       if (messageNum == 11) return Alert[1];
00302 
00303           Exception e("getAlert(): unrecognized value for messageNum: " + messageNum);
00304           GPSTK_THROW(e);
00305    }
00306 
00307    double CNAVEphemeris::getAccuracy()  const
00308       throw(InvalidRequest)
00309    {
00310       if (!dataLoaded)
00311       {
00312          InvalidRequest exc("Required data not stored.");
00313          GPSTK_THROW(exc);
00314       }
00315       return orbit.getAccuracy();
00316    }  
00317 
00318    short CNAVEphemeris::getURAoe() const
00319       throw( InvalidRequest )
00320    {
00321       if(!dataLoaded)
00322       {
00323          InvalidRequest exc("getURAoe(): Required data not stored.");
00324          GPSTK_THROW(exc);
00325       }
00326       return orbit.getURAoe();
00327    }
00328 
00329    short CNAVEphemeris::getHealth(const ObsID::CarrierBand cb) const
00330       throw( InvalidRequest )
00331    {
00332       if(!dataLoaded)
00333       {
00334          InvalidRequest exc("getHealth(): Required data not stored.");
00335          GPSTK_THROW(exc);
00336       }
00337       short retVal;
00338       switch (cb)
00339       {
00340          case ObsID::cbL1:
00341             retVal = L1Health;
00342             break;
00343          case ObsID::cbL2:
00344             retVal = L2Health;
00345             break;
00346          case ObsID::cbL5:
00347             retVal = L5Health;
00348             break;
00349          default:
00350             InvalidRequest exc("getHealth(): Invalid carrier selection");
00351             GPSTK_THROW(exc);
00352       }
00353       return retVal;
00354    }
00355 
00356    long CNAVEphemeris::getTop() const
00357       throw(InvalidRequest)
00358    {
00359       if (!dataLoaded)
00360       {
00361          InvalidRequest exc("Required data not stored.");
00362          GPSTK_THROW(exc);
00363       }
00364       return Top;
00365    }
00366   
00367    BrcKeplerOrbit CNAVEphemeris::getOrbit() const
00368       throw(InvalidRequest )
00369    {
00370       if(!orbit.hasData())
00371       {
00372          InvalidRequest exc("getOrbit(): Required Orbit data not stored.");
00373          GPSTK_THROW(exc);
00374       }
00375       return (orbit);
00376    }
00377 
00378    static void timeDisplay( ostream & os, const CommonTime& t )
00379    {
00380          // Convert to CommonTime struct from GPS wk,SOW to M/D/Y, H:M:S.
00381       GPSWeekSecond dummyTime;
00382       dummyTime = GPSWeekSecond(t);
00383       os << dec;
00384       os << setw(4) << dummyTime.week << "(";
00385       os << setw(4) << (dummyTime.week & 0x03FF) << ")  ";
00386       os << setw(6) << setfill(' ') << dummyTime.sow << "   ";
00387 
00388       switch (dummyTime.getDayOfWeek())
00389       {
00390          case 0: os << "Sun-0"; break;
00391          case 1: os << "Mon-1"; break;
00392          case 2: os << "Tue-2"; break;
00393          case 3: os << "Wed-3"; break;
00394          case 4: os << "Thu-4"; break;
00395          case 5: os << "Fri-5"; break;
00396          case 6: os << "Sat-6"; break;
00397          default: break;
00398       }
00399       os << "   " << (static_cast<YDSTime>(t)).printf("%3j   %5.0s  ") 
00400          << (static_cast<CivilTime>(t)).printf("%02m/%02d/%04Y   %02H:%02M:%02S");
00401    }
00402 
00403 
00404    static void shortcut(ostream & os, const long HOW )
00405    {
00406       short DOW, hour, min, sec;
00407       long SOD, SOW;
00408       short SOH;
00409       
00410       SOW = static_cast<long>( HOW );
00411       DOW = static_cast<short>( SOW / SEC_PER_DAY );
00412       SOD = SOW - static_cast<long>( DOW * SEC_PER_DAY );
00413       hour = static_cast<short>( SOD/3600 );
00414 
00415       SOH = static_cast<short>( SOD - (hour*3600) );
00416       min = SOH/60;
00417 
00418       sec = SOH - min * 60;
00419       switch (DOW)
00420       {
00421          case 0: os << "Sun-0"; break;
00422          case 1: os << "Mon-1"; break;
00423          case 2: os << "Tue-2"; break;
00424          case 3: os << "Wed-3"; break;
00425          case 4: os << "Thu-4"; break;
00426          case 5: os << "Fri-5"; break;
00427          case 6: os << "Sat-6"; break;
00428          default: break;
00429       }
00430 
00431       os << ":" << setfill('0')
00432          << setw(2) << hour
00433          << ":" << setw(2) << min
00434          << ":" << setw(2) << sec
00435          << setfill(' ');
00436    }
00437 
00438    void CNAVEphemeris :: dump(ostream& s) const
00439       throw()
00440    { 
00441       s.setf(ios::fixed, ios::floatfield);
00442       s.setf(ios::right, ios::adjustfield);
00443       s.setf(ios::uppercase);
00444       s.precision(0);
00445       s.fill(' ');
00446       
00447       s << "****************************************************************"
00448         << "************" << endl
00449         << "CNAV Message Types 10 and 11" << endl
00450         << endl
00451         << "PRN : " << setw(2) << PRNID << "      "
00452         << "System : " << satSys << "      "
00453         << "Carrier: " << ObsID::cbDesc[obsID.band] << "      "
00454         << "Code: " << ObsID::tcDesc[obsID.code] << endl << endl;
00455   
00456 
00457       s << "                  Week        SOW     DOW   UTD     SOD"
00458         << "   MM/DD/YYYY   HH:MM:SS\n";
00459       s << "Transmit Time:  ";
00460 
00461       timeDisplay(s, getTransmitTime());
00462       s << endl;
00463       s << "Time of Predict:";
00464       timeDisplay(s, getTimeOfPrediction());
00465       s << endl;
00466      
00467       s << endl
00468         << "          ACCURACY PARAMETERS"
00469         << endl
00470         << endl
00471         << "URAoe index:  " << setw(4) << orbit.getURAoe() << endl;
00472 
00473       s.setf(ios::scientific, ios::floatfield);
00474       s.precision(11);
00475 
00476       s << endl
00477       << "           SIGNAL PARAMETERS"
00478       << endl
00479       << endl
00480       << "L1 Health bit:  " << setw(2) << L1Health << endl
00481       << "L2 Health bit:  " << setw(2) << L2Health << endl
00482       << "L5 Health bit:  " << setw(2) << L5Health << endl
00483       << setfill(' ') << endl;  
00484      
00485       s << endl
00486         << "           ORBIT PARAMETERS"
00487         << endl
00488         << endl
00489         << "Semi-major axis:       " << setw(18) << orbit.getAhalf()  << " m**.5" << endl
00490         << "Motion correction:     " << setw(18) << orbit.getDn()     << " rad/sec"
00491         << endl
00492         << "Eccentricity:          " << setw(18) << orbit.getEcc()    << endl
00493         << "Arg of perigee:        " << setw(18) << orbit.getW()      << " rad" << endl
00494         << "Mean anomaly at epoch: " << setw(18) << orbit.getM0()     << " rad" << endl
00495         << "Right ascension:       " << setw(18) << orbit.getOmega0() << " rad    "
00496         << setw(18) << orbit.getOmegaDot() << " rad/sec" << endl
00497         << "Inclination:           " << setw(18) << orbit.getI0()     << " rad    "
00498         << setw(18) << orbit.getIDot()     << " rad/sec" << endl;
00499       
00500       s << endl
00501         << "           HARMONIC CORRECTIONS"
00502         << endl
00503         << endl
00504         << "Radial        Sine: " << setw(18) << orbit.getCrs() << " m    Cosine: "
00505         << setw(18) << orbit.getCrc() << " m" << endl
00506         << "Inclination   Sine: " << setw(18) << orbit.getCis() << " rad  Cosine: "
00507         << setw(18) << orbit.getCic() << " rad" << endl
00508         << "In-track      Sine: " << setw(18) << orbit.getCus() << " rad  Cosine: "
00509         << setw(18) << orbit.getCuc() << " rad" << endl;    
00510       
00511       s << "****************************************************************"
00512         << "************" << endl;
00513 
00514    } // end of CNAVEphemeris::dump()
00515 
00516    ostream& operator<<(ostream& s, const CNAVEphemeris& eph)
00517    {
00518       eph.dump(s);
00519       return s;
00520    } // end of operator<<
00521 
00522 } // namespace

Generated on Thu May 23 03:31:04 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1