TabularEphemerisStore.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: TabularEphemerisStore.cpp 2741 2011-06-22 16:37:02Z nwu $"
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 //
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 
00047 #include "TabularEphemerisStore.hpp"
00048 #include "MiscMath.hpp"
00049 #include "ECEF.hpp"
00050 #include "icd_200_constants.hpp"
00051 
00052 using namespace gpstk::StringUtils;
00053 
00054 namespace gpstk
00055 {
00056 
00057 
00058       /* A debugging function that outputs in human readable form,
00059        * all data stored in this object.
00060        *
00061        * @param[in] s the stream to receive the output; defaults to cout
00062        * @param[in] detail the level of detail to provide
00063        */
00064    void TabularEphemerisStore::dump( std::ostream& s,
00065                                      short detail )
00066       const throw()
00067    {
00068 
00069       s << "Dump of TabularEphemerisStore:" << std::endl;
00070 
00071       if(detail >= 0)
00072       {
00073 
00074          EphMap::const_iterator it;
00075 
00076          s << " Data stored for " << pe.size() << " satellites, over time span "
00077            << initialTime << " to " << finalTime << "." << std::endl;
00078 
00079          if(detail == 0) return;
00080 
00081          for(it=pe.begin(); it!=pe.end(); it++)
00082          {
00083 
00084             s << "  PRN " << it->first << " : "
00085               << it->second.size() << " records.";
00086             if(detail == 1) { s << std::endl; continue; }
00087             s << "  Data:" << std::endl;
00088             SvEphMap::const_iterator jt;
00089 
00090             for(jt=it->second.begin(); jt!=it->second.end(); jt++)
00091             {
00092                s << " " << jt->first << " P "
00093                  << std::fixed << std::setprecision(6)
00094                  << std::setw(13) << jt->second.x[0] << " "
00095                  << std::setw(13) << jt->second.x[1] << " "
00096                  << std::setw(13) << jt->second.x[2] << " "
00097                  << std::setw(13) << jt->second.dtime
00098                  << " V "
00099                  << std::setw(13) << jt->second.v[0] << " "
00100                  << std::setw(13) << jt->second.v[1] << " "
00101                  << std::setw(13) << jt->second.v[2] << " "
00102                  << std::setw(13) << jt->second.ddtime
00103                  << std::endl;
00104             }
00105 
00106          }
00107 
00108       }  // End of 'if(detail >= 0)...'
00109 
00110    }  // End of method 'TabularEphemerisStore::dump()'
00111 
00112 
00113 
00114       /* Edit the dataset, removing data outside the indicated time
00115        * interval.
00116        *
00117        * @param[in] tmin defines the beginning of the time interval
00118        * @param[in] tmax defines the end of the time interval
00119        */
00120    void TabularEphemerisStore::edit( const DayTime& tmin,
00121                                      const DayTime& tmax )
00122       throw()
00123    {
00124 
00125       EphMap::iterator kt;
00126 
00127       for(kt=pe.begin(); kt!=pe.end(); kt++)
00128       {
00129 
00130          SvEphMap::reverse_iterator jt=(kt->second).rbegin();
00131 
00132          while(jt != (kt->second).rend())
00133          {
00134 
00135             if(jt->first < tmin || jt->first > tmax)
00136             {
00137                (kt->second).erase(jt->first);
00138             }
00139 
00140             jt ++;
00141 
00142          }
00143 
00144       }
00145 
00146       initialTime = tmin;
00147       finalTime = tmax;
00148 
00149    }  // End of method 'TabularEphemerisStore::edit()'
00150 
00151 
00152 
00153       // Remove all data
00154    void TabularEphemerisStore::clear()
00155       throw()
00156    {
00157 
00158       pe.clear();
00159       initialTime = DayTime::END_OF_TIME;
00160       finalTime = DayTime::BEGINNING_OF_TIME;
00161 
00162    }  // End of method 'TabularEphemerisStore::clear()'
00163 
00164 
00165 
00166       /* Returns the position, velocity, and clock offset of the indicated
00167        * object in ECEF coordinates (meters) at the indicated time.
00168        *
00169        * @param[in] id the object's identifier
00170        * @param[in] t the time to look up
00171        *
00172        * @return the Xvt of the object at the indicated time
00173        *
00174        * @throw InvalidRequest If the request can not be completed for any
00175        *    reason, this is thrown. The text may have additional
00176        *    information as to why the request failed.
00177        */
00178    Xvt TabularEphemerisStore::getXvt( const SatID sat,
00179                                       const DayTime& t )
00180       const throw(InvalidRequest)
00181    {
00182 
00183       EphMap::const_iterator svmap = pe.find(sat);
00184       if (svmap==pe.end()) {
00185          InvalidRequest e("Ephemeris for satellite  " + asString(sat)
00186                             + " not found.");
00187          GPSTK_THROW(e);
00188       }
00189 
00190       const SvEphMap& sem=svmap->second;
00191       SvEphMap::const_iterator i=sem.find(t);
00192       Xvt sv;
00193       if (i!= sem.end() && haveVelocity) {      // exact match of t
00194          sv = i->second;
00195          sv.x[0] *= 1.e3;     // m
00196          sv.x[1] *= 1.e3;     // m
00197          sv.x[2] *= 1.e3;     // m
00198          sv.dtime *= 1.e-6;   // sec
00199          sv.v[0] *= 1.e-1;    // m/sec
00200          sv.v[1] *= 1.e-1;    // m/sec
00201          sv.v[2] *= 1.e-1;    // m/sec
00202          sv.ddtime *= 1.e-10; // sec/sec
00203 
00204          sv.dtime += -2*(sv.x[0]/C_GPS_M)*(sv.v[0]/C_GPS_M)
00205             -2*(sv.x[1]/C_GPS_M)*(sv.v[1]/C_GPS_M)
00206             -2*(sv.x[2]/C_GPS_M)*(sv.v[2]/C_GPS_M);
00207          return sv;
00208       }
00209 
00210          // Note that the order of the Lagrange interpolation
00211          // is twice this value
00212       const int half=5;
00213 
00214          //  i will be the lower bound, j the upper (in time).
00215       i = sem.lower_bound(t); // i points to first element with key >= t
00216 
00217       SvEphMap::const_iterator j=i;
00218 
00219       if(i == sem.begin() || --i == sem.begin()) {
00220          InvalidRequest e("Inadequate data before requested time, satellite "
00221                           + asString(sat));
00222          GPSTK_THROW(e);
00223       }
00224       if(j == sem.end()) {
00225          InvalidRequest e("Inadequate data after requested time, satellite "
00226                           + asString(sat));
00227          GPSTK_THROW(e);
00228       }
00229 
00230          // "t" is now just between "i" and "j"; therefore, it is time to check
00231          // for data gaps ("checkDataGap" must be enabled for this).
00232       if ( checkDataGap                               &&
00233            ( std::abs( t - i->first ) > gapInterval ) &&
00234            ( std::abs( j->first - t ) > gapInterval ) )
00235       {
00236             // There was a data gap
00237          InvalidRequest e( "Data gap too wide detected for satellite "
00238                            + asString(sat) );
00239          GPSTK_THROW(e);
00240       }
00241 
00242       for(int k=0; k<half-1; k++)
00243       {
00244 
00245          i--;
00246 
00247             // if k==half-2, this is last iteration
00248          if(i == sem.begin() && k<half-2)
00249          {
00250             InvalidRequest e("Inadequate data before requested time, satellite "
00251                              + asString(sat));
00252             GPSTK_THROW(e);
00253          }
00254          j++;
00255          if(j == sem.end() && k<half-2) {
00256             InvalidRequest e("Inadequate data after requested time, satellite "
00257                                + asString(sat));
00258             GPSTK_THROW(e);
00259          }
00260       }
00261 
00262          // Now that we have fully defined the i-j interval, let's check if
00263          // the interpolation interval is too wide ("checkInterval" must be
00264          // enabled for this).
00265       if ( checkInterval                                     &&
00266            ( std::abs( j->first - i->first ) > maxInterval ) )
00267       {
00268             // There was a data gap
00269          InvalidRequest e( "Interpolation interval too wide detected for SV "
00270                            + asString(sat) );
00271          GPSTK_THROW(e);
00272       }
00273 
00274 
00275          // pull data and interpolate
00276       SvEphMap::const_iterator itr;
00277       DayTime t0=i->first;
00278       double dt=t-t0,err;
00279       std::vector<double> times,X,Y,Z,T,VX,VY,VZ,F;
00280 
00281       for (itr=i; itr!=sem.end(); itr++)
00282       {
00283          times.push_back(itr->first - t0);      // sec
00284          X.push_back(itr->second.x[0]);         // km
00285          Y.push_back(itr->second.x[1]);         // km
00286          Z.push_back(itr->second.x[2]);         // km
00287          T.push_back(itr->second.dtime);        // microsec
00288          VX.push_back(itr->second.v[0]);        // decimeters/sec
00289          VY.push_back(itr->second.v[1]);        // decimeters/sec
00290          VZ.push_back(itr->second.v[2]);        // decimeters/sec
00291          F.push_back(itr->second.ddtime);       // 1.e-4 microsec/sec
00292          if(itr == j) break;
00293       }
00294 
00295       if (haveVelocity)
00296       {
00297          sv.x[0] = LagrangeInterpolation(times,X,dt,err);
00298          sv.x[1] = LagrangeInterpolation(times,Y,dt,err);
00299          sv.x[2] = LagrangeInterpolation(times,Z,dt,err);
00300          sv.dtime = LagrangeInterpolation(times,T,dt,err);
00301          sv.v[0] = LagrangeInterpolation(times,VX,dt,err);
00302          sv.v[1] = LagrangeInterpolation(times,VY,dt,err);
00303          sv.v[2] = LagrangeInterpolation(times,VZ,dt,err);
00304          sv.ddtime = LagrangeInterpolation(times,F,dt,err);
00305       }
00306       else {
00307          LagrangeInterpolation(times,X,dt,sv.x[0],sv.v[0]);
00308          LagrangeInterpolation(times,Y,dt,sv.x[1],sv.v[1]);
00309          LagrangeInterpolation(times,Z,dt,sv.x[2],sv.v[2]);
00310          LagrangeInterpolation(times,T,dt,sv.dtime,sv.ddtime);
00311          sv.v[0] *= 1.e4;              // decimeters/sec
00312          sv.v[1] *= 1.e4;              // decimeters/sec
00313          sv.v[2] *= 1.e4;              // decimeters/sec
00314          sv.ddtime *= 1.e4;            // 1.e-4 microsec/sec
00315       }
00316 
00317       sv.x[0] *= 1.e3;     // m
00318       sv.x[1] *= 1.e3;     // m
00319       sv.x[2] *= 1.e3;     // m
00320       sv.dtime *= 1.e-6;   // sec
00321       sv.v[0] *= 1.e-1;    // m/sec
00322       sv.v[1] *= 1.e-1;    // m/sec
00323       sv.v[2] *= 1.e-1;    // m/sec
00324       sv.ddtime *= 1.e-10; // sec/sec
00325 
00326       // add relativity correction to dtime
00327       // this only for consistency with GPSEphemerisStore::getSatXvt ....
00328       // dtr = -2*dot(R,V)/(c*c) = -4.4428e-10 * ecc * sqrt(A(m))*sinE
00329       // (do it this way for numerical reasons)
00330       sv.dtime += -2*(sv.x[0]/C_GPS_M)*(sv.v[0]/C_GPS_M)
00331          -2*(sv.x[1]/C_GPS_M)*(sv.v[1]/C_GPS_M)
00332          -2*(sv.x[2]/C_GPS_M)*(sv.v[2]/C_GPS_M);
00333 
00334       return sv;
00335 
00336    }  // end Xvt TabularEphemerisStore::getSatXvt
00337 
00338 
00339 
00340       /* Returns the acceleration of the indicated object in ECEF
00341        * coordinates (meters) at the indicated time.
00342        *
00343        * @param[in] id the object's identifier
00344        * @param[in] t the time to look up
00345        *
00346        * @return the Triple holding the acceleration of the object at the
00347        * indicated time
00348        *
00349        * @throw InvalidRequest If the request can not be completed for any
00350        *    reason, this is thrown. The text may have additional
00351        *    information as to why the request failed.
00352        */
00353    Triple TabularEphemerisStore::getAccel( const SatID sat,
00354                                            const DayTime& t )
00355       const throw(InvalidRequest)
00356    {
00357 
00358       EphMap::const_iterator svmap = pe.find(sat);
00359       if (svmap==pe.end()) {
00360          InvalidRequest e("Ephemeris for satellite  " + asString(sat)
00361                             + " not found.");
00362          GPSTK_THROW(e);
00363       }
00364 
00365       const SvEphMap& sem=svmap->second;
00366 
00367       SvEphMap::const_iterator i=sem.find(t);
00368 
00369          // Note that the order of the Lagrange interpolation
00370          // is twice this value
00371       const int half=5;
00372 
00373          //  i will be the lower bound, j the upper (in time).
00374       i = sem.lower_bound(t); // i points to first element with key >= t
00375 
00376       SvEphMap::const_iterator j=i;
00377 
00378       if(i == sem.begin() || --i == sem.begin()) {
00379          InvalidRequest e("Inadequate data before requested time, satellite "
00380                           + asString(sat));
00381          GPSTK_THROW(e);
00382       }
00383       if(j == sem.end()) {
00384          InvalidRequest e("Inadequate data after requested time, satellite "
00385                           + asString(sat));
00386          GPSTK_THROW(e);
00387       }
00388 
00389          // "t" is now just between "i" and "j"; therefore, it is time to check
00390          // for data gaps ("checkDataGap" must be enabled for this).
00391       if ( checkDataGap                               &&
00392            ( std::abs( t - i->first ) > gapInterval ) &&
00393            ( std::abs( j->first - t ) > gapInterval ) )
00394       {
00395             // There was a data gap
00396          InvalidRequest e( "Data gap too wide detected for satellite "
00397                            + asString(sat) );
00398          GPSTK_THROW(e);
00399       }
00400 
00401       for(int k=0; k<half-1; k++)
00402       {
00403 
00404          i--;
00405 
00406             // if k==half-2, this is last iteration
00407          if(i == sem.begin() && k<half-2)
00408          {
00409             InvalidRequest e("Inadequate data before requested time, satellite "
00410                              + asString(sat));
00411             GPSTK_THROW(e);
00412          }
00413          j++;
00414          if(j == sem.end() && k<half-2) {
00415             InvalidRequest e("Inadequate data after requested time, satellite "
00416                                + asString(sat));
00417             GPSTK_THROW(e);
00418          }
00419       }
00420 
00421          // Now that we have fully defined the i-j interval, let's check if
00422          // the interpolation interval is too wide ("checkInterval" must be
00423          // enabled for this).
00424       if ( checkInterval                                     &&
00425            ( std::abs( j->first - i->first ) > maxInterval ) )
00426       {
00427             // There was a data gap
00428          InvalidRequest e( "Interpolation interval too wide detected for SV "
00429                            + asString(sat) );
00430          GPSTK_THROW(e);
00431       }
00432 
00433 
00434          // pull data and interpolate
00435       SvEphMap::const_iterator itr;
00436       DayTime t0(i->first);
00437       double dt(t-t0);
00438       std::vector<double> times,X,Y,Z;
00439 
00440       for (itr=i; itr!=sem.end(); itr++)
00441       {
00442          times.push_back(itr->first - t0);      // sec
00443          X.push_back(itr->second.x[0]);         // km
00444          Y.push_back(itr->second.x[1]);         // km
00445          Z.push_back(itr->second.x[2]);         // km
00446          if(itr == j) break;
00447       }
00448 
00449       Triple accel;
00450 
00451          // Let's interpolate
00452       accel[0] = LagrangeInterpolating2ndDerivative(times,X,dt);
00453       accel[1] = LagrangeInterpolating2ndDerivative(times,Y,dt);
00454       accel[2] = LagrangeInterpolating2ndDerivative(times,Z,dt);
00455 
00456       accel[0] *= 1.e3;     // m/s^2
00457       accel[1] *= 1.e3;     // m/s^2
00458       accel[2] *= 1.e3;     // m/s^2
00459 
00460       return accel;
00461 
00462    }  // End of method 'TabularEphemerisStore::getAccel()'
00463 
00464 
00465 
00466 
00467 
00468    //-----------------------------------------------------------------------------
00469    //-----------------------------------------------------------------------------
00470    void TabularEphemerisStore::addEphemeris(const SP3Data& data)
00471       throw()
00472    {
00473       DayTime t = data.time;
00474       SatID sat = data.sat;
00475       Xvt&  xvt = pe[sat][t];
00476 
00477       if (data.flag=='P')
00478       {
00479          xvt.x = ECEF(data.x[0], data.x[1], data.x[2]);
00480          xvt.dtime = data.clk;
00481          haveVelocity=false;
00482       }
00483       else if (data.flag=='V')
00484       {
00485          xvt.v = Triple(data.x[0],data.x[1],data.x[2]);
00486          xvt.ddtime = data.clk;
00487          haveVelocity=true;
00488       }
00489 
00490       if (t<initialTime)
00491          initialTime = t;
00492       else if (t>finalTime)
00493          finalTime = t;
00494    }
00495 
00496 }  // namespace gpstk

Generated on Tue May 22 03:31:02 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1