PreciseRange.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: PreciseRange.cpp 2293 2010-02-12 18:14:16Z btolman $"
00002 
00009 //============================================================================
00010 //
00011 //  This file is part of GPSTk, the GPS Toolkit.
00012 //
00013 //  The GPSTk is free software; you can redistribute it and/or modify
00014 //  it under the terms of the GNU Lesser General Public License as published
00015 //  by the Free Software Foundation; either version 2.1 of the License, or
00016 //  any later version.
00017 //
00018 //  The GPSTk is distributed in the hope that it will be useful,
00019 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021 //  GNU Lesser General Public License for more details.
00022 //
00023 //  You should have received a copy of the GNU Lesser General Public
00024 //  License along with GPSTk; if not, write to the Free Software Foundation,
00025 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026 //  
00027 //  Copyright 2004, The University of Texas at Austin
00028 //
00029 //============================================================================
00030 //============================================================================
00031 //
00032 //This software developed by Applied Research Laboratories at the University of
00033 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00034 //Department of Defense. The U.S. Government retains all rights to use,
00035 //duplicate, distribute, disclose, or release this software. 
00036 //
00037 //Pursuant to DoD Directive 523024 
00038 //
00039 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00040 //                           release, distribution is unlimited.
00041 //
00042 //=============================================================================
00043 
00044 // GPSTk includes
00045 #include "MiscMath.hpp"
00046 #include "GPSGeoid.hpp"
00047 #include "icd_200_constants.hpp"
00048 #include "geometry.hpp"
00049 #include "Xvt.hpp"
00050 // geomatics
00051 #include "SunEarthSatGeometry.hpp"
00052 #include "PreciseRange.hpp"
00053 
00054 using namespace std;
00055 
00056 namespace gpstk
00057 {
00058    double PreciseRange::ComputeAtTransmitTime(const DayTime& nomRecTime,
00059                                               const double pr,
00060                                               const Position& Receiver,
00061                                               const SatID sat,
00062                                               const AntexData& antenna,
00063                                               const SolarSystem& SSEph,
00064                                               const EarthOrientation& EO,
00065                                               const XvtStore<SatID>& Eph,
00066                                               const bool isCOM)
00067       throw(Exception)
00068    {
00069    try {
00070       int i;
00071       Position Rx(Receiver);
00072       GPSGeoid geoid;
00073       Xvt svPosVel;
00074 
00075       // nominal transmit time
00076       transmit = nomRecTime;     // receive time on receiver's clock
00077       transmit -= pr/geoid.c();  // correct for measured time of flight and Rx clock
00078    
00079       // get the satellite position at the nominal time, computing and
00080       // correcting for the satellite clock bias and other delays
00081       try {
00082          svPosVel = Eph.getXvt(sat,transmit);
00083          SatR.setECEF(svPosVel.x[0],svPosVel.x[1],svPosVel.x[2]);
00084       }
00085       // this should be a 'no ephemeris' exception
00086       catch(InvalidRequest& e) { GPSTK_RETHROW(e); }
00087 
00088       // update the transmit time for sat clk bias + relativity
00089       transmit -= svPosVel.dtime;   // NB. getXvt has dtime = relativity + clock bias
00090 
00091       // Sagnac effect
00092       // ref. Ashby and Spilker, GPS: Theory and Application, 1996 Vol 1, pg 673.
00093       // this is w(Earth) * (SatR cross Rx).Z() / c*c in seconds
00094       // beware numerical error by differencing very large to get very small
00095       Sagnac = ( (SatR.X()/geoid.c()) * (Rx.Y()/geoid.c())
00096                - (SatR.Y()/geoid.c()) * (Rx.X()/geoid.c()) ) * geoid.angVelocity();
00097       transmit -= Sagnac;
00098 
00099       // compute other delays -- very small
00100       // 2GM/c^2 = 0.00887005608 m^3/s^2 * s^2/m^2 = m
00101       double rx = Rx.radius();
00102       double rs = SatR.radius();
00103       double dr = range(SatR,Rx);
00104       relativity2 = -0.00887005608 * ::log((rx+rs+dr)/(rx+rs-dr));
00105       transmit -= relativity2 / geoid.c();
00106 
00107       // iterate satellite position
00108       try {
00109          svPosVel = Eph.getXvt(sat,transmit);
00110          // Do NOT replace these with Xvt
00111          SatR.setECEF(svPosVel.x[0],svPosVel.x[1],svPosVel.x[2]);
00112          SatV.setECEF(svPosVel.v[0],svPosVel.v[1],svPosVel.v[2]);
00113       }
00114       catch(InvalidRequest& e) { GPSTK_RETHROW(e); }
00115 
00116       // ----------------------------------------------------------
00117       // compute relativity separate from satellite clock
00118       relativity = RelativityCorrection(SatR,SatV) * geoid.c();
00119 
00120       // relativity correction is added to dtime by XvtStore::getPrnXvt();
00121       // remove it here so clk bias and relativity can be used separately
00122       satclkbias = svPosVel.dtime * geoid.c() - relativity;
00123       satclkdrift = svPosVel.ddtime * geoid.c();
00124    
00125       // correct for Earth rotation
00126       double sxyz[3], wt;
00127       rawrange = range(SatR,Rx);
00128       wt = geoid.angVelocity() * rawrange/geoid.c();
00129       sxyz[0] =  ::cos(wt)*SatR.X() + ::sin(wt)*SatR.Y();
00130       sxyz[1] = -::sin(wt)*SatR.X() + ::cos(wt)*SatR.Y();
00131       sxyz[2] = SatR.Z();
00132       SatR.setECEF(sxyz);
00133       sxyz[0] =  ::cos(wt)*SatV.X() + ::sin(wt)*SatV.Y();
00134       sxyz[1] = -::sin(wt)*SatV.X() + ::cos(wt)*SatV.Y();
00135       sxyz[2] = SatV.Z();
00136       SatV.setECEF(sxyz);
00137    
00138       // geometric range, again
00139       rawrange = range(SatR,Rx);
00140 
00141       // Compute line of sight, satellite to receiver
00142       Triple S2R(Rx.X()-SatR.X(),Rx.Y()-SatR.Y(),Rx.Z()-SatR.Z());
00143       S2R = S2R.unitVector();
00144 
00145       // ----------------------------------------------------------
00146       // satellite antenna pco and pcv
00147       if(isCOM && antenna.isValid()) {
00148          double sf;
00149          // rotation matrix from satellite attitude: Rot*[XYZ]=[body frame]
00150          Matrix<double> Rotation;
00151          if(SSEph.JPLNumber() > -1) {
00152             // use full JPL ephemeris
00153             Rotation = SatelliteAttitude(transmit, SatR, SSEph, EO, sf);
00154          }
00155          else {
00156             // use SolarPosition
00157             Rotation = SatelliteAttitude(transmit, SatR, sf);
00158          }
00159 
00160          // phase center offset vector in body frame (at L1)
00161          Triple pco = antenna.getPhaseCenterOffset(1);
00162          Vector<double> PCO(3);
00163          for(i=0; i<3; i++) PCO(i) = pco[i]/1000.0;      // body frame, mm -> m
00164 
00165          // PCO vector (from COM to PC) in ECEF XYZ frame, m
00166          SatPCOXYZ = transpose(Rotation) * PCO;
00167 
00168          Triple pcoxyz(SatPCOXYZ(0),SatPCOXYZ(1),SatPCOXYZ(2));
00169          satLOSPCO = pcoxyz.dot(S2R);                       // meters
00170 
00171          // phase center variation NB. this should be subtracted from rawrange
00172          // get the body frame azimuth and nadir angles
00173          double nadir,az;
00174          SatelliteNadirAzimuthAngles(SatR, Rx, Rotation, nadir, az);
00175          satLOSPCV = antenna.getPhaseCenterVariation(1, az, nadir) / 1000.; // meters
00176       }
00177       else {
00178          satLOSPCO = satLOSPCV = 0.0;
00179          SatPCOXYZ=Vector<double>(3,0.0);
00180       }
00181    
00182       // ----------------------------------------------------------
00183       // other quanitites
00184       // direction cosines
00185       //cosines[0] = (Rx.X()-SatR.X())/rawrange;
00186       //cosines[1] = (Rx.Y()-SatR.Y())/rawrange;
00187       //cosines[2] = (Rx.Z()-SatR.Z())/rawrange;
00188       for(i=0; i<3; i++) cosines[i] = -S2R[i];            // receiver to satellite
00189    
00190       // elevation and azimuth
00191       elevation = Rx.elevation(SatR);
00192       azimuth = Rx.azimuth(SatR);
00193       elevationGeodetic = Rx.elevationGeodetic(SatR);
00194       azimuthGeodetic = Rx.azimuthGeodetic(SatR);
00195    
00196       // return corrected ephemeris range
00197       return (rawrange-satclkbias-relativity-relativity2-satLOSPCO+satLOSPCV);
00198 
00199    }  // end try
00200    catch(gpstk::Exception& e) { GPSTK_RETHROW(e); }
00201 
00202    }  // end PreciseRange::ComputeAtTransmitTime
00203    
00204    //------------------------------------------------------------------
00205    double RelativityCorrection(const Position& R, const Position& V)
00206    {
00207       // relativity correction is added to dtime by the
00208       // XvtStore::getPrnXvt routines...
00209       // dtr = -2*dot(R,V)/(c*c) = -4.4428e-10(s/sqrt(m)) * ecc * sqrt(A(m)) * sinE
00210       // compute it separately here, in units seconds.
00211       double dtr = -2*(R.X()/C_GPS_M)*(V.X()/C_GPS_M)
00212                    -2*(R.Y()/C_GPS_M)*(V.Y()/C_GPS_M)
00213                    -2*(R.Z()/C_GPS_M)*(V.Z()/C_GPS_M);
00214    
00215       return dtr;
00216    }
00217    
00218 }  // namespace gpstk

Generated on Thu Jul 29 03:30:54 2010 for GPS ToolKit Software Library by  doxygen 1.3.9.1