source: ntrip/trunk/BNC/src/rinex/reqcanalyze.cpp@ 6255

Last change on this file since 6255 was 6255, checked in by stuerze, 10 years ago

scaling (integer or dbHz) in SNR plots depends now on SNR1 avarage value

File size: 24.0 KB
RevLine 
[3899]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 *
29 * Class: t_reqcAnalyze
30 *
31 * Purpose: Analyze RINEX Files
32 *
33 * Author: L. Mervart
34 *
35 * Created: 11-Apr-2012
36 *
[6255]37 * Changes:
[3899]38 *
39 * -----------------------------------------------------------------------*/
40
41#include <iostream>
[4361]42#include <iomanip>
[4579]43#include <qwt_plot_renderer.h>
[4574]44
[3899]45#include "reqcanalyze.h"
[5070]46#include "bnccore.h"
[3899]47#include "bncsettings.h"
[4254]48#include "reqcedit.h"
[4255]49#include "bncutils.h"
[4300]50#include "graphwin.h"
[4307]51#include "polarplot.h"
[4577]52#include "availplot.h"
[4662]53#include "eleplot.h"
[4672]54#include "dopplot.h"
[3899]55
56using namespace std;
57
[4700]58const double SLIPTRESH = 10.0; // cycle-slip threshold (meters)
[4357]59
[3899]60// Constructor
61////////////////////////////////////////////////////////////////////////////
62t_reqcAnalyze::t_reqcAnalyze(QObject* parent) : QThread(parent) {
63
64 bncSettings settings;
[4254]65
[4257]66 _logFileName = settings.value("reqcOutLogFile").toString(); expandEnvVar(_logFileName);
67 _logFile = 0;
68 _log = 0;
[4254]69 _obsFileNames = settings.value("reqcObsFile").toString().split(",", QString::SkipEmptyParts);
[4257]70 _navFileNames = settings.value("reqcNavFile").toString().split(",", QString::SkipEmptyParts);
[4266]71
72 _currEpo = 0;
[4300]73
[6255]74 connect(this, SIGNAL(dspSkyPlot(const QString&,
[4572]75 const QByteArray&,
[6255]76 QVector<t_polarPoint*>*,
[4572]77 const QByteArray&,
78 QVector<t_polarPoint*>*,
[6255]79 const QByteArray&, double)),
80 this, SLOT(slotDspSkyPlot(const QString&,
[4556]81 const QByteArray&,
[6255]82 QVector<t_polarPoint*>*,
[4556]83 const QByteArray&,
84 QVector<t_polarPoint*>*,
[4572]85 const QByteArray&, double)));
86
[4584]87 connect(this, SIGNAL(dspAvailPlot(const QString&, const QByteArray&)),
88 this, SLOT(slotDspAvailPlot(const QString&, const QByteArray&)));
[3899]89}
90
91// Destructor
92////////////////////////////////////////////////////////////////////////////
93t_reqcAnalyze::~t_reqcAnalyze() {
[4255]94 for (int ii = 0; ii < _rnxObsFiles.size(); ii++) {
95 delete _rnxObsFiles[ii];
96 }
97 for (int ii = 0; ii < _ephs.size(); ii++) {
98 delete _ephs[ii];
99 }
100 delete _log; _log = 0;
101 delete _logFile; _logFile = 0;
[5072]102 if (BNC_CORE->mode() != t_bncCore::interactive) {
[5066]103 qApp->exit(0);
[4452]104 }
[3899]105}
106
[6255]107//
[3899]108////////////////////////////////////////////////////////////////////////////
[6255]109void t_reqcAnalyze::slotDspSkyPlot(const QString& fileName,
[4572]110 const QByteArray& title1,
[6255]111 QVector<t_polarPoint*>* data1,
[4572]112 const QByteArray& title2,
113 QVector<t_polarPoint*>* data2,
114 const QByteArray& scaleTitle,
115 double maxValue) {
[4342]116
[5068]117 if (BNC_CORE->GUIenabled()) {
[4334]118
[4556]119 if (maxValue == 0.0) {
120 if (data1) {
121 for (int ii = 0; ii < data1->size(); ii++) {
[4566]122 double val = data1->at(ii)->_value;
123 if (maxValue < val) {
124 maxValue = val;
[4556]125 }
126 }
[4356]127 }
[4557]128 if (data2) {
[4556]129 for (int ii = 0; ii < data2->size(); ii++) {
[4566]130 double val = data2->at(ii)->_value;
131 if (maxValue < val) {
132 maxValue = val;
[4556]133 }
134 }
[4356]135 }
136 }
[6255]137
[4556]138 QwtInterval scaleInterval(0.0, maxValue);
[4356]139
[4556]140 QVector<QWidget*> plots;
141 if (data1) {
142 t_polarPlot* plot1 = new t_polarPlot(QwtText(title1), scaleInterval,
[5068]143 BNC_CORE->mainWindow());
[4556]144 plot1->addCurve(data1);
145 plots << plot1;
146 }
[4557]147 if (data2) {
[4556]148 t_polarPlot* plot2 = new t_polarPlot(QwtText(title2), scaleInterval,
[5068]149 BNC_CORE->mainWindow());
[4556]150 plot2->addCurve(data2);
151 plots << plot2;
152 }
[4334]153
[6255]154 t_graphWin* graphWin = new t_graphWin(0, fileName, plots,
[4573]155 &scaleTitle, &scaleInterval);
[4334]156
[4445]157 graphWin->show();
158
[4451]159 bncSettings settings;
160 QString dirName = settings.value("reqcPlotDir").toString();
161 if (!dirName.isEmpty()) {
[4606]162 QByteArray ext = scaleTitle.isEmpty() ? "_S.png" : "_M.png";
[4579]163 graphWin->savePNG(dirName, ext);
[4451]164 }
[4308]165 }
[4300]166}
167
[6255]168//
[4300]169////////////////////////////////////////////////////////////////////////////
[3899]170void t_reqcAnalyze::run() {
171
[4255]172 // Open Log File
173 // -------------
174 _logFile = new QFile(_logFileName);
[4517]175 if (_logFile->open(QIODevice::WriteOnly | QIODevice::Text)) {
176 _log = new QTextStream();
177 _log->setDevice(_logFile);
178 }
[4255]179
180 // Initialize RINEX Observation Files
181 // ----------------------------------
[4525]182 t_reqcEdit::initRnxObsFiles(_obsFileNames, _rnxObsFiles, _log);
[3899]183
[4257]184 // Read Ephemerides
185 // ----------------
186 t_reqcEdit::readEphemerides(_navFileNames, _ephs);
187
[4255]188 // Loop over all RINEX Files
189 // -------------------------
[4254]190 for (int ii = 0; ii < _rnxObsFiles.size(); ii++) {
191 analyzeFile(_rnxObsFiles[ii]);
192 }
193
[4255]194 // Exit
195 // ----
[4452]196 emit finished();
197 deleteLater();
[3899]198}
[4254]199
[6255]200//
[4254]201////////////////////////////////////////////////////////////////////////////
[4260]202void t_reqcAnalyze::analyzeFile(t_rnxObsFile* obsFile) {
[4259]203
[4715]204 _mutex.lock();
[4704]205
[4517]206 if (_log) {
207 *_log << "\nAnalyze File\n"
208 << "------------\n"
[4701]209 << "File: " << obsFile->fileName().toAscii().data() << endl;
[4517]210 }
[4260]211
[4584]212 _allObsMap.clear();
213 _availDataMap.clear();
[4717]214 _obsStat.reset();
[4343]215
[4342]216 // A priori Coordinates
217 // --------------------
[4679]218 ColumnVector xyzSta = obsFile->xyz();
[4342]219
[4262]220 // Loop over all Epochs
221 // --------------------
[4541]222 try {
[4675]223 unsigned iEpo = 0;
[4541]224 while ( (_currEpo = obsFile->nextEpoch()) != 0) {
[4688]225
226 if (iEpo == 0) {
227 _obsStat._startTime = _currEpo->tt;
228 _obsStat._antennaName = obsFile->antennaName();
229 _obsStat._markerName = obsFile->markerName();
230 _obsStat._receiverType = obsFile->receiverType();
231 _obsStat._interval = obsFile->interval();
232 }
233 _obsStat._endTime = _currEpo->tt;
[6255]234
[4541]235 // Loop over all satellites
236 // ------------------------
237 for (unsigned iObs = 0; iObs < _currEpo->rnxSat.size(); iObs++) {
238 const t_rnxObsFile::t_rnxSat& rnxSat = _currEpo->rnxSat[iObs];
[6137]239 t_satObs obs;
[5884]240 t_rnxObsFile::setObsFromRnx(obsFile, _currEpo, rnxSat, obs);
[6255]241
[6137]242 QString prn(obs._prn.toString().c_str());
[6255]243
[6137]244 t_ephGlo* ephGlo = 0;
245 int slotNum = 0;
246 if (obs._prn.system() == 'R') {
[5140]247 for (int ie = 0; ie < _ephs.size(); ie++) {
[5776]248 if (QString(_ephs[ie]->prn().toString().c_str()) == prn) {
[5140]249 ephGlo = dynamic_cast<t_ephGlo*>(_ephs[ie]);
250 break;
251 }
252 }
253 if (ephGlo) {
[6137]254 slotNum = ephGlo->slotNum();
[5140]255 }
[4541]256 }
[6255]257
[6137]258 t_irc irc = _allObsMap[prn].addObs(obs, slotNum);
[4675]259
[4694]260 if (irc == success) {
[5140]261 t_oneObs* newObs = _allObsMap[prn]._oneObsVec.last();
262 if (ephGlo) {
263 newObs->_slotSet = true;
264 }
[4694]265 if (newObs->_hasL1 && newObs->_hasL2) {
266 _obsStat._prnStat[prn]._numObs += 1;
267 }
[4695]268 if (newObs->_slipL1 && newObs->_slipL2) {
[4701]269 _obsStat._prnStat[prn]._numSlipsFlagged += 1;
[4695]270 }
[4694]271 }
[4262]272 }
[6255]273
[4679]274 prepareObsStat(iEpo, obsFile->interval(), xyzSta);
[4678]275 iEpo++;
276
[4541]277 } // while (_currEpo)
278 }
279 catch (QString str) {
280 if (_log) {
281 *_log << "Exception " << str << endl;
[4262]282 }
[4541]283 else {
[6255]284 qDebug() << str;
[4541]285 }
[4715]286 _mutex.unlock();
[4541]287 return;
288 }
[4262]289
[4268]290 // Analyze the Multipath
291 // ---------------------
[4718]292 QVector<t_polarPoint*>* dataMP1 = new QVector<t_polarPoint*>;
293 QVector<t_polarPoint*>* dataMP2 = new QVector<t_polarPoint*>;
294 QVector<t_polarPoint*>* dataSNR1 = new QVector<t_polarPoint*>;
295 QVector<t_polarPoint*>* dataSNR2 = new QVector<t_polarPoint*>;
[4268]296
[4584]297 QMutableMapIterator<QString, t_allObs> it(_allObsMap);
[4268]298 while (it.hasNext()) {
299 it.next();
[4584]300 QString prn = it.key();
[6255]301 preparePlotData(prn, xyzSta, obsFile->interval(),
[4675]302 dataMP1, dataMP2, dataSNR1, dataSNR2);
[4268]303 }
304
[4706]305 printReport(dataMP1, dataMP2, dataSNR1, dataSNR2);
306
[4718]307 // Show the plots
308 // --------------
[5068]309 if (BNC_CORE->GUIenabled()) {
[4718]310 QFileInfo fileInfo(obsFile->fileName());
311 QByteArray title = fileInfo.fileName().toAscii();
[6255]312 emit dspSkyPlot(obsFile->fileName(), "MP1", dataMP1, "MP2", dataMP2,
[4718]313 "Meters", 2.0);
[6255]314 double mean = 0.0;
315 for (int ii = 0; ii < dataSNR1->size(); ii++) {
316 const t_polarPoint* point = dataSNR1->at(ii);
317 mean += point->_value;
318 }
319 mean /= dataSNR1->size();
320 double max = (mean > 9.0) ? 54.0 : 9.0;
321 QByteArray str = (mean > 9.0) ? "dbHz" : "";
322 emit dspSkyPlot(obsFile->fileName(), "SNR1", dataSNR1, "SNR2", dataSNR2,
323 str, max);
[4718]324 emit dspAvailPlot(obsFile->fileName(), title);
325 }
326 else {
327 for (int ii = 0; ii < dataMP1->size(); ii++) {
328 delete dataMP1->at(ii);
329 }
330 delete dataMP1;
331 for (int ii = 0; ii < dataMP2->size(); ii++) {
332 delete dataMP2->at(ii);
333 }
334 delete dataMP2;
335 for (int ii = 0; ii < dataSNR1->size(); ii++) {
336 delete dataSNR1->at(ii);
337 }
338 delete dataSNR1;
339 for (int ii = 0; ii < dataSNR2->size(); ii++) {
340 delete dataSNR2->at(ii);
341 }
342 delete dataSNR2;
343 _mutex.unlock();
344 }
[4254]345}
[4263]346
[6255]347//
[4263]348////////////////////////////////////////////////////////////////////////////
[6255]349t_irc t_reqcAnalyze::t_allObs::addObs(const t_satObs& obs, int slotNum) {
[4265]350
[6137]351 t_oneObs* newObs = new t_oneObs(obs._time.gpsw(), obs._time.gpssec());
[4354]352 bool okFlag = false;
[4338]353
[4608]354 // Availability and Slip Flags
355 // ---------------------------
[6137]356 double L1 = 0.0;
357 double L2 = 0.0;
358 double P1 = 0.0;
359 double P2 = 0.0;
360
361 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) {
362 const t_frqObs* frqObs = obs._obs[iFrq];
363 if (frqObs->_rnxType2ch[0] == '1') {
364 if (frqObs->_phaseValid) {
365 L1 = frqObs->_phase;
366 newObs->_hasL1 = true;
367 newObs->_slipL1 = frqObs->_slip;
368 }
369 if (frqObs->_codeValid) {
[6255]370 P1 = frqObs->_code;
[6137]371 }
372 if (frqObs->_snrValid) {
[6255]373 newObs->_SNR1 = frqObs->_snr;
[6137]374 }
375 }
376 else if ( (obs._prn.system() != 'E' && frqObs->_rnxType2ch[0] == '2') ||
377 (obs._prn.system() == 'E' && frqObs->_rnxType2ch[0] == '5') ) {
378 if (frqObs->_phaseValid) {
379 L2 = frqObs->_phase;
380 newObs->_hasL2 = true;
381 newObs->_slipL2 = frqObs->_slip;
382 }
383 if (frqObs->_codeValid) {
[6255]384 P2 = frqObs->_code;
[6137]385 }
386 if (frqObs->_snrValid) {
[6255]387 newObs->_SNR2 = frqObs->_snr;
[6137]388 }
389 }
[4571]390 }
[4608]391
392 // Compute the Multipath
393 // ----------------------
[4391]394 if (L1 != 0.0 && L2 != 0.0) {
[6017]395 double f1 = 0.0;
396 double f2 = 0.0;
[6137]397 if (obs._prn.system() == 'G') {
[6017]398 f1 = t_CST::freq(t_frequency::G1, 0);
399 f2 = t_CST::freq(t_frequency::G2, 0);
400 }
[6137]401 else if (obs._prn.system() == 'R') {
402 f1 = t_CST::freq(t_frequency::R1, slotNum);
403 f2 = t_CST::freq(t_frequency::R2, slotNum);
[6017]404 }
[6137]405 else if (obs._prn.system() == 'E') {
[6017]406 f1 = t_CST::freq(t_frequency::E1, 0);
407 f2 = t_CST::freq(t_frequency::E5, 0);
408 }
[4266]409
[4391]410 L1 = L1 * t_CST::c / f1;
411 L2 = L2 * t_CST::c / f2;
[4266]412
[4391]413 if (P1 != 0.0) {
414 newObs->_MP1 = P1 - L1 - 2.0*f2*f2/(f1*f1-f2*f2) * (L1 - L2);
[4354]415 okFlag = true;
[4268]416 }
[4391]417 if (P2 != 0.0) {
418 newObs->_MP2 = P2 - L2 - 2.0*f1*f1/(f1*f1-f2*f2) * (L1 - L2);
[4354]419 okFlag = true;
[4268]420 }
[4265]421 }
[4338]422
[4354]423 // Remember the Observation
424 // ------------------------
425 if (okFlag) {
[4584]426 _oneObsVec << newObs;
[4694]427 return success;
[4354]428 }
429 else {
430 delete newObs;
[4694]431 return failure;
[4354]432 }
[4263]433}
[4350]434
[6255]435//
[4350]436////////////////////////////////////////////////////////////////////////////
[4679]437void t_reqcAnalyze::prepareObsStat(unsigned iEpo, double obsInterval,
438 const ColumnVector& xyzSta) {
[4677]439 const int sampl = int(30.0 / obsInterval);
440 if (iEpo % sampl == 0) {
[4676]441 double mjdX24 = _currEpo->tt.mjddec() * 24.0;
442 if (iEpo != 0) {
443 _obsStat._mjdX24 << mjdX24;
444 _obsStat._numSat << _obsStat._numSat.last();
[4680]445 _obsStat._PDOP << _obsStat._PDOP.last();
[4676]446 }
447 _obsStat._mjdX24 << mjdX24;
[4675]448 _obsStat._numSat << _currEpo->rnxSat.size();
[4680]449 _obsStat._PDOP << cmpDOP(xyzSta);
[4675]450 }
451}
452
[6255]453//
[4675]454////////////////////////////////////////////////////////////////////////////
[6255]455void t_reqcAnalyze::preparePlotData(const QString& prn,
[4679]456 const ColumnVector& xyzSta,
[4572]457 double obsInterval,
[6255]458 QVector<t_polarPoint*>* dataMP1,
[4572]459 QVector<t_polarPoint*>* dataMP2,
[6255]460 QVector<t_polarPoint*>* dataSNR1,
[4675]461 QVector<t_polarPoint*>* dataSNR2) {
[4350]462
[6255]463 const int chunkStep = int( 30.0 / obsInterval); // chunk step (30 sec)
[4544]464 const int numEpo = int(600.0 / obsInterval); // # epochs in one chunk (10 min)
[4350]465
[4584]466 t_allObs& allObs = _allObsMap[prn];
467
[5141]468 bncSettings settings;
469 QString reqSkyPlotSystems = settings.value("reqcSkyPlotSystems").toString();
470 bool plotGPS = false;
471 bool plotGlo = false;
472 bool plotGal = false;
473 if (reqSkyPlotSystems == "GPS") {
474 plotGPS = true;
475 }
476 else if (reqSkyPlotSystems == "GLONASS") {
477 plotGlo = true;
478 }
479 else if (reqSkyPlotSystems == "Galileo") {
480 plotGal = true;
481 }
482 else {
483 plotGPS = true;
484 plotGlo = true;
485 plotGal = true;
486 }
487
[4591]488 // Loop over all Chunks of Data
489 // ----------------------------
[4702]490 bool slipFound = false;
[4584]491 for (int chunkStart = 0; chunkStart + numEpo < allObs._oneObsVec.size();
[4361]492 chunkStart += chunkStep) {
[4351]493
[4703]494 if (chunkStart * chunkStep == numEpo) {
[4702]495 slipFound = false;
496 }
497
[6255]498 // Chunk-Specific Variables
[4675]499 // ------------------------
[4591]500 bncTime currTime;
501 bncTime prevTime;
[4590]502 bncTime chunkStartTime;
[4675]503 double mjdX24 = 0.0;
[4607]504 bool availL1 = false;
505 bool availL2 = false;
506 bool gapL1 = false;
507 bool gapL2 = false;
508 bool slipL1 = false;
509 bool slipL2 = false;
510 double meanMP1 = 0.0;
511 double meanMP2 = 0.0;
512 double minSNR1 = 0.0;
513 double minSNR2 = 0.0;
514 double aziDeg = 0.0;
515 double zenDeg = 0.0;
[4659]516 bool zenFlag = false;
[4353]517
[4591]518 // Loop over all Epochs within one Chunk of Data
519 // ---------------------------------------------
[5140]520 bool slotSet = false;
[4361]521 for (int ii = 0; ii < numEpo; ii++) {
[4351]522 int iEpo = chunkStart + ii;
[4584]523 const t_oneObs* oneObs = allObs._oneObsVec[iEpo];
[5140]524 if (oneObs->_slotSet) {
525 slotSet = true;
526 }
[4572]527
[4590]528 currTime.set(oneObs->_GPSWeek, oneObs->_GPSWeeks);
529
530 // Compute the Azimuth and Zenith Distance
531 // ---------------------------------------
[4572]532 if (ii == 0) {
[4590]533 chunkStartTime = currTime;
[4675]534 mjdX24 = chunkStartTime.mjddec() * 24.0;
[4590]535
[4679]536 if (xyzSta.size()) {
[4590]537 t_eph* eph = 0;
538 for (int ie = 0; ie < _ephs.size(); ie++) {
[5776]539 if (QString(_ephs[ie]->prn().toString().c_str()) == prn) {
[4590]540 eph = _ephs[ie];
541 break;
542 }
543 }
[6255]544
[4590]545 if (eph) {
[6109]546 ColumnVector xc(4);
547 ColumnVector vv(3);
[6213]548 if (eph->getCrd(bncTime(oneObs->_GPSWeek, oneObs->_GPSWeeks), xc, vv, false) == success) {
549 double rho, eleSat, azSat;
550 topos(xyzSta(1), xyzSta(2), xyzSta(3), xc(1), xc(2), xc(3), rho, eleSat, azSat);
551 aziDeg = azSat * 180.0/M_PI;
552 zenDeg = 90.0 - eleSat * 180.0/M_PI;
553 zenFlag = true;
554 }
[4590]555 }
556 }
[4572]557 }
[6255]558
[4590]559 // Check Interval
560 // --------------
561 if (prevTime.valid()) {
[4591]562 double dt = currTime - prevTime;
563 if (dt != obsInterval) {
564 gapL1 = true;
565 gapL2 = true;
566 }
[4590]567 }
568 prevTime = currTime;
[4563]569
[4590]570 // Check L1 and L2 availability
571 // ----------------------------
572 if (oneObs->_hasL1) {
573 availL1 = true;
[4566]574 }
[4590]575 else {
[4591]576 gapL1 = true;
[4566]577 }
[4590]578 if (oneObs->_hasL2) {
579 availL2 = true;
580 }
581 else {
[4591]582 gapL2 = true;
[4590]583 }
584
585 // Check Minimal Signal-to-Noise Ratio
586 // -----------------------------------
587 if ( oneObs->_SNR1 > 0 && (minSNR1 == 0 || minSNR1 > oneObs->_SNR1) ) {
588 minSNR1 = oneObs->_SNR1;
589 }
590 if ( oneObs->_SNR2 > 0 && (minSNR2 == 0 || minSNR2 > oneObs->_SNR2) ) {
591 minSNR2 = oneObs->_SNR2;
592 }
593
[4607]594 // Check Slip Flags
595 // ----------------
596 if (oneObs->_slipL1) {
597 slipL1 = true;
598 }
599 if (oneObs->_slipL2) {
600 slipL2 = true;
601 }
602
[4698]603 meanMP1 += oneObs->_MP1;
604 meanMP2 += oneObs->_MP2;
605 }
606
607 // Compute the Multipath
608 // ---------------------
[5141]609 if ( (prn[0] == 'G' && plotGPS ) ||
610 (prn[0] == 'R' && plotGlo && slotSet) ||
611 (prn[0] == 'E' && plotGal ) ) {
[4700]612 bool slipMP = false;
613 meanMP1 /= numEpo;
614 meanMP2 /= numEpo;
615 double MP1 = 0.0;
616 double MP2 = 0.0;
617 for (int ii = 0; ii < numEpo; ii++) {
618 int iEpo = chunkStart + ii;
619 const t_oneObs* oneObs = allObs._oneObsVec[iEpo];
620 double diff1 = oneObs->_MP1 - meanMP1;
621 double diff2 = oneObs->_MP2 - meanMP2;
[6255]622
[4700]623 // Check Slip Threshold
624 // --------------------
625 if (fabs(diff1) > SLIPTRESH || fabs(diff2) > SLIPTRESH) {
626 slipMP = true;
627 break;
628 }
[6255]629
[4700]630 MP1 += diff1 * diff1;
631 MP2 += diff2 * diff2;
[4353]632 }
[4700]633 if (slipMP) {
634 slipL1 = true;
635 slipL2 = true;
[4702]636 if (!slipFound) {
637 slipFound = true;
638 _obsStat._prnStat[prn]._numSlipsFound += 1;
639 }
[6255]640 }
[4700]641 else {
642 MP1 = sqrt(MP1 / (numEpo-1));
643 MP2 = sqrt(MP2 / (numEpo-1));
644 (*dataMP1) << (new t_polarPoint(aziDeg, zenDeg, MP1));
645 (*dataMP2) << (new t_polarPoint(aziDeg, zenDeg, MP2));
646 }
[4353]647 }
648
[4590]649 // Availability Plot Data
650 // ----------------------
651 if (availL1) {
[4607]652 if (slipL1) {
[4617]653 _availDataMap[prn]._L1slip << mjdX24;
[4591]654 }
655 else if (gapL1) {
[4617]656 _availDataMap[prn]._L1gap << mjdX24;
[4591]657 }
658 else {
[4617]659 _availDataMap[prn]._L1ok << mjdX24;
[4591]660 }
[4351]661 }
[4591]662 if (availL2) {
[4607]663 if (slipL2) {
[4617]664 _availDataMap[prn]._L2slip << mjdX24;
[4591]665 }
666 else if (gapL2) {
[4617]667 _availDataMap[prn]._L2gap << mjdX24;
[4591]668 }
669 else {
[4617]670 _availDataMap[prn]._L2ok << mjdX24;
[4591]671 }
672 }
[4659]673 if (zenFlag) {
[4662]674 _availDataMap[prn]._eleTim << mjdX24;
675 _availDataMap[prn]._eleDeg << 90.0 - zenDeg;
[4659]676 }
[4351]677
[5142]678 // Signal-to-Noise Ratio Plot Data
679 // -------------------------------
[5143]680 if ( (prn[0] == 'G' && plotGPS) ||
681 (prn[0] == 'R' && plotGlo) ||
682 (prn[0] == 'E' && plotGal) ) {
[5141]683 (*dataSNR1) << (new t_polarPoint(aziDeg, zenDeg, minSNR1));
684 (*dataSNR2) << (new t_polarPoint(aziDeg, zenDeg, minSNR2));
685 }
[4350]686 }
687}
[4572]688
[6255]689//
[4572]690////////////////////////////////////////////////////////////////////////////
[6255]691void t_reqcAnalyze::slotDspAvailPlot(const QString& fileName,
[4584]692 const QByteArray& title) {
[4572]693
[5068]694 if (BNC_CORE->GUIenabled()) {
[4659]695 t_availPlot* plotA = new t_availPlot(0, &_availDataMap);
696 plotA->setTitle(title);
[4573]697
[4662]698 t_elePlot* plotZ = new t_elePlot(0, &_availDataMap);
[4659]699
[4672]700 t_dopPlot* plotD = new t_dopPlot(0, &_obsStat);
[4671]701
[4573]702 QVector<QWidget*> plots;
[4671]703 plots << plotA << plotZ << plotD;
[4573]704 t_graphWin* graphWin = new t_graphWin(0, fileName, plots, 0, 0);
[4666]705
706 int ww = QFontMetrics(graphWin->font()).width('w');
707 graphWin->setMinimumSize(120*ww, 40*ww);
708
[4573]709 graphWin->show();
710
711 bncSettings settings;
712 QString dirName = settings.value("reqcPlotDir").toString();
713 if (!dirName.isEmpty()) {
[4606]714 QByteArray ext = "_A.png";
[4579]715 graphWin->savePNG(dirName, ext);
[4573]716 }
717 }
[4715]718 _mutex.unlock();
[4572]719}
[4679]720
721// Compute Dilution of Precision
722////////////////////////////////////////////////////////////////////////////
723double t_reqcAnalyze::cmpDOP(const ColumnVector& xyzSta) const {
724
725 if (xyzSta.size() != 3) {
726 return 0.0;
727 }
728
729 unsigned nSat = _currEpo->rnxSat.size();
730
731 if (nSat < 4) {
732 return 0.0;
733 }
734
735 Matrix AA(nSat, 4);
736
737 unsigned nSatUsed = 0;
738 for (unsigned iSat = 0; iSat < nSat; iSat++) {
739
740 const t_rnxObsFile::t_rnxSat& rnxSat = _currEpo->rnxSat[iSat];
[6122]741 const t_prn& prn = rnxSat.prn;
[4679]742
743 t_eph* eph = 0;
744 for (int ie = 0; ie < _ephs.size(); ie++) {
[6122]745 if (_ephs[ie]->prn() == prn) {
[4679]746 eph = _ephs[ie];
747 break;
748 }
749 }
750 if (eph) {
[6109]751 ColumnVector xSat(4);
752 ColumnVector vv(3);
[6213]753 if (eph->getCrd(_currEpo->tt, xSat, vv, false) == success) {
754 ++nSatUsed;
755 ColumnVector dx = xSat.Rows(1,3) - xyzSta;
756 double rho = dx.norm_Frobenius();
757 AA(nSatUsed,1) = dx(1) / rho;
758 AA(nSatUsed,2) = dx(2) / rho;
759 AA(nSatUsed,3) = dx(3) / rho;
760 AA(nSatUsed,4) = 1.0;
761 }
[4679]762 }
[4681]763 }
[4679]764
[4681]765 if (nSatUsed < 4) {
766 return 0.0;
[4679]767 }
768
[4681]769 AA = AA.Rows(1, nSatUsed);
770
[6255]771 SymmetricMatrix QQ;
[4681]772 QQ << AA.t() * AA;
773 QQ = QQ.i();
774
775 return sqrt(QQ.trace());
[4679]776}
[4689]777
778// Finish the report
779////////////////////////////////////////////////////////////////////////////
[4696]780void t_reqcAnalyze::printReport(QVector<t_polarPoint*>* dataMP1,
781 QVector<t_polarPoint*>* dataMP2,
782 QVector<t_polarPoint*>* dataSNR1,
783 QVector<t_polarPoint*>* dataSNR2) {
[5368]784
[4689]785 if (!_log) {
786 return;
787 }
788
[6255]789 *_log << "Marker name: " << _obsStat._markerName << endl
[4701]790 << "Receiver: " << _obsStat._receiverType << endl
791 << "Antenna: " << _obsStat._antennaName << endl
792 << "Start time: " << _obsStat._startTime.datestr().c_str() << ' '
793 << _obsStat._startTime.timestr().c_str() << endl
794 << "End time: " << _obsStat._endTime.datestr().c_str() << ' '
795 << _obsStat._endTime.timestr().c_str() << endl
796 << "Interval: " << _obsStat._interval << endl
797 << "# Sat.: " << _obsStat._prnStat.size() << endl;
[4689]798
[4701]799 int numObs = 0;
800 int numSlipsFlagged = 0;
801 int numSlipsFound = 0;
[4693]802 QMapIterator<QString, t_prnStat> it(_obsStat._prnStat);
803 while (it.hasNext()) {
804 it.next();
805 const t_prnStat& prnStat = it.value();
[4701]806 numObs += prnStat._numObs;
807 numSlipsFlagged += prnStat._numSlipsFlagged;
808 numSlipsFound += prnStat._numSlipsFound;
[4693]809 }
[4701]810 *_log << "# Obs.: " << numObs << endl
811 << "# Slips (file): " << numSlipsFlagged << endl
812 << "# Slips (found): " << numSlipsFound << endl;
[4693]813
[4697]814 for (int kk = 1; kk <= 4; kk++) {
815 QVector<t_polarPoint*>* data = 0;
816 QString text;
817 if (kk == 1) {
818 data = dataMP1;
[4701]819 text = "Mean MP1: ";
[4697]820 }
821 else if (kk == 2) {
822 data = dataMP2;
[4701]823 text = "Mean MP2: ";
[4697]824 }
825 else if (kk == 3) {
826 data = dataSNR1;
[4701]827 text = "Mean SNR1: ";
[4697]828 }
829 else if (kk == 4) {
830 data = dataSNR2;
[4701]831 text = "Mean SNR2: ";
[4697]832 }
833 double mean = 0.0;
834 for (int ii = 0; ii < data->size(); ii++) {
835 const t_polarPoint* point = data->at(ii);
836 mean += point->_value;
837 }
838 mean /= data->size();
839 *_log << text << mean << endl;
840 }
841
[4689]842 _log->flush();
843}
Note: See TracBrowser for help on using the repository browser.