source: ntrip/trunk/BNC/src/PPP/pppSatObs.cpp@ 6033

Last change on this file since 6033 was 6033, checked in by mervart, 10 years ago
File size: 15.8 KB
RevLine 
[5743]1// Part of BNC, a utility for retrieving decoding and
2// converting GNSS data streams from NTRIP broadcasters.
3//
4// Copyright (C) 2007
5// German Federal Agency for Cartography and Geodesy (BKG)
6// http://www.bkg.bund.de
7// Czech Technical University Prague, Department of Geodesy
8// http://www.fsv.cvut.cz
9//
10// Email: euref-ip@bkg.bund.de
11//
12// This program is free software; you can redistribute it and/or
13// modify it under the terms of the GNU General Public License
14// as published by the Free Software Foundation, version 2.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
25/* -------------------------------------------------------------------------
26 * BKG NTRIP Client
27 * -------------------------------------------------------------------------
28 *
[5819]29 * Class: t_pppSatObs
[5743]30 *
31 * Purpose: Satellite observations
32 *
33 * Author: L. Mervart
34 *
35 * Created: 29-Jul-2014
36 *
37 * Changes:
38 *
39 * -----------------------------------------------------------------------*/
40
41
42#include <iostream>
43#include <cmath>
44#include <newmatio.h>
[5822]45
46#include "pppSatObs.h"
[5750]47#include "bncconst.h"
[5810]48#include "pppEphPool.h"
49#include "pppStation.h"
[5750]50#include "bncutils.h"
51#include "bncantex.h"
[5810]52#include "pppObsPool.h"
[5750]53#include "pppClient.h"
[5743]54
[5814]55using namespace BNC_PPP;
[5743]56using namespace std;
57
58// Constructor
59////////////////////////////////////////////////////////////////////////////
[5819]60t_pppSatObs::t_pppSatObs(const t_satObs& pppSatObs) {
[6017]61 _prn = pppSatObs._prn;
62 _time = pppSatObs._time;
63 _outlier = false;
[6023]64 _valid = true;
[6017]65 for (unsigned ii = 0; ii < t_frequency::max; ii++) {
66 _obs[ii] = 0;
[5743]67 }
[6017]68 prepareObs(pppSatObs);
[5743]69}
70
71// Destructor
72////////////////////////////////////////////////////////////////////////////
[5819]73t_pppSatObs::~t_pppSatObs() {
[6017]74 for (unsigned iFreq = 1; iFreq < t_frequency::max; iFreq++) {
75 delete _obs[iFreq];
[5743]76 }
77}
78
79//
80////////////////////////////////////////////////////////////////////////////
[6017]81void t_pppSatObs::prepareObs(const t_satObs& pppSatObs) {
82
[5743]83 _model.reset();
84
[6017]85 // Select pseudoranges and phase observations
86 // ------------------------------------------
87 const string preferredAttrib = "CWP_";
[5743]88
[6017]89 for (unsigned iFreq = 1; iFreq < t_frequency::max; iFreq++) {
90 string frqNum = t_frequency::toString(t_frequency::type(iFreq)).substr(1);
91 for (unsigned iPref = 0; iPref < preferredAttrib.length(); iPref++) {
92 string obsType = (preferredAttrib[iPref] == '_') ? frqNum : frqNum + preferredAttrib[iPref];
93 if (_obs[iFreq] == 0) {
94 for (unsigned ii = 0; ii < pppSatObs._obs.size(); ii++) {
95 const t_frqObs* obs = pppSatObs._obs[ii];
96 if (obs->_rnxType2ch == obsType && obs->_codeValid && obs->_phaseValid) {
97 _obs[iFreq] = new t_frqObs(*obs);
[5830]98 }
[5743]99 }
100 }
101 }
102 }
103
[6026]104 // Used frequency types
105 // --------------------
106 _fType1 = t_lc::toFreq(_prn.system(),t_lc::l1);
107 _fType2 = t_lc::toFreq(_prn.system(),t_lc::l2);
108
[6024]109 // Check whether all required frequencies available
110 // ------------------------------------------------
111 for (unsigned ii = 0; ii < OPT->LCs(_prn.system()).size(); ii++) {
112 t_lc::type tLC = OPT->LCs(_prn.system())[ii];
113 if (!isValid(tLC)) {
114 _valid = false;
115 return;
116 }
117 }
118
[5743]119 // Find Glonass Channel Number
120 // ---------------------------
121 if (_prn.system() == 'R') {
122 _channel = PPP_CLIENT->ephPool()->getChannel(_prn);
123 }
124 else {
125 _channel = 0;
126 }
127
128 // Compute Satellite Coordinates at Time of Transmission
129 // -----------------------------------------------------
130 _xcSat.ReSize(4); _xcSat = 0.0;
131 _vvSat.ReSize(4); _vvSat = 0.0;
132 bool totOK = false;
133 ColumnVector satPosOld(4); satPosOld = 0.0;
[6023]134 t_lc::type tLC = isValid(t_lc::cIF) ? t_lc::cIF : t_lc::c1;
[5743]135 double prange = obsValue(tLC);
136 for (int ii = 1; ii <= 10; ii++) {
[5750]137 bncTime ToT = _time - prange / t_CST::c - _xcSat[3];
138 if (PPP_CLIENT->ephPool()->getCrd(_prn, ToT, _xcSat, _vvSat) != success) {
[5743]139 _valid = false;
140 return;
141 }
142 ColumnVector dx = _xcSat - satPosOld;
[5750]143 dx[3] *= t_CST::c;
[5743]144 if (dx.norm_Frobenius() < 1.e-4) {
145 totOK = true;
146 break;
147 }
148 satPosOld = _xcSat;
149 }
150 if (totOK) {
[5750]151 _model._satClkM = _xcSat[3] * t_CST::c;
[5743]152 }
153 else {
154 _valid = false;
155 }
156}
157
158//
159////////////////////////////////////////////////////////////////////////////
[6025]160void t_pppSatObs::lcCoeff(t_lc::type tLC,
161 map<t_frequency::type, double>& codeCoeff,
162 map<t_frequency::type, double>& phaseCoeff) const {
163
164 codeCoeff.clear();
165 phaseCoeff.clear();
166
[6026]167 double f1 = t_CST::freq(_fType1, _channel);
168 double f2 = t_CST::freq(_fType2, _channel);
[6025]169
170 switch (tLC) {
171 case t_lc::l1:
[6026]172 phaseCoeff[_fType1] = 1.0;
[6025]173 return;
174 case t_lc::l2:
[6026]175 phaseCoeff[_fType2] = 1.0;
[6025]176 return;
177 case t_lc::lIF:
[6026]178 phaseCoeff[_fType1] = f1 * f1 / (f1 * f1 - f2 * f2);
179 phaseCoeff[_fType2] = -f2 * f2 / (f1 * f1 - f2 * f2);
[6025]180 return;
181 case t_lc::MW:
[6026]182 phaseCoeff[_fType1] = f1 / (f1 - f2);
183 phaseCoeff[_fType2] = -f2 / (f1 - f2);
184 codeCoeff[_fType1] = -f1 / (f1 + f2);
185 codeCoeff[_fType2] = -f2 / (f1 + f2);
[6025]186 return;
187 case t_lc::CL:
[6026]188 phaseCoeff[_fType1] = 0.5;
189 codeCoeff[_fType1] = 0.5;
[6025]190 return;
191 case t_lc::c1:
[6026]192 codeCoeff[_fType1] = 1.0;
[6025]193 return;
194 case t_lc::c2:
[6026]195 codeCoeff[_fType2] = 1.0;
[6025]196 return;
197 case t_lc::cIF:
[6026]198 codeCoeff[_fType1] = f1 * f1 / (f1 * f1 - f2 * f2);
199 codeCoeff[_fType2] = -f2 * f2 / (f1 * f1 - f2 * f2);
[6025]200 return;
201 case t_lc::dummy:
202 case t_lc::maxLc:
203 return;
204 }
205}
206
[6026]207//
208////////////////////////////////////////////////////////////////////////////
209bool t_pppSatObs::isValid(t_lc::type tLC) const {
[6027]210 bool valid = true;
211 obsValue(tLC, &valid);
212 return valid;
213}
214//
215////////////////////////////////////////////////////////////////////////////
216double t_pppSatObs::obsValue(t_lc::type tLC, bool* valid) const {
[6025]217
[6026]218 map<t_frequency::type, double> codeCoeff;
219 map<t_frequency::type, double> phaseCoeff;
220 lcCoeff(tLC, codeCoeff, phaseCoeff);
221
[6027]222 double retVal = 0.0;
223 if (valid) *valid = true;
224
[6026]225 map<t_frequency::type, double>::const_iterator it;
226 for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
227 t_frequency::type tFreq = it->first;
228 if (_obs[tFreq] == 0) {
[6027]229 if (valid) *valid = false;
230 return 0.0;
[6026]231 }
[6027]232 else {
[6028]233 retVal += it->second * _obs[tFreq]->_code;
[6027]234 }
[6026]235 }
236 for (it = phaseCoeff.begin(); it != phaseCoeff.end(); it++) {
237 t_frequency::type tFreq = it->first;
238 if (_obs[tFreq] == 0) {
[6027]239 if (valid) *valid = false;
240 return 0.0;
[6026]241 }
[6027]242 else {
[6028]243 retVal += it->second * _obs[tFreq]->_phase * t_CST::lambda(tFreq, _channel);
[6027]244 }
[6026]245 }
246
[6027]247 return retVal;
[6026]248}
249
[6029]250//
251////////////////////////////////////////////////////////////////////////////
252double t_pppSatObs::lambda(t_lc::type tLC) const {
[6026]253
[6029]254 double f1 = t_CST::freq(_fType1, _channel);
255 double f2 = t_CST::freq(_fType2, _channel);
256
257 if (tLC == t_lc::l1) {
258 return t_CST::c / f1;
259 }
260 else if (tLC == t_lc::l2) {
261 return t_CST::c / f2;
262 }
263 else if (tLC == t_lc::lIF) {
264 return t_CST::c / (f1 + f2);
265 }
266 else if (tLC == t_lc::MW) {
267 return t_CST::c / (f1 - f2);
268 }
269 else if (tLC == t_lc::CL) {
270 return t_CST::c / f1 / 2.0;
271 }
272
273 return 0.0;
274}
275
[6026]276//
277////////////////////////////////////////////////////////////////////////////
[6029]278double t_pppSatObs::sigma(t_lc::type tLC) const {
279
280 map<t_frequency::type, double> codeCoeff;
281 map<t_frequency::type, double> phaseCoeff;
282 lcCoeff(tLC, codeCoeff, phaseCoeff);
283
284 double retVal = 0.0;
285
286 map<t_frequency::type, double>::const_iterator it;
287 for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
288 retVal += it->second * it->second * OPT->_sigmaC1 * OPT->_sigmaC1;
289 }
290 for (it = phaseCoeff.begin(); it != phaseCoeff.end(); it++) {
291 retVal += it->second * it->second * OPT->_sigmaL1 * OPT->_sigmaL1;
292 }
293
294 retVal = sqrt(retVal);
295
296 // Elevation-Dependent Weighting
297 // -----------------------------
298 double cEle = 1.0;
299 if ( (OPT->_eleWgtCode && t_lc::includesCode(tLC)) ||
300 (OPT->_eleWgtPhase && t_lc::includesPhase(tLC)) ) {
301 double eleD = eleSat()*180.0/M_PI;
302 double hlp = fabs(90.0 - eleD);
303 cEle = (1.0 + hlp*hlp*hlp*0.000004);
304 }
305
306 return cEle * retVal;
307}
308
309//
310////////////////////////////////////////////////////////////////////////////
311double t_pppSatObs::maxRes(t_lc::type tLC) const {
312
313 map<t_frequency::type, double> codeCoeff;
314 map<t_frequency::type, double> phaseCoeff;
315 lcCoeff(tLC, codeCoeff, phaseCoeff);
316
317 double retVal = 0.0;
318
319 map<t_frequency::type, double>::const_iterator it;
320 for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
321 retVal += it->second * OPT->_maxResC1;
322 }
323 for (it = phaseCoeff.begin(); it != phaseCoeff.end(); it++) {
324 retVal += it->second * OPT->_maxResL1;
325 }
326
327 return retVal;
328}
329
330
331//
332////////////////////////////////////////////////////////////////////////////
[5819]333t_irc t_pppSatObs::cmpModel(const t_pppStation* station) {
[5743]334
335 // Reset all model values
336 // ----------------------
337 _model.reset();
338
339 // Topocentric Satellite Position
340 // ------------------------------
341 ColumnVector rSat = _xcSat.Rows(1,3);
342 ColumnVector rhoV = rSat - station->xyzApr();
343 _model._rho = rhoV.norm_Frobenius();
344
345 ColumnVector neu(3);
346 xyz2neu(station->ellApr().data(), rhoV.data(), neu.data());
347
348 _model._eleSat = acos( sqrt(neu[0]*neu[0] + neu[1]*neu[1]) / _model._rho );
349 if (neu[2] < 0) {
350 _model._eleSat *= -1.0;
351 }
352 _model._azSat = atan2(neu[1], neu[0]);
353
354 // Satellite Clocks
355 // ----------------
[5750]356 _model._satClkM = _xcSat[3] * t_CST::c;
[5743]357
358 // Receiver Clocks
359 // ---------------
[5750]360 _model._recClkM = station->dClk() * t_CST::c;
[5743]361
362 // Sagnac Effect (correction due to Earth rotation)
363 // ------------------------------------------------
364 ColumnVector Omega(3);
365 Omega[0] = 0.0;
366 Omega[1] = 0.0;
[5750]367 Omega[2] = t_CST::omega / t_CST::c;
[5743]368 _model._sagnac = DotProduct(Omega, crossproduct(rSat, station->xyzApr()));
369
370 // Antenna Eccentricity
371 // --------------------
372 _model._antEcc = -DotProduct(station->xyzEcc(), rhoV) / _model._rho;
373
374 // Antenna Phase Center Offsets and Variations
375 // -------------------------------------------
376 if (PPP_CLIENT->antex()) {
377 bool found;
[6030]378 double pco = PPP_CLIENT->antex()->rcvCorr(station->antName(), _model._eleSat, found);
379 for (unsigned ii = 0; ii < t_frequency::max; ii++) {
380 _model._antPCO[ii] = pco;
381 }
[5743]382 }
383
384 // Tropospheric Delay
385 // ------------------
[5829]386 _model._tropo = t_tropo::delay_saast(station->xyzApr(), _model._eleSat);
[5743]387
388 // Phase Wind-Up
389 // -------------
390 _model._windUp = station->windUp(_time, _prn, rSat);
391
[6030]392 // Code and Phase Biases
393 // ---------------------
[5827]394 const t_satBias* satBias = PPP_CLIENT->obsPool()->satBias(_prn);
[5743]395 if (satBias) {
[5827]396 for (unsigned ii = 0; ii < satBias->_bias.size(); ii++) {
397 const t_frqBias& bias = satBias->_bias[ii];
[6030]398 for (unsigned iFreq = 1; iFreq < t_frequency::max; iFreq++) {
399 const t_frqObs* obs = _obs[iFreq];
400 if (obs && obs->_rnxType2ch == bias._rnxType2ch) {
401 _model._codeBias[iFreq] = bias._code;
402 _model._phaseBias[iFreq] = bias._phase;
[5743]403 }
404 }
405 }
406 }
407
408 // Tidal Correction
409 // ----------------
410 _model._tide = -DotProduct(station->tideDspl(), rhoV) / _model._rho;
411
412 // Ionospheric Delay
413 // -----------------
414 // TODO
415
416 // Ocean Loading
417 // -------------
418 // TODO
419
420 // Set Model Set Flag
421 // ------------------
422 _model._set = true;
423
[5750]424 return success;
[5743]425}
426
427//
428////////////////////////////////////////////////////////////////////////////
[5819]429void t_pppSatObs::printModel() const {
[5743]430 LOG.setf(ios::fixed);
431 LOG << "MODEL for Satellite " << _prn.toString() << endl
[6030]432 << "RHO: " << setw(12) << setprecision(3) << _model._rho << endl
433 << "ELE: " << setw(12) << setprecision(3) << _model._eleSat * 180.0 / M_PI << endl
434 << "AZI: " << setw(12) << setprecision(3) << _model._azSat * 180.0 / M_PI << endl
435 << "SATCLK: " << setw(12) << setprecision(3) << _model._satClkM << endl
436 << "RECCLK: " << setw(12) << setprecision(3) << _model._recClkM << endl
437 << "SAGNAC: " << setw(12) << setprecision(3) << _model._sagnac << endl
438 << "ANTECC: " << setw(12) << setprecision(3) << _model._antEcc << endl
439 << "TROPO: " << setw(12) << setprecision(3) << _model._tropo << endl
440 << "WINDUP: " << setw(12) << setprecision(3) << _model._windUp << endl
441 << "TIDES: " << setw(12) << setprecision(3) << _model._tide << endl;
442 for (unsigned iFreq = 1; iFreq < t_frequency::max; iFreq++) {
443 if (_obs[iFreq]) {
444 LOG << "PCO: " << t_frequency::toString(t_frequency::type(iFreq)) << setw(12) << setprecision(3) << _model._antPCO[iFreq] << endl
445 << "BIAS CODE: " << t_frequency::toString(t_frequency::type(iFreq)) << setw(12) << setprecision(3) << _model._codeBias[iFreq] << endl
446 << "BIAS PHASE: " << t_frequency::toString(t_frequency::type(iFreq)) << setw(12) << setprecision(3) << _model._phaseBias[iFreq] << endl;
447 }
448 }
[5743]449 LOG << "OBS-CMP P3: " << _prn.toString() << " "
450 << setw(12) << setprecision(3) << obsValue(t_lc::cIF) << " "
451 << setw(12) << setprecision(3) << cmpValue(t_lc::cIF) << " "
452 << setw(12) << setprecision(3) << obsValue(t_lc::cIF) - cmpValue(t_lc::cIF) << endl;
453
454 LOG << "OBS-CMP L3: " << _prn.toString() << " "
455 << setw(12) << setprecision(3) << obsValue(t_lc::lIF) << " "
456 << setw(12) << setprecision(3) << cmpValue(t_lc::lIF) << " "
457 << setw(12) << setprecision(3) << obsValue(t_lc::lIF) - cmpValue(t_lc::lIF) << endl;
458
459 LOG << "OBS-CMP MW: " << _prn.toString() << " "
460 << setw(12) << setprecision(3) << obsValue(t_lc::MW) << " "
461 << setw(12) << setprecision(3) << cmpValue(t_lc::MW) << " "
462 << setw(12) << setprecision(3) << obsValue(t_lc::MW) - cmpValue(t_lc::MW) << endl;
463}
464
465//
466////////////////////////////////////////////////////////////////////////////
[5819]467double t_pppSatObs::cmpValueForBanc(t_lc::type tLC) const {
[5743]468 return cmpValue(tLC) - _model._rho - _model._sagnac - _model._recClkM;
469}
470
471//
472////////////////////////////////////////////////////////////////////////////
[5819]473double t_pppSatObs::cmpValue(t_lc::type tLC) const {
[5743]474
[6031]475 if (!isValid(tLC)) {
[5743]476 return 0.0;
477 }
478
479 // Non-Dispersive Part
480 // -------------------
481 double nonDisp = _model._rho + _model._recClkM - _model._satClkM
482 + _model._sagnac + _model._antEcc + _model._tropo
483 + _model._tide;
484
485 // Add Dispersive Part
486 // -------------------
[6031]487 map<t_frequency::type, double> codeCoeff;
488 map<t_frequency::type, double> phaseCoeff;
489 lcCoeff(tLC, codeCoeff, phaseCoeff);
[5743]490
[6031]491 double dispPart = 0.0;
492
493 map<t_frequency::type, double>::const_iterator it;
494 for (it = codeCoeff.begin(); it != codeCoeff.end(); it++) {
495 t_frequency::type tFreq = it->first;
496 dispPart += it->second * (_model._antPCO[tFreq] + _model._codeBias[tFreq]);
497 }
498 for (it = phaseCoeff.begin(); it != phaseCoeff.end(); it++) {
499 t_frequency::type tFreq = it->first;
[6032]500 dispPart += it->second * (_model._antPCO[tFreq] + _model._phaseBias[tFreq] +
501 _model._windUp * t_CST::lambda(tFreq, _channel));
[6031]502 }
503
504 return nonDisp + dispPart;
[5743]505}
506
507//
508////////////////////////////////////////////////////////////////////////////
[5819]509void t_pppSatObs::setRes(t_lc::type tLC, double res) {
[5743]510 _res[tLC] = res;
511}
512
513//
514////////////////////////////////////////////////////////////////////////////
[5819]515double t_pppSatObs::getRes(t_lc::type tLC) const {
[5743]516 map<t_lc::type, double>::const_iterator it = _res.find(tLC);
517 if (it != _res.end()) {
518 return it->second;
519 }
520 else {
521 return 0.0;
522 }
523}
Note: See TracBrowser for help on using the repository browser.