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

Last change on this file since 9527 was 9527, checked in by stuerze, 2 years ago

update 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: 29.0 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"
29
30using namespace BNC_PPP;
31using namespace std;
32
33// Constructor
34////////////////////////////////////////////////////////////////////////////
[8905]35t_pppFilter::t_pppFilter(t_pppObsPool* obsPool) {
36 _numSat = 0;
37 _obsPool = obsPool;
[8910]38 _refPrn = t_prn();
[8915]39 _datumTrafo = new t_datumTrafo();
[7237]40}
41
42// Destructor
43////////////////////////////////////////////////////////////////////////////
44t_pppFilter::~t_pppFilter() {
[8915]45 delete _datumTrafo;
[7237]46}
47
48// Process Single Epoch
49////////////////////////////////////////////////////////////////////////////
[9386]50t_irc t_pppFilter::processEpoch() {
[7237]51 _numSat = 0;
[7302]52 const double maxSolGap = 60.0;
[7237]53
54 // Vector of all Observations
55 // --------------------------
[8905]56 t_pppObsPool::t_epoch* epoch = _obsPool->lastEpoch();
[7237]57 if (!epoch) {
58 return failure;
59 }
60 vector<t_pppSatObs*>& allObs = epoch->obsVector();
61
62 // Time of the Epoch
63 // -----------------
64 _epoTime = epoch->epoTime();
65
[7302]66 if (!_firstEpoTime.valid() ||
67 !_lastEpoTimeOK.valid() ||
68 (maxSolGap > 0.0 && _epoTime - _lastEpoTimeOK > maxSolGap)) {
[7237]69 _firstEpoTime = _epoTime;
70 }
71
[7267]72 string epoTimeStr = string(_epoTime);
73
[9508]74 const QMap<char, t_pppRefSat*>& refSatMap = epoch->refSatMap();
[8905]75 //--
[7237]76 // Set Parameters
[9508]77 if (_parlist.set(_epoTime, allObs, refSatMap) != success) {
[9419]78 return failure;
79 }
[9526]80
[9527]81 if (OPT->_obsModelType == OPT->DCMcodeBias ||
82 OPT->_obsModelType == OPT->DCMphaseBias) {
[9386]83#ifdef BNC_DEBUG_PPP
[9527]84 LOG << "processEpoch: printParams after set" << endl;
85 _parlist.printParams(_epoTime);
[9386]86#endif
[9527]87 }
[7237]88 // Status Vector, Variance-Covariance Matrix
89 // -----------------------------------------
90 ColumnVector xFltOld = _xFlt;
91 SymmetricMatrix QFltOld = _QFlt;
[9526]92 setStateVectorAndVarCovMatrix(xFltOld, QFltOld);
[8956]93
[8905]94 // Pre-Process Satellite Systems separately
95 // ----------------------------------------
96 bool preProcessing = false;
97 if (OPT->_obsModelType == OPT->DCMcodeBias ||
98 OPT->_obsModelType == OPT->DCMphaseBias) {
99 preProcessing = true;
[9504]100 const QList<char>& usedSystems = _parlist.usedSystems();
[9431]101 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
102 char sys = usedSystems[iSys];
[9526]103 _refPrn.set(sys, 0);
104 if (OPT->_refSatRequired) {
105 _refPrn = refSatMap[sys]->prn();
106 }
[9386]107 vector<t_pppSatObs*> obsVector;
[8905]108 for (unsigned jj = 0; jj < allObs.size(); jj++) {
[9386]109 if (allObs[jj]->prn().system() == sys) {
[8905]110 obsVector.push_back(allObs[jj]);
111 }
112 }
[9431]113 if (iSys == 0) {
114 _datumTrafo->setFirstSystem(sys);
[9419]115 }
[9386]116 if (processSystem(OPT->LCs(sys), obsVector, _refPrn,
[8905]117 epoch->pseudoObsIono(), preProcessing) != success) {
[9386]118 _xFlt = xFltOld;
119 _QFlt = QFltOld;
[9527]120 restoreState(2);
[8905]121 return failure;
122 }
123 }
[8956]124 // refSat change required?
125 // -----------------------
126 if (_obsPool->refSatChangeRequired()) {
127 _xFlt = xFltOld;
128 _QFlt = QFltOld;
129 return success;
130 }
[9386]131 else if (!_obsPool->refSatChangeRequired()) {
[9419]132 initDatumTransformation(allObs, epoch->pseudoObsIono());
[8956]133 }
[8905]134 }
135
[7237]136 // Process Satellite Systems separately
137 // ------------------------------------
[8912]138 preProcessing = false;
[9504]139 const QList<char>& usedSystems = _parlist. usedSystems();
[9431]140 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
141 char sys = usedSystems[iSys];
[9526]142 _refPrn.set(sys, 0);
[8910]143 if (OPT->_refSatRequired) {
[9508]144 _refPrn = refSatMap[sys]->prn();
[8910]145 }
[7267]146 unsigned int num = 0;
[7237]147 vector<t_pppSatObs*> obsVector;
148 for (unsigned jj = 0; jj < allObs.size(); jj++) {
[9419]149 if (allObs[jj]->prn().system() == sys) {
[7237]150 obsVector.push_back(allObs[jj]);
[9419]151 ++num;
[7237]152 }
153 }
[9431]154 if (iSys == 0 && OPT->_obsModelType == OPT->UncombPPP) {
155 _datumTrafo->setFirstSystem(sys);
[9419]156 }
157 LOG << epoTimeStr << " SATNUM " << sys << ' ' << right << setw(2) << num << endl;
158 if (processSystem(OPT->LCs(sys), obsVector, _refPrn,
[8905]159 epoch->pseudoObsIono(), preProcessing) != success) {
[7237]160 return failure;
161 }
162 }
[8912]163
164 // close epoch processing
165 // ----------------------
[9508]166 cmpDOP(allObs, refSatMap);
[9504]167 _parlist.printResult(_epoTime, _QFlt, _xFlt);
[8956]168 _lastEpoTimeOK = _epoTime; // remember time of last successful epoch processing
[7237]169 return success;
170}
171
172// Process Selected LCs
173////////////////////////////////////////////////////////////////////////////
[7267]174t_irc t_pppFilter::processSystem(const vector<t_lc::type>& LCs,
[8905]175 const vector<t_pppSatObs*>& obsVector,
176 const t_prn& refPrn,
177 bool pseudoObsIonoAvailable,
178 bool preProcessing) {
[7237]179 LOG.setf(ios::fixed);
[9386]180 char sys = refPrn.system();
[7237]181
182 // Detect Cycle Slips
183 // ------------------
[8905]184 if (detectCycleSlips(LCs, obsVector, refPrn, preProcessing) != success) {
[7237]185 return failure;
186 }
[9398]187 if (preProcessing && _obsPool->refSatChangeRequired(sys)) {
[9386]188 return success;
189 }
[7237]190
[8905]191 ColumnVector xSav = _xFlt;
192 SymmetricMatrix QSav = _QFlt;
193 string epoTimeStr = string(_epoTime);
[9504]194 const vector<t_pppParam*>& params = _parlist.params();
[9524]195 unsigned nPar = _parlist.nPar();
[8965]196
[9386]197 unsigned usedLCs = LCs.size();
[8965]198 if (OPT->_pseudoObsIono && !pseudoObsIonoAvailable) {
[9386]199 usedLCs -= 1; // GIM not used
[8961]200 }
[9386]201 int hlpLCs = 0;
202 if (OPT->_pseudoObsTropo) {
203 hlpLCs = -1;
[8965]204 }
[8961]205 // max Obs
[9386]206 unsigned maxObs = obsVector.size() * (usedLCs + hlpLCs);
[9419]207 if (OPT->_pseudoObsTropo && _datumTrafo->firstSystem(sys)) {
[9386]208 maxObs += 1;
209 }
[8965]210 if (OPT->_pseudoObsIono && pseudoObsIonoAvailable) {
211 maxObs -= 1; // pseudo obs iono with respect to refSat
[8905]212 }
213
[7237]214 // Outlier Detection Loop
215 // ----------------------
216 for (unsigned iOutlier = 0; iOutlier < maxObs; iOutlier++) {
217
218 if (iOutlier > 0) {
219 _xFlt = xSav;
220 _QFlt = QSav;
221 }
222
223 // First-Design Matrix, Terms Observed-Computed, Weight Matrix
224 // -----------------------------------------------------------
[9524]225 Matrix AA(maxObs, nPar);
[7237]226 ColumnVector ll(maxObs);
227 DiagonalMatrix PP(maxObs); PP = 0.0;
[8912]228
[7237]229 int iObs = -1;
230 vector<t_pppSatObs*> usedObs;
231 vector<t_lc::type> usedTypes;
[9386]232
233 // Real Observations
234 // =================
[7237]235 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[8956]236 t_pppSatObs* obs = obsVector[ii];
[9419]237 if (iOutlier == 0 && !preProcessing) {
238 obs->resetOutlier();
239 }
[7237]240 if (!obs->outlier()) {
[8905]241 for (unsigned jj = 0; jj < usedLCs; jj++) {
[7237]242 const t_lc::type tLC = LCs[jj];
[9386]243 if (tLC == t_lc::GIM) {continue;}
244 if (tLC == t_lc::Tz0) {continue;}
[7237]245 ++iObs;
246 usedObs.push_back(obs);
247 usedTypes.push_back(tLC);
[9524]248 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[7237]249 const t_pppParam* par = params[iPar];
[8956]250 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC, refPrn);
[7237]251 }
252 ll[iObs] = obs->obsValue(tLC) - obs->cmpValue(tLC) - DotProduct(_x0, AA.Row(iObs+1));
253 PP[iObs] = 1.0 / (obs->sigma(tLC) * obs->sigma(tLC));
254 }
255 }
256 }
257
[9395]258 // pseudo Obs Tropo
259 // ================
[9419]260 if (OPT->_pseudoObsTropo && _datumTrafo->firstSystem(sys)) {
[9421]261 bool _pseudoObsTropoConsidered = false;
[9395]262 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[9421]263 if (_pseudoObsTropoConsidered) {break;}
[9395]264 t_pppSatObs* obs = obsVector[ii];
265 for (unsigned jj = 0; jj < usedLCs; jj++) {
266 const t_lc::type tLC = LCs[jj];
267 if (tLC != t_lc::Tz0) {continue;}
268 ++iObs;
[9421]269 _pseudoObsTropoConsidered = true;
[9395]270 usedObs.push_back(obs);
271 usedTypes.push_back(tLC);
[9524]272 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[9395]273 const t_pppParam* par = params[iPar];
274 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC, refPrn);
275 }
276 ll[iObs] = obs->obsValue(tLC) - obs->cmpValue(tLC) - DotProduct(_x0, AA.Row(iObs+1));
277 PP[iObs] = 1.0 / (obs->sigma(tLC) * obs->sigma(tLC));
278 }
279 }
280 }
281
[9386]282 if ((!iOutlier) &&
283 (OPT->_obsModelType == OPT->DCMcodeBias ||
[9419]284 OPT->_obsModelType == OPT->DCMphaseBias) &&
285 (!preProcessing)) {
286 _datumTrafo->updateIndices(sys, iObs+1);
[9504]287 _datumTrafo->prepareAA(AA.SubMatrix(1, iObs+1 , 1, _parlist.nPar()), 1);
[9386]288 }
289
290 // Pseudo Obs Iono
291 // ================
292 if (OPT->_pseudoObsIono && pseudoObsIonoAvailable) {
293 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
294 t_pppSatObs* obs = obsVector[ii];
295 if (!obs->outlier()) {
296 for (unsigned jj = 0; jj < usedLCs; jj++) {
297 const t_lc::type tLC = LCs[jj];
298 if (tLC == t_lc::GIM && !obs->isReference()) {
299 ++iObs;
300 } else {continue;}
301 usedObs.push_back(obs);
302 usedTypes.push_back(tLC);
[9524]303 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[9386]304 const t_pppParam* par = params[iPar];
305 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC, refPrn);
306 }
307 ll[iObs] = obs->obsValue(tLC) - obs->cmpValue(tLC) - DotProduct(_x0, AA.Row(iObs+1));
308 PP[iObs] = 1.0 / (obs->sigma(tLC) * obs->sigma(tLC));
309 }
310 }
[8956]311 }
[8915]312 }
313
[7237]314 // Check number of observations, truncate matrices
315 // -----------------------------------------------
316 if (iObs == -1) {
317 return failure;
318 }
319 AA = AA.Rows(1, iObs+1);
320 ll = ll.Rows(1, iObs+1);
321 PP = PP.SymSubMatrix(1, iObs+1);
322
323 // Kalman update step
324 // ------------------
325 kalman(AA, ll, PP, _QFlt, _xFlt);
326
327 // Check Residuals
328 // ---------------
329 ColumnVector vv = AA * _xFlt - ll;
330 double maxOutlier = 0.0;
331 int maxOutlierIndex = -1;
332 t_lc::type maxOutlierLC = t_lc::dummy;
333 for (unsigned ii = 0; ii < usedObs.size(); ii++) {
334 const t_lc::type tLC = usedTypes[ii];
335 double res = fabs(vv[ii]);
336 if (res > usedObs[ii]->maxRes(tLC)) {
337 if (res > fabs(maxOutlier)) {
338 maxOutlier = vv[ii];
339 maxOutlierIndex = ii;
340 maxOutlierLC = tLC;
341 }
342 }
343 }
344
345 // Mark outlier or break outlier detection loop
346 // --------------------------------------------
347 if (maxOutlierIndex > -1) {
348 t_pppSatObs* obs = usedObs[maxOutlierIndex];
349 t_pppParam* par = 0;
[9386]350 LOG << epoTimeStr << " Outlier ("
351 << ((preProcessing) ? "pre-processing) " : "fin-processing) ") << t_lc::toString(maxOutlierLC) << ' '
352 << obs->prn().toString() << ' '
353 << setw(8) << setprecision(4) << maxOutlier << endl;
[9524]354 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[7237]355 t_pppParam* hlp = params[iPar];
[8905]356 if (hlp->type() == t_pppParam::amb &&
357 hlp->prn() == obs->prn() &&
[7237]358 hlp->tLC() == usedTypes[maxOutlierIndex]) {
359 par = hlp;
360 }
361 }
[8956]362 if (preProcessing) {
[9491]363 // for refSats no ambiguity parameter exists
[9386]364 if ((obs->prn() == refPrn) &&
365 (t_lc::toString(maxOutlierLC) == "l1" ||
366 t_lc::toString(maxOutlierLC) == "l2") ) {
367 _obsPool->setRefSatChangeRequired(sys, true);
[9491]368 break;
[9386]369 }
370 else {
371 if (par) {
372 par->setAmbResetCandidate();
373 obs->setOutlier();
374 }
375 else {
376 obs->setOutlier();
377 }
[8905]378 }
379 }
[9386]380 else {// fin-processing
[8956]381 if (par) {
[9386]382 if (par->ambResetCandidate()) {
[8956]383 resetAmb(par->prn(), obsVector, &QSav, &xSav);
384 }
385 else {
386 par->setAmbResetCandidate();
387 obs->setOutlier();
388 }
[7237]389 }
390 else {
391 obs->setOutlier();
392 }
393 }
394 }
395 // Print Residuals
396 // ---------------
397 else {
[8905]398 if (!preProcessing) {
399 for (unsigned jj = 0; jj < LCs.size(); jj++) {
400 for (unsigned ii = 0; ii < usedObs.size(); ii++) {
401 const t_lc::type tLC = usedTypes[ii];
[9386]402 t_pppSatObs* obs = usedObs[ii];
[8905]403 if (tLC == LCs[jj]) {
404 obs->setRes(tLC, vv[ii]);
405 LOG << epoTimeStr << " RES "
[9386]406 << left << setw(3) << t_lc::toString(tLC) << right << ' ';
407 if (t_lc::toString(tLC) == "Tz0") {LOG << sys << " ";}
408 else {LOG << obs->prn().toString();}
[9435]409 LOG << setw(9) << setprecision(4) << vv[ii] << endl;
[8905]410 }
[7237]411 }
412 }
413 }
414 break;
415 }
416 }
417 return success;
418}
419
420// Cycle-Slip Detection
421////////////////////////////////////////////////////////////////////////////
[7267]422t_irc t_pppFilter::detectCycleSlips(const vector<t_lc::type>& LCs,
[8905]423 const vector<t_pppSatObs*>& obsVector,
424 const t_prn& refPrn,
425 bool preProcessing) {
[9386]426 const double SLIP = 20.0;
427 char sys = refPrn.system();
428 string epoTimeStr = string(_epoTime);
[9504]429 const vector<t_pppParam*>& params = _parlist.params();
[9524]430 unsigned nPar = _parlist.nPar();
[7237]431
432 for (unsigned ii = 0; ii < LCs.size(); ii++) {
433 const t_lc::type& tLC = LCs[ii];
434 if (t_lc::includesPhase(tLC)) {
435 for (unsigned iObs = 0; iObs < obsVector.size(); iObs++) {
436 const t_pppSatObs* obs = obsVector[iObs];
437
[7267]438 // Check set Slips and Jump Counters
[7237]439 // ---------------------------------
440 bool slip = false;
[9386]441
442 // in pre-processing only the reference satellite has to be checked
443 if (preProcessing && obs->prn() != refPrn) {
444 continue;
445 }
446
[7237]447 if (obs->slip()) {
[8329]448 LOG << epoTimeStr << "cycle slip set (obs) " << obs->prn().toString() << endl;
[7237]449 slip = true;
450 }
451
452 if (_slips[obs->prn()]._obsSlipCounter != -1 &&
[9088]453 _slips[obs->prn()]._obsSlipCounter != obs->slipCounter()) {
[8329]454 LOG << epoTimeStr << "cycle slip set (obsSlipCounter) " << obs->prn().toString() << endl;
[7237]455 slip = true;
456 }
[8956]457 if (!preProcessing) {
458 _slips[obs->prn()]._obsSlipCounter = obs->slipCounter();
459 }
[7237]460 if (_slips[obs->prn()]._biasJumpCounter != -1 &&
461 _slips[obs->prn()]._biasJumpCounter != obs->biasJumpCounter()) {
[8329]462 LOG << epoTimeStr << "cycle slip set (biasJumpCounter) " << obs->prn().toString() << endl;
[7237]463 slip = true;
464 }
[8956]465 if (!preProcessing) {
466 _slips[obs->prn()]._biasJumpCounter = obs->biasJumpCounter();
467 }
[7237]468 // Slip Set
[7267]469 // --------
[7237]470 if (slip) {
[8905]471 if (preProcessing) {
[9386]472 _obsPool->setRefSatChangeRequired(sys, true);
[8905]473 }
474 else {
475 resetAmb(obs->prn(), obsVector);
476 }
[7237]477 }
478 // Check Pre-Fit Residuals
479 // -----------------------
480 else {
[9419]481 if (refPrn != t_prn()) {return success;}
[9524]482 ColumnVector AA(nPar);
483 for (unsigned iPar = 0; iPar < nPar; iPar++) {
[7237]484 const t_pppParam* par = params[iPar];
[8956]485 AA[iPar] = par->partial(_epoTime, obs, tLC, refPrn);
[7237]486 }
487 double ll = obs->obsValue(tLC) - obs->cmpValue(tLC) - DotProduct(_x0, AA);
488 double vv = DotProduct(AA, _xFlt) - ll;
489 if (fabs(vv) > SLIP) {
[9386]490 LOG << epoTimeStr << " cycle slip detected " << t_lc::toString(tLC) << ' '
491 << obs->prn().toString() << ' ' << setw(8) << setprecision(4) << vv << endl;
[8905]492 if (preProcessing) {
[9386]493 _obsPool->setRefSatChangeRequired(sys, true);
[8905]494 }
495 else {
496 resetAmb(obs->prn(), obsVector);
497 }
[7237]498 }
499 }
500 }
501 }
502 }
503 return success;
504}
505
506// Reset Ambiguity Parameter (cycle slip)
507////////////////////////////////////////////////////////////////////////////
508t_irc t_pppFilter::resetAmb(t_prn prn, const vector<t_pppSatObs*>& obsVector,
509 SymmetricMatrix* QSav, ColumnVector* xSav) {
[8965]510
[7237]511 t_irc irc = failure;
[9504]512 vector<t_pppParam*>& params = _parlist.params();
[7237]513 for (unsigned iPar = 0; iPar < params.size(); iPar++) {
514 t_pppParam* par = params[iPar];
515 if (par->type() == t_pppParam::amb && par->prn() == prn) {
516 int ind = par->indexNew();
517 t_lc::type tLC = par->tLC();
518 LOG << string(_epoTime) << " RESET " << par->toString() << endl;
519 delete par; par = new t_pppParam(t_pppParam::amb, prn, tLC, &obsVector);
520 par->setIndex(ind);
521 params[iPar] = par;
522 for (unsigned ii = 1; ii <= params.size(); ii++) {
523 _QFlt(ii, ind+1) = 0.0;
524 if (QSav) {
525 (*QSav)(ii, ind+1) = 0.0;
526 }
527 }
528 _QFlt(ind+1,ind+1) = par->sigma0() * par->sigma0();
529 if (QSav) {
530 (*QSav)(ind+1,ind+1) = _QFlt(ind+1,ind+1);
531 }
532 _xFlt[ind] = 0.0;
533 if (xSav) {
534 (*xSav)[ind] = _xFlt[ind];
535 }
536 _x0[ind] = par->x0();
537 irc = success;
538 }
539 }
540
541 return irc;
542}
543
[9395]544// Add infinite noise to iono
[9386]545////////////////////////////////////////////////////////////////////////////
546t_irc t_pppFilter::addNoiseToIono(char sys) {
547
548 t_irc irc = failure;
[9504]549 vector<t_pppParam*>& params = _parlist.params();
[9386]550 for (unsigned iPar = 0; iPar < params.size(); iPar++) {
551 t_pppParam* par = params[iPar];
552 if (par->type() == t_pppParam::ion && par->prn().system() == sys) {
553 int ind = par->indexNew();
554 LOG << string(_epoTime) << " ADD IONO_NOISE TO " << par->prn().toString() << endl;
555 par->setIndex(ind);
556 _QFlt(ind+1,ind+1) += par->sigma0() * par->sigma0();
557 irc = success;
558 }
559 }
560
561 return irc;
562}
563
[7237]564// Compute various DOP Values
565////////////////////////////////////////////////////////////////////////////
[9521]566void t_pppFilter::cmpDOP(const vector<t_pppSatObs*>& obsVector,
[9508]567 const QMap<char, t_pppRefSat*>& refSatMap) {
[7237]568
569 _dop.reset();
570
571 try {
572 const unsigned numPar = 4;
573 Matrix AA(obsVector.size(), numPar);
574 _numSat = 0;
575 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
576 t_pppSatObs* obs = obsVector[ii];
[9508]577 char sys = obs->prn().system();
[8956]578 t_prn refPrn = t_prn();
579 if (OPT->_refSatRequired) {
[9508]580 refPrn = refSatMap[sys]->prn();
[8956]581 }
[7237]582 if (obs->isValid() && !obs->outlier()) {
583 ++_numSat;
584 for (unsigned iPar = 0; iPar < numPar; iPar++) {
[9504]585 const t_pppParam* par = _parlist.params()[iPar];
[8956]586 AA[_numSat-1][iPar] = par->partial(_epoTime, obs, t_lc::c1, refPrn);
[7237]587 }
588 }
589 }
590 if (_numSat < 4) {
591 return;
592 }
593 AA = AA.Rows(1, _numSat);
[7267]594 SymmetricMatrix NN; NN << AA.t() * AA;
[7237]595 SymmetricMatrix QQ = NN.i();
[7267]596
[7928]597 _dop.H = sqrt(QQ(1,1) + QQ(2,2));
598 _dop.V = sqrt(QQ(3,3));
[7237]599 _dop.P = sqrt(QQ(1,1) + QQ(2,2) + QQ(3,3));
600 _dop.T = sqrt(QQ(4,4));
601 _dop.G = sqrt(QQ(1,1) + QQ(2,2) + QQ(3,3) + QQ(4,4));
602 }
603 catch (...) {
604 }
605}
606
[9526]607//
[7237]608////////////////////////////////////////////////////////////////////////////
609void t_pppFilter::predictCovCrdPart(const SymmetricMatrix& QFltOld) {
610
[9504]611 const vector<t_pppParam*>& params = _parlist.params();
[7237]612 if (params.size() < 3) {
613 return;
614 }
615
616 bool first = (params[0]->indexOld() < 0);
617
618 SymmetricMatrix Qneu(3); Qneu = 0.0;
619 for (unsigned ii = 0; ii < 3; ii++) {
620 const t_pppParam* par = params[ii];
621 if (first) {
622 Qneu[ii][ii] = par->sigma0() * par->sigma0();
623 }
624 else {
625 Qneu[ii][ii] = par->noise() * par->noise();
626 }
627 }
628
629 const t_pppStation* sta = PPP_CLIENT->staRover();
630 SymmetricMatrix Qxyz(3);
631 covariNEU_XYZ(Qneu, sta->ellApr().data(), Qxyz);
632
633 if (first) {
634 _QFlt.SymSubMatrix(1,3) = Qxyz;
635 }
636 else {
637 double dt = _epoTime - _firstEpoTime;
638 if (dt < OPT->_seedingTime) {
639 _QFlt.SymSubMatrix(1,3) = QFltOld.SymSubMatrix(1,3);
640 }
641 else {
642 _QFlt.SymSubMatrix(1,3) = QFltOld.SymSubMatrix(1,3) + Qxyz;
643 }
644 }
645}
[8912]646
[9526]647//
648////////////////////////////////////////////////////////////////////////////
649void t_pppFilter::setStateVectorAndVarCovMatrix(const ColumnVector& xFltOld,
650 const SymmetricMatrix& QFltOld) {
651
652 const vector<t_pppParam*>& params = _parlist.params();
653 unsigned nPar = params.size();
654
655 _QFlt.ReSize(nPar); _QFlt = 0.0;
656 _xFlt.ReSize(nPar); _xFlt = 0.0;
657 _x0.ReSize(nPar); _x0 = 0.0;
658
659 for (unsigned ii = 0; ii < nPar; ii++) {
660 t_pppParam* par1 = params[ii];
661 if (QFltOld.size() == 0) {
662 par1->resetIndex();
663 }
664 _x0[ii] = par1->x0();
665 int iOld = par1->indexOld();
666 if (iOld < 0) {
667 _QFlt[ii][ii] = par1->sigma0() * par1->sigma0(); // new parameter
668 }
669 else {
670 _QFlt[ii][ii] = QFltOld[iOld][iOld] + par1->noise() * par1->noise();
671 _xFlt[ii] = xFltOld[iOld];
672 for (unsigned jj = 0; jj < ii; jj++) {
673 t_pppParam* par2 = params[jj];
674 int jOld = par2->indexOld();
675 if (jOld >= 0) {
676 _QFlt[ii][jj] = QFltOld(iOld+1,jOld+1);
677 }
678 }
679 }
680 }
681 predictCovCrdPart(QFltOld);
682}
683
[8915]684// Compute datum transformation
[8912]685////////////////////////////////////////////////////////////////////////////
[9508]686t_irc t_pppFilter::datumTransformation(const QMap<char, t_pppRefSat*>& refSatMap) {
687
[9419]688 // get last epoch
[9386]689 t_pppObsPool::t_epoch* epoch = _obsPool->lastEpoch();
[9419]690 if (!epoch) {
[9508]691 LOG << "t_pppFilter::datumTransformation: !lastEpoch" << endl;
[9386]692 return failure;
693 }
[9508]694 _epoTime = epoch->epoTime();
695 LOG.setf(ios::fixed);
696 LOG << string(_epoTime) << " DATUM TRANSFORMATION " << endl;
[9419]697
[9386]698 vector<t_pppSatObs*>& allObs = epoch->obsVector();
699
[9508]700 const QMap<char, t_pppRefSat*>& refSatMapLastEpoch = epoch->refSatMap();
701
702 bool peseudoObsIono = epoch->pseudoObsIono();
703
[9419]704 // reset old and set new refSats in last epoch (ambiguities/GIM)
705 // =============================================================
[9508]706 if (resetRefSatellitesLastEpoch(allObs, refSatMap, refSatMapLastEpoch) != true) {
[9527]707 LOG << "datumTransformation: refsatChange required" << endl;
[9431]708 return success;
[9386]709 }
710
[9419]711 if (OPT->_obsModelType == OPT->UncombPPP) {
712 return success;
713 }
714
[9386]715 // set AA2
716 // =======
[9508]717 if (_parlist.set(_epoTime, allObs, refSatMap) != success) {
[9419]718 return failure;
719 }
[9526]720
[9386]721#ifdef BNC_DEBUG_PPP
[9527]722 LOG << "datumTransformation: printParams after set" << endl;
723 _parlist.printParams(_epoTime);
[9386]724#endif
[9526]725
[9504]726 const QList<char>& usedSystems = _parlist.usedSystems();
[9431]727 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
728 char sys = usedSystems[iSys];
[9508]729 t_prn refPrn = refSatMap[sys]->prn();
[9386]730 vector<t_pppSatObs*> obsVector;
731 for (unsigned jj = 0; jj < allObs.size(); jj++) {
732 if (allObs[jj]->prn().system() == sys) {
733 obsVector.push_back(allObs[jj]);
734 }
735 }
[9431]736 if (iSys == 0) {
737 _datumTrafo->setFirstSystem(sys);
[9419]738 }
[9386]739 vector<t_lc::type> LCs = OPT->LCs(sys);
740 unsigned usedLCs = LCs.size();
[9508]741 if (OPT->_pseudoObsIono && !peseudoObsIono) {
[9386]742 usedLCs -= 1; // GIM not used
743 }
744 int hlpLCs = 0;
745 if (OPT->_pseudoObsTropo) {
746 hlpLCs = -1;
747 }
748 // max Obs
749 unsigned maxObs = obsVector.size() * (usedLCs + hlpLCs);
[9419]750
751 if (OPT->_pseudoObsTropo && _datumTrafo->firstSystem(sys)) {
[9386]752 maxObs += 1;
753 }
[9508]754 if (OPT->_pseudoObsIono && peseudoObsIono) {
[9386]755 maxObs -= 1; // pseudo obs iono with respect to refSat
756 }
[9526]757
758 const vector<t_pppParam*>& params = _parlist.params();
759 unsigned nPar = _parlist.nPar();
760
[9419]761 Matrix AA(maxObs, nPar);
[9524]762
[9386]763 // Real Observations
764 // -----------------
765 int iObs = -1;
766 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
767 t_pppSatObs* obs = obsVector[ii];
[9419]768 for (unsigned jj = 0; jj < usedLCs; jj++) {
769 const t_lc::type tLC = LCs[jj];
770 if (tLC == t_lc::GIM) {continue;}
771 if (tLC == t_lc::Tz0) {continue;}
772 ++iObs;
[9524]773 for (unsigned iPar = 0; iPar < nPar; iPar++) {
774 const t_pppParam* par = params[iPar];
[9419]775 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC, refPrn);
[9386]776 }
777 }
778 }
[9395]779 // pseudo Obs Tropo
780 // ================
[9419]781 if (OPT->_pseudoObsTropo && _datumTrafo->firstSystem(sys)) {
[9421]782 bool pseudoObsTropoConsidered = false;
[9395]783 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
[9421]784 if (pseudoObsTropoConsidered) {break;}
[9395]785 t_pppSatObs* obs = obsVector[ii];
786 for (unsigned jj = 0; jj < usedLCs; jj++) {
787 const t_lc::type tLC = LCs[jj];
788 if (tLC != t_lc::Tz0) {continue;}
789 ++iObs;
[9421]790 pseudoObsTropoConsidered = true;
[9524]791 for (unsigned iPar = 0; iPar < nPar; iPar++) {
792 const t_pppParam* par = params[iPar];
[9395]793 AA[iObs][iPar] = par->partial(_epoTime, obs, tLC, refPrn);
794 }
795 }
796 }
797 }
[9419]798 if (!iObs) {
799 continue;
800 }
[9508]801 _datumTrafo->updateIndices(sys, iObs+1); //LOG << "AA Ncols/Nrows: " << AA.Ncols() << "/" << AA.Nrows() << " nPar: " << nPar << endl; //LOG << "AA.SubMatrix(1 .. " << iObs+1 << " , 1 .. " << nPar << ")" << endl;
802 if(_datumTrafo->prepareAA(AA.SubMatrix(1, iObs+1 , 1, nPar), 2) != success) {
803 return failure;
804 }
[9386]805 }
[9419]806 _datumTrafo->updateNumObs();
[9386]807
808 // Datum Transformation
809 // ====================
810#ifdef BNC_DEBUG_PPP
[9527]811 //LOG << "AA1\n"; _datumTrafo->printMatrix(_datumTrafo->AA1(), _datumTrafo->numObs(), _datumTrafo->numPar());
812 //LOG << "AA2\n"; _datumTrafo->printMatrix(_datumTrafo->AA2(), _datumTrafo->numObs(), _datumTrafo->numPar());
[9386]813#endif
[9419]814 if(_datumTrafo->computeTrafoMatrix() != success) {
815 return failure;
816 }
[9386]817#ifdef BNC_DEBUG_PPP
[9419]818 //LOG << "D21" << endl; _datumTrafo->printMatrix(_datumTrafo->D21(), _datumTrafo->numObs(), _datumTrafo->numPar());
[9386]819#endif
820 ColumnVector xFltOld = _xFlt;
821 SymmetricMatrix QFltOld = _QFlt;
822
[9419]823 _QFlt << _datumTrafo->D21() * QFltOld * _datumTrafo->D21().t();
824 _xFlt = _datumTrafo->D21() * xFltOld;
[9386]825
826#ifdef BNC_DEBUG_PPP
[9527]827 //LOG << "xFltOld:\n" << xFltOld << endl;
828 //LOG << "xFlt :\n" << _xFlt << endl;
[9386]829#endif
830
831 // Reset Ambiguities after Datum Transformation
832 // ============================================
[9431]833 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
834 char sys = usedSystems[iSys];
[9508]835 t_prn refPrnOld = refSatMapLastEpoch[sys]->prn();
836 t_prn refPrnNew = refSatMap[sys]->prn();
[9419]837 if (refPrnNew != refPrnOld) {
[9508]838 t_irc irc = resetAmb(refPrnOld, allObs);
[9419]839 if (OPT->_obsModelType == OPT->DCMcodeBias) {
840 if (irc == success) {
841 addNoiseToIono(sys);
842 }
843 }
[9386]844 }
845 }
846
847 // switch AA2 to AA1
848 // =================
849 _datumTrafo->switchAA();
850
[9508]851 _obsPool->putEpoch(_epoTime, allObs, peseudoObsIono, refSatMap);
852
[9386]853 return success;
[8912]854}
855
[9386]856// Init datum transformation
[8956]857////////////////////////////////////////////////////////////////////////////
[9419]858void t_pppFilter::initDatumTransformation(const std::vector<t_pppSatObs*>& allObs,
859 bool pseudoObsIono) {
[9395]860 unsigned trafoObs = 0;
[9504]861 const QList<char>& usedSystems = _parlist. usedSystems();
[9431]862 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
863 char sys = usedSystems[iSys];
[9386]864 int satNum = 0;
865 for (unsigned jj = 0; jj < allObs.size(); jj++) {
[9419]866 if (allObs[jj]->prn().system() == sys) {
[9386]867 satNum++;
[8956]868 }
869 }
[9386]870 // all LCs
[9419]871 unsigned realUsedLCs = OPT->LCs(sys).size();
[9386]872 // exclude pseudo obs GIM
[9419]873 if (OPT->_pseudoObsIono && !pseudoObsIono) {
[9386]874 realUsedLCs -= 1;
875 }
876 if (OPT->_pseudoObsTropo) {
877 realUsedLCs -= 1;
878 }
[9395]879 trafoObs += satNum * realUsedLCs;
880
[9419]881 if (OPT->_pseudoObsTropo && _datumTrafo->firstSystem(sys)) {
[9395]882 trafoObs += 1;
883 }
[9419]884 if (OPT->_pseudoObsIono && pseudoObsIono) {
885 trafoObs -= 1; // pseudo obs iono with respect to refSat
886 }
[8956]887 }
[9419]888 _datumTrafo->setNumObs(trafoObs);
[9504]889 _datumTrafo->setNumPar(_parlist.nPar());
[9386]890 _datumTrafo->initAA();
[8956]891}
[9386]892
893//
894//////////////////////////////////////////////////////////////////////////////
[9508]895bool t_pppFilter::resetRefSatellitesLastEpoch(std::vector<t_pppSatObs*>& obsVector,
896 const QMap<char, t_pppRefSat*>& refSatMap,
897 const QMap<char, t_pppRefSat*>& refSatMapLastEpoch) {
[9431]898 bool resetRefSat;
[9386]899 // reference satellite definition per system
[9504]900 const QList<char>& usedSystems = _parlist.usedSystems();
[9431]901 for (int iSys = 0; iSys < usedSystems.size(); iSys++) {
902 resetRefSat = false;
903 char sys = usedSystems[iSys];
[9508]904 t_prn newPrn = refSatMap[sys]->prn();
905 t_prn oldPrn = refSatMapLastEpoch[sys]->prn();
[9386]906#ifdef BNC_DEBUG_PPP
[9508]907 if (oldPrn != newPrn) {
908 LOG << "oldRef: " << oldPrn.toString() << " => newRef " << newPrn.toString() << endl;
909 }
[9386]910#endif
911 vector<t_pppSatObs*>::iterator it = obsVector.begin();
912 while (it != obsVector.end()) {
913 t_pppSatObs* satObs = *it;
914 if (satObs->prn() == newPrn) {
915 resetRefSat = true;
916 satObs->setAsReference();
[9508]917 } else if (satObs->prn() == oldPrn) {
[9386]918 satObs->resetReference();
919 }
920 it++;
921 }
[9431]922 if (!resetRefSat) {
923 _obsPool->setRefSatChangeRequired(sys, true);
924 return resetRefSat;
925 }
[9386]926 }
927 return resetRefSat;
928}
Note: See TracBrowser for help on using the repository browser.