source: ntrip/trunk/BNC/src/PPP/pppFilter.cpp@ 10257

Last change on this file since 10257 was 10257, checked in by stuerze, 10 months ago

changes regarding PPP

  • Property svn:keywords set to Author Date Id Rev URL;svn:eol-style=native
  • Property svn:mime-type set to text/plain
File size: 17.3 KB
RevLine 
[7237]1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: t_pppFilter
6 *
7 * Purpose: Filter Adjustment
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Jul-2014
12 *
[7267]13 * Changes:
[7237]14 *
15 * -----------------------------------------------------------------------*/
16
17#include <iostream>
18#include <iomanip>
19#include <cmath>
20#include <newmat.h>
21#include <newmatio.h>
22#include <newmatap.h>
23
24#include "pppFilter.h"
25#include "bncutils.h"
26#include "pppParlist.h"
27#include "pppObsPool.h"
28#include "pppStation.h"
[10034]29#include "pppClient.h"
[7237]30
31using namespace BNC_PPP;
32using namespace std;
33
34// Constructor
35////////////////////////////////////////////////////////////////////////////
[10034]36t_pppFilter::t_pppFilter() {
37 _parlist = 0;
[7237]38}
39
40// Destructor
41////////////////////////////////////////////////////////////////////////////
42t_pppFilter::~t_pppFilter() {
[10034]43 delete _parlist;
[7237]44}
45
46// Process Single Epoch
47////////////////////////////////////////////////////////////////////////////
[10034]48t_irc t_pppFilter::processEpoch(t_pppObsPool* obsPool) {
49
[9642]50 _numSat = 0;
[7302]51 const double maxSolGap = 60.0;
[10028]52 bool setNeuNoiseToZero = false;
[7237]53
[10034]54 if (!_parlist) {
55 _parlist = new t_pppParlist();
[10028]56 }
57
[7237]58 // Vector of all Observations
59 // --------------------------
[10034]60 t_pppObsPool::t_epoch *epoch = obsPool->lastEpoch();
[7237]61 if (!epoch) {
62 return failure;
63 }
[9642]64 vector<t_pppSatObs*> &allObs = epoch->obsVector();
[7237]65
66 // Time of the Epoch
67 // -----------------
68 _epoTime = epoch->epoTime();
69
[10015]70 if (!_firstEpoTime.valid() ||
71 !_lastEpoTimeOK.valid()||
72 (maxSolGap > 0.0 && _epoTime - _lastEpoTimeOK > maxSolGap)) {
[7237]73 _firstEpoTime = _epoTime;
74 }
75
[7267]76 string epoTimeStr = string(_epoTime);
77
[10034]78 const QList<char> &usedSystems = _parlist->usedSystems();
[10015]79
[7237]80 // Set Parameters
[10034]81 // --------------
82 if (_parlist->set(_epoTime, allObs) != success) {
[9419]83 return failure;
84 }
[10028]85
[7237]86 // Status Vector, Variance-Covariance Matrix
87 // -----------------------------------------
[10256]88 ColumnVector xFltOld = _xFlt;
89 SymmetricMatrix QFltOld = _QFlt;
90 setStateVectorAndVarCovMatrix(xFltOld, QFltOld, setNeuNoiseToZero);
[8956]91
[7237]92 // Process Satellite Systems separately
93 // ------------------------------------
[9431]94 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
95 char sys = usedSystems[iSys];
[7267]96 unsigned int num = 0;
[7237]97 vector<t_pppSatObs*> obsVector;
98 for (unsigned jj = 0; jj < allObs.size(); jj++) {
[9419]99 if (allObs[jj]->prn().system() == sys) {
[7237]100 obsVector.push_back(allObs[jj]);
[10034]101 num++;
[7237]102 }
103 }
[10034]104 LOG << epoTimeStr << " SATNUM " << sys << ' ' << right << setw(2) << num << endl;
105 if (processSystem(OPT->LCs(sys), obsVector, epoch->pseudoObsIono()) != success) {
[10220]106 LOG << "t_pppFilter::processSystem() != success: " << sys << endl;
[7237]107 return failure;
108 }
109 }
[8912]110
111 // close epoch processing
112 // ----------------------
[10034]113 cmpDOP(allObs);
114 _parlist->printResult(_epoTime, _QFlt, _xFlt);
[9642]115 _lastEpoTimeOK = _epoTime; // remember time of last successful epoch processing
[7237]116 return success;
117}
118
119// Process Selected LCs
120////////////////////////////////////////////////////////////////////////////
[9642]121t_irc t_pppFilter::processSystem(const vector<t_lc::type> &LCs,
[10034]122 const vector<t_pppSatObs*> &obsVector,
123 bool pseudoObsIonoAvailable) {
[7237]124 LOG.setf(ios::fixed);
125
126 // Detect Cycle Slips
127 // ------------------
[10034]128 if (detectCycleSlips(LCs, obsVector) != success) {
[7237]129 return failure;
130 }
131
[10034]132 ColumnVector xSav = _xFlt;
[9642]133 SymmetricMatrix QSav = _QFlt;
[10034]134 string epoTimeStr = string(_epoTime);
135 const vector<t_pppParam*> &params = _parlist->params();
136 unsigned nPar = _parlist->nPar();
[8965]137
[9642]138 unsigned usedLCs = LCs.size();
[8965]139 if (OPT->_pseudoObsIono && !pseudoObsIonoAvailable) {
[9642]140 usedLCs -= 1; // GIM not used
[8961]141 }
142 // max Obs
[9538]143 unsigned maxObs = obsVector.size() * usedLCs;
144
[7237]145 // Outlier Detection Loop
146 // ----------------------
147 for (unsigned iOutlier = 0; iOutlier < maxObs; iOutlier++) {
148
149 if (iOutlier > 0) {
150 _xFlt = xSav;
151 _QFlt = QSav;
152 }
153
154 // First-Design Matrix, Terms Observed-Computed, Weight Matrix
155 // -----------------------------------------------------------
[9642]156 Matrix AA(maxObs, nPar);
[10034]157 ColumnVector ll(maxObs); ll = 0.0;
158 DiagonalMatrix PP(maxObs); PP = 0.0;
[8912]159
[7237]160 int iObs = -1;
161 vector<t_pppSatObs*> usedObs;
[9642]162 vector<t_lc::type> usedTypes;
[9386]163
164 // Real Observations
165 // =================
[10184]166 int nSat = 0;
[7237]167 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[9642]168 t_pppSatObs *obs = obsVector[ii];
[10256]169 char sys = obs->prn().system();
[10034]170 if (iOutlier == 0) {
[9419]171 obs->resetOutlier();
172 }
[7237]173 if (!obs->outlier()) {
[9583]174 nSat++;
[8905]175 for (unsigned jj = 0; jj < usedLCs; jj++) {
[7237]176 const t_lc::type tLC = LCs[jj];
[9642]177 if (tLC == t_lc::GIM) {
178 continue;
179 }
[7237]180 ++iObs;
181 usedObs.push_back(obs);
182 usedTypes.push_back(tLC);
[9524]183 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[9642]184 const t_pppParam *par = params[iPar];
[10034]185 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC);
[7237]186 }
[10256]187 double offGlo = 0;
188 if (sys == 'R' && tLC != t_lc::MW) {
189 offGlo = PPP_CLIENT->offGlo();
190 }
191 double offGal = 0;
192 if (sys == 'E' && tLC != t_lc::MW) {
193 offGal = PPP_CLIENT->offGal();
194 }
195 double offBds = 0;
196 if (sys == 'C' && tLC != t_lc::MW) {
197 offBds = PPP_CLIENT->offBds();
198 }
199 ll[iObs] = obs->obsValue(tLC) - offGlo - offGal - offBds - obs->cmpValue(tLC) - DotProduct(_x0, AA.Row(iObs + 1));
[7237]200 PP[iObs] = 1.0 / (obs->sigma(tLC) * obs->sigma(tLC));
201 }
202 }
203 }
204
[9556]205 // Check number of observations
206 // ----------------------------
[10257]207 if (!nSat) {
[9701]208 return failure;
[9699]209 }
[9625]210
[9386]211 // Pseudo Obs Iono
212 // ================
213 if (OPT->_pseudoObsIono && pseudoObsIonoAvailable) {
214 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[9642]215 t_pppSatObs *obs = obsVector[ii];
[10256]216 char sys = obs->prn().system();
[9386]217 if (!obs->outlier()) {
218 for (unsigned jj = 0; jj < usedLCs; jj++) {
219 const t_lc::type tLC = LCs[jj];
[10034]220 if (tLC == t_lc::GIM) {
[9386]221 ++iObs;
[9642]222 } else {
223 continue;
224 }
[9386]225 usedObs.push_back(obs);
226 usedTypes.push_back(tLC);
[9524]227 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[9642]228 const t_pppParam *par = params[iPar];
[10034]229 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC);
[9386]230 }
[10256]231 double offGlo = 0;
232 if (sys == 'R' && tLC != t_lc::MW) {
233 offGlo = PPP_CLIENT->offGlo();
234 }
235 double offGal = 0;
236 if (sys == 'E' && tLC != t_lc::MW) {
237 offGal = PPP_CLIENT->offGal();
238 }
239 double offBds = 0;
240 if (sys == 'C' && tLC != t_lc::MW) {
241 offBds = PPP_CLIENT->offBds();
242 }
243 ll[iObs] = obs->obsValue(tLC) - offGlo - offGal - offBds - obs->cmpValue(tLC) - DotProduct(_x0, AA.Row(iObs + 1));
[9386]244 PP[iObs] = 1.0 / (obs->sigma(tLC) * obs->sigma(tLC));
245 }
246 }
[8956]247 }
[8915]248 }
249
[9556]250 // Truncate matrices
251 // -----------------
[9642]252 AA = AA.Rows(1, iObs + 1);
253 ll = ll.Rows(1, iObs + 1);
254 PP = PP.SymSubMatrix(1, iObs + 1);
[7237]255
256 // Kalman update step
257 // ------------------
258 kalman(AA, ll, PP, _QFlt, _xFlt);
259
260 // Check Residuals
261 // ---------------
262 ColumnVector vv = AA * _xFlt - ll;
[9642]263 double maxOutlier = 0.0;
264 int maxOutlierIndex = -1;
265 t_lc::type maxOutlierLC = t_lc::dummy;
[7237]266 for (unsigned ii = 0; ii < usedObs.size(); ii++) {
267 const t_lc::type tLC = usedTypes[ii];
268 double res = fabs(vv[ii]);
269 if (res > usedObs[ii]->maxRes(tLC)) {
270 if (res > fabs(maxOutlier)) {
[9642]271 maxOutlier = vv[ii];
[7237]272 maxOutlierIndex = ii;
[9642]273 maxOutlierLC = tLC;
[7237]274 }
275 }
276 }
277
278 // Mark outlier or break outlier detection loop
279 // --------------------------------------------
280 if (maxOutlierIndex > -1) {
[9642]281 t_pppSatObs *obs = usedObs[maxOutlierIndex];
282 t_pppParam *par = 0;
[10034]283 LOG << epoTimeStr << " Outlier " << t_lc::toString(maxOutlierLC) << ' '
284 << obs->prn().toString() << ' ' << setw(8) << setprecision(4)
285 << maxOutlier << endl;
[9524]286 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[9642]287 t_pppParam *hlp = params[iPar];
[10008]288 if (hlp->type() == t_pppParam::amb &&
[10034]289 hlp->prn() == obs->prn() &&
290 hlp->tLC() == usedTypes[maxOutlierIndex]) {
[7237]291 par = hlp;
292 }
293 }
[10034]294 if (par) {
[10253]295// if (par->ambResetCandidate()) {
[10248]296 resetAmb(obs->prn(), obsVector, maxOutlierLC, &QSav, &xSav);
[10253]297// }
298// else {
299// par->setAmbResetCandidate();
300// obs->setOutlier();
301// }
[10021]302 }
[10034]303 else {
304 obs->setOutlier();
[7237]305 }
306 }
307 // Print Residuals
308 // ---------------
309 else {
[8905]310 for (unsigned jj = 0; jj < LCs.size(); jj++) {
311 for (unsigned ii = 0; ii < usedObs.size(); ii++) {
312 const t_lc::type tLC = usedTypes[ii];
[9642]313 t_pppSatObs *obs = usedObs[ii];
[8905]314 if (tLC == LCs[jj]) {
315 obs->setRes(tLC, vv[ii]);
[9642]316 LOG << epoTimeStr << " RES " << left << setw(3)
[9699]317 << t_lc::toString(tLC) << right << ' '
[10034]318 << obs->prn().toString() << ' '
319 << setw(8) << setprecision(4) << vv[ii] << endl;
[7237]320 }
321 }
322 }
323 break;
324 }
325 }
326 return success;
327}
328
329// Cycle-Slip Detection
330////////////////////////////////////////////////////////////////////////////
[9642]331t_irc t_pppFilter::detectCycleSlips(const vector<t_lc::type> &LCs,
[10034]332 const vector<t_pppSatObs*> &obsVector) {
333
[10256]334 const double SLIP = 20.0;
[9386]335 string epoTimeStr = string(_epoTime);
[10034]336 const vector<t_pppParam*> &params = _parlist->params();
[7237]337
338 for (unsigned ii = 0; ii < LCs.size(); ii++) {
[9642]339 const t_lc::type &tLC = LCs[ii];
[7237]340 if (t_lc::includesPhase(tLC)) {
341 for (unsigned iObs = 0; iObs < obsVector.size(); iObs++) {
[9642]342 const t_pppSatObs *obs = obsVector[iObs];
[10256]343 char sys = obs->prn().system();
[7237]344
[7267]345 // Check set Slips and Jump Counters
[7237]346 // ---------------------------------
347 bool slip = false;
[9386]348
[7237]349 if (obs->slip()) {
[10034]350 LOG << epoTimeStr << "cycle slip set (obs) " << obs->prn().toString() << endl;
[7237]351 slip = true;
352 }
353
[10034]354 if (_slips[obs->prn()]._obsSlipCounter != -1 &&
355 _slips[obs->prn()]._obsSlipCounter != obs->slipCounter()) {
356 LOG << epoTimeStr << "cycle slip set (obsSlipCounter) " << obs->prn().toString() << endl;
[7237]357 slip = true;
358 }
[10034]359 _slips[obs->prn()]._obsSlipCounter = obs->slipCounter();
360
361 if (_slips[obs->prn()]._biasJumpCounter != -1 &&
362 _slips[obs->prn()]._biasJumpCounter != obs->biasJumpCounter()) {
363 LOG << epoTimeStr << "cycle slip set (biasJumpCounter) " << obs->prn().toString() << endl;
[7237]364 slip = true;
365 }
[10034]366 _slips[obs->prn()]._biasJumpCounter = obs->biasJumpCounter();
367
[7237]368 // Slip Set
[7267]369 // --------
[7237]370 if (slip) {
[10034]371 resetAmb(obs->prn(), obsVector, tLC);
[7237]372 }
[10034]373
[10256]374 // Check Pre-Fit Residuals => switched off, because after a millisecond receiver clock jump, a cycle slip is detected for all satellites
375 /* -----------------------
376
[7237]377 else {
[10034]378 ColumnVector AA(params.size());
379 for (unsigned iPar = 0; iPar < params.size(); iPar++) {
380 const t_pppParam* par = params[iPar];
381 AA[iPar] = par->partial(_epoTime, obs, tLC);
[7237]382 }
[10256]383 double offGlo = 0;
384 if (sys == 'R' && tLC != t_lc::MW) {
385 offGlo = PPP_CLIENT->offGlo();
386 }
387 double offGal = 0;
388 if (sys == 'E' && tLC != t_lc::MW) {
389 offGal = PPP_CLIENT->offGal();
390 }
391 double offBds = 0;
392 if (sys == 'C' && tLC != t_lc::MW) {
393 offBds = PPP_CLIENT->offBds();
394 }
395 double ll = obs->obsValue(tLC) - offGlo - offGal - offBds - obs->cmpValue(tLC) - DotProduct(_x0, AA);
[10034]396 double vv = DotProduct(AA, _xFlt) - ll;
397
398 if (fabs(vv) > SLIP) {
399 LOG << epoTimeStr << " cycle slip detected " << t_lc::toString(tLC) << ' '
400 << obs->prn().toString() << ' ' << setw(8) << setprecision(4) << vv << endl;
401 resetAmb(obs->prn(), obsVector, tLC);
402 }
[10256]403 }*/
[7237]404 }
405 }
406 }
[10034]407
[7237]408 return success;
409}
410
411// Reset Ambiguity Parameter (cycle slip)
412////////////////////////////////////////////////////////////////////////////
[10248]413t_irc t_pppFilter::resetAmb(const t_prn prn, const vector<t_pppSatObs*> &obsVector, t_lc::type lc,
414 SymmetricMatrix *QSav, ColumnVector *xSav) {
[8965]415
[7237]416 t_irc irc = failure;
[10034]417 vector<t_pppParam*>& params = _parlist->params();
[7237]418 for (unsigned iPar = 0; iPar < params.size(); iPar++) {
[9642]419 t_pppParam *par = params[iPar];
[7237]420 if (par->type() == t_pppParam::amb && par->prn() == prn) {
[10249]421 int ind = par->indexNew();
422 double eleSat = par->ambEleSat();
[10156]423 bncTime firstObsTime;
424 bncTime lastObsTime = par->lastObsTime();
[10249]425 (par->firstObsTime().undef()) ?
426 firstObsTime = lastObsTime : firstObsTime = par->firstObsTime();
[7237]427 t_lc::type tLC = par->tLC();
[10184]428 if (tLC != lc) {continue;}
[7237]429 LOG << string(_epoTime) << " RESET " << par->toString() << endl;
[10034]430 delete par; par = new t_pppParam(t_pppParam::amb, prn, tLC, &obsVector);
[7237]431 par->setIndex(ind);
[10156]432 par->setFirstObsTime(firstObsTime);
433 par->setLastObsTime(lastObsTime);
[10248]434 par->setAmbEleSat(eleSat);
[7237]435 params[iPar] = par;
436 for (unsigned ii = 1; ii <= params.size(); ii++) {
[9642]437 _QFlt(ii, ind + 1) = 0.0;
[7237]438 if (QSav) {
[10250]439 (*QSav)(ii, ind + 1) = 0.0;
[7237]440 }
441 }
[9642]442 _QFlt(ind + 1, ind + 1) = par->sigma0() * par->sigma0();
[7237]443 if (QSav) {
[9642]444 (*QSav)(ind + 1, ind + 1) = _QFlt(ind + 1, ind + 1);
[7237]445 }
446 _xFlt[ind] = 0.0;
447 if (xSav) {
448 (*xSav)[ind] = _xFlt[ind];
449 }
450 _x0[ind] = par->x0();
[10256]451 irc = success;
[7237]452 }
453 }
454
455 return irc;
456}
457
458// Compute various DOP Values
459////////////////////////////////////////////////////////////////////////////
[10034]460void t_pppFilter::cmpDOP(const vector<t_pppSatObs*> &obsVector) {
[7237]461
462 _dop.reset();
463
464 try {
465 const unsigned numPar = 4;
466 Matrix AA(obsVector.size(), numPar);
467 _numSat = 0;
468 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[9642]469 t_pppSatObs *obs = obsVector[ii];
[7237]470 if (obs->isValid() && !obs->outlier()) {
471 ++_numSat;
472 for (unsigned iPar = 0; iPar < numPar; iPar++) {
[10034]473 const t_pppParam* par = _parlist->params()[iPar];
474 AA[_numSat - 1][iPar] = par->partial(_epoTime, obs, t_lc::c1);
[7237]475 }
476 }
477 }
478 if (_numSat < 4) {
479 return;
480 }
481 AA = AA.Rows(1, _numSat);
[10034]482 SymmetricMatrix NN; NN << AA.t() * AA;
[7237]483 SymmetricMatrix QQ = NN.i();
[7267]484
[9642]485 _dop.H = sqrt(QQ(1, 1) + QQ(2, 2));
486 _dop.V = sqrt(QQ(3, 3));
487 _dop.P = sqrt(QQ(1, 1) + QQ(2, 2) + QQ(3, 3));
488 _dop.T = sqrt(QQ(4, 4));
489 _dop.G = sqrt(QQ(1, 1) + QQ(2, 2) + QQ(3, 3) + QQ(4, 4));
[7237]490 }
[10034]491 catch (...) {
492 }
[7237]493}
494
[9526]495//
[7237]496////////////////////////////////////////////////////////////////////////////
[10256]497void t_pppFilter::predictCovCrdPart(const SymmetricMatrix &QFltOld, bool setNeuNoiseToZero) {
[7237]498
[10034]499 const vector<t_pppParam*>& params = _parlist->params();
500
[7237]501 if (params.size() < 3) {
502 return;
503 }
504
505 bool first = (params[0]->indexOld() < 0);
506
[10034]507 SymmetricMatrix Qneu(3); Qneu = 0.0;
[7237]508 for (unsigned ii = 0; ii < 3; ii++) {
[9642]509 const t_pppParam *par = params[ii];
[7237]510 if (first) {
511 Qneu[ii][ii] = par->sigma0() * par->sigma0();
[10034]512 }
513 else {
[7237]514 Qneu[ii][ii] = par->noise() * par->noise();
515 }
516 }
517
[9642]518 const t_pppStation *sta = PPP_CLIENT->staRover();
[7237]519 SymmetricMatrix Qxyz(3);
520 covariNEU_XYZ(Qneu, sta->ellApr().data(), Qxyz);
521
522 if (first) {
[9642]523 _QFlt.SymSubMatrix(1, 3) = Qxyz;
[10034]524 }
525 else {
[7237]526 double dt = _epoTime - _firstEpoTime;
[10010]527 if (dt < OPT->_seedingTime || setNeuNoiseToZero) {
[10256]528 _QFlt.SymSubMatrix(1, 3) = QFltOld.SymSubMatrix(1, 3);
[10034]529 }
530 else {
[10256]531 _QFlt.SymSubMatrix(1, 3) = QFltOld.SymSubMatrix(1, 3) + Qxyz;
[7237]532 }
533 }
534}
[8912]535
[9526]536//
537////////////////////////////////////////////////////////////////////////////
[10256]538void t_pppFilter::setStateVectorAndVarCovMatrix(const ColumnVector &xFltOld,
539 const SymmetricMatrix &QFltOld,
540 bool setNeuNoiseToZero) {
[9526]541
[10034]542 const vector<t_pppParam*>& params = _parlist->params();
[9526]543 unsigned nPar = params.size();
544
[10034]545 _QFlt.ReSize(nPar); _QFlt = 0.0;
546 _xFlt.ReSize(nPar); _xFlt = 0.0;
547 _x0.ReSize(nPar); _x0 = 0.0;
[9526]548
549 for (unsigned ii = 0; ii < nPar; ii++) {
[9642]550 t_pppParam *par1 = params[ii];
[10256]551 if (QFltOld.size() == 0) {
[9526]552 par1->resetIndex();
553 }
554 _x0[ii] = par1->x0();
555 int iOld = par1->indexOld();
556 if (iOld < 0) {
557 _QFlt[ii][ii] = par1->sigma0() * par1->sigma0(); // new parameter
[9642]558 } else {
[10256]559 _QFlt[ii][ii] = QFltOld[iOld][iOld] + par1->noise() * par1->noise();
560 _xFlt[ii] = xFltOld[iOld];
[9526]561 for (unsigned jj = 0; jj < ii; jj++) {
[9642]562 t_pppParam *par2 = params[jj];
563 int jOld = par2->indexOld();
[9526]564 if (jOld >= 0) {
[10256]565 _QFlt[ii][jj] = QFltOld(iOld + 1, jOld + 1);
[9526]566 }
567 }
568 }
569 }
[10256]570 predictCovCrdPart(QFltOld, setNeuNoiseToZero);
[9526]571}
572
Note: See TracBrowser for help on using the repository browser.