00001 #pragma ident "$Id: ObsUtils.cpp 2741 2011-06-22 16:37:02Z nwu $"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00041 #include "StringUtils.hpp"
00042 #include "RinexObsID.hpp"
00043 #include "icd_200_constants.hpp"
00044
00045 #include "ObsUtils.hpp"
00046
00047 using namespace std;
00048
00049 namespace gpstk
00050 {
00051
00052 SvObsEpoch makeSvObsEpoch(const MDPObsEpoch& mdp) throw()
00053 {
00054 SvObsEpoch obs;
00055 MDPObsEpoch::ObsMap::const_iterator i;
00056 obs.svid = SatID(mdp.prn, SatID::systemGPS);
00057 obs.elevation = mdp.elevation;
00058 obs.azimuth = mdp.azimuth;
00059 for (i=mdp.obs.begin(); i!=mdp.obs.end(); i++)
00060 {
00061 CarrierCode cc = i->first.first;
00062 RangeCode rc = i->first.second;
00063 const MDPObsEpoch::Observation& mdp_obs = i->second;
00064
00065 ObsID::CarrierBand cb;
00066 ObsID::TrackingCode tc;
00067
00068 switch(cc)
00069 {
00070 case ccL1: cb = ObsID::cbL1; break;
00071 case ccL2: cb = ObsID::cbL2; break;
00072 case ccL5: cb = ObsID::cbL5; break;
00073 default: cb = ObsID::cbUnknown;
00074 }
00075
00076 switch (rc)
00077 {
00078 case rcCA: tc = ObsID::tcCA; break;
00079 case rcPcode: tc = ObsID::tcP; break;
00080 case rcYcode: tc = ObsID::tcY; break;
00081 case rcCodeless: tc = ObsID::tcW; break;
00082 case rcCM: tc = ObsID::tcC2M; break;
00083 case rcCL: tc = ObsID::tcC2L; break;
00084 case rcMcode1: tc = ObsID::tcM; break;
00085 case rcMcode2: tc = ObsID::tcM; break;
00086 case rcCMCL: tc = ObsID::tcC2LM; break;
00087 default: tc = ObsID::tcUnknown;
00088 }
00089
00090 obs[ObsID(ObsID::otRange, cb, tc)] = mdp_obs.pseudorange;
00091 obs[ObsID(ObsID::otPhase, cb, tc)] = mdp_obs.phase;
00092 obs[ObsID(ObsID::otDoppler, cb, tc)] = mdp_obs.doppler;
00093 obs[ObsID(ObsID::otSNR, cb, tc)] = mdp_obs.snr;
00094 obs[ObsID(ObsID::otTrackLen, cb, tc)] = mdp_obs.lockCount;
00095 }
00096 return obs;
00097 }
00098
00099
00100
00101 SvObsEpoch makeSvObsEpoch(const RinexObsData::RinexObsTypeMap& rotm) throw()
00102 {
00103 SvObsEpoch soe;
00104
00105 RinexObsData::RinexObsTypeMap::const_iterator rotm_itr;
00106 for (rotm_itr = rotm.begin(); rotm_itr != rotm.end(); rotm_itr++)
00107 {
00108 const RinexObsHeader::RinexObsType& rot = rotm_itr->first;
00109 const RinexObsData::RinexDatum& rd = rotm_itr->second;
00110 RinexObsID oid(rot);
00111 soe[oid] = rd.data;
00112 if (rd.ssi>0)
00113 {
00114 oid.type = ObsID::otSSI;
00115 soe[oid] = rd.ssi;
00116 }
00117 if (rd.lli>0)
00118 {
00119 oid.type = ObsID::otLLI;
00120 soe[oid] = rd.lli;
00121 }
00122 }
00123
00124 return soe;
00125 }
00126
00127
00128
00129 ObsEpoch makeObsEpoch(const RinexObsData& rod) throw()
00130 {
00131 ObsEpoch oe;
00132 oe.time = rod.time;
00133
00134 RinexObsData::RinexSatMap::const_iterator rsm_itr;
00135 for (rsm_itr = rod.obs.begin(); rsm_itr != rod.obs.end(); rsm_itr++)
00136 {
00137 const SatID svid(rsm_itr->first);
00138 const RinexObsData::RinexObsTypeMap& rotm = rsm_itr->second;
00139 oe[svid] = makeSvObsEpoch(rotm);
00140 }
00141
00142 return oe;
00143 }
00144
00145
00146
00147 ObsEpoch makeObsEpoch(const MDPEpoch& mdp) throw()
00148 {
00149 ObsEpoch oe;
00150 oe.time = mdp.begin()->second.time;
00151
00152 for (MDPEpoch::const_iterator i=mdp.begin(); i!=mdp.end(); i++)
00153 {
00154 const MDPObsEpoch& moe = i->second;
00155 SatID svid(moe.prn, SatID::systemGPS);
00156 oe[svid] = makeSvObsEpoch(moe);
00157 }
00158 return oe;
00159 }
00160
00161
00162
00163 WxObservation makeWxObs(const SMODFData& smod) throw()
00164 {
00165 WxObservation wx;
00166
00167 wx.t = smod.time;
00168
00169 if (smod.tempSource)
00170 {
00171 wx.temperature = smod.temp;
00172 wx.temperatureSource = WxObservation::obsWx;
00173 }
00174 else
00175 wx.temperatureSource = WxObservation::noWx;;
00176
00177 if (smod.pressSource)
00178 {
00179 wx.pressure = smod.pressure;
00180 wx.pressureSource = WxObservation::obsWx;
00181 }
00182 else
00183 wx.pressureSource = WxObservation::noWx;;
00184
00185 if (smod.humidSource)
00186 {
00187 wx.humidity = smod.humidity;
00188 wx.humiditySource = WxObservation::obsWx;
00189 }
00190 else
00191 wx.humiditySource = WxObservation::noWx;
00192
00193 return wx;
00194 }
00195
00196
00197
00198 void addMDPObservation(MDPObsEpoch& moe,
00199 const AshtechMBEN::code_block& cb,
00200 CarrierCode cc,
00201 RangeCode rc,
00202 const MDPObsEpoch& moe_hint) throw()
00203 {
00204
00205 if (rc != rcCA)
00206 switch (cb.goodbad)
00207 {
00208 case 22: rc = rcPcode; break;
00209 case 24: rc = rcYcode; break;
00210 case 25: rc = rcCodeless; break;
00211 }
00212
00213 float chipRate=PY_CHIP_FREQ;
00214 if (rc == rcCA)
00215 chipRate = CA_CHIP_FREQ;
00216
00217 MDPObsEpoch::Observation obs;
00218 obs.carrier = cc;
00219 obs.range = rc;
00220 obs.snr = cb.snr(chipRate);
00221 obs.pseudorange = cb.raw_range * C_GPS_M;
00222 obs.phase = cb.full_phase;
00223 obs.doppler = -cb.doppler;
00224 obs.bw=1;
00225 obs.lockCount = 0;
00226
00227 if (moe_hint.haveObservation(cc, rc))
00228 {
00229 MDPObsEpoch::Observation obs_hint = moe_hint.getObservation(cc, rc);
00230 obs.bw = obs_hint.bw;
00231
00232
00233 if (!(cb.warning & ~0x23))
00234 obs.lockCount = obs_hint.lockCount+1;
00235 }
00236
00237 moe.obs[MDPObsEpoch::ObsKey(cc, rc)] = obs;
00238 }
00239
00240
00241
00242 MDPObsEpoch makeMDPObsEpoch(
00243 const AshtechMBEN& mben,
00244 const MDPObsEpoch& hint) throw()
00245 {
00246 MDPObsEpoch moe;
00247
00248
00249 moe.time = hint.time;
00250 double sow1 = moe.time.GPSsecond();
00251 int sow2 = static_cast<int>(sow1/1800);
00252 double sow3 = static_cast<double>(sow2 * 1800);
00253 double sow_mben = 0.05 * mben.seq;
00254 double sow4 = sow3 + sow_mben;
00255 long week = moe.time.GPSfullweek();
00256 if (sow4 < sow1)
00257 sow4 += 1800;
00258 while (sow4 >= DayTime::FULLWEEK)
00259 {
00260 sow4 -= DayTime::FULLWEEK;
00261 week += 1;
00262 }
00263 moe.time.setGPS(week, sow4);
00264
00265 moe.numSVs = hint.numSVs;
00266 moe.channel = mben.chid;
00267 moe.prn = mben.svprn;
00268 moe.status = hint.status;
00269 moe.elevation = mben.el;
00270 moe.azimuth = mben.az;
00271
00272 addMDPObservation(moe, mben.ca, ccL1, rcCA, hint);
00273
00274 if (mben.id == AshtechMBEN::mpcId)
00275 {
00276 addMDPObservation(moe, mben.p1, ccL1, rcPcode, hint);
00277 addMDPObservation(moe, mben.p2, ccL2, rcPcode, hint);
00278 }
00279 return moe;
00280 }
00281
00282
00283
00284 MDPPVTSolution makeMDPPVTSolution(
00285 const AshtechPBEN& pben,
00286 const unsigned week) throw()
00287 {
00288 MDPPVTSolution pvt;
00289
00290 pvt.x[0] = pben.navx;
00291 pvt.x[1] = pben.navy;
00292 pvt.x[2] = pben.navz;
00293 pvt.dtime = pben.navt / C_GPS_M;
00294 pvt.v[0] = pben.navxdot;
00295 pvt.v[1] = pben.navydot;
00296 pvt.v[2] = pben.navzdot;
00297 pvt.ddtime = pben.navtdot / C_GPS_M;
00298
00299 pvt.time.setGPS(week, pben.sow);
00300 pvt.timep = pvt.time + pvt.dtime;
00301
00302 pvt.fom = pben.pdop;
00303 pvt.numSVs = (int)pben.numSV;
00304 pvt.pvtMode = 0;
00305 pvt.corrections = 0;
00306
00307 return pvt;
00308 }
00309
00310
00311 MDPEpoch makeMDPEpoch(const ATSData& ats, const MDPEpoch& hint) throw()
00312 {
00313 MDPEpoch me;
00314 DayTime t0(DayTime::BEGINNING_OF_TIME);
00315
00316 for (int i=0; i < ats.channels.size(); i++)
00317 {
00318 const ATSData::ChannelBlock& cb = ats.channels[i];
00319 short week = static_cast<short>(cb.absTime / DayTime::FULLWEEK);
00320
00321
00322 if (week==0)
00323 continue;
00324
00325 double sow = cb.absTime - week * DayTime::FULLWEEK;
00326 DayTime t(week, sow);
00327 if (i==0 || t0 == DayTime(DayTime::BEGINNING_OF_TIME))
00328 t0 = t;
00329 else if (std::abs(t - t0) > 0.1)
00330 {
00331 if (ats.debugLevel>1)
00332 cout << "# Epoch with inconsistent times t:" << t
00333 << ", t0:" << t0 << endl;
00334 continue;
00335 }
00336
00337 MDPObsEpoch moe;
00338
00339 moe.time = t;
00340 moe.prn = cb.svid.id;
00341 moe.status = 0;
00342 moe.elevation = 0;
00343 moe.azimuth = 0;
00344 moe.channel = i + 1;
00345
00346 MDPObsEpoch moe_hint;
00347 MCIP mcip = hint.equal_range(cb.svid.id);
00348
00349 MDPEpoch::const_iterator k;
00350 for (k=mcip.first; k != mcip.second; k++)
00351 if (k->second.channel == moe.channel)
00352 {
00353 moe_hint = k->second;
00354 break;
00355 }
00356
00357 for (int j=0; j<ats.numSubChan; j++)
00358 {
00359 const ATSData::SubChannelBlock& scb=cb.subChannels[j];
00360
00361 MDPObsEpoch::ObsKey obsKey;
00362 switch (j)
00363 {
00364 case 0: obsKey = MDPObsEpoch::ObsKey(ccL1, rcCA); break;
00365 case 1: obsKey = MDPObsEpoch::ObsKey(ccL1, rcYcode); break;
00366 case 2: obsKey = MDPObsEpoch::ObsKey(ccL2, rcYcode); break;
00367 case 3: obsKey = MDPObsEpoch::ObsKey(ccL1, rcMcode1); break;
00368 case 4: obsKey = MDPObsEpoch::ObsKey(ccL2, rcMcode1); break;
00369 }
00370
00371 MDPObsEpoch::Observation obs;
00372 obs.carrier = obsKey.first;
00373 obs.range = obsKey.second;
00374 obs.bw = 1;
00375 obs.snr = scb.cn0;
00376 obs.pseudorange = scb.pseudorange;
00377 obs.phase = scb.phase;
00378 obs.lockCount = 0;
00379
00380
00381
00382 if (scb.flags & 0x1 && j<3)
00383 continue;
00384 else if (scb.cn0 < 20)
00385 continue;
00386 else if (moe_hint.haveObservation(obsKey))
00387 {
00388 MDPObsEpoch::Observation oh = moe_hint.getObservation(obsKey);
00389 obs.lockCount = oh.lockCount+1;
00390 }
00391
00392 if (obs.carrier == ccL1)
00393 obs.doppler = scb.rangeRate ;
00394 else if (obs.carrier == ccL2)
00395 obs.doppler = scb.rangeRate;
00396
00397 moe.obs[obsKey] = obs;
00398 }
00399
00400 me.insert(pair<const int, MDPObsEpoch>(moe.prn, moe));
00401 }
00402
00403 int numSVs = me.size();
00404 MDPEpoch::iterator i;
00405 for (i=me.begin(); i != me.end(); i++)
00406 i->second.numSVs = numSVs;
00407 return me;
00408 }
00409
00410 }