예제 #1
0
      // Casts Rinex3NavData to a QZSEphemeris object.
   Rinex3NavData::operator QZSEphemeris() const throw()
   {
      QZSEphemeris qzse;

      // fill the OrbitEph parts
      castTo(dynamic_cast<OrbitEph*>(&qzse));

      // is it right?
      if(qzse.satID.system != SatID::systemQZSS)
         qzse.dataLoadedFlag = false;

      if(!qzse.dataLoadedFlag)
         return qzse;          // throw?

      // get the epochs right
      CommonTime ct = time;
      unsigned int year = static_cast<CivilTime>(ct).year;

      // Get week for clock, to build Toc
      double dt = Toc - HOWtime;
      int week = weeknum;
      if(dt < -HALFWEEK) week++; else if(dt > HALFWEEK) week--;
      QZSWeekSecond qzsws = QZSWeekSecond(week, Toc, TimeSystem::QZS);
      qzsws.adjustToYear(year);
      qzse.ctToc = CommonTime(qzsws);

      //MGEX NB MGEX data has GPS week numbers in all systems except BeiDou,
      //MGEX so must implement temporary fixes: use GPS Toc for QZS and QZSS
      CommonTime gpstoc = GPSWeekSecond(week, Toc, TimeSystem::GPS);    //MGEX
      qzse.ctToc = gpstoc;                                              //MGEX

      qzse.ctToc.setTimeSystem(TimeSystem::QZS);

      // now load the QZSS-specific parts
      qzse.satID = SatID(qzse.satID.id + 192, SatID::systemQZSS);
      qzse.IODC = IODC;
      qzse.IODE = IODE;
      qzse.health = health;
      qzse.accuracy = accuracy;
      qzse.Tgd = Tgd;

      qzse.HOWtime = HOWtime;
      week = static_cast<QZSWeekSecond>(qzse.ctToe).getWeek();
      qzse.transmitTime = QZSWeekSecond(week, static_cast<double>(HOWtime),
                                          TimeSystem::QZS);

      qzse.codeflags = codeflgs;
      qzse.L2Pdata = L2Pdata;

      // NB IODC must be set first...
      qzse.fitint = fitint;
      qzse.setFitIntervalFlag(int(fitint));  // calls adjustValidity();

      return qzse;
   }
예제 #2
0
      // Casts Rinex3NavData to a GalEphemeris object.
   Rinex3NavData::operator GalEphemeris() const throw()
   {
      GalEphemeris gale;

      // fill the OrbitEph parts
      OrbitEph *ptr = dynamic_cast<OrbitEph*>(&gale);
      castTo(ptr);                                          // sets dataLoadedFlag

      // is it right?
      if(gale.satID.system != SatID::systemGalileo)
         gale.dataLoadedFlag = false;

      if(!gale.dataLoadedFlag)
         return gale;          // throw?

      // get the epochs right
      CommonTime ct = time;
      //unsigned int year = static_cast<CivilTime>(ct).year;

      // Get week for clock, to build Toc
      double dt = Toc - HOWtime;
      int week = weeknum;
      if(dt < -HALFWEEK) week++; else if(dt > HALFWEEK) week--;
      //MGEX NB MGEX data has GPS week numbers in all systems except BeiDou,
      //MGEX so must implement temporary fixes: use GPS Toc for GAL and QZSS
      //MGEX GALWeekSecond galws = GALWeekSecond(week, Toc, TimeSystem::GAL);
      //MGEX galws.adjustToYear(year);
      //MGEX gale.ctToc = CommonTime(galws);
      CommonTime gpstoc = GPSWeekSecond(week, Toc, TimeSystem::GPS);    //MGEX
      gale.ctToc = gpstoc;                                              //MGEX
      gale.ctToc.setTimeSystem(TimeSystem::GAL);

      // now load the Galileo-specific parts
      gale.IODnav = IODnav;
      gale.health = health;
      gale.accuracy = accuracy;
      gale.Tgda = Tgd;
      gale.Tgdb = Tgd2;
      gale.datasources = datasources;
      gale.fitDuration = 4;

      gale.HOWtime = HOWtime;
      week = static_cast<GALWeekSecond>(gale.ctToe).getWeek();
      gale.transmitTime = GALWeekSecond(week, static_cast<double>(HOWtime),
                                       TimeSystem::GAL);
      gale.adjustValidity();

      return gale;
   }
예제 #3
0
   // adjustBeginningValidity determines the beginValid and endValid times.
   // @throw Invalid Request if the required data has not been stored.
   void GPSEphemeris::adjustValidity(void)
   {
      try {
         OrbitEph::adjustValidity();   // for dataLoaded check

	      // Beginning of Validity
               // New concept.  Admit the following.
	      //  (a.) The collection system may not capture the data at earliest transmit.
	      //  (b.) The collection system may not capture the three SFs consecutively.
	      // Consider a couple of IS-GPS-200 promises,
	      //  (c.) By definition, beginning of validity == beginning of transmission.
	      //  (d.) Except for uploads, cutovers will only happen on hour boundaries
	      //  (e.) Cutovers can be detected by non-even Toc.
	      //  (f.) Even uploads will cutover on a frame (30s) boundary.
               // Therefore,
	      //   1.) If Toc is NOT even two hour interval, pick lowest HOW time,
	      //   round back to even 30s.  That's the earliest Xmit time we can prove.
	      //   NOTE: For the case where this is the SECOND SF 1/2/3 after an upload,
	      //   this may yield a later time as such a SF 1/2/3 will be on a even
	      //   hour boundary.  Unfortunately, we have no way of knowing whether
	      //   this item is first or second after upload without additional information
	      //   2.) If Toc IS even two hour interval, pick time from SF 1,
	      //   round back to nearest EVEN two hour boundary.  This assumes collection
	      //   SOMETIME in first hour of transmission.  Could be more
	      //   complete by looking at fit interval and IODC to more accurately
	      //   determine earliest transmission time.
         long longToc = static_cast<GPSWeekSecond>(ctToc).getSOW();
         long XmitWeek = static_cast<GPSWeekSecond>(transmitTime).getWeek();
         double XmitSOW = 0.0;
         if ( (longToc % 7200) != 0)     // NOT an even two hour change
         {
            long Xmit = HOWtime - (HOWtime % 30);
	         XmitSOW = (double) Xmit;
         }
         else
         {
            long Xmit = HOWtime - HOWtime % 7200;
	         XmitSOW = (double) Xmit;
         }
         beginValid = GPSWeekSecond( XmitWeek, XmitSOW, TimeSystem::GPS );

	      // End of Validity.
	      // The end of validity is calculated from the fit interval
	      // and the Toe.  The fit interval is either trivial
	      // (if fit interval flag==0, fit interval is 4 hours)
	      // or a look-up table based on the IODC.
	      // Round the Toe value to the hour to elminate confusion
	      // due to possible "small offsets" indicating uploads
         long epochWeek = static_cast<GPSWeekSecond>(ctToe).getWeek();
         double Toe = static_cast<GPSWeekSecond>(ctToe).getSOW();
         long ToeOffset = (long) Toe % 3600;
         double adjToe = Toe;                  // Default case
         if (ToeOffset)
         {
            adjToe += 3600.0 - (double)ToeOffset;  // If offset, then adjust to remove
         }
         long endFitSOW = adjToe + (fitDuration/2)*3600;
         short endFitWk = epochWeek;
         if (endFitSOW >= FULLWEEK)
         {
            endFitSOW -= FULLWEEK;
            endFitWk++;
         }
         endValid = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS);
      }
      catch(Exception& e) { GPSTK_RETHROW(e); }
   }
예제 #4
0
   //  BDS is different in that some satellites are in GEO orbits.
   //  According to the ICD, the 
   //  SV position derivation for MEO and IGSO is identical to 
   //  that for other kepler+perturbation systems (e.g. GPS); however,
   //  the position derivation for the GEO SVs is different.
   //  According to the ICD, the GEO SVs are those with PRNs 1-5.
   //  The following method overrides OrbitEph.svXvt( ).  It uses
   //  OrbitEph::svXvt( ) for PRNs above 5, but implements a different
   //  algorithm for PRNs 1-5.
   Xvt BDSEphemeris::svXvt(const CommonTime& t) const
   {
      if(!dataLoadedFlag)
         GPSTK_THROW(InvalidRequest("Data not loaded"));
      
         // If the PRN ID is greatet than 5, assume this
         // is a MEO or IGSO SV and use the standard OrbitEph
         // version of svXvt
      if (satID.id>5) return(OrbitEph::svXvt(t));

         // If PRN ID is in the range 1-5, treat this as a GEO
         // 
         // The initial calculations are identical to the standard
         // Kepler+preturbation model
      Xvt sv;
      double ea;              // eccentric anomaly
      double delea;           // delta eccentric anomaly during iteration
      double elapte;          // elapsed time since Toe
      //double elaptc;          // elapsed time since Toc
      //double dtc,dtr;
      double q,sinea,cosea;
      double GSTA,GCTA;
      double amm;
      double meana;           // mean anomaly
      double F,G;             // temporary real variables
      double alat,talat,c2al,s2al,du,dr,di,U,R,truea,AINC;
      double ANLON,cosu,sinu,xip,yip,can,san,cinc,sinc;
      double dek,dlk,div,duv,drv;
      double dxp,dyp;
      double xGK,yGK,zGK;

      WGS84Ellipsoid ell;
      double sqrtgm = SQRT(ell.gm());
      double twoPI = 2.0e0 * PI;
      double lecc;            // eccentricity
      double tdrinc;          // dt inclination
      double Ahalf = SQRT(A); // A is semi-major axis of orbit
      double ToeSOW = GPSWeekSecond(ctToe).sow;    // SOW is time-system-independent

      lecc = ecc;
      tdrinc = idot;

      // Compute time since ephemeris & clock epochs
      elapte = t - ctToe;

      // Compute mean motion
      amm  = (sqrtgm / (A*Ahalf)) + dn;

      // In-plane angles
      //     meana - Mean anomaly
      //     ea    - Eccentric anomaly
      //     truea - True anomaly
      meana = M0 + elapte * amm;
      meana = fmod(meana, twoPI);
      ea = meana + lecc * ::sin(meana);

      int loop_cnt = 1;
      do  {
         F = meana - (ea - lecc * ::sin(ea));
         G = 1.0 - lecc * ::cos(ea);
         delea = F/G;
         ea = ea + delea;
         loop_cnt++;
      } while ((fabs(delea) > 1.0e-11) && (loop_cnt <= 20));

      // Compute clock corrections
      sv.relcorr = svRelativity(t);
      sv.clkbias = svClockBias(t);
      sv.clkdrift = svClockDrift(t);
      sv.frame = ReferenceFrame::WGS84;

      // Compute true anomaly
      q     = SQRT(1.0e0 - lecc*lecc);
      sinea = ::sin(ea);
      cosea = ::cos(ea);
      G     = 1.0e0 - lecc * cosea;

      //  G*SIN(TA) AND G*COS(TA)
      GSTA  = q * sinea;
      GCTA  = cosea - lecc;

      //  True anomaly
      truea = atan2 (GSTA, GCTA);

      // Argument of lat and correction terms (2nd harmonic)
      alat  = truea + w;
      talat = 2.0e0 * alat;
      c2al  = ::cos(talat);
      s2al  = ::sin(talat);

      du  = c2al * Cuc +  s2al * Cus;
      dr  = c2al * Crc +  s2al * Crs;
      di  = c2al * Cic +  s2al * Cis;

      // U = updated argument of lat, R = radius, AINC = inclination
      U    = alat + du;
      R    = A*G  + dr;
      AINC = i0 + tdrinc * elapte  +  di;

      // At this point, the ICD formulation diverges to something 
      // different. 
      //  Longitude of ascending node (ANLON)
      ANLON = OMEGA0 + OMEGAdot * elapte
                     - ell.angVelocity() * ToeSOW;

      // In plane location
      cosu = ::cos(U);
      sinu = ::sin(U);
      xip  = R * cosu;
      yip  = R * sinu;

      //  Angles for rotation
      can  = ::cos(ANLON);
      san  = ::sin(ANLON);
      cinc = ::cos(AINC);
      sinc = ::sin(AINC);

      // GEO satellite coordinates in user-defined inertial system
      xGK  =  xip*can  -  yip*cinc*san;
      yGK  =  xip*san  +  yip*cinc*can;
      zGK  =              yip*sinc;

      // Rz matrix
      double angleZ = ell.angVelocity() * elapte;
      double cosZ = ::cos(angleZ);
      double sinZ = ::sin(angleZ); 

         // Initiailize 3X3 with all 0.0
      gpstk::Matrix<double> matZ(3,3); 
      // Row,Col
      matZ(0,0) =  cosZ;
      matZ(0,1) =  sinZ;
      matZ(0,2) =   0.0;
      matZ(1,0) = -sinZ;
      matZ(1,1) =  cosZ; 
      matZ(1,2) =   0.0;
      matZ(2,0) =   0.0;
      matZ(2,1) =   0.0;
      matZ(2,2) =   1.0; 

      // Rx matrix
      double angleX = -5.0 * PI/180.0;    /// This is a constant.  Should set it once
      double cosX = ::cos(angleX);
      double sinX = ::sin(angleX); 
      gpstk::Matrix<double> matX(3,3);
      matX(0,0) =   1.0;
      matX(0,1) =   0.0;
      matX(0,2) =   0.0;
      matX(1,0) =   0.0;
      matX(1,1) =  cosX;
      matX(1,2) =  sinX;
      matX(2,0) =   0.0;
      matX(2,1) = -sinX;
      matX(2,2) =  cosX;

      // Matrix (single column) of xGK, yGK, zGK
      gpstk::Matrix<double> inertialPos(3,1);
      inertialPos(0,0) = xGK;
      inertialPos(1,0) = yGK;
      inertialPos(2,0) = zGK;

      gpstk::Matrix<double> result(3,1);
      result = matZ * matX * inertialPos;

      sv.x[0] = result(0,0);
      sv.x[1] = result(1,0);
      sv.x[2] = result(2,0);

      // derivatives of true anamoly and arg of latitude
      dek = amm / G; 
      dlk =  Ahalf * q * sqrtgm / (R*R);

      // in-plane, cross-plane, and radial derivatives
      div = tdrinc - 2.0e0 * dlk * (Cis  * c2al - Cic * s2al);
      duv = dlk*(1.e0+ 2.e0 * (Cus*c2al - Cuc*s2al));
      drv = A * lecc * dek * sinea + 2.e0 * dlk * (Crs * c2al - Crc * s2al);

      //
      dxp = drv*cosu - R*sinu*duv;
      dyp = drv*sinu + R*cosu*duv;

      // Time-derivative of Rz matrix
      gpstk::Matrix<double> dmatZ(3,3);
      // Row,Col
      dmatZ(0,0) =  sinZ * -ell.angVelocity();
      dmatZ(0,1) = -cosZ * -ell.angVelocity();
      dmatZ(0,2) =   0.0;
      dmatZ(1,0) =  cosZ * -ell.angVelocity();
      dmatZ(1,1) =  sinZ * -ell.angVelocity();
      dmatZ(1,2) =   0.0;
      dmatZ(2,0) =   0.0;
      dmatZ(2,1) =   0.0;
      dmatZ(2,2) =   0.0;

      // Time-derivative of X,Y,Z in interial form
      gpstk::Matrix<double> dIntPos(3,1);
      dIntPos(0,0) = - xip * san * OMEGAdot
                     + dxp * can
                     - yip * (cinc * can * OMEGAdot
                             -sinc * san * div )
                     - dyp * cinc * san;
      dIntPos(1,0) =   xip * can * OMEGAdot
                     + dxp * san
                     - yip * (cinc * san * OMEGAdot
                             +sinc * can * div )
                     + dyp * cinc * can;
      dIntPos(2,0) = yip * cinc * div + dyp * sinc;

      /*
      cout << "dIntPos : " << dIntPos(0,0) 
                           << ", " << dIntPos(1,0)
                           << ", " << dIntPos(2,0) << endl;
      double vMag = ::sqrt(dIntPos(0,0)*dIntPos(0,0) + 
                           dIntPos(1,0)*dIntPos(1,0) +                    
                           dIntPos(2,0)*dIntPos(2,0) );
      cout << " dIntPos Mag: " << vMag << endl;     
      cout << "dmatZ : " << dmatZ(0,0) 
                   << ", " << dmatZ(0,1)
                   << ", " << dmatZ(0,2) << endl; 
      cout << "dmatZ : " << dmatZ(1,0) 
                   << ", " << dmatZ(1,1)
                   << ", " << dmatZ(1,2) << endl; 
      cout << "dmatZ : " << dmatZ(2,0) 
                   << ", " << dmatZ(2,1)
                   << ", " << dmatZ(2,2) << endl; 
      */
      gpstk::Matrix<double> vresult(3,1);
      vresult =  matZ * matX * dIntPos + 
                dmatZ * matX * inertialPos;

      /* debug
      gpstk::Matrix<double> firstHalf(3,1);
      firstHalf = matZ * matX * dIntPos;
      gpstk::Matrix<double> secondHalf(3,1);
      secondHalf = dmatZ * matX * inertialPos;

      cout << "firstHalf: " << firstHalf(0,0)
                    << ", " << firstHalf(1,0)
                    << ", " << firstHalf(2,0) << endl;
      cout << "secondHalf: " << secondHalf(0,0)
                    << ", " << secondHalf(1,0)
                    << ", " << secondHalf(2,0) << endl;
      end debug */
     
      // Move results into output variables
      sv.v[0] = vresult(0,0);
      sv.v[1] = vresult(1,0);
      sv.v[2] = vresult(2,0);
      
      return sv;
   }
예제 #5
0
      // Casts Rinex3NavData to a GPSEphemeris object.
   Rinex3NavData::operator GPSEphemeris() const throw()
   {
      GPSEphemeris gpse;

      // fill the OrbitEph parts
      OrbitEph* ptr = dynamic_cast<OrbitEph*>(&gpse);
      castTo(ptr);                                 //sets dataLoadedFlag

      // is it right?
      if(gpse.satID.system != SatID::systemGPS)
         gpse.dataLoadedFlag = false;

      if(!gpse.dataLoadedFlag)
         return gpse;          // throw?

         // Special case to address common problem in IGS aggregate brdc
         // files.   In some cases (typ. beginning of week) the last
         // SF 1/2/3 for the previous day is being output with a HOWtime of 
         // zero.  This leaves it in conflict with the first SF 1/2/3 of
         // the new day (which typically has a HOW of zero)
      long adjHOWtime = HOWtime;
      short adjWeeknum = weeknum;
      long lToc = (long) Toc;
      if ((HOWtime%SEC_PER_DAY)==0 && 
         ((lToc)%SEC_PER_DAY)==0 &&
           HOWtime == lToc) 
      {
         adjHOWtime = HOWtime - 30;  
         if (adjHOWtime<0)
         {
            adjHOWtime += FULLWEEK;  
            adjWeeknum--;     
         }
      }
         // end special case adjustment (except for use of adjHOWtime below)

      // get the epochs right
      CommonTime ct = time;
      //unsigned int year = static_cast<CivilTime>(ct).year;

      // Get week for clock, to build Toc
      double dt = Toc - adjHOWtime;
      int week = adjWeeknum;
      if(dt < -HALFWEEK) week++; else if(dt > HALFWEEK) week--;
      gpse.ctToc = GPSWeekSecond(week, Toc, TimeSystem::GPS);
      gpse.ctToc.setTimeSystem(TimeSystem::GPS);

      // now load the GPS-specific parts
      gpse.IODC = IODC;
      gpse.IODE = IODE;
      gpse.health = health;
      gpse.accuracyFlag = accuracy;
      gpse.Tgd = Tgd;

      gpse.HOWtime = HOWtime;
      week = static_cast<GPSWeekSecond>(gpse.ctToe).getWeek();
      
      gpse.transmitTime = GPSWeekSecond(adjWeeknum, static_cast<double>(adjHOWtime),
         TimeSystem::GPS);

      gpse.codeflags = codeflgs;
      gpse.L2Pdata = L2Pdata;

      // NB IODC must be set first...
      gpse.fitint = fitint;
      gpse.setFitIntervalFlag(int(fitint));  // calls adjustValidity();

      return gpse;
   }
예제 #6
0
      // Deprecated; use GPSEphemeris.
      // Converts this Rinex3NavData to an EngEphemeris object.
   Rinex3NavData::operator EngEphemeris() const throw()
   {
      EngEphemeris ee;

      // There's no TLM word in Rinex3NavData, so it's set to 0.
      // Likewise, there's no AS alert or tracker.
      // Also, in RINEX, the accuracy is in meters, and setSF1 expects
      // the accuracy flag.  We'll give it zero and pass the accuracy
      // separately via the setAccuracy() method.

      ee.tlm_message[0] = 0;           
      ee.tlm_message[1] = 0;
      ee.tlm_message[2] = 0;
      ee.HOWtime[0] = HOWtime;  // RINEX does not actually specify 
      ee.HOWtime[1] = HOWtime;  // how the transmit time is derived.  Therefore,
      ee.HOWtime[2] = HOWtime;  // These values may be misleading.  
      ee.ASalert[0] = 1;               //AS and alert flags set to 1 (default)
      ee.ASalert[1] = 1;
      ee.ASalert[2] = 1;

      ee.weeknum    = weeknum;
      ee.codeflags  = codeflgs;
      ee.health     = health;  
      ee.IODC       = short(IODC);
      ee.L2Pdata    = L2Pdata;
      ee.Tgd        = Tgd;
      ee.tracker    = 0;
      ee.PRNID      = PRNID;
      ee.satSys     = satSys;
      bool healthy = false;
      if (health == 0) healthy = true;
      short accFlag = 0; //will be set later.
          //BrcClockCorrection takes a flag, while EngEphemeris takes a double.
      double toc    = Toc;

      double timeDiff =toc - ee.HOWtime[0];
      short epochWeek = ee.weeknum;
      if (timeDiff < -HALFWEEK) epochWeek++;
      else if (timeDiff > HALFWEEK) epochWeek--;

      CommonTime tocCT = GPSWeekSecond(epochWeek, Toc, TimeSystem::GPS);

         // The observation ID has a type of navigation, but the
         // carrier and code types are undefined.  They could be
         // L1/L2 C/A, P, Y,.....
      ObsID obsID(ObsID::otNavMsg, ObsID::cbUndefined, ObsID::tcUndefined);
      ee.bcClock.loadData( satSys, obsID, PRNID, tocCT,
                        accFlag, healthy, af0, af1, af2);

      ee.IODE    = short(IODE);      
      ee.fitint  = (fitint > 4) ? 1 : 0;
      //double toe = Toe; //?????
      
      //Needed for modernized nav quatities
      double A = Ahalf * Ahalf;
      double dndot = 0.0;
      double Adot = 0.0;

      short fitHours = getLegacyFitInterval(ee.IODC, ee.fitint);
      long beginFitSOW = Toe - (fitHours/2)*3600.0;
      long endFitSOW = Toe + (fitHours/2)*3600.0;
      short beginFitWk = ee.weeknum;
      short endFitWk = ee.weeknum;

      if (beginFitSOW < 0)
      {
         beginFitSOW += FULLWEEK;
         beginFitWk--;
      }
      CommonTime beginFit = GPSWeekSecond(beginFitWk, beginFitSOW, TimeSystem::GPS);
      if (endFitSOW >= FULLWEEK)
      {
         endFitSOW += FULLWEEK;
         endFitWk++;
      }

      CommonTime endFit = GPSWeekSecond(endFitWk, endFitSOW, TimeSystem::GPS);
      CommonTime toeCT = GPSWeekSecond(epochWeek, Toe, TimeSystem::GPS);

      ee.orbit.loadData( satSys, obsID, PRNID, beginFit, endFit, toeCT,
                      accFlag, healthy, Cuc, Cus, Crc, Crs, Cic, Cis, 
                      M0, dn, dndot, ecc, A, Ahalf, Adot, OMEGA0, i0, 
                      w, OMEGAdot, idot);

      ee.haveSubframe[0] = true;    // need to be true to perform certain EngEphemeris functions
      ee.haveSubframe[1] = true;    // examples: ee.dump(), ee.setAccuracy()
      ee.haveSubframe[2] = true;

      ee.setAccuracy(accuracy);

     return ee;

   }  // End of 'Rinex3NavData::operator EngEphemeris()'
예제 #7
0
    /**
     * Get the ephemeris reference time as a GPSWeekSecond object.
     */
 GPSWeekSecond getToeWS() const
 { return GPSWeekSecond(toeWeek, Toe, TimeSystem::GPS); }
예제 #8
0
   double TimeSystemCorrection ::
   Correction(const CommonTime& ct) const
   {
      double corr(0.0), dt;
      TimeSystem fromTS(ct.getTimeSystem());
      GPSWeekSecond gpsws;
      CommonTime refTime;
      Exception e("Unable to compute correction - wrong TimeSystem");
      Exception eSBAS("TimeSystemCorrection SBAS <=> UTC has not been implemented");

      switch(type)
      {
         case GPUT:
            if(fromTS != TimeSystem::GPS && fromTS != TimeSystem::UTC)
            {
               GPSTK_THROW(e);
            }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::GPS)             // GPS => UTC
               corr = -A0-A1*dt;
            else                                      // UTC => GPS
               corr = A0+A1*dt;

            break;

         case GAUT:
            if(fromTS != TimeSystem::GAL && fromTS != TimeSystem::UTC)
            { GPSTK_THROW(e); }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::GAL)             // GAL => UTC
               corr = A0+A1*dt;
            else                                      // UTC => GAL
               corr = -A0-A1*dt;

            break;

         case SBUT:
            GPSTK_THROW(eSBAS);
            break;

         case GLUT:
            if(fromTS != TimeSystem::GLO && fromTS != TimeSystem::UTC)
            {
               GPSTK_THROW(e);
            }

            if(fromTS == TimeSystem::GLO)             // GLO => UTC
               corr = A0;
            else                                      // UTC => GLO
               corr = -A0;

            break;

         case GPGA:
            if(fromTS != TimeSystem::GPS && fromTS != TimeSystem::GAL)
            {
               GPSTK_THROW(e);
            }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::GPS)             // GPS => GAL
               corr = A0+A1*dt;
            else                                      // GAL => GPS
               corr = -A0-A1*dt;

            break;

         case GLGP:
            if(fromTS != TimeSystem::GLO && fromTS != TimeSystem::GPS)
            {
               GPSTK_THROW(e);
            }

            if(fromTS == TimeSystem::GLO)             // GLO => GPS
               corr = A0;
            else                                      // GPS => GLO
               corr = -A0;

            break;

         case QZGP:
            if(fromTS != TimeSystem::QZS && fromTS != TimeSystem::GPS)
            {
               GPSTK_THROW(e);
            }

            if(fromTS == TimeSystem::QZS)             // QZS => GPS
               corr = 0.0;    // TD?
            else                                      // GPS => QZS
               corr = 0.0;    // TD?

            break;

         case QZUT:
            if(fromTS != TimeSystem::QZS && fromTS != TimeSystem::UTC)
            {
               GPSTK_THROW(e);
            }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::QZS)             // QZS => UTC
               corr = A0+A1*dt;
            else                                      // UTC => QZS
               corr = -A0-A1*dt;

            break;

         case BDUT:
            if(fromTS != TimeSystem::BDT && fromTS != TimeSystem::UTC)
            {
               GPSTK_THROW(e);
            }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::BDT)             // BDT => UTC
               corr = A0+A1*dt;
            else                                      // UTC => BDT
               corr = -A0-A1*dt;

            break;

         case BDGP:
            if(fromTS != TimeSystem::BDT && fromTS != TimeSystem::GPS)
            {
               GPSTK_THROW(e);
            }

               // dt = fromTime - refTime
            gpsws = GPSWeekSecond(refWeek,refSOW);
            refTime = gpsws.convertToCommonTime();
            refTime.setTimeSystem(fromTS);
            dt = ct - refTime;

            if(fromTS == TimeSystem::BDT)             // BDT => GPS
               corr = A0;
            else                                      // GPS => BDT
               corr = -A0;

            break;

         default:
            Exception e("TimeSystemCorrection is not defined.");
            GPSTK_THROW(e);
            break;
      }

      return corr;
   }
예제 #9
0
   // Convert this RinexNavData to a GPSEphemeris object.
   // for backward compatibility only - use Rinex3NavData
   RinexNavData::operator GPSEphemeris() const
   {
      GPSEphemeris gpse;
      try {
         // Overhead
         gpse.satID = SatID(PRNID, SatID::systemGPS);
         gpse.ctToe = time;

         // clock model
         gpse.af0 = af0;
         gpse.af1 = af1;
         gpse.af2 = af2;
   
         // Major orbit parameters
         gpse.M0 = M0;
         gpse.dn = dn;
         gpse.ecc = ecc;
         gpse.A = Ahalf * Ahalf;
         gpse.OMEGA0 = OMEGA0;
         gpse.i0 = i0;
         gpse.w = w;
         gpse.OMEGAdot = OMEGAdot;
         gpse.idot = idot;
         // modern nav msg
         gpse.dndot = 0.;
         gpse.Adot = 0.;
   
         // Harmonic perturbations
         gpse.Cuc = Cuc;
         gpse.Cus = Cus;
         gpse.Crc = Crc;
         gpse.Crs = Crs;
         gpse.Cic = Cic;
         gpse.Cis = Cis;
   
         gpse.dataLoadedFlag = true;

         // get the epochs right
         CommonTime ct = time;
         //unsigned int year = static_cast<CivilTime>(ct).year;

         // Get week for clock, to build Toc
         double dt = Toc - HOWtime;
         int week = weeknum;
         if(dt < -HALFWEEK) week++; else if(dt > HALFWEEK) week--;
         gpse.ctToc = GPSWeekSecond(week, Toc, TimeSystem::GPS);
         gpse.ctToc.setTimeSystem(TimeSystem::GPS);

         // now load the GPS-specific parts
         gpse.IODC = IODC;
         gpse.IODE = IODE;
         gpse.health = health;
         gpse.accuracyFlag = accuracy;
         gpse.Tgd = Tgd;

         gpse.HOWtime = HOWtime;
         week = static_cast<GPSWeekSecond>(gpse.ctToe).getWeek();
         gpse.transmitTime = GPSWeekSecond(week, static_cast<double>(HOWtime),
            TimeSystem::GPS);

         gpse.codeflags = codeflgs;
         gpse.L2Pdata = L2Pdata;

         // NB IODC must be set first...
         gpse.fitint = fitint;
         gpse.setFitIntervalFlag(int(fitint));  // calls adjustValidity();
      }
      catch(Exception& e) { GPSTK_RETHROW(e); }

      return gpse;
   }