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