source: ntrip/trunk/BNC/src/PPP/pppClient.cpp@ 10793

Last change on this file since 10793 was 10791, checked in by mervart, 10 days ago

BNC Multifrequency and PPPAR Client (initial version)

  • 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.9 KB
Line 
1/* -------------------------------------------------------------------------
2 * BKG NTRIP Client
3 * -------------------------------------------------------------------------
4 *
5 * Class: t_pppClient
6 *
7 * Purpose: PPP Client processing starts here
8 *
9 * Author: L. Mervart
10 *
11 * Created: 29-Jul-2014
12 *
13 * Changes:
14 *
15 * -----------------------------------------------------------------------*/
16
17#include <QThreadStorage>
18
19#include <iostream>
20#include <iomanip>
21#include <cmath>
22#include <stdlib.h>
23#include <string.h>
24#include <stdexcept>
25
26#include "pppClient.h"
27#include "pppEphPool.h"
28#include "pppObsPool.h"
29#include "bncconst.h"
30#include "bncutils.h"
31#include "pppStation.h"
32#include "bncantex.h"
33#include "pppFilter.h"
34
35using namespace BNC_PPP;
36using namespace std;
37
38// Global variable holding thread-specific pointers
39//////////////////////////////////////////////////////////////////////////////
40QThreadStorage<t_pppClient*> CLIENTS;
41
42// Static function returning thread-specific pointer
43//////////////////////////////////////////////////////////////////////////////
44t_pppClient* t_pppClient::instance() {
45 return CLIENTS.localData();
46}
47
48// Constructor
49//////////////////////////////////////////////////////////////////////////////
50t_pppClient::t_pppClient(const t_pppOptions* opt) {
51 _running = true;
52 _output = 0;
53 _opt = new t_pppOptions(*opt);
54 _log = new ostringstream();
55 _ephPool = new t_pppEphPool();
56 _obsPool = new t_pppObsPool();
57 _staRover = new t_pppStation();
58 _filter = new t_pppFilter();
59 _tides = new t_tides();
60 _antex = 0;
61 if (!_opt->_antexFileName.empty()) {
62 _antex = new bncAntex(_opt->_antexFileName.c_str());
63 }
64 if (!_opt->_blqFileName.empty()) {
65 if (_tides->readBlqFile(_opt->_blqFileName.c_str()) == success) {
66 //_tides->printAllBlqSets();
67 }
68 }
69 CLIENTS.setLocalData(this); // CLIENTS takes ownership over "this"
70}
71
72// Destructor
73//////////////////////////////////////////////////////////////////////////////
74t_pppClient::~t_pppClient() {
75 _running = false;
76 delete _log;
77 delete _opt;
78 delete _ephPool;
79 delete _obsPool;
80 delete _staRover;
81 if (_antex) {
82 delete _antex;
83 }
84 delete _filter;
85 delete _tides;
86 clearObs();
87}
88
89//
90//////////////////////////////////////////////////////////////////////////////
91void t_pppClient::putEphemeris(const t_eph* eph) {
92 const t_ephGPS* ephGPS = dynamic_cast<const t_ephGPS*>(eph);
93 const t_ephGlo* ephGlo = dynamic_cast<const t_ephGlo*>(eph);
94 const t_ephGal* ephGal = dynamic_cast<const t_ephGal*>(eph);
95 const t_ephBDS* ephBDS = dynamic_cast<const t_ephBDS*>(eph);
96 if (ephGPS) {
97 _ephPool->putEphemeris(new t_ephGPS(*ephGPS));
98 }
99 else if (ephGlo) {
100 _ephPool->putEphemeris(new t_ephGlo(*ephGlo));
101 }
102 else if (ephGal) {
103 _ephPool->putEphemeris(new t_ephGal(*ephGal));
104 }
105 else if (ephBDS) {
106 _ephPool->putEphemeris(new t_ephBDS(*ephBDS));
107 }
108}
109
110//
111//////////////////////////////////////////////////////////////////////////////
112void t_pppClient::putTec(const t_vTec* vTec) {
113 _obsPool->putTec(new t_vTec(*vTec));
114}
115
116//
117//////////////////////////////////////////////////////////////////////////////
118void t_pppClient::putOrbCorrections(const vector<t_orbCorr*>& corr) {
119 if (OPT->_logMode == t_pppOptions::normal && corr.size() > 0) {
120 LOG << "orbCorrections " << string(corr[0]->_time) << ' ' << corr.size() << endl;
121 }
122 for (unsigned ii = 0; ii < corr.size(); ii++) {
123 _ephPool->putOrbCorrection(new t_orbCorr(*corr[ii]));
124 }
125}
126
127//
128//////////////////////////////////////////////////////////////////////////////
129void t_pppClient::putClkCorrections(const vector<t_clkCorr*>& corr) {
130 if (OPT->_logMode == t_pppOptions::normal && corr.size() > 0) {
131 LOG << "clkCorrections " << string(corr[0]->_time) << ' ' << corr.size() << endl;
132 }
133 for (unsigned ii = 0; ii < corr.size(); ii++) {
134 _ephPool->putClkCorrection(new t_clkCorr(*corr[ii]));
135 }
136}
137
138//
139//////////////////////////////////////////////////////////////////////////////
140void t_pppClient::putCodeBiases(const vector<t_satCodeBias*>& biases) {
141 if (OPT->_logMode == t_pppOptions::normal && biases.size() > 0) {
142 LOG << "codeBiases " << string(biases[0]->_time) << ' ' << biases.size() << endl;
143 }
144 set<char> systems;
145 for (unsigned ii = 0; ii < biases.size(); ii++) {
146 t_satCodeBias* newBias = new t_satCodeBias(*biases[ii]);
147 char sys = newBias->_prn.system();
148 if (systems.find(sys) == systems.end()) {
149 _obsPool->clearCodeBiases(sys);
150 systems.insert(sys);
151 }
152 _obsPool->putCodeBias(newBias);
153 }
154}
155
156//
157//////////////////////////////////////////////////////////////////////////////
158void t_pppClient::putPhaseBiases(const vector<t_satPhaseBias*>& biases) {
159 if (OPT->_logMode == t_pppOptions::normal && biases.size() > 0) {
160 LOG << "phaseBiases " << string(biases[0]->_time) << ' ' << biases.size() << endl;
161 }
162 set<char> systems;
163 for (unsigned ii = 0; ii < biases.size(); ii++) {
164 t_satPhaseBias* newBias = new t_satPhaseBias(*biases[ii]);
165 char sys = newBias->_prn.system();
166 if (systems.find(sys) == systems.end()) {
167 _obsPool->clearPhaseBiases(sys);
168 systems.insert(sys);
169 }
170 _obsPool->putPhaseBias(newBias);
171 }
172}
173
174//
175//////////////////////////////////////////////////////////////////////////////
176t_irc t_pppClient::prepareObs(const vector<t_satObs*>& satObs,
177 vector<t_pppSatObs*>& obsVector, bncTime& epoTime) {
178
179 // Default
180 // -------
181 epoTime.reset();
182 clearObs();
183
184 // Create vector of valid observations
185 // -----------------------------------
186 for (unsigned ii = 0; ii < satObs.size(); ii++) {
187 char sys = satObs[ii]->_prn.system();
188 if (_opt->useSystem(sys)) {
189 t_pppSatObs* pppSatObs = new t_pppSatObs(*satObs[ii]);
190 if (pppSatObs->isValid()) {
191 obsVector.push_back(pppSatObs);
192 }
193 else {
194 delete pppSatObs;
195 }
196 }
197 }
198
199 // Check whether data are synchronized, compute epoTime
200 // ----------------------------------------------------
201 const double MAXSYNC = 0.05; // synchronization limit
202 double meanDt = 0.0;
203 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
204 const t_pppSatObs* satObs = obsVector.at(ii);
205 if (epoTime.undef()) {
206 epoTime = satObs->time();
207 }
208 else {
209 double dt = satObs->time() - epoTime;
210 if (fabs(dt) > MAXSYNC) {
211 LOG << "t_pppClient::prepareObs asynchronous observations" << endl;
212 return failure;
213 }
214 meanDt += dt;
215 }
216 }
217
218 if (obsVector.size() > 0) {
219 epoTime += meanDt / obsVector.size();
220 }
221
222 return success;
223}
224
225//
226//////////////////////////////////////////////////////////////////////////////
227bool t_pppClient::preparePseudoObs(std::vector<t_pppSatObs*>& obsVector) {
228
229 bool pseudoObsIono = false;
230
231 if (_opt->_pseudoObsIono) {
232 vector<t_pppSatObs*>::iterator it = obsVector.begin();
233 while (it != obsVector.end()) {
234 t_pppSatObs* satObs = *it;
235 pseudoObsIono = satObs->setPseudoObsIono(t_frequency::G1);
236 it++;
237 }
238 }
239
240 if (OPT->_logMode == t_pppOptions::all) {
241 vector<t_pppSatObs*>::iterator it = obsVector.begin();
242 while (it != obsVector.end()) {
243 t_pppSatObs* satObs = *it;
244 satObs->printObsMinusComputed();
245 it++;
246 }
247 }
248 return pseudoObsIono;
249}
250
251// Compute the Bancroft position, check for blunders
252//////////////////////////////////////////////////////////////////////////////
253t_irc t_pppClient::cmpBancroft(const bncTime& epoTime,
254 vector<t_pppSatObs*>& obsVector,
255 ColumnVector& xyzc, bool print) {
256
257 int numBancroft = obsVector.size();
258
259 while (_running) {
260 Matrix BB(numBancroft, 4);
261 int iObs = -1;
262 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
263 const t_pppSatObs* satObs = obsVector.at(ii);
264 t_lc LC = satObs->rangeLC();
265 if ( satObs->isValid(LC) &&
266 (!satObs->modelSet() || satObs->eleSat() >= _opt->_minEle) ) {
267 ++iObs;
268 BB[iObs][0] = satObs->xc()[0];
269 BB[iObs][1] = satObs->xc()[1];
270 BB[iObs][2] = satObs->xc()[2];
271 BB[iObs][3] = satObs->obsValue(LC) - satObs->cmpValueForBanc(LC);
272 }
273 }
274 if (iObs + 1 < _opt->_minObs) {
275 LOG << "t_pppClient::cmpBancroft not enough observations: " << iObs + 1 << endl;
276 return failure;
277 }
278 BB = BB.Rows(1,iObs+1);
279 if (bancroft(BB, xyzc) != success) {
280 return failure;
281 }
282
283 xyzc[3] /= t_CST::c;
284
285 // Check Blunders
286 // --------------
287 const double BLUNDER = 1500.0;
288 double maxRes = 0.0;
289 unsigned maxResIndex = 0;
290 for (unsigned ii = 0; ii < obsVector.size(); ii++) {
291 const t_pppSatObs* satObs = obsVector.at(ii);
292 t_lc LC = satObs->rangeLC();
293 if (satObs->isValid(LC) &&
294 (!satObs->modelSet() || satObs->eleSat() >= _opt->_minEle) ) {
295 ColumnVector rr = satObs->xc().Rows(1,3) - xyzc.Rows(1,3);
296 double res = rr.NormFrobenius() - satObs->obsValue(LC)
297 - (satObs->xc()[3] - xyzc[3]) * t_CST::c;
298 if (fabs(res) > maxRes) {
299 maxRes = fabs(res);
300 maxResIndex = ii;
301 }
302 }
303 }
304 if (maxRes < BLUNDER) {
305 if (print) {
306 LOG.setf(ios::fixed);
307 LOG << "\nPPP of Epoch ";
308 if (!_epoTimeRover.undef()) LOG << string(_epoTimeRover);
309 LOG << "\n---------------------------------------------------------------\n";
310 LOG << string(epoTime) << " BANCROFT: "
311 << setw(14) << setprecision(3) << xyzc[0] << ' '
312 << setw(14) << setprecision(3) << xyzc[1] << ' '
313 << setw(14) << setprecision(3) << xyzc[2] << ' '
314 << setw(14) << setprecision(3) << xyzc[3] * t_CST::c << endl << endl;
315 }
316 break;
317 }
318 else {
319 t_pppSatObs* satObs = obsVector.at(maxResIndex);
320 LOG << "t_pppClient::cmpBancroft Outlier " << satObs->prn().toString()
321 << " " << maxRes << endl;
322 delete satObs;
323 obsVector.erase(obsVector.begin() + maxResIndex);
324 }
325 }
326
327 return success;
328}
329
330//
331//////////////////////////////////////////////////////////////////////////////
332void t_pppClient::initOutput(t_output* output) {
333 _output = output;
334 _output->_numSat = 0;
335 _output->_hDop = 0.0;
336 _output->_error = false;
337}
338
339//
340//////////////////////////////////////////////////////////////////////////////
341void t_pppClient::clearObs() {
342 for (unsigned ii = 0; ii < _obsRover.size(); ii++) {
343 delete _obsRover.at(ii);
344 }
345 _obsRover.clear();
346}
347
348//
349//////////////////////////////////////////////////////////////////////////////
350void t_pppClient::finish(t_irc irc, int /*ind*/) {
351#ifdef BNC_DEBUG_PPP
352 LOG << "t_pppClient::finish(" << ind << "): " << irc << endl;
353#endif
354
355 clearObs();
356
357 _output->_epoTime = _epoTimeRover;
358
359 if (irc == success) {
360 _output->_xyzRover[0] = _staRover->xyzApr()[0] + _filter->x()[0];
361 _output->_xyzRover[1] = _staRover->xyzApr()[1] + _filter->x()[1];
362 _output->_xyzRover[2] = _staRover->xyzApr()[2] + _filter->x()[2];
363
364 xyz2neu(_staRover->ellApr().data(), _filter->x().data(), _output->_neu);
365
366 copy(&_filter->Q().data()[0], &_filter->Q().data()[6], _output->_covMatrix);
367
368 _output->_trp0 = t_tropo::delay_saast(_staRover->xyzApr(), M_PI/2.0);
369 _output->_trp = _filter->trp();
370 _output->_trpStdev = _filter->trpStdev();
371
372 _output->_numSat = _filter->numSat();
373 _output->_hDop = _filter->HDOP();
374 _output->_error = false;
375 }
376 else {
377 _output->_error = true;
378 }
379
380 _output->_log = _log->str();
381 delete _log; _log = new ostringstream();
382
383 return;
384}
385
386//
387//////////////////////////////////////////////////////////////////////////////
388t_irc t_pppClient::cmpModel(t_pppStation* station, const ColumnVector& xyzc,
389 vector<t_pppSatObs*>& obsVector) {
390 bncTime time;
391 time = _epoTimeRover;
392 station->setName(_opt->_roverName);
393 station->setAntName(_opt->_antNameRover);
394 station->setEpochTime(time);
395
396 if (_opt->xyzAprRoverSet()) {
397 station->setXyzApr(_opt->_xyzAprRover);
398 }
399 else {
400 station->setXyzApr(xyzc.Rows(1,3));
401 }
402 station->setNeuEcc(_opt->_neuEccRover);
403
404 // Receiver Clock
405 // --------------
406 station->setDClk(xyzc[3]);
407
408 // Tides
409 // -----
410 station->setTideDsplEarth(_tides->earth(time, station->xyzApr()));
411 station->setTideDsplOcean(_tides->ocean(time, station->xyzApr(), station->name()));
412
413 // Observation model
414 // -----------------
415 vector<t_pppSatObs*>::iterator it = obsVector.begin();
416 while (it != obsVector.end()) {
417 t_pppSatObs* satObs = *it;
418 t_irc modelSetup;
419 if (satObs->isValid()) {
420 modelSetup = satObs->cmpModel(station);
421 }
422 if (satObs->isValid() &&
423 satObs->eleSat() >= _opt->_minEle &&
424 modelSetup == success) {
425 ++it;
426 }
427 else {
428 delete satObs;
429 it = obsVector.erase(it);
430 }
431 }
432
433 return success;
434}
435
436//
437//////////////////////////////////////////////////////////////////////////////
438void t_pppClient::processEpoch(const vector<t_satObs*>& satObs, t_output* output) {
439
440 try {
441 initOutput(output);
442
443 // Prepare Observations of the Rover
444 // ---------------------------------
445 if (prepareObs(satObs, _obsRover, _epoTimeRover) != success) {
446 return finish(failure, 1);
447 }
448
449 for (int iter = 1; iter <= 2; iter++) {
450 ColumnVector xyzc(4); xyzc = 0.0;
451 bool print = (iter == 2);
452 if (cmpBancroft(_epoTimeRover, _obsRover, xyzc, print) != success) {
453 return finish(failure, 2);
454 }
455 if (cmpModel(_staRover, xyzc, _obsRover) != success) {
456 return finish(failure, 3);
457 }
458 }
459
460 // Use observations only if satellite code biases are available
461 // ------------------------------------------------------------
462 if (_opt->ambRes()) {
463 useObsWithBiasesOnly(_obsRover);
464 }
465
466 if (int(_obsRover.size()) < _opt->_minObs) {
467 LOG << "t_pppClient::processEpoch not enough observations" << endl;
468 return finish(failure, 4);
469 }
470
471 // Prepare Pseudo Observations of the Rover
472 // ----------------------------------------
473 _pseudoObsIono = preparePseudoObs(_obsRover);
474
475 // Store last epoch of data
476 // ------------------------
477 _obsPool->putEpoch(_epoTimeRover, _obsRover, _pseudoObsIono);
478
479 // Process Epoch in Filter
480 // -----------------------
481 if (_filter->processEpoch(_obsPool) != success) {
482 LOG << "t_pppFilter::processEpoch() != success" << endl;
483 return finish(failure, 5);
484 }
485 }
486 catch (Exception& exc) {
487 LOG << exc.what() << endl;
488 return finish(failure, 6);
489 }
490 catch (t_except msg) {
491 LOG << msg.what() << endl;
492 return finish(failure, 7);
493 }
494 catch (const char* msg) {
495 LOG << msg << endl;
496 return finish(failure, 8);
497 }
498 catch (...) {
499 LOG << "unknown exception" << endl;
500 return finish(failure, 9);
501 }
502 return finish(success, 0);
503}
504
505//
506////////////////////////////////////////////////////////////////////////////
507double lorentz(const ColumnVector& aa, const ColumnVector& bb) {
508 return aa[0]*bb[0] + aa[1]*bb[1] + aa[2]*bb[2] - aa[3]*bb[3];
509}
510
511//
512////////////////////////////////////////////////////////////////////////////
513t_irc t_pppClient::bancroft(const Matrix& BBpass, ColumnVector& pos) {
514
515 if (pos.Nrows() != 4) {
516 pos.ReSize(4);
517 }
518 pos = 0.0;
519
520 for (int iter = 1; iter <= 2; iter++) {
521 Matrix BB = BBpass;
522 int mm = BB.Nrows();
523 for (int ii = 1; ii <= mm; ii++) {
524 double xx = BB(ii,1);
525 double yy = BB(ii,2);
526 double traveltime = 0.072;
527 if (iter > 1) {
528 double zz = BB(ii,3);
529 double rho = sqrt( (xx-pos(1)) * (xx-pos(1)) +
530 (yy-pos(2)) * (yy-pos(2)) +
531 (zz-pos(3)) * (zz-pos(3)) );
532 traveltime = rho / t_CST::c;
533 }
534 double angle = traveltime * t_CST::omega;
535 double cosa = cos(angle);
536 double sina = sin(angle);
537 BB(ii,1) = cosa * xx + sina * yy;
538 BB(ii,2) = -sina * xx + cosa * yy;
539 }
540
541 Matrix BBB;
542 if (mm > 4) {
543 SymmetricMatrix hlp; hlp << BB.t() * BB;
544 BBB = hlp.i() * BB.t();
545 }
546 else {
547 BBB = BB.i();
548 }
549 ColumnVector ee(mm); ee = 1.0;
550 ColumnVector alpha(mm); alpha = 0.0;
551 for (int ii = 1; ii <= mm; ii++) {
552 alpha(ii) = lorentz(BB.Row(ii).t(),BB.Row(ii).t())/2.0;
553 }
554 ColumnVector BBBe = BBB * ee;
555 ColumnVector BBBalpha = BBB * alpha;
556 double aa = lorentz(BBBe, BBBe);
557 double bb = lorentz(BBBe, BBBalpha)-1;
558 double cc = lorentz(BBBalpha, BBBalpha);
559 double root = sqrt(bb*bb-aa*cc);
560
561 Matrix hlpPos(4,2);
562 hlpPos.Column(1) = (-bb-root)/aa * BBBe + BBBalpha;
563 hlpPos.Column(2) = (-bb+root)/aa * BBBe + BBBalpha;
564
565 ColumnVector omc(2);
566 for (int pp = 1; pp <= 2; pp++) {
567 hlpPos(4,pp) = -hlpPos(4,pp);
568 omc(pp) = BB(1,4) -
569 sqrt( (BB(1,1)-hlpPos(1,pp)) * (BB(1,1)-hlpPos(1,pp)) +
570 (BB(1,2)-hlpPos(2,pp)) * (BB(1,2)-hlpPos(2,pp)) +
571 (BB(1,3)-hlpPos(3,pp)) * (BB(1,3)-hlpPos(3,pp)) ) -
572 hlpPos(4,pp);
573 }
574 if ( fabs(omc(1)) > fabs(omc(2)) ) {
575 pos = hlpPos.Column(2);
576 }
577 else {
578 pos = hlpPos.Column(1);
579 }
580 }
581 if (pos.size() != 4 ||
582 std::isnan(pos(1)) ||
583 std::isnan(pos(2)) ||
584 std::isnan(pos(3)) ||
585 std::isnan(pos(4))) {
586 return failure;
587 }
588
589 return success;
590}
591
592//
593//////////////////////////////////////////////////////////////////////////////
594void t_pppClient::reset() {
595
596 LOG << "pppClient: reset" << endl;
597 // to delete old orbit and clock corrections
598 delete _ephPool;
599 _ephPool = new t_pppEphPool();
600
601 // to delete old biases
602 delete _obsPool;
603 _obsPool = new t_pppObsPool();
604
605 // to delete all parameters
606 delete _filter;
607 _filter = new t_pppFilter();
608
609}
610
611//
612//////////////////////////////////////////////////////////////////////////////
613void t_pppClient::useObsWithBiasesOnly(vector<t_pppSatObs*>& obsVector) const {
614 vector<t_pppSatObs*>::iterator it = obsVector.begin();
615 while (it != obsVector.end()) {
616 t_pppSatObs* pppSatObs = *it;
617 if (pppSatObs->hasBiases()) {
618 ++it;
619 }
620 else {
621 it = obsVector.erase(it);
622 delete pppSatObs;
623 }
624 }
625}
Note: See TracBrowser for help on using the repository browser.