EngEphemeris.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: EngEphemeris.cpp 3161 2012-06-22 20:20:38Z jwbasden $"
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 
00046 #include "StringUtils.hpp"
00047 #include "GNSSconstants.hpp"
00048 #include "MathBase.hpp"
00049 #include "GPSEllipsoid.hpp"
00050 #include "EngEphemeris.hpp"
00051 #include "GPSWeekSecond.hpp"
00052 #include "YDSTime.hpp"
00053 #include "CivilTime.hpp"
00054 #include "TimeSystem.hpp"
00055 #include "GPS_URA.hpp"
00056 #include "TimeString.hpp"
00057 #include "SVNumXRef.hpp"
00058 
00059 namespace gpstk
00060 {
00061    using namespace std;
00062 
00063    EngEphemeris::EngEphemeris()
00064       throw()
00065    {
00066       haveSubframe[0] = haveSubframe[1] = haveSubframe[2] = false;
00067 
00068       tlm_message[0] = tlm_message[1] = tlm_message[2] = 0;
00069 
00070       satSys = "";
00071 
00072       PRNID = tracker = ASalert[0] = ASalert[1] = ASalert[2] = weeknum =
00073            codeflags = health = L2Pdata = 0;
00074 
00075       HOWtime[0] = HOWtime[1] = HOWtime[2] = 0;
00076 
00077       IODC = IODE = 0;
00078       Tgd = 0.0;
00079      
00080       isFIC = true;
00081 
00082       fitint = 0;
00083 
00084       for (int j = 0; j<3; j++)
00085       {
00086          for (int i = 0; i<10; i++) subframeStore[j][i] = 0L;
00087       }
00088    }
00089 
00102    bool EngEphemeris::addSubframe(const long subframe[10], const int gpsWeek,
00103                                   const short PRN, const short track)
00104       throw( InvalidParameter )
00105    {
00106          // Determine the subframe number
00107       unsigned long SFword2 = (unsigned long) subframe[1];
00108       SFword2 &= 0x00000700;      // Strip all but three bit subframe ID
00109       SFword2 >>= 8;              // Right shift to move to lsbs;
00110       short sfID = static_cast<short>( SFword2 );
00111 
00112       if (sfID<1 || sfID>3)
00113       {
00114          InvalidParameter exc("Invalid SF ID: "+StringUtils::asString(sfID));
00115          GPSTK_THROW(exc);
00116       }
00117       
00118          // Store the subframe in the appropriate location 
00119          // and set the flag
00120       int sfNdx = sfID - 1; 
00121       for (int i=0;i<10;++i) subframeStore[sfNdx][i] = subframe[i];
00122       haveSubframe[sfNdx] = true;
00123       
00124          // Determine if all subframes are available.  If so,
00125          // load the data. Otherwise return and try again later.
00126       bool result = true;  // default return OK in cases where no cracking occurs
00127       if (haveSubframe[0] &&
00128           haveSubframe[1] &&
00129           haveSubframe[2])
00130       {
00131          result = unifiedConvert( gpsWeek, PRN, track );
00132       }
00133       return(result);
00134    }  
00135    
00136    bool EngEphemeris::addSubframeNoParity(const long subframe[10],
00137                                           const int  gpsWeek,
00138                                           const short PRN,
00139                                           const short track)
00140       throw( InvalidParameter )
00141    {
00142       long paddedSF[10];
00143       short PRNArg;
00144       short trackArg;
00145 
00146       for (int i=0;i<10;++i)
00147       {
00148          paddedSF[i] = subframe[i];
00149          paddedSF[i] <<= 6;
00150          paddedSF[i] &= 0x3FFFFFC0;    // Guarantee 2 msb and 6 lsb are zeroes
00151       }
00152       PRNArg = PRN;
00153       trackArg = track;
00154       return( addSubframe( paddedSF, gpsWeek, PRNArg, trackArg ));
00155    }
00156 
00157    bool EngEphemeris::addIncompleteSF1Thru3(
00158       const long sf1[8], const long sf2[8], const long sf3[8],
00159       const long sf1TransmitSOW, const int gpsWeek,
00160       const short PRN, const short track)
00161    {
00162          // Need to provide a valid subframe number in the handover word.
00163          // While we're at it, we'll fake the A-S bit such that it
00164          // appears A-S is ON, even though we warn the user NOT to trust
00165          // returns from the getASAlert() method.
00166       const long sf1Lead[2] = { 0x00000000, 0x00000900 };
00167       const long sf2Lead[2] = { 0x00000000, 0x00000A00 };
00168       const long sf3Lead[2] = { 0x00000000, 0x00000B00 };
00169 
00170          // Handover word times represent the time of the leading edge of the
00171          // NEXvt subframe.  Therefore, HOW should always correspond to
00172          //   :06/:36 for SF 1
00173          //   :12/:42 for SF 2
00174          //   :18/:48 for SF 3
00175          // This method hasn't a clue about the accuracy of the SOW input by the
00176          // user, but it WILL enforce this relationship.
00177       long frameCount = sf1TransmitSOW / 30;
00178       long SF1HOWTime = (frameCount * 30) + 6;
00179 
00180          // Convert subframe 1 parameters
00181       subframeStore[0][0] = sf1Lead[0];
00182       subframeStore[0][1] = sf1Lead[1];
00183       int i;
00184       for (i=0; i<8; ++i) subframeStore[0][i+2] = sf1[i];
00185       haveSubframe[0] = true;
00186 
00187          // Convert subframe 2 parameters
00188       subframeStore[1][0] = sf2Lead[0];
00189       subframeStore[1][1] = sf2Lead[1];
00190       for (i=0; i<8; ++i) subframeStore[1][i+2] = sf2[i];
00191       haveSubframe[1] = true;
00192 
00193          // Convert subframe 3 parameters
00194       subframeStore[2][0] = sf3Lead[0];
00195       subframeStore[2][1] = sf3Lead[1];
00196       for (i=0; i<8; ++i) subframeStore[2][i+2] = sf3[i];
00197       haveSubframe[2] = true;
00198 
00199          // Call method to crack and load the data.
00200       bool result = unifiedConvert( gpsWeek, PRN, track );
00201 
00202       return(result);
00203    }
00204 
00210    bool EngEphemeris::unifiedConvert( const int gpsWeek, 
00211                                       const short PRN, 
00212                                       const short track)
00213    {
00214       double ficked[60];
00215 
00216       if (!subframeConvert(subframeStore[0], gpsWeek, ficked))
00217          return false;
00218       tlm_message[0] = (subframeStore[0][0] >> 8) & 0x3fff;
00219       HOWtime[0] = static_cast<long>( ficked[2] );
00220       ASalert[0] = static_cast<short>( ficked[3] );
00221       weeknum    = static_cast<short>( ficked[5] );
00222       codeflags  = static_cast<short>( ficked[6] );
00223       short accFlag = static_cast<short>( ficked[7] );
00224       health     = static_cast<short>( ficked[8] );
00225       IODC       = static_cast<short>( ldexp( ficked[9], -11 ) );
00226       L2Pdata    = static_cast<short>( ficked[10] );
00227       Tgd        = ficked[11];
00228       double Toc = ficked[12];
00229       double af2 = ficked[13];
00230       double af1 = ficked[14];
00231       double af0 = ficked[15];
00232       tracker    = track;
00233 
00234       if (!subframeConvert(subframeStore[1], gpsWeek, ficked))
00235          return false;
00236          
00237       tlm_message[1] = (subframeStore[1][0] >> 8) & 0x3fff;
00238       HOWtime[1]     = static_cast<long>( ficked[2] );
00239       ASalert[1]     = static_cast<short>( ficked[3] );
00240       IODE           = static_cast<short>( ldexp( ficked[5], -11 ) );
00241       double Crs     = ficked[6];
00242       double dn      = ficked[7];
00243       double M0      = ficked[8];
00244       double Cuc     = ficked[9];
00245       double ecc     = ficked[10];
00246       double Cus     = ficked[11];
00247       double Ahalf   = ficked[12];
00248       double Toe     = ficked[13];
00249       fitint         = static_cast<short>( ficked[14] );
00250       AODO           = static_cast<long>( ficked[15] );
00251 
00252 
00253       if (!subframeConvert(subframeStore[2], gpsWeek, ficked))
00254          return false;
00255 
00256       tlm_message[2]   = (subframeStore[2][0] >> 8) & 0x3fff;
00257       HOWtime[2]       = static_cast<long>( ficked[2] );
00258       ASalert[2]       = static_cast<short>( ficked[3] );
00259       double Cic       = ficked[5];
00260       double OMEGA0    = ficked[6];
00261       double Cis       = ficked[7];
00262       double i0        = ficked[8];
00263       double Crc       = ficked[9];
00264       double w         = ficked[10];
00265       double OMEGAdot  = ficked[11];
00266       double idot      = ficked[13];
00267 
00268          // The system is assumed (legacy navigation message is from GPS)
00269       satSys = "G";
00270       PRNID = PRN;
00271 
00272          // The observation ID has a type of navigation, but the
00273          // carrier and code types are undefined.  They could be
00274          // L1/L2 C/A, P, Y,.....
00275       ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
00276       
00277       bool healthy = false;
00278       if (health==0) healthy = true;
00279       double Adot = 0.0;
00280       double dnDot = 0.0; 
00281       double A = Ahalf * Ahalf;
00282 
00283       double timeDiff = Toe - HOWtime[1];
00284       short epochWeek = weeknum;
00285       if (timeDiff < -HALFWEEK) epochWeek++;
00286       else if (timeDiff > HALFWEEK) epochWeek--;
00287 
00288          // Toe is now in CommonTime, and needs to be passed to BrcKeplerOrbit as a CommonTime variable.
00289          // URAoc and URAoe in legacy nav message are equal. Only CNAV and CNAV2 are they different
00290       CommonTime ToeCT = GPSWeekSecond(epochWeek, Toe, TimeSystem::GPS);
00291       CommonTime TocCT = GPSWeekSecond(epochWeek, Toc, TimeSystem::GPS);
00292 
00293       short fiti = static_cast<short>(ficked[14]);
00294       short fitHours = getLegacyFitInterval(IODC, fitint);
00295       long beginFitSOW = Toe - (fitHours/2)*3600;
00296       long endFitSOW = Toe + (fitHours/2)*3600;
00297       short beginFitWk = epochWeek;
00298       short endFitWk = epochWeek;
00299       if (beginFitSOW < 0)
00300       {
00301          beginFitSOW += FULLWEEK;
00302          beginFitWk--;
00303       }
00304       CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
00305 
00306       if (endFitSOW >= FULLWEEK)
00307       {
00308          endFitSOW -= FULLWEEK;
00309          endFitWk++;
00310       }
00311       CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS);   
00312 
00313       orbit.loadData(satSys, obsID, PRN, beginFit, endFit, ToeCT, 
00314                      accFlag, healthy, Cuc, Cus, Crc, Crs, Cic, Cis, M0, 
00315                      dn, dnDot, ecc, A, Ahalf, Adot, OMEGA0, i0, w, OMEGAdot, idot);
00316          
00317       bcClock.loadData( satSys, obsID, PRNID, TocCT,
00318                         accFlag, healthy, af0, af1, af2); 
00319 
00320           return true;
00321    }
00322 
00323    bool EngEphemeris::isData(short subframe) const
00324       throw( InvalidRequest )
00325    {
00326       if ((subframe < 1) || (subframe > 3))
00327       {
00328          InvalidRequest exc("Subframe "+StringUtils::asString(subframe)+
00329                             " is not a valid ephemeris subframe.");
00330          GPSTK_THROW(exc);
00331       }
00332 
00333       return haveSubframe[subframe-1];
00334    }
00335 
00336    void EngEphemeris::setAccuracy(const double& acc)
00337       throw( InvalidParameter )
00338    {
00339       if( acc < 0 )
00340       {
00341          InvalidParameter exc("SV Accuracy of " + StringUtils::asString(acc) +
00342                               " meters is invalid.");
00343          GPSTK_THROW(exc);
00344       }
00345       orbit.setAccuracy(acc);
00346    }
00347 
00352    short EngEphemeris :: getFitInterval() const
00353       throw( InvalidRequest )
00354    {
00355       short iodc = getIODC();
00356       short fiti = getFitInt();
00357 
00358          /* check the IODC */
00359       if (iodc < 0 || iodc > 1023)
00360       {
00361             /* error in iodc, return minimum fit */
00362          return 4;
00363       }
00364 
00365       if (((fiti == 0) &&
00366            (iodc & 0xFF) < 240 || (iodc & 0xFF) > 255 ))
00367       {
00368             /* fit interval of 4 hours */
00369          return 4;
00370       }
00371       else if (fiti == 1)
00372       {
00373          if( ((iodc & 0xFF) < 240 || (iodc & 0xFF) > 255))
00374          {
00375                /* fit interval of 6 hours */
00376             return 6;
00377          }
00378          else if(iodc >=240 && iodc <=247)
00379          {
00380                /* fit interval of 8 hours */
00381             return 8;
00382          }
00383          else if(iodc >= 248 && iodc <= 255 || iodc == 496)
00384          {
00385                /* fit interval of 14 hours */
00386             return 14;
00387          }
00388          // Revised in IS-GPS-200 Revision D for Block IIR/IIR-M/IIF
00389          else if(iodc >= 497 && iodc <=503 || iodc >= 1021 && iodc <= 1023)
00390          {
00391                /* fit interval of 26 hours */
00392             return 26;
00393          }
00394          else if(iodc >= 504 && iodc <=510)
00395          {
00396                /* fit interval of 50 hours */
00397             return 50;
00398          }
00399          else if(iodc == 511 || iodc >= 752 && iodc <= 756)
00400          {
00401                /* fit interval of 74 hours */
00402             return 74;
00403          }
00404          /* NOTE:
00405           * The following represents old fit intervals for Block II (not IIA)
00406           * and is present only in old versions of the ICD-GPS-200 Rev. C.
00407           * Please do not remove them as there are still people that may
00408           * want to process old Block II data and none of the IODC intervals
00409           * overlap (so far) so there is no need to remove them.
00410           */
00411          else if(iodc >= 757 && iodc <= 763)
00412          {
00413                /* fit interval of 98 hours */
00414             return 98;
00415          }
00416          else if(iodc >= 764 && iodc <=767 || iodc >=1008 && iodc <=1010)
00417          {
00418                /* fit interval of 122 hours */
00419             return 122;
00420          }
00421          else if(iodc >= 1011 && iodc <=1020)
00422          {
00423                /* fit interval of 146 hours */
00424             return 146;
00425          }
00426          else
00427          {
00428                /* error in the iodc or ephemeris, return minimum
00429                   fit */
00430             return 4;
00431          }
00432       }
00433       else
00434       {
00435             /* error in ephemeris/iodc, return minimum fit */
00436          return 4;
00437       }
00438 
00439       return 0; // never reached
00440    }
00441 
00442 
00443    Xvt EngEphemeris::svXvt(const CommonTime& t) const
00444       throw( InvalidRequest )
00445    {
00446       Xvt sv;
00447 
00448       Xv xv = orbit.svXv(t);
00449 
00450       sv.x = xv.x;
00451       sv.v = xv.v;
00452 
00453       sv.clkbias = bcClock.svClockBias(t);
00454       sv.relcorr = orbit.svRelativity(t);
00455 
00456       sv.clkdrift = bcClock.svClockDrift(t);
00457       
00458       return sv;
00459    }
00460 
00461    double EngEphemeris::svRelativity(const CommonTime& t) const
00462       throw( InvalidRequest )
00463    {
00464       return orbit.svRelativity(t);
00465    }
00466 
00467    double EngEphemeris::svClockBias(const CommonTime& t) const
00468       throw( InvalidRequest )
00469    {
00470       return bcClock.svClockBias(t);
00471    }
00472 
00473    double EngEphemeris::svClockDrift(const CommonTime& t) const
00474       throw( InvalidRequest )
00475    {
00476       return bcClock.svClockDrift(t);
00477    }
00478 
00479    unsigned EngEphemeris::getTLMMessage(short subframe) const
00480       throw( InvalidRequest )
00481    {
00482       if (!haveSubframe[subframe-1])
00483       {
00484          InvalidRequest exc("Subframe "+StringUtils::asString(subframe)+
00485                             " not stored.");
00486          GPSTK_THROW(exc);
00487       }
00488       return tlm_message[subframe-1];
00489    }
00490 
00491    CommonTime EngEphemeris::getTransmitTime() const
00492       throw()
00493    {
00494       CommonTime toReturn;
00495       toReturn = GPSWeekSecond(getFullWeek(), static_cast<double>(getTot()), TimeSystem::GPS);
00496       return toReturn;
00497    }
00498 
00499    CommonTime EngEphemeris::getEpochTime() const
00500       throw( InvalidRequest )
00501    {
00502       return bcClock.getEpochTime();
00503    }
00504 
00505    CommonTime EngEphemeris::getEphemerisEpoch() const
00506       throw( InvalidRequest )
00507    {
00508       return orbit.getOrbitEpoch();
00509    }
00510 
00511    BrcKeplerOrbit EngEphemeris::getOrbit() const
00512       throw(InvalidRequest )
00513    {
00514       if(!orbit.hasData())
00515       {
00516          InvalidRequest exc("getOrbit(): Required Orbit data not stored.");
00517          GPSTK_THROW(exc);
00518       }
00519       return (orbit);
00520    }
00521 
00522    BrcClockCorrection EngEphemeris::getClock() const
00523       throw(InvalidRequest )
00524    {
00525       if(!bcClock.hasData())
00526       {
00527          InvalidRequest exc("getClock(): Required Clock Correction data not stored.");
00528          GPSTK_THROW(exc);
00529       }
00530       return (bcClock);
00531    }
00532 
00533    short EngEphemeris::getPRNID() const
00534       throw( InvalidRequest )
00535    {
00536       if(!haveSubframe[0])
00537       {
00538          InvalidRequest exc("getPRNID(): Required subframe 1 not stored.");
00539          GPSTK_THROW(exc);
00540       }
00541       return PRNID;
00542    }
00543 
00544    short EngEphemeris::getTracker() const
00545       throw( InvalidRequest )
00546    {
00547       if(!haveSubframe[0])
00548       {
00549          InvalidRequest exc("getTracker(): Required subframe 1 not stored.");
00550          GPSTK_THROW(exc);
00551       }
00552       return tracker;
00553    }
00554 
00555    double EngEphemeris::getHOWTime(short subframe) const
00556       throw( InvalidRequest )
00557    {
00558       if (!haveSubframe[subframe-1])
00559       {
00560          InvalidRequest exc("getHOWTime(): Subframe "
00561                             +StringUtils::asString(subframe)+" not stored.");
00562          GPSTK_THROW(exc);
00563       }
00564          // This return as a double is necessary for sets into CommonTime 
00565          // to not get confused.  Ints are Zcounts whereas doubles are seconds.
00566          // This should still return a double after CommonTime->CommonTime
00567          // conversion, for backwards compatibility. [DR]
00568       return static_cast<double>(HOWtime[subframe-1]);
00569    }
00570 
00571    short EngEphemeris::getASAlert(short subframe)  const
00572       throw( InvalidRequest )
00573    {
00574       if (!haveSubframe[subframe-1])
00575       {
00576          InvalidRequest exc("getASAlert(): Subframe "
00577                             +StringUtils::asString(subframe)+" not stored.");
00578          GPSTK_THROW(exc);
00579       }
00580       return ASalert[subframe-1];
00581    }
00582 
00583    short EngEphemeris::getFullWeek()  const
00584       throw( InvalidRequest )
00585    {
00586       if (!haveSubframe[0])
00587       {
00588          InvalidRequest exc("getFullWeek(): Required subframe 1 not stored.");
00589          GPSTK_THROW(exc);
00590       }
00591       return weeknum;
00592    }
00593 
00594    short EngEphemeris::getCodeFlags()  const
00595       throw( InvalidRequest )
00596    {
00597       if (!haveSubframe[0])
00598       {
00599          InvalidRequest exc("getCodeFlags(): Required subframe 1 not stored.");
00600          GPSTK_THROW(exc);
00601       }
00602       return codeflags;
00603    }
00604 
00605    double EngEphemeris::getAccuracy()  const
00606       throw( InvalidRequest )
00607    {
00608       if (!haveSubframe[0])
00609       {
00610          InvalidRequest exc("getAccuracy(): Required subframe 1 not stored.");
00611          GPSTK_THROW(exc);
00612       }
00613       return orbit.getAccuracy();
00614    }
00615 
00616    short EngEphemeris::getAccFlag()  const
00617       throw( InvalidRequest )
00618    {
00619       if (!haveSubframe[0])
00620       {
00621          InvalidRequest exc("getAccFlag(): Required subframe 1 not stored.");
00622          GPSTK_THROW(exc);
00623       }
00624       return orbit.getURAoe();
00625    }
00626 
00627    short EngEphemeris::getHealth() const
00628       throw( InvalidRequest )
00629    {
00630       if (!haveSubframe[0])
00631       {
00632          InvalidRequest exc("getHealth(): Required subframe 1 not stored.");
00633          GPSTK_THROW(exc);
00634       }
00635       return health;
00636    }
00637 
00638    short EngEphemeris::getL2Pdata() const
00639       throw( InvalidRequest )
00640    {
00641       if (!haveSubframe[0])
00642       {
00643          InvalidRequest exc("getL2Pdata(): Required subframe 1 not stored.");
00644          GPSTK_THROW(exc);
00645       }
00646       return L2Pdata;
00647    }
00648 
00649    short EngEphemeris::getIODC() const
00650       throw( InvalidRequest )
00651    {
00652       if (!haveSubframe[0])
00653       {
00654          InvalidRequest exc("getIODC(): Required subframe 1 not stored.");
00655          GPSTK_THROW(exc);
00656       }
00657       return static_cast<short>(IODC);
00658    }
00659 
00660    short EngEphemeris::getIODE() const
00661       throw( InvalidRequest )
00662    {
00663       if (!haveSubframe[1])
00664       {
00665          InvalidRequest exc("getIODE(): Required subframe 2 not stored.");
00666          GPSTK_THROW(exc);
00667       }
00668       return static_cast<short>(IODE);
00669    }
00670 
00671    long EngEphemeris::getAODO() const
00672       throw( InvalidRequest )
00673    {
00674       if (!haveSubframe[1])
00675       {
00676          InvalidRequest exc("getAODO(): Required subframe 2 not stored.");
00677          GPSTK_THROW(exc);
00678       }
00679       return AODO;
00680    }
00681 
00682    double EngEphemeris::getToc() const
00683       throw( InvalidRequest )
00684    {
00685       if (!haveSubframe[0])
00686       {
00687          InvalidRequest exc("getToc(): Required subframe 1 not stored.");
00688          GPSTK_THROW(exc);
00689       }
00690       return bcClock.getToc();
00691    }
00692 
00693    double EngEphemeris::getAf0() const
00694       throw( InvalidRequest )
00695    {
00696       if (!haveSubframe[0])
00697       {
00698          InvalidRequest exc("getAf0(): Required subframe 1 not stored.");
00699          GPSTK_THROW(exc);
00700       }
00701       return bcClock.getAf0();
00702    }
00703 
00704    double EngEphemeris::getAf1() const
00705       throw( InvalidRequest )
00706    {
00707       if (!haveSubframe[0])
00708       {
00709          InvalidRequest exc("getAf1(): Required subframe 1 not stored.");
00710          GPSTK_THROW(exc);
00711       }
00712       return bcClock.getAf1();
00713    }
00714 
00715    double EngEphemeris::getAf2() const
00716       throw( InvalidRequest )
00717    {
00718       if (!haveSubframe[0])
00719       {
00720          InvalidRequest exc("getAf1(): Required subframe 1 not stored.");
00721          GPSTK_THROW(exc);
00722       }
00723       return bcClock.getAf2();
00724    }
00725 
00726    double EngEphemeris::getTgd() const
00727       throw( InvalidRequest )
00728    {
00729       if (!haveSubframe[0])
00730       {
00731          InvalidRequest exc("getTgd(): Required subframe 1 not stored.");
00732          GPSTK_THROW(exc);
00733       }
00734       return Tgd;
00735    }
00736 
00737    double EngEphemeris::getCus() const
00738       throw( InvalidRequest )
00739    {
00740       if (!haveSubframe[1])
00741       {
00742          InvalidRequest exc("getCus(): Required subframe 2 not stored.");
00743          GPSTK_THROW(exc);
00744       }
00745       return orbit.getCus();
00746    }
00747 
00748    double EngEphemeris::getCrs() const
00749       throw( InvalidRequest )
00750    {
00751       if (!haveSubframe[1])
00752       {
00753          InvalidRequest exc("getCrs(): Required subframe 2 not stored.");
00754          GPSTK_THROW(exc);
00755       }
00756       return orbit.getCrs();
00757    }
00758 
00759    double EngEphemeris::getCis() const
00760       throw( InvalidRequest )
00761    {
00762       if (!haveSubframe[2])
00763       {
00764          InvalidRequest exc("getCis(): Required subframe 3 not stored.");
00765          GPSTK_THROW(exc);
00766       }
00767       return orbit.getCis();
00768    }
00769 
00770    double EngEphemeris::getCrc() const
00771       throw( InvalidRequest )
00772    {
00773       if (!haveSubframe[2])
00774       {
00775          InvalidRequest exc("getCrc(): Required subframe 3 not stored.");
00776          GPSTK_THROW(exc);
00777       }
00778       return orbit.getCrc();
00779    }
00780 
00781    double EngEphemeris::getCuc() const
00782       throw( InvalidRequest )
00783    {
00784       if (!haveSubframe[1])
00785       {
00786          InvalidRequest exc("getCuc(): Required subframe 2 not stored.");
00787          GPSTK_THROW(exc);
00788       }
00789       return orbit.getCuc();
00790    }
00791 
00792    double EngEphemeris::getCic() const
00793       throw( InvalidRequest )
00794    {
00795       if (!haveSubframe[2])
00796       {
00797          InvalidRequest exc("getCic(): Required subframe 3 not stored.");
00798          GPSTK_THROW(exc);
00799       }
00800       return orbit.getCic();
00801    }
00802 
00803    double EngEphemeris::getToe() const
00804       throw( InvalidRequest )
00805    {
00806       if (!haveSubframe[1])
00807       {
00808          InvalidRequest exc("getToe(): Required subframe 2 not stored.");
00809          GPSTK_THROW(exc);
00810       }
00811       return orbit.getToe();
00812    }
00813 
00814    double EngEphemeris::getM0() const
00815       throw( InvalidRequest )
00816    {
00817       if (!haveSubframe[1])
00818       {
00819          InvalidRequest exc("getM0(): Required subframe 2 not stored.");
00820          GPSTK_THROW(exc);
00821       }
00822       return orbit.getM0();
00823    }
00824 
00825    double EngEphemeris::getDn() const
00826       throw( InvalidRequest )
00827    {
00828       if (!haveSubframe[1])
00829       {
00830          InvalidRequest exc("getDn(): Required subframe 2 not stored.");
00831          GPSTK_THROW(exc);
00832       }
00833       return orbit.getDn();
00834    }
00835 
00836    double EngEphemeris::getEcc() const
00837       throw( InvalidRequest )
00838    {
00839       if (!haveSubframe[1])
00840       {
00841          InvalidRequest exc("getEcc(): Required subframe 2 not stored.");
00842          GPSTK_THROW(exc);
00843       }
00844       return orbit.getEcc();
00845    }
00846 
00847    double EngEphemeris::getAhalf() const
00848       throw( InvalidRequest )
00849    {
00850       if (!haveSubframe[1])
00851       {
00852          InvalidRequest exc("getAhalf(): Required subframe 2 not stored.");
00853          GPSTK_THROW(exc);
00854       }
00855       return orbit.getAhalf();
00856    }
00857 
00858    double EngEphemeris::getA() const
00859       throw( InvalidRequest )
00860    {
00861       if (!haveSubframe[1])
00862       {
00863          InvalidRequest exc("getA(): Required subframe 2 not stored.");
00864          GPSTK_THROW(exc);
00865       }
00866       return orbit.getA();
00867    }
00868 
00869    double EngEphemeris::getOmega0() const
00870       throw( InvalidRequest )
00871    {
00872       if (!haveSubframe[2])
00873       {
00874          InvalidRequest exc("getOmega0(): Required subframe 3 not stored.");
00875          GPSTK_THROW(exc);
00876       }
00877       return orbit.getOmega0();
00878    }
00879 
00880    double EngEphemeris::getI0() const
00881       throw( InvalidRequest )
00882    {
00883       if (!haveSubframe[2])
00884       {
00885          InvalidRequest exc("getI0(): Required subframe 3 not stored.");
00886          GPSTK_THROW(exc);
00887       }
00888       return orbit.getI0();
00889    }
00890 
00891    double EngEphemeris::getW() const
00892       throw( InvalidRequest )
00893    {
00894       if (!haveSubframe[2])
00895       {
00896          InvalidRequest exc("getW(): Required subframe 3 not stored.");
00897          GPSTK_THROW(exc);
00898       }
00899       return orbit.getW();
00900    }
00901 
00902    double EngEphemeris::getOmegaDot() const
00903       throw( InvalidRequest )
00904    {
00905       if (!haveSubframe[2])
00906       {
00907          InvalidRequest exc("getOmegaDot(): Required subframe 3 not stored.");
00908          GPSTK_THROW(exc);
00909       }
00910       return orbit.getOmegaDot();
00911    }
00912 
00913    double EngEphemeris::getIDot() const
00914       throw( InvalidRequest )
00915    {
00916       if (!haveSubframe[2])
00917       {
00918          InvalidRequest exc("getIDot(): Required subframe 3 not stored.");
00919          GPSTK_THROW(exc);
00920       }
00921       return orbit.getIDot();
00922    }
00923 
00924    short EngEphemeris::getFitInt() const
00925       throw( InvalidRequest )
00926    {
00927       if (!haveSubframe[1])
00928       {
00929          InvalidRequest exc("getFitInt(): Required subframe 2 not stored.");
00930          GPSTK_THROW(exc);
00931       }
00932       return fitint;
00933    }
00934 
00935    long EngEphemeris::getTot() const
00936       throw( InvalidRequest )
00937    {
00938       if(!haveSubframe[0])
00939       {
00940          InvalidRequest exc("getTot(): Required subframe 1 not stored.");
00941          GPSTK_THROW(exc);
00942       }
00943       if(!haveSubframe[1])
00944       {
00945          InvalidRequest exc("getTot(): Required subframe 2 not stored.");
00946          GPSTK_THROW(exc);
00947       }
00948       if(!haveSubframe[2])
00949       {
00950          InvalidRequest exc("getTot(): Required subframe 3 not stored.");
00951          GPSTK_THROW(exc);
00952       }
00953 
00954       // MSVC
00955 #ifdef _MSC_VER
00956       long foo = static_cast<long>( getHOWTime(1) < getHOWTime(2) ) ? getHOWTime(1) : getHOWTime(2);
00957       foo = ( foo < getHOWTime(3) ) ? foo : getHOWTime(3) ;
00958 #else
00959       long foo =
00960          static_cast<long>( std::min( getHOWTime(1),
00961                             std::min( getHOWTime(2), getHOWTime(3) ) ) );
00962 #endif
00963          // The ephemeris comes on 30 second boundaries, so...
00964       foo/=30;
00965       foo*=30;
00966       return foo;
00967    }
00968    
00969    EngEphemeris& EngEphemeris::loadData( const std::string satSysArg, unsigned short tlm[3], 
00970                                          const long how[3], const short asalert[3],
00971                                          const short Tracker, const short prn, 
00972                                          const short fullweek, const short cflags, const short acc, 
00973                                          const short svhealth, const short iodc, const short l2pdata,
00974                                          const long aodo, const double tgd, const double toc,
00975                                          const double Af2, const double Af1, const double Af0,
00976                                          const short iode, const double crs, const double Dn,
00977                                          const double m0, const double cuc, const double Ecc,
00978                                          const double cus, const double ahalf, const double toe,
00979                                          const short fitInt, const double cic, const double Omega0,
00980                                          const double cis, const double I0, const double crc,
00981                                          const double W, const double OmegaDot, const double IDot )
00982       throw()
00983    {
00984       PRNID = prn;
00985       tracker = Tracker;
00986       for (int i=0; i<3; i++)
00987       {
00988          tlm_message[i] = tlm[i];
00989          HOWtime[i] = how[i];
00990          ASalert[i] = asalert[i];
00991       }
00992       weeknum   = fullweek;
00993       codeflags = cflags;
00994       short accFlag = acc;
00995       double accuracy = gpstk::ura2accuracy(accFlag);
00996       health    = svhealth;
00997       L2Pdata   = l2pdata;
00998       IODC      = iodc;
00999       IODE      = iode;
01000       AODO      = aodo;
01001       fitint    = fitInt;
01002       Tgd       = tgd;
01003       satSys = satSysArg;
01004 
01005       satSys = "G";
01006 
01007          // The observation ID has a type of navigation, but the
01008          // carrier and code types are undefined.  They could be
01009          // L1/L2 C/A, P, Y,.....
01010       ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
01011 
01012       CommonTime toeCT = GPSWeekSecond(weeknum, toe, TimeSystem::GPS);
01013       CommonTime tocCT = GPSWeekSecond(weeknum, toc, TimeSystem::GPS);
01014 
01015       double A = ahalf*ahalf;
01016       double dndot = 0.0;
01017       double Adot = 0.0;
01018       short fitHours = getLegacyFitInterval(IODC, fitint);
01019       long beginFitSOW = toe - (fitHours/2)*3600;
01020       long endFitSOW = toe + (fitHours/2)*3600;
01021       short beginFitWk = weeknum;
01022       short endFitWk = weeknum;
01023       if (beginFitSOW < 0)
01024       {
01025          beginFitSOW += FULLWEEK;
01026          beginFitWk--;
01027       }
01028       CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
01029       if (endFitSOW >= FULLWEEK)
01030       {
01031          endFitSOW += FULLWEEK;
01032          endFitWk++;
01033       }
01034       CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS);
01035 
01036       orbit.loadData(satSys, obsID, PRNID, beginFit, endFit, toeCT,
01037                      accFlag, health, cuc, cus, crc, crs, cic, cis, m0, Dn, 
01038                      dndot, Ecc, A, ahalf, Adot, Omega0, I0, W, OmegaDot, IDot);
01039          
01040       bcClock.loadData( satSys, obsID, PRNID, tocCT,
01041                         accFlag, health, Af0, Af1, Af2);
01042       haveSubframe[0] = true;
01043       haveSubframe[1] = true;
01044       haveSubframe[2] = true;
01045       return *this;
01046    } 
01047 
01048    EngEphemeris& EngEphemeris::setSF1( unsigned tlm, double how, short asalert, 
01049                                        short fullweek, short cflags, short acc, 
01050                                        short svhealth, short iodc, short l2pdata,
01051                                        double tgd, double toc, double Af2,
01052                                        double Af1, double Af0, short Tracker,
01053                                        short prn )
01054       throw()
01055    {
01056 
01057       tlm_message[0] = tlm;
01058       HOWtime[0] = static_cast<long>( how );
01059       ASalert[0] = asalert;
01060       weeknum    = fullweek;
01061       codeflags  = cflags;
01062       accFlagTmp = acc;
01063       health     = svhealth;  
01064       IODC       = iodc;
01065       L2Pdata    = l2pdata;
01066       Tgd        = tgd;
01067       tracker    = Tracker;
01068       PRNID      = prn;
01069       bool healthy = false;
01070       if (health == 0) healthy = true;
01071 
01072       double timeDiff = toc - HOWtime[0];
01073       short epochWeek = fullweek;
01074       if (timeDiff < -HALFWEEK) epochWeek++;
01075       else if (timeDiff > HALFWEEK) epochWeek--;
01076 
01077       CommonTime tocCT = GPSWeekSecond(epochWeek, toc, TimeSystem::GPS);
01078 
01079          // The system is assumed (legacy navigation message is from GPS)
01080       satSys = "G";
01081 
01082          // The observation ID has a type of navigation, but the
01083          // carrier and code types are undefined.  They could be
01084          // L1/L2 C/A, P, Y,.....
01085       ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
01086          
01087       bcClock.loadData( satSys, obsID, PRNID, tocCT,
01088                         accFlagTmp, healthy, Af0, Af1, Af2);
01089       haveSubframe[0] = true;
01090       return *this;
01091    }
01092 
01093    EngEphemeris& EngEphemeris::setSF2( unsigned tlm, double how, short asalert,
01094                                        short iode, double crs, double Dn,
01095                                        double m0, double cuc, double Ecc,
01096                                        double cus, double ahalf, double toe,
01097                                        short fitInt )
01098       throw( InvalidRequest )
01099    {
01100       tlm_message[1] = tlm;
01101       HOWtime[1] = static_cast<long>( how );
01102       ASalert[1] = asalert;
01103       IODE       = iode;
01104       fitint     = fitInt;
01105       
01106       if (!haveSubframe[0])
01107       {
01108          InvalidRequest exc("Need to load subframe 1 before subframe 2");
01109          GPSTK_THROW(exc);
01110       }
01111       bool healthy = false;
01112       if (health == 0) healthy = true;
01113 
01114       double timeDiff = toe - HOWtime[1];
01115       short epochWeek = weeknum;
01116       if (timeDiff < -HALFWEEK) epochWeek++;
01117       else if (timeDiff > HALFWEEK) epochWeek--;
01118 
01119          // The observation ID has a type of navigation, but the
01120          // carrier and code types are undefined.  They could be
01121          // L1/L2 C/A, P, Y,.....
01122       ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
01123 
01124       short accFlag = accFlagTmp;   // accFlagTmp set in setSF1( )
01125       //local variables in SF3 that are needed to load SF2
01126       double crc = 0.0;
01127       double cis = 0.0;
01128       double cic = 0.0;
01129       double Omega0 = 0.0; 
01130       double I0 = 0.0;
01131       double W = 0.0;
01132       double OmegaDot = 0.0;
01133       double IDot = 0.0;
01134       //also need locals for modernized nav quantaties not in SF2 or SF3
01135       double A = ahalf*ahalf;     // TEMP fix BWT
01136       double dndot = 0.0;  
01137       double Adot = 0.0;
01138 
01139       short fitHours = getLegacyFitInterval(IODC, fitint);
01140       long beginFitSOW = toe - (fitHours/2)*3600.0;
01141       long endFitSOW = toe + (fitHours/2)*3600.0;
01142       short beginFitWk = weeknum;
01143       short endFitWk = weeknum;
01144       if (beginFitSOW < 0)
01145       {
01146          beginFitSOW += FULLWEEK;
01147          beginFitWk--;
01148       }
01149       CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
01150       if (endFitSOW >= FULLWEEK)
01151       {
01152          endFitSOW += FULLWEEK;
01153          endFitWk++;
01154       }
01155       CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS);
01156 
01157       CommonTime toeCT = GPSWeekSecond(epochWeek, toe, TimeSystem::GPS);
01158 
01159       orbit.loadData(satSys, obsID, PRNID, beginFit, endFit, toeCT,
01160                      accFlag, healthy, cuc, cus, crc, crs, cic, cis, m0, Dn, 
01161                      dndot, Ecc, A, ahalf, Adot, Omega0, I0, W, OmegaDot, IDot);
01162       haveSubframe[1] = true;
01163       return *this;
01164    }
01165 
01166    EngEphemeris& EngEphemeris::setSF3( unsigned tlm, double how, short asalert,
01167                                        double cic, double Omega0, double cis,
01168                                        double I0, double crc, double W,
01169                                        double OmegaDot, double IDot )
01170       throw( InvalidRequest )
01171    {
01172       tlm_message[2] = tlm;
01173       HOWtime[2] = static_cast<long>( how );
01174       ASalert[2] = asalert;
01175 
01176       if (!haveSubframe[1])
01177       {
01178          InvalidRequest exc("Need to load subframe 2 before subframe 3");
01179          GPSTK_THROW(exc);
01180       }
01181       bool healthy = false;
01182       if (health == 0) healthy = true;
01183 
01184       double timeDiff = orbit.getToe() - HOWtime[2];
01185       short epochWeek = weeknum;
01186       if (timeDiff < -HALFWEEK) epochWeek++;
01187       else if (timeDiff > HALFWEEK) epochWeek--;
01188 
01189          // The observation ID has a type of navigation, but the
01190          // carrier and code types are undefined.  They could be
01191          // L1/L2 C/A, P, Y,.....
01192       ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
01193     
01194       short accFlag = 0;
01195       double toe = 0.0;
01196       double cuc = 0.0;
01197       double cus = 0.0;
01198       double crs = 0.0;
01199       double m0 = 0.0;
01200       double Dn = 0.0;
01201       double dndot = 0.0;
01202       double Ecc = 0.0;
01203       double A = 0.0;
01204       double ahalf = 0.0;
01205       double Adot = 0.0;
01206       CommonTime beginFit;
01207       CommonTime endFit;
01208       try
01209       {
01210          accFlag = orbit.getURAoe();
01211          toe = orbit.getToe();
01212          cuc = orbit.getCuc();
01213          cus = orbit.getCus();
01214          dndot = orbit.getDnDot();
01215          A = orbit.getA();
01216          Adot = orbit.getAdot();
01217          crs = orbit.getCrs();
01218          m0 = orbit.getM0();
01219          Dn = orbit.getDn();
01220          Ecc = orbit.getEcc();
01221          ahalf = orbit.getAhalf();
01222          beginFit = orbit.getBeginningOfFitInterval();
01223          endFit = orbit.getEndOfFitInterval();
01224       }
01225       catch(InvalidRequest)
01226       {
01227          //Should not get to this point because of the if(!haveSubFrame[1]) check above.
01228          haveSubframe[1] = false;
01229          haveSubframe[2] = false;
01230          return *this;
01231       }
01232       
01233       CommonTime toeCT = GPSWeekSecond(epochWeek, toe, TimeSystem::GPS);
01234 
01235       orbit.loadData( satSys, obsID, PRNID, beginFit, endFit, toeCT,
01236                       accFlag, healthy, cuc, cus, crc, crs, cic, cis, m0, Dn, 
01237                       dndot, Ecc, A, ahalf, Adot, Omega0, I0, W, OmegaDot, IDot);
01238 
01239       haveSubframe[2] = true;
01240       return *this;
01241    }
01242      
01243   void EngEphemeris::setFIC(const bool arg)
01244   {
01245         isFIC = arg;
01246   } 
01247 
01248    static void timeDisplay( ostream & os, const CommonTime& t )
01249    {
01250          // Convert to CommonTime struct from GPS wk,SOW to M/D/Y, H:M:S.
01251       GPSWeekSecond dummyTime;
01252       dummyTime = GPSWeekSecond(t);
01253       os << setw(4) << dummyTime.week << "(";
01254       os << setw(4) << (dummyTime.week & 0x03FF) << ")  ";
01255       os << setw(6) << setfill(' ') << dummyTime.sow << "   ";
01256 
01257       switch (dummyTime.getDayOfWeek())
01258       {
01259          case 0: os << "Sun-0"; break;
01260          case 1: os << "Mon-1"; break;
01261          case 2: os << "Tue-2"; break;
01262          case 3: os << "Wed-3"; break;
01263          case 4: os << "Thu-4"; break;
01264          case 5: os << "Fri-5"; break;
01265          case 6: os << "Sat-6"; break;
01266          default: break;
01267       }
01268       os << "   " << (static_cast<YDSTime>(t)).printf("%3j   %5.0s   ") 
01269          << (static_cast<CivilTime>(t)).printf("%02m/%02d/%04Y   %02H:%02M:%02S");
01270    }
01271 
01272    static void shortcut(ostream & os, const long HOW )
01273    {
01274       short DOW, hour, min, sec;
01275       long SOD, SOW;
01276       short SOH;
01277 
01278       SOW = static_cast<long>( HOW );
01279       DOW = static_cast<short>( SOW / SEC_PER_DAY );
01280       SOD = SOW - static_cast<long>( DOW * SEC_PER_DAY );
01281       hour = static_cast<short>( SOD/3600 );
01282 
01283       SOH = static_cast<short>( SOD - (hour*3600) );
01284       min = SOH/60;
01285 
01286       sec = SOH - min * 60;
01287       switch (DOW)
01288       {
01289          case 0: os << "Sun-0"; break;
01290          case 1: os << "Mon-1"; break;
01291          case 2: os << "Tue-2"; break;
01292          case 3: os << "Wed-3"; break;
01293          case 4: os << "Thu-4"; break;
01294          case 5: os << "Fri-5"; break;
01295          case 6: os << "Sat-6"; break;
01296          default: break;
01297       }
01298 
01299       os << ":" << setfill('0')
01300          << setw(2) << hour
01301          << ":" << setw(2) << min
01302          << ":" << setw(2) << sec
01303          << setfill(' ');
01304    }
01305     void EngEphemeris :: dumpTerse(ostream& s) const
01306       throw(InvalidRequest )
01307    {
01308      
01309        // Check if the subframes have been loaded before attempting
01310        // to dump them.
01311       if (!haveSubframe[0] || !haveSubframe[1] || !haveSubframe[2])
01312       {
01313          InvalidRequest exc("Need to load subframes 1,2 and 3");
01314          GPSTK_THROW(exc);
01315       }
01316 
01317       ios::fmtflags oldFlags = s.flags();
01318 
01319       s.setf(ios::fixed, ios::floatfield);
01320       s.setf(ios::right, ios::adjustfield);
01321       s.setf(ios::uppercase);
01322       s.precision(0);
01323       s.fill(' ');
01324 
01325       SVNumXRef svNumXRef; 
01326       int NAVSTARNum = 0;
01327       try
01328       {
01329         NAVSTARNum = svNumXRef.getNAVSTAR(PRNID, bcClock.getEpochTime());
01330         
01331      
01332         s << setw(2) << " " << NAVSTARNum << "  ";
01333       }
01334       catch(SVNumXRef::NoNAVSTARNumberFound)
01335       { 
01336         s << "  XX  ";
01337       }
01338 
01339       s << setw(2) << PRNID << " ! ";
01340       
01341       string tform = "%3j %02H:%02M:%02S";
01342 
01343       s << printTime(getTransmitTime(), tform) << " ! ";
01344       s << printTime(bcClock.getEpochTime(), tform) << " ! ";
01345       s << printTime(orbit.getEndOfFitInterval(), tform) << " !  ";
01346 
01347       s << setw(4) << setprecision(1) << getAccuracy() << "  ! ";
01348       s << "0x" << setfill('0') << hex << setw(3) << IODC << " ! ";
01349       s << "0x" << setfill('0')  << setw(2) << health;
01350       s << setfill(' ') << dec;
01351       s << "   " << setw(2) << health << " ! ";
01352 
01353       s << endl;
01354       s.flags(oldFlags);
01355 
01356     } // end of SF123::dumpTerse()
01357 
01358 
01359 
01360    void EngEphemeris :: dump(ostream& s) const
01361       throw( InvalidRequest )
01362    {
01363       
01364        
01365        // Check if the subframes have been loaded before attempting
01366        // to dump them.
01367       if (!haveSubframe[0] || !haveSubframe[1] || !haveSubframe[2])
01368       {
01369          InvalidRequest exc("Need to load subframes 1,2 and 3");
01370          GPSTK_THROW(exc);
01371       }
01372 
01373       ios::fmtflags oldFlags = s.flags();
01374 
01375       s.setf(ios::fixed, ios::floatfield);
01376       s.setf(ios::right, ios::adjustfield);
01377       s.setf(ios::uppercase);
01378       s.precision(0);
01379       s.fill(' ');
01380 
01381       s << "****************************************************************"
01382         << "************" << endl
01383         << "Broadcast Ephemeris (Engineering Units)";
01384         if(isFIC)
01385         {
01386                 s << " -FIC" << endl;
01387         }
01388         else
01389         {
01390                 s << " -RINEX" << endl;
01391         }
01392       s << endl;
01393       s << "PRN : " << setw(2) << PRNID << endl;
01394       s << endl;
01395 
01396 
01397       s << "              Week(10bt)     SOW     DOW   UTD     SOD"
01398         << "   MM/DD/YYYY   HH:MM:SS\n";
01399       s << "Clock Epoch:  ";
01400 
01401       timeDisplay(s, bcClock.getEpochTime());
01402       s << endl;
01403       s << "Eph Epoch:    ";
01404       timeDisplay(s, orbit.getOrbitEpoch());
01405       s << endl;
01406 /*
01407 #if 0
01408          // FIX when moved from sf123, the tot got zapped.. because in
01409          // order for EngEphemeris to be able to use such a thing, it
01410          // needs to be pulled out of as-broadcast bits somehow.
01411       s << "Transmit time:" << setw(4) << weeknum << ", sow=" << Tot.GPSsecond() << endl
01412         << "Fit interval flag :  " << setw(2) << fitint
01413         << " (" << fitintlen << " hours)" << endl;
01414 #elsif 0
01415       s << "Transmit time:" << setw(4) << weeknum << endl
01416         << "Fit interval flag :  " << setw(2) << fitint
01417         << " (" << getFitInt() << " hours)" << endl;
01418 #endif
01419          // nuts to the above, let's just make it look like navdump output
01420 */
01421       s << "Transmit Time:";
01422         timeDisplay(s, getTransmitTime());
01423       s << endl;
01424       s << "Fit interval flag :  " << fitint << endl;
01425       if(isFIC)
01426       {
01427          s << endl
01428           << "          SUBFRAME OVERHEAD"
01429           << endl
01430           << endl
01431           << "               SOW    DOW:HH:MM:SS     IOD    ALERT   A-S\n";
01432          for (int i=0;i<3;i++)
01433          {
01434                  s << "SF" << setw(1) << (i+1)
01435                  << " HOW:   " << setw(7) << HOWtime[i]
01436                  << "  ";
01437 
01438                  shortcut( s, HOWtime[i]);
01439                  if (i==0)
01440                     s << "   ";
01441                  else
01442                     s << "    ";
01443 
01444                   s << "0x" << setfill('0') << hex;
01445 
01446                  if (i==0)
01447                          s << setw(3) << IODC;
01448                  else
01449                     s << setw(2) << IODE;
01450         
01451                   s << dec << "      " << setfill(' ');
01452 
01453                  if (ASalert[i] & 0x0002)    // "Alert" bit handling
01454                     s << "1     ";
01455                  else
01456                     s << "0     ";
01457 
01458                   if (ASalert[i] & 0x0001)     // A-S flag handling
01459                     s << " on";
01460                  else
01461                     s << "off";
01462                  s << endl;
01463        }
01464      }
01465      else
01466      {
01467         s << endl;
01468         s << "IODC: 0x"
01469           << setfill('0') << hex;
01470         s << setw(3) << IODC << endl;
01471         s << "IODE:  0x"
01472           << setfill('0') << hex;
01473         s << setw(2) << IODE << endl;
01474     }
01475       s.setf(ios::scientific, ios::floatfield);
01476       s.precision(8);
01477       s.fill(' ');
01478 
01479       s << endl
01480         << "           CLOCK"
01481         << endl
01482         << endl
01483         << "Bias T0:     " << setw(16) << bcClock.getAf0() << " sec" << endl
01484         << "Drift:       " << setw(16) << bcClock.getAf1() << " sec/sec" << endl
01485         << "Drift rate:  " << setw(16) << bcClock.getAf2() << " sec/(sec**2)" << endl
01486         << "Group delay: " << setw(16) << Tgd << " sec" << endl;
01487 
01488       s << endl
01489         << "           ORBIT PARAMETERS"
01490         << endl
01491         << endl
01492         << "Semi-major axis:       " << setw(16) << orbit.getAhalf()  << " m**.5" << endl
01493         << "Motion correction:     " << setw(16) << orbit.getDn()     << " rad/sec"
01494         << endl
01495         << "Eccentricity:          " << setw(16) << orbit.getEcc()    << endl
01496         << "Arg of perigee:        " << setw(16) << orbit.getW()      << " rad" << endl
01497         << "Mean anomaly at epoch: " << setw(16) << orbit.getM0()     << " rad" << endl
01498         << "Right ascension:       " << setw(16) << orbit.getOmega0() << " rad    "
01499         << setw(16) << orbit.getOmegaDot() << " rad/sec" << endl
01500         << "Inclination:           " << setw(16) << orbit.getI0()     << " rad    "
01501         << setw(16) << orbit.getIDot()     << " rad/sec" << endl;
01502 
01503       s << endl
01504         << "           HARMONIC CORRECTIONS"
01505         << endl
01506         << endl
01507         << "Radial        Sine: " << setw(16) << orbit.getCrs() << " m    Cosine: "
01508         << setw(16) << orbit.getCrc() << " m" << endl
01509         << "Inclination   Sine: " << setw(16) << orbit.getCis() << " rad  Cosine: "
01510         << setw(16) << orbit.getCic() << " rad" << endl
01511         << "In-track      Sine: " << setw(16) << orbit.getCus() << " rad  Cosine: "
01512         << setw(16) << orbit.getCuc() << " rad" << endl;    
01513       
01514       s << endl
01515         << "           SV STATUS"
01516         << endl
01517         << endl
01518         << "Health bits:   0x" << setfill('0')  << setw(2) << health
01519         << "      URA index: " << setfill(' ') << setw(4) << orbit.getURAoe() << endl
01520         << "Code on L2:   ";
01521 
01522       switch (codeflags)
01523       {
01524          case 0:
01525             s << "reserved ";
01526             break;
01527 
01528          case 1:
01529             s << " P only  ";
01530             break;
01531 
01532          case 2:
01533             s << " C/A only";
01534             break;
01535 
01536          case 3:
01537             s << " P & C/A ";
01538             break;
01539 
01540          default:
01541             break;
01542 
01543       }
01544       if(isFIC)
01545       {
01546         s << "  L2 P Nav data:          ";
01547         if (L2Pdata!=0)
01548                 s << "off";
01549         else
01550                 s << "on";
01551       }
01552 
01553       s << endl;
01554       s.flags(oldFlags);
01555 
01556    } // end of SF123::dump()
01557 
01558    ostream& operator<<(ostream& s, const EngEphemeris& eph)
01559    {
01560      try
01561 {
01562       eph.dump(s);
01563 }
01564      catch(gpstk::Exception& ex)
01565 {
01566      ex.addLocation(FILE_LOCATION);
01567      GPSTK_RETHROW(ex);
01568 }
01569       return s;
01570 
01571    } // end of operator<<
01572 
01573 } // namespace

Generated on Tue May 21 03:31:07 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1