1 //==============================================================================
2 //
3 //  This file is part of GPSTk, the GPS Toolkit.
4 //
5 //  The GPSTk is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU Lesser General Public License as published
7 //  by the Free Software Foundation; either version 3.0 of the License, or
8 //  any later version.
9 //
10 //  The GPSTk is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Lesser General Public License for more details.
14 //
15 //  You should have received a copy of the GNU Lesser General Public
16 //  License along with GPSTk; if not, write to the Free Software Foundation,
17 //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
18 //
19 //  This software was developed by Applied Research Laboratories at the
20 //  University of Texas at Austin.
21 //  Copyright 2004-2020, The Board of Regents of The University of Texas System
22 //
23 //==============================================================================
24 
25 //==============================================================================
26 //
27 //  This software was developed by Applied Research Laboratories at the
28 //  University of Texas at Austin, under contract to an agency or agencies
29 //  within the U.S. Department of Defense. The U.S. Government retains all
30 //  rights to use, duplicate, distribute, disclose, or release this software.
31 //
32 //  Pursuant to DoD Directive 523024
33 //
34 //  DISTRIBUTION STATEMENT A: This software has been approved for public
35 //                            release, distribution is unlimited.
36 //
37 //==============================================================================
38 
39 /** @file SP3EphemerisStore.hpp
40  * Store a tabular list of position and clock bias (perhaps also
41  * velocity and clock drift) data from SP3 file(s) for several
42  * satellites; access the tables to compute values at any timetag,
43  * within the limits of the data, from this table via interpolation.
44  * An option allows assigning the clock store to RINEX clock files,
45  * with separate timestep and interpolation algorithm. */
46 
47 #ifndef GPSTK_SP3_EPHEMERIS_STORE_INCLUDE
48 #define GPSTK_SP3_EPHEMERIS_STORE_INCLUDE
49 
50 #include <map>
51 #include <vector>
52 #include <algorithm>
53 #include <iostream>
54 
55 #include "Exception.hpp"
56 #include "SatID.hpp"
57 #include "CommonTime.hpp"
58 #include "XvtStore.hpp"
59 
60 #include "FileStore.hpp"
61 #include "ClockSatStore.hpp"
62 #include "PositionSatStore.hpp"
63 
64 #include "SP3Header.hpp"
65 #include "Rinex3ClockHeader.hpp"
66 
67 namespace gpstk
68 {
69       /// @ingroup GNSSEph
70       //@{
71 
72       /** Store position and clock bias (and perhaps velocity and
73        * drift) data from SP3 files, using (separate) stores based on
74        * TabularSatStore. An option allows the clock store to be taken
75        * from RINEX clock files instead.  Keep a FileStore for the SP3
76        * input files, and for the RINEX clock files, if they are
77        * used. Inherit XvtStore for the interface it defines. */
78    class SP3EphemerisStore : public XvtStore<SatID>
79    {
80 
81          // member data
82    private:
83          /** Time system for this store. Must set, and keep
84           * consistent, in loadFile.  Returned in getTimeSystem()
85           * (virtual in XvtStore).
86           * @note usually GPS, but CANNOT assume so. */
87       TimeSystem storeTimeSystem;
88 
89          /// PositionSatStore for SP3 ephemeris data
90       PositionSatStore posStore;
91 
92          /// ClockSatStore for SP3 OR RINEX clock data
93       ClockSatStore clkStore;
94 
95          /// FileStore for the SP3 input files
96       FileStore<SP3Header> SP3Files;
97 
98          /// FileStore for the (optional) RINEX clock input files
99       FileStore<Rinex3ClockHeader> clkFiles;
100 
101          /** flag indicating whether the clock store contains data
102           * from SP3 (true, the default) or Rinex clock (false)
103           * files */
104       bool useSP3clock;
105 
106          /** Flag to reject all data when there are bad positions,
107           * default true. */
108       bool rejectBadPosFlag;
109 
110          /** Flag to reject all data when there are bad clocks,
111           * default true.
112           * @note this flag has no effect if the clock store comes
113           * from RINEX clock files. */
114       bool rejectBadClockFlag;
115 
116          /** Flag to reject predicted position data, using
117           * orbitPredFlag in SP3Data. */
118       bool rejectPredPosFlag;
119 
120          /** Flag to reject predicted clock data, using clockPredFlag
121           * in SP3Data.
122           * @note this flag has no effect if the clock store comes
123           * from RINEX clock files. */
124       bool rejectPredClockFlag;
125 
126          // member functions
127 
128          /** Private utility routine used by the loadFile and
129          * loadSP3File routines.  Store position (velocity) and clock
130          * data from SP3 files in clock and position stores. Also
131          * update the FileStore with the filename and SP3 header.
132          * Check time systems consistentcy, and if possible set store
133          * time system.
134          * @throw Exception
135          */
136       void loadSP3Store(const std::string& filename, bool fillClockStore);
137 
138    public:
139 
140          /// Default constructor
SP3EphemerisStore()141       SP3EphemerisStore() throw() : storeTimeSystem(TimeSystem::Any),
142          useSP3clock(true),
143          rejectBadPosFlag(true),
144          rejectBadClockFlag(true),
145          rejectPredPosFlag(false),
146          rejectPredClockFlag(false)
147       { }
148 
149          /// Destructor
~SP3EphemerisStore()150       virtual ~SP3EphemerisStore()
151       { }
152 
153          // XvtStore interface:
154          /** Returns the position, velocity, and clock offset of the
155           * indicated object in ECEF coordinates (meters) at the
156           * indicated time.
157           * @param[in] sat the satellite of interest
158           * @param[in] ttag the time to look up
159           * @return the Xvt of the object at the indicated time
160           * @throw InvalidRequest If the request can not be completed for any
161           *    reason, this is thrown. The text may have additional
162           *    information as to why the request failed. */
163       virtual Xvt getXvt(const SatID& sat, const CommonTime& ttag) const;
164 
165          /** Compute the position, velocity and clock offset of the
166           * indicated object in ECEF coordinates (meters) at the
167           * indicated time.
168           * This method functions similarly to getXvt() except that it
169           * does not throw an exception for any reason.  Instead, the
170           * caller is expected to check the value of the "health"
171           * field of the returned Xvt and decide what to do with the
172           * data.
173           * @note This function ignores the onlyHealthy flag as health
174           *   information is not available in the SP3 format.
175           * @note The health flag in the returned Xvt can have one of
176           *   two values, "Unavailable", in which case the Xvt could
177           *   not be determined from the data in the store, or
178           *   "Unused" in which case the Xvt could be determined.
179           *   "Unused" because the SP3 format does not include health
180           *   status information.
181           * @param[in] id the object's identifier
182           * @param[in] t the time to look up
183           * @return the Xvt of the object at the indicated time */
184       virtual Xvt computeXvt(const SatID& id, const CommonTime& t) const
185          throw();
186 
187          /** Get the satellite health at a specific time.
188           * @param[in] id the object's identifier
189           * @param[in] t the time to look up
190           * @return "Unused" at all times as the SP3 format does not
191           *   provide health status. */
192       virtual Xvt::HealthStatus getSVHealth(const SatID& id,
193                                             const CommonTime& t) const throw();
194 
195          /** Dump information about the store to an ostream.
196           * @param[in] os ostream to receive the output; defaults to std::cout
197           * @param[in] detail integer level of detail to provide;
198           *   allowed values are
199           *    0: number of satellites, time step and time limits
200           *    1: above plus flags, gap and interval values, and
201           *       number of data/sat
202           *    2: above plus all the data tables */
dump(std::ostream & os=std::cout,short detail=0) const203       virtual void dump(std::ostream& os = std::cout, short detail = 0)
204          const throw()
205       {
206             // may have to re-write this...
207          os << "Dump SP3EphemerisStore:" << std::endl;
208             // 'reject' flags
209          os << (rejectBadPosFlag ? " Reject":" Do not reject")
210             << " bad positions." << std::endl;
211          os << (rejectBadClockFlag ? " Reject":" Do not reject")
212             << " bad clocks." << std::endl;
213          os << (rejectPredPosFlag ? " Reject":" Do not reject")
214             << " predicted positions." << std::endl;
215          os << (rejectPredClockFlag ? " Reject":" Do not reject")
216             << " predicted clocks." << std::endl;
217 
218          SP3Files.dump(os, detail);
219          posStore.dump(os, detail);
220          if(!useSP3clock) clkFiles.dump(os, detail);
221          clkStore.dump(os, detail);
222 
223          os << "End dump SP3EphemerisStore." << std::endl;
224       }
225 
226          /** Edit the dataset, removing data outside the indicated
227           * time interval
228           * @param[in] tmin defines the beginning of the time interval
229           * @param[in] tmax defines the end of the time interval */
edit(const CommonTime & tmin,const CommonTime & tmax=CommonTime::END_OF_TIME)230       virtual void edit(const CommonTime& tmin,
231                         const CommonTime& tmax = CommonTime::END_OF_TIME) throw()
232       {
233          posStore.edit(tmin, tmax);
234          clkStore.edit(tmin, tmax);
235       }
236 
237          /// Clear the dataset, meaning remove all data
clear(void)238       virtual void clear(void) throw()
239       { clearPosition(); clearClock(); }
240 
241          /// Return time system (@note usually GPS, but CANNOT assume so)
getTimeSystem(void) const242       virtual TimeSystem getTimeSystem(void) const throw()
243       { return storeTimeSystem; }
244 
245          /** Determine the earliest time for which this object can
246           * successfully determine the Xvt for any object.
247           * @return the earliest time in the table
248           * @throw InvalidRequest if the object has no data. */
249       virtual CommonTime getInitialTime() const;
250 
251          /** Determine the latest time for which this object can
252           * successfully determine the Xvt for any object.
253           * @return the latest time in the table
254           * @throw InvalidRequest if the object has no data. */
255       virtual CommonTime getFinalTime() const;
256 
257          /// Return true if IndexType=SatID is present in the data tables
isPresent(const SatID & sat) const258       virtual bool isPresent(const SatID& sat) const throw()
259       { return (posStore.isPresent(sat) && clkStore.isPresent(sat)); }
260 
261          /// Return true if velocity is present in the data tables
hasVelocity() const262       virtual bool hasVelocity() const throw()
263       {  return posStore.hasVelocity(); }
264 
265          // end of XvtStore interface
266 
267          /** Dump information about the position store to an ostream.
268           * @param[in] os ostream to receive the output; defaults to std::cout
269           * @param[in] detail integer level of detail to provide;
270           *   allowed values are
271           *    0: number of satellites, time step and time limits
272           *    1: above plus flags, gap and interval values, and
273           *       number of data/sat
274           *    2: above plus all the data tables */
dumpPosition(std::ostream & os=std::cout,short detail=0) const275       void dumpPosition(std::ostream& os = std::cout, short detail = 0)
276          const throw()
277       {
278          SP3Files.dump(os, detail);
279          posStore.dump(os, detail);
280       }
281 
282          /** Dump information about the clock store to an ostream.
283           * @param[in] os ostream to receive the output; defaults to std::cout
284           * @param[in] detail integer level of detail to provide;
285           *   allowed values are
286           *    0: number of satellites, time step and time limits
287           *    1: above plus flags, gap and interval values, and
288           *       number of data/sat
289           *    2: above plus all the data tables */
dumpClock(std::ostream & os=std::cout,short detail=0) const290       void dumpClock(std::ostream& os = std::cout, short detail = 0)
291          const throw()
292       {
293          if(useSP3clock)
294             SP3Files.dump(os, detail);
295          else
296             clkFiles.dump(os, detail);
297          clkStore.dump(os, detail);
298       }
299 
300          /** Return the position for the given satellite at the given time.
301           * @param[in] sat the SatID of the satellite of interest
302           * @param[in] ttag the time (CommonTime) of interest
303           * @return Triple containing the position ECEF XYZ meters
304           * @throw InvalidRequest if result cannot be computed, for
305           *   example because:
306           *  a) the time t does not lie within the time limits of the
307           *     data table
308           *  b) checkDataGap is true and there is a data gap
309           *  c) checkInterval is true and the interval is larger than
310           *     maxInterval */
311       Triple getPosition(const SatID sat, const CommonTime ttag)
312          const;
313 
314          /** Return the velocity for the given satellite at the given time
315           * @param[in] sat the SatID of the satellite of interest
316           * @param[in] ttag the time (CommonTime) of interest
317           * @return Triple containing the velocity ECEF XYZ meters/second
318           * @throw InvalidRequest if result cannot be computed, for
319           *   example because
320           *  a) the time t does not lie within the time limits of the
321           *     data table
322           *  b) checkDataGap is true and there is a data gap
323           *  c) checkInterval is true and the interval is larger than
324           *     maxInterval */
325       Triple getVelocity(const SatID sat, const CommonTime ttag)
326          const;
327 
328          /** Return the acceleration for the given satellite at the given time
329           * @param[in] sat the SatID of the satellite of interest
330           * @param[in] ttag the time (CommonTime) of interest
331           * @return Triple containing the acceleration ECEF XYZ
332           *   meters/second/second
333           * @throw InvalidRequest if result cannot be computed, for
334           *   example because
335           *  a) the time t does not lie within the time limits of the
336           *     data table
337           *  b) checkDataGap is true and there is a data gap
338           *  c) checkInterval is true and the interval is larger than
339           *     maxInterval */
getAcceleration(const SatID sat,const CommonTime ttag) const340       Triple getAcceleration(const SatID sat, const CommonTime ttag)
341          const
342       { return posStore.getAcceleration(sat,ttag); }
343 
344 
345          /** Clear the position dataset only, meaning remove all data
346           * from the tables. */
clearPosition(void)347       virtual void clearPosition(void) throw()
348       { posStore.clear(); }
349 
350          /** Clear the clock dataset only, meaning remove all data
351           * from the tables. */
clearClock(void)352       virtual void clearClock(void) throw()
353       { clkStore.clear(); }
354 
355 
356          /** Choose to load the clock data tables from RINEX clock
357           * files. This will clear the clock store; loadFile() or
358           * loadRinexClockFile() should be called after this, to load
359           * data into the clock store from RINEX clock files.  This
360           * routine has no effect if the clock store is already set to
361           * RINEX clock.
362           * @note will be called by loadRinexClockFile() if clock
363           * store is set to SP3. */
useRinexClockData(void)364       void useRinexClockData(void) throw()
365       {
366          if(!useSP3clock) return;
367          useSP3clock = false;
368          clearClock();
369       }
370 
371          /** Choose to load the clock data tables from SP3 files (this
372          * is the default).  This will clear the clock store; if the
373          * position store has already been loaded it should also be
374          * cleared. The routines loadFile() or loadSP3File() should be
375          * called after this, to load data into the clock store from
376          * SP3 files.
377          * @note this will also load position data into the position
378          * store.  This routine has no effect if the clock store is
379          * already set to SP3. */
useSP3ClockData(void)380       void useSP3ClockData(void) throw()
381       {
382          if(useSP3clock) return;
383          useSP3clock = true;
384          clearClock();
385       }
386 
387          /** Get the earliest time of data in the position store.
388           * @return CommonTime the first time
389           * @throw InvalidRequest if there is no data */
getPositionInitialTime(void) const390       CommonTime getPositionInitialTime(void) const
391       { return posStore.getInitialTime(); }
392 
393          /** Get the latest time of data in the position store.
394           * @return CommonTime the latest time
395           * @throw InvalidRequest if there is no data */
getPositionFinalTime(void) const396       CommonTime getPositionFinalTime(void) const
397       { return posStore.getFinalTime(); }
398 
399          /** Get the earliest time of data in the clock store.
400           * @return CommonTime the first time
401           * @throw InvalidRequest if there is no data */
getClockInitialTime(void) const402       CommonTime getClockInitialTime(void) const
403       { return clkStore.getInitialTime(); }
404 
405          /** Get the latest time of data in the clock store.
406           * @return CommonTime the latest time
407           * @throw InvalidRequest if there is no data */
getClockFinalTime(void) const408       CommonTime getClockFinalTime(void) const
409       { return clkStore.getFinalTime(); }
410 
411          /** Get the earliest time of data in the position store for
412           * the given satellite.
413           * @return CommonTime the first time
414           * @throw InvalidRequest if there is no data */
getPositionInitialTime(const SatID & sat) const415       CommonTime getPositionInitialTime(const SatID& sat) const
416       { return posStore.getInitialTime(sat); }
417 
418          /** Get the latest time of data in the position store for the
419           * given satellite.
420           * @return CommonTime the latest time
421           * @throw InvalidRequest if there is no data */
getPositionFinalTime(const SatID & sat) const422       CommonTime getPositionFinalTime(const SatID& sat) const
423       { return posStore.getFinalTime(sat); }
424 
425          /** Get the earliest time of data in the clock store for the
426           * given satellite.
427           * @return CommonTime the first time
428           * @throw InvalidRequest if there is no data */
getClockInitialTime(const SatID & sat) const429       CommonTime getClockInitialTime(const SatID& sat) const
430       { return clkStore.getInitialTime(sat); }
431 
432          /** Get the latest time of data in the clock store for the
433           * given satellite.
434           * @return CommonTime the latest time
435           * @throw InvalidRequest if there is no data */
getClockFinalTime(const SatID & sat) const436       CommonTime getClockFinalTime(const SatID& sat) const
437       { return clkStore.getFinalTime(sat); }
438 
439          /** Get the earliest time of both clock and position data in
440          * the store for the given satellite.
441          * @return CommonTime the first time
442          * @throw InvalidRequest if there is no data */
443       CommonTime getInitialTime(const SatID& sat) const;
444 
445          /** Get the latest time of both clock and position data in
446           * the store for the given satellite.
447           * @return the latest time
448           * @throw InvalidRequest if there is no data */
449       CommonTime getFinalTime(const SatID& sat) const;
450 
451 
452          /** Get the nominal time step in seconds for the position
453           * data and the given sat */
getPositionTimeStep(const SatID & sat) const454       double getPositionTimeStep(const SatID& sat) const throw()
455       { return posStore.nomTimeStep(sat); }
456 
457          /** Get the nominal time step in seconds for the clock data
458           * and the given sat */
getClockTimeStep(const SatID & sat) const459       double getClockTimeStep(const SatID& sat) const throw()
460       { return clkStore.nomTimeStep(sat); }
461 
462 
463          /// Get current interpolation order for the position table
getPositionInterpOrder(void) const464       unsigned int getPositionInterpOrder(void) const throw()
465       { return posStore.getInterpolationOrder(); }
466 
467          /** Set the interpolation order for the position table; it is
468           * forced to be even. */
setPositionInterpOrder(unsigned int order)469       void setPositionInterpOrder(unsigned int order) throw()
470       { posStore.setInterpolationOrder(order); }
471 
472          /** Get current interpolation order for the clock data
473           * (meaningless if the interpolation type is linear). */
getClockInterpOrder(void)474       unsigned int getClockInterpOrder(void) throw()
475       { return clkStore.getInterpolationOrder(); }
476 
477          /** Set the interpolation order for the clock table; it is
478           * forced to be even.  This is ignored if the clock
479           * interpolation type is linear. */
setClockInterpOrder(unsigned int order)480       void setClockInterpOrder(unsigned int order) throw()
481       { clkStore.setInterpolationOrder(order); }
482 
483          /** Set the type of clock interpolation to Lagrange (the
484           * default); set the order of the interpolation with
485           * setClockInterpolationOrder(order); */
setClockLagrangeInterp(void)486       void setClockLagrangeInterp(void) throw()
487       { clkStore.setLagrangeInterp(); }
488 
489          /** Set the type of clock interpolation to linear
490           * (interpolation order is ignored). */
setClockLinearInterp(void)491       void setClockLinearInterp(void) throw()
492       { clkStore.setLinearInterp(); }
493 
494 
495          /** Get a list (std::vector) of SatIDs present in both clock
496           * and position stores */
getSatList(void) const497       std::vector<SatID> getSatList(void) const throw()
498       {
499          std::vector<SatID> posList(posStore.getSatList());
500          std::vector<SatID> clkList(clkStore.getSatList());
501          std::vector<SatID> retList;
502          for(size_t i=0; i<posList.size(); i++)
503             if(std::find(clkList.begin(),clkList.end(),posList[i]) != clkList.end())
504                retList.push_back(posList[i]);
505          return retList;
506       }
507 
508          // Get a set of the SatIDs present in both clock and position stores
getIndexSet(void) const509       std::set<SatID> getIndexSet(void) const
510       {
511          std::set<SatID> retSet;
512          try
513          {
514             std::vector<SatID> posList(posStore.getSatList());
515             std::vector<SatID> clkList(clkStore.getSatList());
516             for(size_t i=0; i<posList.size(); i++)
517                if(std::find(clkList.begin(),clkList.end(),posList[i]) != clkList.end())
518                   retSet.insert(posList[i]);
519          }
520          catch(gpstk::Exception)
521          {
522             // do nothing
523          }
524          return retSet;
525       }
526 
527          /// Get a list (std::vector) of SatIDs present in the position store
getPositionSatList(void) const528       std::vector<SatID> getPositionSatList(void) const throw()
529       { return posStore.getSatList(); }
530 
531          /// Get a list (std::vector) of SatIDs present in the clock store
getClockSatList(void) const532       std::vector<SatID> getClockSatList(void) const throw()
533       { return clkStore.getSatList(); }
534 
535 
536          /// Get the total number of (position) data records in the store
ndata(void) const537       inline int ndata(void) const throw()
538       { return posStore.ndata(); }
539 
540          /// Get the number of (position) data records for the given sat
ndata(const SatID & sat) const541       inline int ndata(const SatID& sat) const throw()
542       { return posStore.ndata(sat); }
543 
544          /** Get the number of (position) data records for the given
545           * satellite system */
ndata(const SatelliteSystem & sys) const546       inline int ndata(const SatelliteSystem& sys) const throw()
547       { return posStore.ndata(sys); }
548 
549          /// Get the total number of position data records in the store
ndataPosition(void) const550       inline int ndataPosition(void) const throw()
551       { return posStore.ndata(); }
552 
553          /// Get the number of position data records for the given sat
ndataPosition(const SatID & sat) const554       inline int ndataPosition(const SatID& sat) const throw()
555       { return posStore.ndata(sat); }
556 
557          /** Get the number of position data records for the given
558           * satellite system */
ndataPosition(const SatelliteSystem & sys) const559       inline int ndataPosition(const SatelliteSystem& sys) const throw()
560       { return posStore.ndata(sys); }
561 
562          /// Get the total number of clock data records in the store
ndataClock(void) const563       inline int ndataClock(void) const throw()
564       { return clkStore.ndata(); }
565 
566          /// Get the number of clock data records for the given sat
ndataClock(const SatID & sat) const567       inline int ndataClock(const SatID& sat) const throw()
568       { return clkStore.ndata(sat); }
569 
570          /** Get the number of clock data records for the given
571           * satellite system */
ndataClock(const SatelliteSystem & sys) const572       inline int ndataClock(const SatelliteSystem& sys) const throw()
573       { return clkStore.ndata(sys); }
574 
575          /// same as ndataPosition()
size(void) const576       inline int size(void) const throw() { return ndataPosition(); }
577 
578 
579          /** Load an SP3 ephemeris file; if the clock store uses RINEX
580           * clock files, this routine will also accept that file type
581           * and load the data into the clock store. This routine will
582           * may set the velocity, acceleration, bias or drift 'have'
583           * flags.
584           * @param filename name of file (SP3 or RINEX clock format) to load
585           * @throw Exception if time step is inconsistent with previous value
586           */
587       void loadFile(const std::string& filename);
588 
589          /** Load an SP3 ephemeris file; may set the velocity and
590           * acceleration flags.  If the clock store uses RINEX clock
591           * data, this will ignore the clock data.
592           * @param filename name of file (SP3 format) to load
593           * @throw Exception if time step is inconsistent with previous value
594           */
595       void loadSP3File(const std::string& filename);
596 
597          /** Load a RINEX clock file; may set the 'have' bias and
598           * drift flags.  If clock store is set to use SP3 data, this
599           * will call useRinexClockData()
600           * @param filename name of file (RINEX clock format) to load
601           * @throw Exception if time step is inconsistent with previous value
602           */
603       void loadRinexClockFile(const std::string& filename);
604 
605 
606          /** Add a complete PositionRecord to the store; this is the
607           * preferred method of adding data to the tables.
608           * @note If these addXXX() routines are used more than once
609           * for the same record (sat,ttag), be aware that since ttag
610           * is used as they key in a std::map, the value used must be
611           * EXACTLY the same in all calls; (numerical noise could
612           * cause the std::map to consider two "equal" ttags as
613           * different).
614           * @throw InvalidRequest
615           */
addPositionRecord(const SatID & sat,const CommonTime & ttag,const PositionRecord & data)616       void addPositionRecord(const SatID& sat, const CommonTime& ttag,
617                              const PositionRecord& data)
618       {
619          try { posStore.addPositionRecord(sat,ttag,data); }
620          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
621       }
622 
623          /** Add position data to the store
624           * @throw InvalidRequest
625           */
addPositionData(const SatID & sat,const CommonTime & ttag,const Triple & Pos,const Triple & sig)626       void addPositionData(const SatID& sat, const CommonTime& ttag,
627                            const Triple& Pos, const Triple& sig)
628       {
629          try { posStore.addPositionData(sat,ttag,Pos,sig); }
630          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
631       }
632 
633          /** Add velocity data to the store
634           * @throw InvalidRequest
635           */
addVelocityData(const SatID & sat,const CommonTime & ttag,const Triple & Vel,const Triple & sig)636       void addVelocityData(const SatID& sat, const CommonTime& ttag,
637                            const Triple& Vel, const Triple& sig)
638       {
639          try { posStore.addVelocityData(sat,ttag,Vel,sig); }
640          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
641       }
642 
643          /** Add a complete ClockRecord to the store; this is the
644           * preferred method of adding data to the tables.
645           * @note If these addXXX() routines are used more than once
646           * for the same record (sat,ttag), be aware that since ttag
647           * is used as they key in a std::map, the value used must be
648           * EXACTLY the same in all calls; (numerical noise could
649           * cause the std::map to consider two "equal" ttags as
650           * different).
651           * @throw InvalidRequest
652           */
addClockRecord(const SatID & sat,const CommonTime & ttag,const ClockRecord & rec)653       void addClockRecord(const SatID& sat, const CommonTime& ttag,
654                           const ClockRecord& rec)
655       {
656          try { clkStore.addClockRecord(sat,ttag,rec); }
657          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
658       }
659 
660          /** Add clock bias data (only) to the store
661           * @throw InvalidRequest
662           */
addClockBias(const SatID & sat,const CommonTime & ttag,const double & bias,const double & sig=0.0)663       void addClockBias(const SatID& sat, const CommonTime& ttag,
664                         const double& bias, const double& sig=0.0)
665       {
666          try { clkStore.addClockBias(sat,ttag,bias,sig); }
667          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
668       }
669 
670          /** Add clock drift data (only) to the store
671           * @throw InvalidRequest
672           */
addClockDrift(const SatID & sat,const CommonTime & ttag,const double & drift,const double & sig=0.0)673       void addClockDrift(const SatID& sat, const CommonTime& ttag,
674                          const double& drift, const double& sig=0.0)
675       {
676          try { clkStore.addClockDrift(sat,ttag,drift,sig); }
677          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
678       }
679 
680          /** Add clock acceleration data (only) to the store
681           * @throw InvalidRequest
682           */
addClockAcceleration(const SatID & sat,const CommonTime & ttag,const double & accel,const double & sig=0.0)683       void addClockAcceleration(const SatID& sat, const CommonTime& ttag,
684                                 const double& accel, const double& sig=0.0)
685       {
686          try { clkStore.addClockAcceleration(sat,ttag,accel,sig); }
687          catch(InvalidRequest& ir) { GPSTK_RETHROW(ir); }
688       }
689 
690 
691          /// Get number of files (all types) in FileStore.
nfiles(void)692       int nfiles(void) throw()
693       { return (SP3Files.size() + (useSP3clock ? 0 : clkFiles.size())); }
694 
695          /// Get number of SP3 files in FileStore.
nSP3files(void)696       int nSP3files(void) throw()
697       { return SP3Files.size(); }
698 
699          /// Get number of clock files in FileStore.
nClockfiles(void)700       int nClockfiles(void) throw()
701       { return (useSP3clock ? SP3Files.size() : clkFiles.size()); }
702 
703 
704          /// Return true if there is drift data in the tables
hasClockDrift() const705       virtual bool hasClockDrift() const throw()
706       {  return clkStore.hasClockDrift(); }
707 
708 
709          /** Set the flag; if true then all values are rejected when a
710           * bad position value is found, while adding data to the
711           * store. */
rejectBadPositions(const bool flag)712       void rejectBadPositions(const bool flag)
713       { rejectBadPosFlag = flag; }
714 
715          /** Set the flag; if true then all values are rejected when bad clock
716           * values are found, while adding data to the store. */
rejectBadClocks(const bool flag)717       void rejectBadClocks(const bool flag)
718       { rejectBadClockFlag = flag; }
719 
720          /** Set the flag; if true then predicted position values are
721           * rejected when adding data to the store. */
rejectPredPositions(const bool flag)722       void rejectPredPositions(const bool flag)
723       { rejectPredPosFlag = flag; }
724 
725          /** Set the flag; if true then predicted clock values are
726           * rejected when adding data to the store. */
rejectPredClocks(const bool flag)727       void rejectPredClocks(const bool flag)
728       { rejectPredClockFlag = flag; }
729 
730 
731          /// Is gap checking for position on?
isPosDataGapCheck(void)732       bool isPosDataGapCheck(void) throw()
733       { return posStore.isDataGapCheck(); }
734 
735          /// Is gap checking for clock on?
isClkDataGapCheck(void)736       bool isClkDataGapCheck(void) throw()
737       { return clkStore.isDataGapCheck(); }
738 
739          /// Disable checking of data gaps in both position and clock.
disableDataGapCheck(void)740       void disableDataGapCheck(void) throw()
741       { posStore.disableDataGapCheck(); clkStore.disableDataGapCheck(); }
742 
743          /// Disable checking of data gaps in position store
disablePosDataGapCheck(void)744       void disablePosDataGapCheck(void) throw()
745       { posStore.disableDataGapCheck(); }
746 
747          /// Disable checking of data gaps in clock store
disableClockDataGapCheck(void)748       void disableClockDataGapCheck(void) throw()
749       { clkStore.disableDataGapCheck(); }
750 
751          /// Get current gap interval in the position store.
getPosGapInterval(void)752       double getPosGapInterval(void) throw()
753       { return posStore.getGapInterval(); }
754 
755          /// Get current gap interval in the clock store.
getClockGapInterval(void)756       double getClockGapInterval(void) throw()
757       { return clkStore.getGapInterval(); }
758 
759          /** Set gap interval and turn on gap checking in the position
760           * store. There is no default. */
setPosGapInterval(double interval)761       void setPosGapInterval(double interval) throw()
762       { posStore.setGapInterval(interval); }
763 
764          /** Set gap interval and turn on gap checking in the clock
765           * store.  There is no default. */
setClockGapInterval(double interval)766       void setClockGapInterval(double interval) throw()
767       { clkStore.setGapInterval(interval); }
768 
769 
770          /// Is interval checking for position on?
isPosIntervalCheck(void)771       bool isPosIntervalCheck(void) throw()
772       { return posStore.isIntervalCheck(); }
773 
774          /// Is interval checking for clock on?
isClkIntervalCheck(void)775       bool isClkIntervalCheck(void) throw()
776       { return clkStore.isIntervalCheck(); }
777 
778          /// Disable checking of maximum interval in both position and clock.
disableIntervalCheck(void)779       void disableIntervalCheck(void) throw()
780       { posStore.disableIntervalCheck(); clkStore.disableIntervalCheck(); }
781 
782          /// Disable checking of maximum interval in position store
disablePosIntervalCheck(void)783       void disablePosIntervalCheck(void) throw()
784       { posStore.disableIntervalCheck(); }
785 
786          /// Disable checking of maximum interval in clock store
disableClockIntervalCheck(void)787       void disableClockIntervalCheck(void) throw()
788       { clkStore.disableIntervalCheck(); }
789 
790          /// Get current maximum interval in the position store
getPosMaxInterval(void)791       double getPosMaxInterval(void) throw()
792       { return posStore.getMaxInterval(); }
793 
794          /// Get current maximum interval in the clock store
getClockMaxInterval(void)795       double getClockMaxInterval(void) throw()
796       { return clkStore.getMaxInterval(); }
797 
798          /** Set maximum interval and turn on interval checking in the
799           * position store There is no default. */
setPosMaxInterval(double interval)800       void setPosMaxInterval(double interval) throw()
801       { posStore.setMaxInterval(interval); }
802 
803          /** Set maximum interval and turn on interval checking in the
804           * clock store There is no default. */
setClockMaxInterval(double interval)805       void setClockMaxInterval(double interval) throw()
806       { clkStore.setMaxInterval(interval); }
807 
808 
809          /// @deprecated
velocityIsPresent() const810       virtual bool velocityIsPresent() const throw()
811       { return posStore.hasVelocity(); }
812 
813          /// @deprecated
clockIsPresent() const814       virtual bool clockIsPresent() const throw()
815       { return true; }
816 
817          /** @deprecated
818           * Get current (position) interpolation order */
getInterpolationOrder(void)819       unsigned int getInterpolationOrder(void) throw()
820       { return getPositionInterpOrder(); }
821 
822          /** @deprecated
823           * Set the (position) interpolation order for the position table;
824           * it is forced to be even. */
setInterpolationOrder(unsigned int order)825       void setInterpolationOrder(unsigned int order) throw()
826       { setPositionInterpOrder(order); }
827 
828    }; // end class SP3EphemerisStore
829 
830       //@}
831 
832 }  // End of namespace gpstk
833 
834 #endif // GPSTK_SP3_EPHEMERIS_STORE_INCLUDE
835