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 /**
40  * @file ObsClockModel.cpp
41  * Yet another abstract class used to define an interface to a model that
42  * accepts GPS observation datat and determines a clock model from it. It
43  * mainly adds the ability to specify the characteristcs of the observations
44  * that are to be accpeted into the model. It also defines a function that
45  * accepts Observed Range Deviations and computes the mean of these (that
46  * meet the selection criteria) as an estimate of the receiver clock.
47  */
48 
49 #include <math.h>
50 
51 #include "ObsClockModel.hpp"
52 
53 namespace gpstk
54 {
55    using namespace std;
56 
57 
58       /**
59        * @throw ObjectNotFound
60        */
getSvStatus(const SatID & svid) const61    ObsClockModel::SvStatus ObsClockModel::getSvStatus(const SatID& svid) const
62    {
63       SvStatusMap::const_iterator i = status.find(svid);
64       if(i == status.end())
65       {
66          gpstk::ObjectNotFound e("No status for SV " +
67                                  StringUtils::asString(svid) +
68                                  " available.");
69          GPSTK_THROW(e);
70       }
71       else
72          return i->second;
73    }
74 
75 
setSvModeMap(const SvModeMap & right)76    ObsClockModel& ObsClockModel::setSvModeMap(const SvModeMap& right)
77       throw()
78    {
79       for(int prn = 1; prn <= gpstk::MAX_PRN; prn++)
80          modes[SatID(prn, SatelliteSystem::GPS)] = IGNORE;
81 
82       for(SvModeMap::const_iterator i = right.begin(); i != right.end(); i++)
83          modes[i->first] = i->second;
84 
85       return *this;
86    }
87 
88 
89       /**
90        * @throw ObjectNotFound
91        */
getSvMode(const SatID & svid) const92    ObsClockModel::SvMode ObsClockModel::getSvMode(const SatID& svid) const
93    {
94       SvModeMap::const_iterator i = modes.find(svid);
95       if(i == modes.end())
96       {
97          gpstk::ObjectNotFound e("No status for SV " +
98                                  StringUtils::asString(svid) +
99                                  " available.");
100          GPSTK_THROW(e);
101       }
102       else
103          return i->second;
104    }
105 
106 
107       /**
108        * @throw InvalidValue
109        */
simpleOrdClock(const ORDEpoch & oe)110    gpstk::Stats<double> ObsClockModel::simpleOrdClock(const ORDEpoch& oe)
111    {
112       gpstk::Stats<double> stat;
113 
114       status.clear();
115 
116       ORDEpoch::ORDMap::const_iterator itr;
117       for(itr = oe.ords.begin(); itr != oe.ords.end(); itr++)
118       {
119          const SatID& svid = itr->first;
120          const ObsRngDev& ord=itr->second;
121          switch (modes[svid])
122          {
123             case IGNORE:
124                status[svid] = MANUAL;
125                break;
126             case ALWAYS:
127                status[svid] = USED;
128                break;
129             case HEALTHY:
130                // SV Health bits are defined in ICD-GPS-200C-IRN4 20.3.3.3.1.4
131                // It is a 6-bit value where the MSB (0x20) indicates a summary of
132                // of NAV data health where 0 = OK, 1 = some or all BAD
133                if (ord.getHealth().is_valid() && (ord.getHealth() & 0x20))
134                   status[svid] = SVHEALTH;
135                else
136                   status[svid] = USED;
137                break;
138          }
139 
140          if (ord.getElevation() < elvmask)
141             status[svid] = ELEVATION;
142 
143          if (ord.wonky && !useWonkyData)
144             status[svid] = WONKY;
145 
146          if (status[svid] == USED)
147             stat.Add(ord.getORD());
148       }
149 
150       if (stat.N() > 2)
151       {
152          for (itr = oe.ords.begin(); itr != oe.ords.end(); itr++)
153          {
154             const SatID& svid = itr->first;
155 
156             // don't override other types of stripping
157             if (status[svid] == USED)
158             {
159                // get absolute distance of residual from mean
160                double res = itr->second.getORD();
161                double dist = res - stat.Average();
162                if(fabs(dist) > (sigmam * stat.StdDev()))
163                   status[svid] = SIGMA;
164             }
165          }
166 
167          // now, recompute the statistics on unstripped residuals to get
168          // the clock bias value
169          stat.Reset();
170          for (itr = oe.ords.begin(); itr != oe.ords.end(); itr++)
171             if (status[itr->second.getSvID()] == USED)
172                stat.Add(itr->second.getORD());
173       }
174 
175       return stat;
176    }
177 
dump(ostream & s,short detail) const178    void ObsClockModel::dump(ostream& s, short detail) const throw()
179    {
180       s << "min elev:" << elvmask
181         << ", max sigma:" << sigmam
182         << ", prn/status: ";
183 
184       ObsClockModel::SvStatusMap::const_iterator i;
185       for ( i=status.begin(); i!= status.end(); i++)
186          s << i->first << "/" << i->second << " ";
187    }
188 }
189