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 ClockSatStore.hpp Store a tabular list of clock data (bias,
40  * drift, accel) for several satellites, and compute values at any
41  * timetag from this table. Inherits TabularSatStore.  This class is
42  * not virtual and could be used as is, however note there is no
43  * FileStore, and no data file input (loadFile()), but there are
44  * addData() routines. */
45 
46 #ifndef GPSTK_CLOCK_SAT_STORE_INCLUDE
47 #define GPSTK_CLOCK_SAT_STORE_INCLUDE
48 
49 #include <map>
50 #include <iostream>
51 
52 #include "Exception.hpp"
53 #include "SatID.hpp"
54 #include "CommonTime.hpp"
55 #include "TabularSatStore.hpp"
56 #include "FileStore.hpp"
57 
58 namespace gpstk
59 {
60       /// @ingroup GNSSEph
61       //@{
62 
63       /** Data record for storing clock data. See note on units in
64        * class ClockSatStore. */
65    typedef struct ClockDataRecord
66    {
67       double bias, sig_bias;     ///< clock bias and sigma
68       double drift, sig_drift;   ///< clock drift and sigma
69       double accel, sig_accel;   ///< clock acceleration and sigma
70    } ClockRecord;
71 
72       /// Output stream operator is used by dump() in TabularSatStore
73    std::ostream& operator<<(std::ostream& os, const ClockRecord& rec) throw();
74 
75       // This is a helper for SWIG processing - it needs a template
76       // instation of the base type of ClockSatStore before it is
77       // used, so this statement must be between the ClockDataRecord
78       // and ClockSatStore declarations.
79 #ifdef SWIG
80    %template(TabularSatStore_ClockRecord) gpstk::TabularSatStore<gpstk::ClockRecord>;
81 #endif
82 
83       /** Store a table of data vs time for each of several
84        * satellites.  The data are stored as ClockRecords, one for
85        * each (satellite,time) pair.  The getValue(sat, t) routine
86        * interpolates the table for sat at time t and returns the
87        * result as a DataRecord object.
88        * @note this class (dump()) requires that
89        *   operator<<(DataRecord) be defined, unless dump() is
90        *   declared and defined in this class.
91        * @note It is assumed that the units of the quanitities are
92        *   'coordinated' meaning that units(drift) == units(bias)/sec,
93        *   units(acc) == units(drift)/s/s and units(sigX) ==
94        *   units(X). This assumption is critical only when
95        *   interpolation is used to estimate X/sec from X data.  No
96        *   other assumptions are made about units.
97        * @note SP3 data (in the file and in SP3Data) are NOT
98        *   coordinated; users and derived classes must deal with units
99        *   consistently. */
100    class ClockSatStore : public TabularSatStore<ClockRecord>
101    {
102 
103          // member data
104    protected:
105 
106          /// flag indicating whether acceleration data is present
107       bool haveClockAccel;
108 
109          /** Type of interpolation: 1=linear, 2=Lagrange, 3=numerical
110           * derivative? */
111       int interpType;
112 
113          /** Order of Lagrange interpolation; should be even, is
114           * forced to be even in setInterpolationOrder (for linear
115           * interpolation it is 2). */
116       unsigned int interpOrder;
117 
118          /// Store half the interpolation order, for convenience
119       unsigned int Nhalf;
120 
121          /// Flag to reject bad clock data; default true
122       bool rejectBadClockFlag;
123 
124          // member functions
125    public:
126 
127          /// Default constructor
ClockSatStore()128       ClockSatStore() throw() : haveClockAccel(false),
129          interpType(2), Nhalf(5),
130          rejectBadClockFlag(true)
131       {
132             // @note if interpType = 1, interpOrder = 2 (linear)
133          interpOrder = 2*Nhalf;
134          haveClockBias = true;
135          haveClockDrift = havePosition = haveVelocity = false;
136       }
137 
138          /// Destructor
~ClockSatStore()139       virtual ~ClockSatStore() {};
140 
hasClockAccel() const141       bool hasClockAccel() const throw() { return haveClockAccel; }
142 
143          /** Return value for the given satellite at the given time
144           * (usually via interpolation of the data table). This
145           * interface from TabularSatStore.
146           * @param[in] sat the SatID of the satellite of interest
147           * @param[in] ttag the time (CommonTime) of interest
148           * @return object of type ClockRecord containing the data value(s).
149           * @throw InvalidRequest if data value cannot be computed,
150           *   for example because
151           *  a) the time t does not lie within the time limits of the
152           *     data table
153           *  b) checkDataGap is true and there is a data gap
154           *  c) checkInterval is true and the interval is larger than
155           *     maxInterval */
156       virtual ClockRecord getValue(const SatID& sat, const CommonTime& ttag)
157          const;
158 
159          /** Return the clock bias for the given satellite at the given time
160           * @param[in] sat the SatID of the satellite of interest
161           * @param[in] ttag the time (CommonTime) of interest
162           * @return double the clock bias
163           * @throw InvalidRequest if bias cannot be computed, for
164           *   example because
165           *  a) the time t does not lie within the time limits of the
166           *     data table
167           *  b) checkDataGap is true and there is a data gap
168           *  c) checkInterval is true and the interval is larger than
169           *     maxInterval */
170       double getClockBias(const SatID& sat, const CommonTime& ttag)
171          const;
172 
173          /** Return the clock drift for the given satellite at the given time
174           * @param[in] sat the SatID of the satellite of interest
175           * @param[in] ttag the time (CommonTime) of interest
176           * @return double the clock drift
177           * @throw InvalidRequest if drift cannot be computed, for
178           *   example because
179           *  a) the time t does not lie within the time limits of the
180           *     data table
181           *  b) checkDataGap is true and there is a data gap
182           *  c) checkInterval is true and the interval is larger than
183           *     maxInterval
184           *  d) there is no drift data in the store */
185       double getClockDrift(const SatID& sat, const CommonTime& ttag)
186          const;
187 
188          /** Dump information about the object to an ostream.
189           * @param[in] os ostream to receive the output; defaults to std::cout
190           * @param[in] detail integer level of detail to provide;
191           *   allowed values are:
192           *    0: number of satellites, time step and time limits, flags,
193           *           gap and interval flags and values, and file information
194           *    1: number of data/sat
195           *    2: above plus all the data tables */
dump(std::ostream & os=std::cout,int detail=0) const196       virtual void dump(std::ostream& os = std::cout, int detail = 0) const throw()
197       {
198          os << "Dump of ClockSatStore(" << detail << "):\n";
199          os << " This store "
200             << (haveClockAccel ? "contains":" does not contain")
201             << " clock acceleration data." << std::endl;
202          os << " Interpolation is ";
203          if(interpType == 2)
204             os << "Lagrange, of order " << interpOrder
205                << " (" << Nhalf << " points on each side)" << std::endl;
206          else
207             os << "Linear." << std::endl;
208          TabularSatStore<ClockRecord>::dump(os,detail);
209          os << "End dump of ClockSatStore.\n";
210       }
211 
212          /** Add a complete ClockRecord to the store; this is the
213           * preferred method of adding data to the tables.
214           * @note If these addXXX() routines are used more than once
215           *   for the same record (sat,ttag), be aware that since ttag
216           *   is used as they key in a std::map, the value used must
217           *   be EXACTLY the same in all calls; (numerical noise could
218           *   cause the std::map to consider two "equal" ttags as
219           *   different).
220           * @throw InvalidRequest
221           */
222       void addClockRecord(const SatID& sat, const CommonTime& ttag,
223                           const ClockRecord& rec);
224 
225          /** Add clock bias data (only) to the store
226           * @throw InvalidRequest
227           */
228       void addClockBias(const SatID& sat, const CommonTime& ttag,
229                         const double& bias, const double& sig=0.0);
230 
231          /** Add clock drift data (only) to the store
232           * @throw InvalidRequest
233           */
234       void addClockDrift(const SatID& sat, const CommonTime& ttag,
235                          const double& drift, const double& sig=0.0);
236 
237          /** Add clock acceleration data (only) to the store
238           * @throw InvalidRequest
239           */
240       void addClockAcceleration(const SatID& sat, const CommonTime& ttag,
241                                 const double& accel, const double& sig=0.0);
242 
243          /// Get current interpolation order.
getInterpolationOrder(void)244       unsigned int getInterpolationOrder(void) throw()
245       { return interpOrder; }
246 
247          /** Set the interpolation order; this routine forces the
248           * order to be even. */
setInterpolationOrder(unsigned int order)249       void setInterpolationOrder(unsigned int order) throw()
250       {
251          if(interpType == 2) Nhalf = (order+1)/2;
252          else                Nhalf = 1;
253          interpOrder = 2*Nhalf;
254       }
255 
256          /** Set the flag; if true then bad position values are rejected when
257           * adding data to the store. */
rejectBadClocks(const bool flag)258       void rejectBadClocks(const bool flag)
259       { rejectBadClockFlag = flag; }
260 
261          /// Set the type of interpolation to Lagrange (default)
setLagrangeInterp(void)262       void setLagrangeInterp(void) throw()
263       { interpType = 2; setInterpolationOrder(10); }
264 
265          /// Set the type of interpolation to linear. Note that
setLinearInterp(void)266       void setLinearInterp(void) throw()
267       { interpType = 1; setInterpolationOrder(2); }
268 
269    }; // end class ClockSatStore
270 
271       //@}
272 
273 }  // End of namespace gpstk
274 
275 #endif // GPSTK_CLOCK_SAT_STORE_INCLUDE
276