EphemerisRange.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: EphemerisRange.cpp 1264 2008-06-25 13:18:27Z ocibu $"
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //  
00021 //  Copyright 2004, The University of Texas at Austin
00022 //
00023 //============================================================================
00024 //============================================================================
00025 //
00026 //This software developed by Applied Research Laboratories at the University of
00027 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00028 //Department of Defense. The U.S. Government retains all rights to use,
00029 //duplicate, distribute, disclose, or release this software. 
00030 //
00031 //Pursuant to DoD Directive 523024 
00032 //
00033 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00034 //                           release, distribution is unlimited.
00035 //
00036 //=============================================================================
00037 
00044 #include "EphemerisRange.hpp"
00045 #include "MiscMath.hpp"
00046 #include "GPSGeoid.hpp"
00047 #include "icd_200_constants.hpp"
00048 #include "geometry.hpp"
00049 
00050 using namespace std;
00051 using namespace gpstk;
00052 
00053 namespace gpstk
00054 {
00055    // Compute the corrected range at RECEIVE time, from receiver at position Rx,
00056    // to the GPS satellite given by SatID sat, as well as all the CER quantities,
00057    // given the nominal receive time tr_nom and an EphemerisStore. Note that this
00058    // routine does not intrinsicly account for the receiver clock error
00059    // like the ComputeAtTransmitTime routine does.
00060    double CorrectedEphemerisRange::ComputeAtReceiveTime(
00061       const DayTime& tr_nom,
00062       const Position& Rx,
00063       const SatID sat,
00064       const XvtStore<SatID>& Eph)
00065    {
00066       try {
00067          int nit;
00068          double tof,tof_old,wt,sx,sy;
00069          GPSGeoid geoid;
00070 
00071          nit = 0;
00072          tof = 0.07;       // initial guess 70ms
00073          do {
00074             // best estimate of transmit time
00075             transmit = tr_nom;
00076             transmit -= tof;
00077             tof_old = tof;
00078             // get SV position
00079             try {
00080                svPosVel = Eph.getXvt(sat, transmit);
00081             }
00082             catch(InvalidRequest& e) {
00083                GPSTK_RETHROW(e);
00084             }
00085 
00086             rotateEarth(Rx);
00087             // update raw range and time of flight
00088             rawrange = RSS(svPosVel.x[0]-Rx.X(),
00089                            svPosVel.x[1]-Rx.Y(),
00090                            svPosVel.x[2]-Rx.Z());
00091             tof = rawrange/geoid.c();
00092 
00093          } while(ABS(tof-tof_old)>1.e-13 && ++nit<5);
00094 
00095          updateCER(Rx);
00096 
00097          return (rawrange-svclkbias-relativity);
00098       }
00099       catch(gpstk::Exception& e) {
00100          GPSTK_RETHROW(e);
00101       }
00102    }  // end CorrectedEphemerisRange::ComputeAtReceiveTime
00103 
00104 
00105       // Compute the corrected range at TRANSMIT time, from receiver at position Rx,
00106       // to the GPS satellite given by SatID sat, as well as all the CER quantities,
00107       // given the nominal receive time tr_nom and an EphemerisStore, as well as
00108       // the raw measured pseudorange.
00109    double CorrectedEphemerisRange::ComputeAtTransmitTime(
00110       const DayTime& tr_nom,
00111       const double& pr,
00112       const Position& Rx,
00113       const SatID sat,
00114       const XvtStore<SatID>& Eph)
00115    {
00116       try {
00117          DayTime tt;
00118 
00119          // 0-th order estimate of transmit time = receiver - pseudorange/c
00120          transmit = tr_nom;
00121          transmit -= pr/C_GPS_M;
00122          tt = transmit;
00123 
00124          // correct for SV clock
00125          for(int i=0; i<2; i++) {
00126             // get SV position
00127             try {
00128                svPosVel = Eph.getXvt(sat,tt);
00129             }
00130             catch(InvalidRequest& e) {
00131                GPSTK_RETHROW(e);
00132             }
00133             tt = transmit;
00134             tt -= svPosVel.dtime;      // clock and relativity
00135          }
00136 
00137          rotateEarth(Rx);
00138          // raw range
00139          rawrange = RSS(svPosVel.x[0]-Rx.X(),
00140                         svPosVel.x[1]-Rx.Y(),
00141                         svPosVel.x[2]-Rx.Z());
00142 
00143          updateCER(Rx);
00144 
00145          return (rawrange-svclkbias-relativity);
00146       }
00147       catch(gpstk::Exception& e) {
00148          GPSTK_RETHROW(e);
00149       }
00150    }  // end CorrectedEphemerisRange::ComputeAtTransmitTime
00151 
00152 
00153 
00154    double CorrectedEphemerisRange::ComputeAtTransmitSvTime(
00155       const DayTime& tt_nom,
00156       const double& pr,
00157       const Position& rx,
00158       const SatID sat,
00159       const XvtStore<SatID>& eph)
00160    {
00161       try {
00162          svPosVel = eph.getXvt(sat, tt_nom);
00163 
00164          // compute rotation angle in the time of signal transit
00165          // While this is quite similiar to rotateEarth, its not the same and jcl doesn't
00166          // know which is really correct
00167          GPSGeoid gm;
00168          double rotation_angle = -gm.angVelocity() * (pr/gm.c() - svPosVel.dtime);         
00169          svPosVel.x[0] = svPosVel.x[0] - svPosVel.x[1] * rotation_angle;
00170          svPosVel.x[1] = svPosVel.x[1] + svPosVel.x[0] * rotation_angle;
00171          svPosVel.x[2] = svPosVel.x[2];
00172 
00173          rawrange =rx.slantRange(svPosVel.x);
00174          updateCER(rx);
00175          
00176          return rawrange - svclkbias - relativity;
00177       }
00178       catch (Exception& e) {
00179          GPSTK_RETHROW(e);
00180       }
00181    }
00182 
00183    void CorrectedEphemerisRange::updateCER(const Position& Rx)
00184    {
00185       relativity = RelativityCorrection(svPosVel) * C_GPS_M;
00186       // relativity correction is added to dtime by the
00187       // EphemerisStore::getSatXvt routines...
00188       
00189       svclkbias = svPosVel.dtime*C_GPS_M - relativity;
00190       svclkdrift = svPosVel.ddtime * C_GPS_M;
00191       
00192       cosines[0] = (Rx.X()-svPosVel.x[0])/rawrange;
00193       cosines[1] = (Rx.Y()-svPosVel.x[1])/rawrange;
00194       cosines[2] = (Rx.Z()-svPosVel.x[2])/rawrange;
00195       
00196       Position SV(svPosVel);
00197       elevation = Rx.elevation(SV);
00198       azimuth = Rx.azimuth(SV);
00199       elevationGeodetic = Rx.elevationGeodetic(SV);
00200       azimuthGeodetic = Rx.azimuthGeodetic(SV);
00201    }
00202 
00203 
00204    void CorrectedEphemerisRange::rotateEarth(const Position& Rx)
00205    {
00206       GPSGeoid geoid;
00207       double tof = RSS(svPosVel.x[0]-Rx.X(),
00208                        svPosVel.x[1]-Rx.Y(),
00209                        svPosVel.x[2]-Rx.Z())/geoid.c();
00210       double wt = geoid.angVelocity()*tof;
00211       double sx =  cos(wt)*svPosVel.x[0] + sin(wt)*svPosVel.x[1];
00212       double sy = -sin(wt)*svPosVel.x[0] + cos(wt)*svPosVel.x[1];
00213       svPosVel.x[0] = sx;
00214       svPosVel.x[1] = sy;
00215       sx =  cos(wt)*svPosVel.v[0] + sin(wt)*svPosVel.v[1];
00216       sy = -sin(wt)*svPosVel.v[0] + cos(wt)*svPosVel.v[1];
00217       svPosVel.v[0] = sx;
00218       svPosVel.v[1] = sy;
00219    }
00220 
00221 
00222    double RelativityCorrection(const Xvt& svPosVel)
00223    {
00224       // relativity correction is added to dtime by the
00225       // EphemerisStore::getSatXvt routines...
00226       // dtr = -2*dot(R,V)/(c*c) = -4.4428e-10(s/sqrt(m)) * ecc * sqrt(A(m)) * sinE
00227       // compute it separately here, in units seconds.
00228       double dtr = ( -2.0 *( svPosVel.x[0] * svPosVel.v[0]
00229                              + svPosVel.x[1] * svPosVel.v[1]
00230                              + svPosVel.x[2] * svPosVel.v[2] ) / C_GPS_M ) / C_GPS_M;
00231       return dtr;
00232    }
00233 
00234 }  // namespace gpstk

Generated on Thu Sep 9 03:30:52 2010 for GPS ToolKit Software Library by  doxygen 1.3.9.1