GloEphemerisStore.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: GloEphemerisStore.cpp 3319 2012-09-19 16:58:10Z prestonherrmann $"
00002 
00008 //============================================================================
00009 //
00010 //  This file is part of GPSTk, the GPS Toolkit.
00011 //
00012 //  The GPSTk is free software; you can redistribute it and/or modify
00013 //  it under the terms of the GNU Lesser General Public License as published
00014 //  by the Free Software Foundation; either version 2.1 of the License, or
00015 //  any later version.
00016 //
00017 //  The GPSTk is distributed in the hope that it will be useful,
00018 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 //  GNU Lesser General Public License for more details.
00021 //
00022 //  You should have received a copy of the GNU Lesser General Public
00023 //  License along with GPSTk; if not, write to the Free Software Foundation,
00024 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
00025 //
00026 //  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2011
00027 //
00028 //============================================================================
00029 
00030 
00031 #include "GloEphemerisStore.hpp"
00032 #include "TimeString.hpp"
00033 
00034 using namespace std;
00035 
00036 namespace gpstk
00037 {
00038 
00039 
00040       // Add ephemeris information from a Rinex3NavData object.
00041    bool GloEphemerisStore::addEphemeris(const Rinex3NavData& data)
00042       throw()
00043    {
00044 
00045          // If enabled, check SV health before entering here (health = 0 -> OK)
00046       if( (data.health == 0) || (!checkHealthFlag) )
00047       {
00048             // Get a GloEphemeris object from Rinex3NavData object
00049          GloEphemeris gloEphem(data);
00050 
00051          CommonTime t( data.time);
00052          t.setTimeSystem(TimeSystem::GLO);   // must be GLONASS time
00053 
00054          SatID sat( data.sat );
00055          pe[sat][t] = gloEphem; // find or add entry
00056 
00057          if (t < initialTime)
00058             initialTime = t;
00059          else if (t > finalTime)
00060             finalTime = t;
00061 
00062          return true;
00063 
00064       }  // End of 'if( (data.health == 0) || (!checkHealthFlag) )'
00065 
00066       return false;
00067 
00068    }  // End of method 'GloEphemerisStore::addEphemeris()'
00069 
00070 
00071       /* Returns the position, velocity and clock offset of the indicated
00072        * satellite in ECEF coordinates (meters) at the indicated time,
00073        * in the PZ-90 ellipsoid.
00074        *
00075        *  @param[in] sat   Satellite's identifier
00076        *  @param[in] epoch Time to look up
00077        *
00078        *  @return the Xvt of the object at the indicated time
00079        *
00080        *  @throw InvalidRequest If the request can not be completed for any
00081        *  reason, this is thrown. The text may have additional information
00082        *  as to why the request failed.
00083        */
00084    Xvt GloEphemerisStore::getXvt( const SatID& sat,
00085                                   const CommonTime& epoch ) const
00086       throw( InvalidRequest )
00087    {
00088       // TD is this too strict?
00089       if(epoch.getTimeSystem() != initialTime.getTimeSystem())
00090       {
00091          InvalidRequest e(string("Requested time system is not GLONASS time"));
00092          GPSTK_THROW(e);
00093       }
00094       
00095          // Check that the given epoch is within the available time limits.
00096          // We have to add a margin of 15 minutes (900 seconds).
00097       if ( epoch <  (initialTime - 900.0) ||
00098            epoch >= (finalTime   + 900.0)   )
00099       {
00100          InvalidRequest e( "Requested time is out of boundaries for satellite "
00101                           + StringUtils::asString(sat) );
00102          GPSTK_THROW(e);
00103       }
00104 
00105          // Look for the satellite in the 'pe' (EphMap) data structure.
00106       GloEphMap::const_iterator svmap = pe.find(sat);
00107 
00108          // If satellite was not found, issue an exception
00109       if (svmap == pe.end())
00110       {
00111          InvalidRequest e( "Ephemeris for satellite  "
00112                            + StringUtils::asString(sat) + " not found." );
00113          GPSTK_THROW(e);
00114       }
00115 
00116          // Let's take the second part of the EphMap
00117       const TimeGloMap& sem = svmap->second;
00118 
00119          // Look for 'i': the first element whose key >= epoch.
00120       TimeGloMap::const_iterator i = sem.lower_bound(epoch);;
00121 
00122          // Values to be returned will be stored here
00123       Xvt sv;
00124 
00125          // If we reached the end, the requested time is beyond the last
00126          // ephemeris record, but it may still be within the allowable time
00127          // span, so we can use the last record.
00128       if ( i == sem.end() )
00129       {
00130          i = --i;
00131       }
00132 
00133          // If key > (epoch+900), we must use the previous record if possible.
00134       if ( ( i->first > (epoch+900.0) ) && ( i != sem.begin() ) )
00135       {
00136          i = --i;
00137       }
00138 
00139          // Check that the given epoch is within the available time limits for
00140          // this specific satellite, with a margin of 15 minutes (900 seconds).
00141       if ( epoch <  (i->first - 900.0) ||
00142            epoch >= (i->first   + 900.0)   )
00143       {
00144          InvalidRequest e( "Requested time is out of boundaries for satellite "
00145                           + StringUtils::asString(sat) );
00146          GPSTK_THROW(e);
00147       }
00148 
00149          // We now have the proper reference data record. Let's use it
00150       GloEphemeris data( i->second );
00151 
00152          // Compute the satellite position, velocity and clock offset
00153       sv = data.svXvt( epoch );
00154 
00155          // We are done, let's return
00156       return sv;
00157 
00158    }; // End of method 'GloEphemerisStore::getXvt()'
00159 
00160 
00161       /* A debugging function that outputs in human readable form,
00162        * all data stored in this object.
00163        *
00164        * @param[in] s      The stream to receive the output; defaults to cout
00165        * @param[in] detail The level of detail to provide
00166        *
00167        * @warning GLONASS position, velocity and acceleration information are
00168        * given in km, km/s and km/(s*s), respectively.
00169        */
00170    void GloEphemerisStore::dump( std::ostream& s, short detail ) const
00171       throw()
00172    {
00173       static const string fmt("%4F %10.3g = %04Y/%02m/%02d %02H:%02M:%02S %P");
00174       s << "Dump of GloEphemerisStore:\n";
00175 
00176       if (detail == 0 )
00177       {
00178         s << " Span is " << (initialTime == CommonTime::END_OF_TIME
00179                                       ? "End_time" : printTime(initialTime, fmt))
00180           << " to " << (finalTime == CommonTime::BEGINNING_OF_TIME
00181                                       ? "Begin_time" : printTime(finalTime, fmt))
00182           << " with " << pe.size() << " entries."
00183           << std::endl;
00184       }
00185       else
00186       {
00187       if (pe.size()) s << "Dump every record:\nweek   sow      = year/mn/dy hr:mi:sc Sys Sat   "
00188          << "X                   Y                   Z                   "
00189          << "VX                  VY                  VZ                  "
00190          << "AX                  AY                  AZ                  "
00191          << "TauN                GammaN            MFtime Hlth fNo AgeInfo\n";
00192 
00193          // Iterate through all items in the 'pe' GloEphMap
00194         for( GloEphMap::const_iterator it = pe.begin();
00195            it != pe.end();
00196            ++it )
00197         {
00198 
00199             // Then, iterate through corresponding 'TimeGloMap'
00200           for( TimeGloMap::const_iterator tgmIter = (*it).second.begin();
00201               tgmIter != (*it).second.end();
00202               ++tgmIter )
00203           {
00204 
00205                  // First, print year, Day-Of-Year and Seconds of Day
00206             s << printTime(tgmIter->first,fmt) << " ";
00207 
00208                // Second, print SatID information
00209             s << RinexSatID((*it).first) << " ";
00210 
00211                // Third, print satellite ephemeris data
00212             GloEphemeris data( (*tgmIter).second );
00213                // Get the satellite's acceleration
00214             Triple a( data.getAcc() );
00215 
00216             s << scientific << setprecision(12);
00217             s << setw(19) << data.x[0] << " "
00218               << setw(19) << data.x[1] << " "
00219               << setw(19) << data.x[2] << " "
00220               << setw(19) << data.v[0] << " "
00221               << setw(19) << data.v[1] << " "
00222               << setw(19) << data.v[2] << " "
00223               << setw(19) << a[0] << " "
00224               << setw(19) << a[1] << " "
00225               << setw(19) << a[2] << " "
00226               << setw(19) << data.getTauN() << " "
00227               << setw(19) << data.getGammaN() << " "
00228               << setw(6) << data.getMFtime() << " "
00229               << setw(3) << data.getHealth() << " "
00230               << setw(3) << data.getfreqNum() << " "
00231               << setprecision(2) << setw(5) << data.getAgeOfInfo();
00232 
00233                // Add end-of-line
00234             s << endl;
00235 
00236           }  // End of 'for( TimeGloMap::const_iterator tgmIter = ...'
00237 
00238         }  // End of 'for( GloEphMap::const_iterator it = pe.begin(); ...'
00239 
00240         s << "  End of GloEphemerisStore data." << std::endl << std::endl;
00241 
00242       }  // End of 'else', i.e., detail != 0
00243 
00244    }; // End of method 'GloEphemerisStore::dump()'
00245 
00246 
00247       /* Edit the dataset, removing data outside the indicated time interval
00248        *
00249        * @param[in] tmin   Defines the beginning of the time interval
00250        * @param[in] tmax   Defines the end of the time interval
00251        */
00252    void GloEphemerisStore::edit( const CommonTime& tmin,
00253                                  const CommonTime& tmax )
00254       throw()
00255    {
00256 
00257          // Create a working copy
00258       GloEphMap bak;
00259 
00260          // Reset the initial and final times
00261       initialTime = CommonTime::END_OF_TIME;
00262       finalTime   = CommonTime::BEGINNING_OF_TIME;
00263 
00264          // Iterate through all items in the 'bak' GloEphMap
00265       for( GloEphMap::const_iterator it = pe.begin();
00266            it != pe.end();
00267            ++it )
00268       {
00269 
00270             // Then, iterate through corresponding 'TimeGloMap'
00271          for( TimeGloMap::const_iterator tgmIter = (*it).second.begin();
00272               tgmIter != (*it).second.end();
00273               ++tgmIter )
00274          {
00275 
00276             CommonTime t( (*tgmIter).first );
00277 
00278                // Check if the current record is within the given time interval
00279             if( ( tmin <= t ) && ( t <= tmax ) )
00280             {
00281 
00282                   // If we are within the proper boundaries, let's add the data
00283                GloEphemeris data( (*tgmIter).second );
00284             
00285                SatID sat( (*it).first );
00286                bak[sat][t] = data;     // Add entry
00287 
00288                   // Update 'initialTime' and 'finalTime', if necessary
00289                if (t < initialTime)
00290                   initialTime = t;
00291                else if (t > finalTime)
00292                   finalTime = t;
00293 
00294             }  // End of 'if ( ( (*tgmIter).first >= tmin ) && ...'
00295 
00296          }  // End of 'for( TimeGloMap::const_iterator tgmIter = ...'
00297 
00298       }  // End of 'for( GloEphMap::const_iterator it = pe.begin(); ...'
00299 
00300          // Update the data map before returning
00301       pe = bak;
00302 
00303       return;
00304       
00305    }; // End of method 'GloEphemerisStore::edit()'
00306 
00307 
00308       // Determine the earliest time for which this object can successfully
00309       // determine the Xvt for any object.
00310       // @return The initial time
00311       // @throw InvalidRequest This is thrown if the object has no data.
00312    CommonTime GloEphemerisStore::getInitialTime() const
00313       throw(InvalidRequest)
00314    {
00315 
00316          // Check if the data map is empty
00317       if( pe.empty() )
00318       {
00319          InvalidRequest e( "GloEphemerisStore object has no data." );
00320          GPSTK_THROW(e);
00321       }
00322       
00323       return initialTime;
00324 
00325    }; // End of method 'GloEphemerisStore::getInitialTime()'
00326 
00327 
00328       // Determine the latest time for which this object can successfully
00329       // determine the Xvt for any object.
00330       // @return The final time
00331       // @throw InvalidRequest This is thrown if the object has no data.
00332    CommonTime GloEphemerisStore::getFinalTime() const
00333       throw(InvalidRequest)
00334    {
00335 
00336          // Check if the data map is empty
00337       if( pe.empty() )
00338       {
00339          InvalidRequest e( "GloEphemerisStore object has no data." );
00340          GPSTK_THROW(e);
00341       }
00342 
00343       return finalTime;
00344 
00345    }; // End of method 'GloEphemerisStore::getFinalTime()'
00346 
00347 
00348       /* Find the corresponding GLONASS ephemeris for the given epoch.
00349        *
00350        * @param sat SatID of satellite of interest.
00351        * @param t time with which to search for ephemeris.
00352        *
00353        * @return a reference to the desired ephemeris.
00354        * @throw InvalidRequest object thrown when no ephemeris is found.
00355        */
00356    const GloEphemeris& GloEphemerisStore::findEphemeris( const SatID& sat,
00357                                                 const CommonTime& epoch ) const
00358       throw( InvalidRequest )
00359    {
00360 
00361          // Check that the given epoch is within the available time limits.
00362          // We have to add a margin of 15 minutes (900 seconds).
00363       if ( epoch <  (initialTime - 900.0) ||
00364            epoch >= (finalTime   + 900.0)   )
00365       {
00366          InvalidRequest e( "Requested time is out of boundaries for satellite "
00367                           + StringUtils::asString(sat) );
00368          GPSTK_THROW(e);
00369       }
00370 
00371          // Look for the satellite in the 'pe' (EphMap) data structure.
00372       GloEphMap::const_iterator svmap = pe.find(sat);
00373 
00374          // If satellite was not found, issue an exception
00375       if (svmap == pe.end())
00376       {
00377          InvalidRequest e( "Ephemeris for satellite  "
00378                            + StringUtils::asString(sat) + " not found." );
00379          GPSTK_THROW(e);
00380       }
00381 
00382          // Let's take the second part of the EphMap
00383       const TimeGloMap& sem = svmap->second;
00384 
00385          // 'i' will be the first element whose key >= epoch.
00386       TimeGloMap::const_iterator i = sem.lower_bound(epoch);
00387 
00388          // If we reached the end, the requested time is beyond the last
00389          // ephemeris record, but it may still be within the allowable time
00390          // span, so we can use the last record.
00391       if ( i == sem.end() )
00392       {
00393          i = --i;
00394       }
00395 
00396          // If key > (epoch+900), we must use the previous record if possible.
00397       if ( ( i->first > (epoch+900.0) ) && ( i != sem.begin() ) )
00398       {
00399          i = --i;
00400       }
00401 
00402          // Check that the given epoch is within the available time limits for
00403          // this specific satellite, with a margin of 15 minutes (900 seconds).
00404       if ( epoch <  (i->first - 900.0) ||
00405            epoch >= (i->first   + 900.0)   )
00406       {
00407          InvalidRequest e( "Requested time is out of boundaries for satellite "
00408                           + StringUtils::asString(sat) );
00409          GPSTK_THROW(e);
00410       }
00411 
00412          // We now have the proper reference data record. Let's return it
00413       return ( i->second );
00414 
00415    }; // End of method 'GloEphemerisStore::findEphemeris()'
00416 
00417 
00418       // Return true if the given SatID is present in the store
00419    bool GloEphemerisStore::isPresent(const SatID& id) const throw()
00420    {
00421 
00422          // Look for the satellite in the 'pe' (GloEphMap) data structure.
00423       GloEphMap::const_iterator svmap = pe.find(id);
00424 
00425          // If satellite was not found return false, else return true
00426       if (svmap == pe.end())
00427       {
00428          return false;
00429       }
00430       else
00431       {
00432          return true;
00433       }
00434 
00435    }; // End of method 'GloEphemerisStore::isPresent(const SatID& id)'
00436 
00437 
00438    int GloEphemerisStore::addToList(std::list<GloEphemeris>& v) const
00439       throw()
00440    {
00441       int n = 0;
00442       for(GloEphMap::const_iterator it = pe.begin(); it != pe.end(); ++it )
00443       {
00444          for(TimeGloMap::const_iterator tgmIter = (*it).second.begin();
00445               tgmIter != (*it).second.end(); ++tgmIter )
00446          {
00447              v.push_back(tgmIter->second);
00448              n++;
00449          }
00450       }
00451       return n;
00452    }
00453 
00454 
00455 }  // End of namespace gpstk

Generated on Sat May 25 03:31:09 2013 for GPS ToolKit Software Library by  doxygen 1.3.9.1