Changeset 6271 in ntrip for trunk/BNC/src
- Timestamp:
- Oct 31, 2014, 5:45:35 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/src/rinex/reqcanalyze.cpp
r6269 r6271 56 56 using namespace std; 57 57 58 const double SLIPTRESH = 10.0; // cycle-slip threshold (meters)59 60 58 // Constructor 61 59 //////////////////////////////////////////////////////////////////////////// … … 67 65 _logFile = 0; 68 66 _log = 0; 67 _currEpo = 0; 69 68 _obsFileNames = settings.value("reqcObsFile").toString().split(",", QString::SkipEmptyParts); 70 69 _navFileNames = settings.value("reqcNavFile").toString().split(",", QString::SkipEmptyParts); 71 72 _currEpo = 0;73 74 connect(this, SIGNAL(dspSkyPlot(const QString&,75 const QByteArray&,76 QVector<t_polarPoint*>*,77 const QByteArray&,78 QVector<t_polarPoint*>*,79 const QByteArray&, double)),80 this, SLOT(slotDspSkyPlot(const QString&,81 const QByteArray&,82 QVector<t_polarPoint*>*,83 const QByteArray&,84 QVector<t_polarPoint*>*,85 const QByteArray&, double)));86 87 connect(this, SIGNAL(dspAvailPlot(const QString&, const QByteArray&)),88 this, SLOT(slotDspAvailPlot(const QString&, const QByteArray&)));89 70 } 90 71 … … 102 83 if (BNC_CORE->mode() != t_bncCore::interactive) { 103 84 qApp->exit(0); 104 }105 }106 107 //108 ////////////////////////////////////////////////////////////////////////////109 void t_reqcAnalyze::slotDspSkyPlot(const QString& fileName,110 const QByteArray& title1,111 QVector<t_polarPoint*>* data1,112 const QByteArray& title2,113 QVector<t_polarPoint*>* data2,114 const QByteArray& scaleTitle,115 double maxValue) {116 117 if (BNC_CORE->GUIenabled()) {118 119 if (maxValue == 0.0) {120 if (data1) {121 for (int ii = 0; ii < data1->size(); ii++) {122 double val = data1->at(ii)->_value;123 if (maxValue < val) {124 maxValue = val;125 }126 }127 }128 if (data2) {129 for (int ii = 0; ii < data2->size(); ii++) {130 double val = data2->at(ii)->_value;131 if (maxValue < val) {132 maxValue = val;133 }134 }135 }136 }137 138 QwtInterval scaleInterval(0.0, maxValue);139 140 QVector<QWidget*> plots;141 if (data1) {142 t_polarPlot* plot1 = new t_polarPlot(QwtText(title1), scaleInterval,143 BNC_CORE->mainWindow());144 plot1->addCurve(data1);145 plots << plot1;146 }147 if (data2) {148 t_polarPlot* plot2 = new t_polarPlot(QwtText(title2), scaleInterval,149 BNC_CORE->mainWindow());150 plot2->addCurve(data2);151 plots << plot2;152 }153 154 t_graphWin* graphWin = new t_graphWin(0, fileName, plots,155 &scaleTitle, &scaleInterval);156 157 graphWin->show();158 159 bncSettings settings;160 QString dirName = settings.value("reqcPlotDir").toString();161 if (!dirName.isEmpty()) {162 QByteArray ext = (scaleTitle == "Meters") ? "_M.png" : "_S.png";163 graphWin->savePNG(dirName, ext);164 }165 85 } 166 86 } … … 202 122 void t_reqcAnalyze::analyzeFile(t_rnxObsFile* obsFile) { 203 123 204 _mutex.lock();124 QMutexLocker lock(&_mutex); 205 125 206 126 if (_log) { … … 210 130 } 211 131 212 _allObsMap.clear(); 213 _availDataMap.clear(); 214 _obsStat.reset(); 132 _qcFile.clear(); 215 133 216 134 // A priori Coordinates … … 221 139 // -------------------- 222 140 try { 223 unsigned iEpo = 0;141 bool firstEpo = true; 224 142 while ( (_currEpo = obsFile->nextEpoch()) != 0) { 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; 143 if (firstEpo) { 144 firstEpo = false; 145 _qcFile._startTime = _currEpo->tt; 146 _qcFile._antennaName = obsFile->antennaName(); 147 _qcFile._markerName = obsFile->markerName(); 148 _qcFile._receiverType = obsFile->receiverType(); 149 _qcFile._interval = obsFile->interval(); 150 } 151 _qcFile._endTime = _currEpo->tt; 152 153 t_qcEpo qcEpo; 154 qcEpo._epoTime = _currEpo->tt; 155 qcEpo._PDOP = cmpDOP(xyzSta); 234 156 235 157 // Loop over all satellites … … 237 159 for (unsigned iObs = 0; iObs < _currEpo->rnxSat.size(); iObs++) { 238 160 const t_rnxObsFile::t_rnxSat& rnxSat = _currEpo->rnxSat[iObs]; 239 t_satObs obs; 240 t_rnxObsFile::setObsFromRnx(obsFile, _currEpo, rnxSat, obs); 241 242 const t_prn& prn = obs._prn; 243 244 t_ephGlo* ephGlo = 0; 245 int slotNum = 0; 246 if (prn.system() == 'R') { 247 for (int ie = 0; ie < _ephs.size(); ie++) { 248 if (_ephs[ie]->prn() == prn) { 249 ephGlo = dynamic_cast<t_ephGlo*>(_ephs[ie]); 250 break; 251 } 252 } 253 if (ephGlo) { 254 slotNum = ephGlo->slotNum(); 255 } 256 } 257 258 t_irc irc = _allObsMap[prn].addObs(obs, slotNum); 259 260 if (irc == success) { 261 t_oneObs* newObs = _allObsMap[prn]._oneObsVec.last(); 262 if (ephGlo) { 263 newObs->_slotSet = true; 264 } 265 if (newObs->_hasL1 && newObs->_hasL2) { 266 _obsStat._prnStat[prn]._numObs += 1; 267 } 268 if (newObs->_slipL1 && newObs->_slipL2) { 269 _obsStat._prnStat[prn]._numSlipsFlagged += 1; 270 } 271 } 272 } 273 274 prepareObsStat(iEpo, obsFile->interval(), xyzSta); 275 iEpo++; 276 277 } // while (_currEpo) 161 t_satObs satObs; 162 t_rnxObsFile::setObsFromRnx(obsFile, _currEpo, rnxSat, satObs); 163 t_qcObs qcObs; 164 if (setQcObs(satObs, qcObs) == success) { 165 qcEpo._qcObs[satObs._prn] = qcObs; 166 updateQcSat(qcObs, _qcFile._qcSat[satObs._prn]); 167 } 168 } 169 _qcFile._qcEpo.push_back(qcEpo); 170 } 171 172 preparePlotData(obsFile); 173 174 printReport(); 278 175 } 279 176 catch (QString str) { … … 284 181 qDebug() << str; 285 182 } 286 _mutex.unlock(); 287 return; 288 } 289 290 // Analyze the Multipath 291 // --------------------- 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*>; 296 297 QMutableMapIterator<t_prn, t_allObs> it(_allObsMap); 298 while (it.hasNext()) { 299 it.next(); 300 const t_prn& prn = it.key(); 301 preparePlotData(prn, xyzSta, obsFile->interval(), 302 dataMP1, dataMP2, dataSNR1, dataSNR2); 303 } 304 305 printReport(dataMP1, dataMP2, dataSNR1, dataSNR2); 306 307 // Show the plots 308 // -------------- 309 if (BNC_CORE->GUIenabled()) { 310 QFileInfo fileInfo(obsFile->fileName()); 311 QByteArray title = fileInfo.fileName().toAscii(); 312 emit dspSkyPlot(obsFile->fileName(), "MP1", dataMP1, "MP2", dataMP2, 313 "Meters", 2.0); 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 if (dataSNR1->size() > 0) { 320 mean /= dataSNR1->size(); 321 } 322 double max = (mean > 9.0) ? 54.0 : 9.0; 323 QByteArray str = (mean > 9.0) ? "dbHz" : ""; 324 emit dspSkyPlot(obsFile->fileName(), "SNR1", dataSNR1, "SNR2", dataSNR2, 325 str, max); 326 emit dspAvailPlot(obsFile->fileName(), title); 327 } 328 else { 329 for (int ii = 0; ii < dataMP1->size(); ii++) { 330 delete dataMP1->at(ii); 331 } 332 delete dataMP1; 333 for (int ii = 0; ii < dataMP2->size(); ii++) { 334 delete dataMP2->at(ii); 335 } 336 delete dataMP2; 337 for (int ii = 0; ii < dataSNR1->size(); ii++) { 338 delete dataSNR1->at(ii); 339 } 340 delete dataSNR1; 341 for (int ii = 0; ii < dataSNR2->size(); ii++) { 342 delete dataSNR2->at(ii); 343 } 344 delete dataSNR2; 345 _mutex.unlock(); 346 } 347 } 348 349 // 350 //////////////////////////////////////////////////////////////////////////// 351 t_irc t_reqcAnalyze::t_allObs::addObs(const t_satObs& obs, int slotNum) { 352 353 t_oneObs* newObs = new t_oneObs(obs._time.gpsw(), obs._time.gpssec()); 354 bool okFlag = false; 355 356 // Availability and Slip Flags 357 // --------------------------- 358 double L1 = 0.0; 359 double L2 = 0.0; 360 double P1 = 0.0; 361 double P2 = 0.0; 362 363 for (unsigned iFrq = 0; iFrq < obs._obs.size(); iFrq++) { 364 const t_frqObs* frqObs = obs._obs[iFrq]; 365 if (frqObs->_rnxType2ch[0] == '1') { 366 if (frqObs->_phaseValid) { 367 L1 = frqObs->_phase; 368 newObs->_hasL1 = true; 369 newObs->_slipL1 = frqObs->_slip; 370 } 371 if (frqObs->_codeValid) { 372 P1 = frqObs->_code; 373 } 374 if (frqObs->_snrValid) { 375 newObs->_SNR1 = frqObs->_snr; 376 } 377 } 378 else if ( (obs._prn.system() != 'E' && frqObs->_rnxType2ch[0] == '2') || 379 (obs._prn.system() == 'E' && frqObs->_rnxType2ch[0] == '5') ) { 380 if (frqObs->_phaseValid) { 381 L2 = frqObs->_phase; 382 newObs->_hasL2 = true; 383 newObs->_slipL2 = frqObs->_slip; 384 } 385 if (frqObs->_codeValid) { 386 P2 = frqObs->_code; 387 } 388 if (frqObs->_snrValid) { 389 newObs->_SNR2 = frqObs->_snr; 390 } 391 } 392 } 393 394 // Compute the Multipath 395 // ---------------------- 396 if (L1 != 0.0 && L2 != 0.0) { 397 double f1 = 0.0; 398 double f2 = 0.0; 399 if (obs._prn.system() == 'G') { 400 f1 = t_CST::freq(t_frequency::G1, 0); 401 f2 = t_CST::freq(t_frequency::G2, 0); 402 } 403 else if (obs._prn.system() == 'R') { 404 f1 = t_CST::freq(t_frequency::R1, slotNum); 405 f2 = t_CST::freq(t_frequency::R2, slotNum); 406 } 407 else if (obs._prn.system() == 'E') { 408 f1 = t_CST::freq(t_frequency::E1, 0); 409 f2 = t_CST::freq(t_frequency::E5, 0); 410 } 411 412 L1 = L1 * t_CST::c / f1; 413 L2 = L2 * t_CST::c / f2; 414 415 if (P1 != 0.0) { 416 newObs->_MP1 = P1 - L1 - 2.0*f2*f2/(f1*f1-f2*f2) * (L1 - L2); 417 okFlag = true; 418 } 419 if (P2 != 0.0) { 420 newObs->_MP2 = P2 - L2 - 2.0*f1*f1/(f1*f1-f2*f2) * (L1 - L2); 421 okFlag = true; 422 } 423 } 424 425 // Remember the Observation 426 // ------------------------ 427 if (okFlag) { 428 _oneObsVec << newObs; 429 return success; 430 } 431 else { 432 delete newObs; 433 return failure; 434 } 435 } 436 437 // 438 //////////////////////////////////////////////////////////////////////////// 439 void t_reqcAnalyze::prepareObsStat(unsigned iEpo, double obsInterval, 440 const ColumnVector& xyzSta) { 441 const int sampl = int(30.0 / obsInterval); 442 if (iEpo % sampl == 0) { 443 double mjdX24 = _currEpo->tt.mjddec() * 24.0; 444 if (iEpo != 0) { 445 _obsStat._mjdX24 << mjdX24; 446 _obsStat._numSat << _obsStat._numSat.last(); 447 _obsStat._PDOP << _obsStat._PDOP.last(); 448 } 449 _obsStat._mjdX24 << mjdX24; 450 _obsStat._numSat << _currEpo->rnxSat.size(); 451 _obsStat._PDOP << cmpDOP(xyzSta); 452 } 453 } 454 455 // 456 //////////////////////////////////////////////////////////////////////////// 457 void t_reqcAnalyze::preparePlotData(const t_prn& prn, 458 const ColumnVector& xyzSta, 459 double obsInterval, 460 QVector<t_polarPoint*>* dataMP1, 461 QVector<t_polarPoint*>* dataMP2, 462 QVector<t_polarPoint*>* dataSNR1, 463 QVector<t_polarPoint*>* dataSNR2) { 464 465 const int chunkStep = int( 30.0 / obsInterval); // chunk step (30 sec) 466 const int numEpo = int(600.0 / obsInterval); // # epochs in one chunk (10 min) 467 468 t_allObs& allObs = _allObsMap[prn]; 469 470 bncSettings settings; 471 QString reqSkyPlotSystems = settings.value("reqcSkyPlotSystems").toString(); 472 bool plotGPS = false; 473 bool plotGlo = false; 474 bool plotGal = false; 475 if (reqSkyPlotSystems == "GPS") { 476 plotGPS = true; 477 } 478 else if (reqSkyPlotSystems == "GLONASS") { 479 plotGlo = true; 480 } 481 else if (reqSkyPlotSystems == "Galileo") { 482 plotGal = true; 483 } 484 else { 485 plotGPS = true; 486 plotGlo = true; 487 plotGal = true; 488 } 489 490 // Loop over all Chunks of Data 491 // ---------------------------- 492 bool slipFound = false; 493 for (int chunkStart = 0; chunkStart + numEpo < allObs._oneObsVec.size(); 494 chunkStart += chunkStep) { 495 496 if (chunkStart * chunkStep == numEpo) { 497 slipFound = false; 498 } 499 500 // Chunk-Specific Variables 501 // ------------------------ 502 bncTime currTime; 503 bncTime prevTime; 504 bncTime chunkStartTime; 505 double mjdX24 = 0.0; 506 bool availL1 = false; 507 bool availL2 = false; 508 bool gapL1 = false; 509 bool gapL2 = false; 510 bool slipL1 = false; 511 bool slipL2 = false; 512 double meanMP1 = 0.0; 513 double meanMP2 = 0.0; 514 double minSNR1 = 0.0; 515 double minSNR2 = 0.0; 516 double aziDeg = 0.0; 517 double zenDeg = 0.0; 518 bool zenFlag = false; 519 520 // Loop over all Epochs within one Chunk of Data 521 // --------------------------------------------- 522 bool slotSet = false; 523 for (int ii = 0; ii < numEpo; ii++) { 524 int iEpo = chunkStart + ii; 525 const t_oneObs* oneObs = allObs._oneObsVec[iEpo]; 526 if (oneObs->_slotSet) { 527 slotSet = true; 528 } 529 530 currTime.set(oneObs->_GPSWeek, oneObs->_GPSWeeks); 531 532 // Compute the Azimuth and Zenith Distance 533 // --------------------------------------- 534 if (ii == 0) { 535 chunkStartTime = currTime; 536 mjdX24 = chunkStartTime.mjddec() * 24.0; 537 538 if (xyzSta.size()) { 539 t_eph* eph = 0; 540 for (int ie = 0; ie < _ephs.size(); ie++) { 541 if (_ephs[ie]->prn() == prn) { 542 eph = _ephs[ie]; 543 break; 544 } 545 } 546 547 if (eph) { 548 ColumnVector xc(4); 549 ColumnVector vv(3); 550 if (eph->getCrd(bncTime(oneObs->_GPSWeek, oneObs->_GPSWeeks), xc, vv, false) == success) { 551 double rho, eleSat, azSat; 552 topos(xyzSta(1), xyzSta(2), xyzSta(3), xc(1), xc(2), xc(3), rho, eleSat, azSat); 553 aziDeg = azSat * 180.0/M_PI; 554 zenDeg = 90.0 - eleSat * 180.0/M_PI; 555 zenFlag = true; 556 } 557 } 558 } 559 } 560 561 // Check Interval 562 // -------------- 563 if (prevTime.valid()) { 564 double dt = currTime - prevTime; 565 if (dt > 1.5 * obsInterval) { 566 gapL1 = true; 567 gapL2 = true; 568 } 569 } 570 prevTime = currTime; 571 572 // Check L1 and L2 availability 573 // ---------------------------- 574 if (oneObs->_hasL1) { 575 availL1 = true; 576 } 577 else { 578 gapL1 = true; 579 } 580 if (oneObs->_hasL2) { 581 availL2 = true; 582 } 583 else { 584 gapL2 = true; 585 } 586 587 // Check Minimal Signal-to-Noise Ratio 588 // ----------------------------------- 589 if ( oneObs->_SNR1 > 0 && (minSNR1 == 0 || minSNR1 > oneObs->_SNR1) ) { 590 minSNR1 = oneObs->_SNR1; 591 } 592 if ( oneObs->_SNR2 > 0 && (minSNR2 == 0 || minSNR2 > oneObs->_SNR2) ) { 593 minSNR2 = oneObs->_SNR2; 594 } 595 596 // Check Slip Flags 597 // ---------------- 598 if (oneObs->_slipL1) { 599 slipL1 = true; 600 } 601 if (oneObs->_slipL2) { 602 slipL2 = true; 603 } 604 605 meanMP1 += oneObs->_MP1; 606 meanMP2 += oneObs->_MP2; 607 } 608 609 // Compute the Multipath 610 // --------------------- 611 if ( (prn.system() == 'G' && plotGPS ) || 612 (prn.system() == 'R' && plotGlo && slotSet) || 613 (prn.system() == 'E' && plotGal ) ) { 614 bool slipMP = false; 615 meanMP1 /= numEpo; 616 meanMP2 /= numEpo; 617 double MP1 = 0.0; 618 double MP2 = 0.0; 619 for (int ii = 0; ii < numEpo; ii++) { 620 int iEpo = chunkStart + ii; 621 const t_oneObs* oneObs = allObs._oneObsVec[iEpo]; 622 double diff1 = oneObs->_MP1 - meanMP1; 623 double diff2 = oneObs->_MP2 - meanMP2; 624 625 // Check Slip Threshold 626 // -------------------- 627 if (fabs(diff1) > SLIPTRESH || fabs(diff2) > SLIPTRESH) { 628 slipMP = true; 629 break; 630 } 631 632 MP1 += diff1 * diff1; 633 MP2 += diff2 * diff2; 634 } 635 if (slipMP) { 636 slipL1 = true; 637 slipL2 = true; 638 if (!slipFound) { 639 slipFound = true; 640 _obsStat._prnStat[prn]._numSlipsFound += 1; 641 } 642 } 643 else { 644 MP1 = sqrt(MP1 / (numEpo-1)); 645 MP2 = sqrt(MP2 / (numEpo-1)); 646 (*dataMP1) << (new t_polarPoint(aziDeg, zenDeg, MP1)); 647 (*dataMP2) << (new t_polarPoint(aziDeg, zenDeg, MP2)); 648 } 649 } 650 651 // Availability Plot Data 652 // ---------------------- 653 if (availL1) { 654 if (slipL1) { 655 _availDataMap[prn]._L1slip << mjdX24; 656 } 657 else if (gapL1) { 658 _availDataMap[prn]._L1gap << mjdX24; 659 } 660 else { 661 _availDataMap[prn]._L1ok << mjdX24; 662 } 663 } 664 if (availL2) { 665 if (slipL2) { 666 _availDataMap[prn]._L2slip << mjdX24; 667 } 668 else if (gapL2) { 669 _availDataMap[prn]._L2gap << mjdX24; 670 } 671 else { 672 _availDataMap[prn]._L2ok << mjdX24; 673 } 674 } 675 if (zenFlag) { 676 _availDataMap[prn]._eleTim << mjdX24; 677 _availDataMap[prn]._eleDeg << 90.0 - zenDeg; 678 } 679 680 // Signal-to-Noise Ratio Plot Data 681 // ------------------------------- 682 if ( (prn.system() == 'G' && plotGPS) || 683 (prn.system() == 'R' && plotGlo) || 684 (prn.system() == 'E' && plotGal) ) { 685 (*dataSNR1) << (new t_polarPoint(aziDeg, zenDeg, minSNR1)); 686 (*dataSNR2) << (new t_polarPoint(aziDeg, zenDeg, minSNR2)); 687 } 688 } 689 } 690 691 // 692 //////////////////////////////////////////////////////////////////////////// 693 void t_reqcAnalyze::slotDspAvailPlot(const QString& fileName, 694 const QByteArray& title) { 695 696 if (BNC_CORE->GUIenabled()) { 697 t_availPlot* plotA = new t_availPlot(0, &_availDataMap); 698 plotA->setTitle(title); 699 700 t_elePlot* plotZ = new t_elePlot(0, &_availDataMap); 701 702 t_dopPlot* plotD = new t_dopPlot(0, &_obsStat); 703 704 QVector<QWidget*> plots; 705 plots << plotA << plotZ << plotD; 706 t_graphWin* graphWin = new t_graphWin(0, fileName, plots, 0, 0); 707 708 int ww = QFontMetrics(graphWin->font()).width('w'); 709 graphWin->setMinimumSize(120*ww, 40*ww); 710 711 graphWin->show(); 712 713 bncSettings settings; 714 QString dirName = settings.value("reqcPlotDir").toString(); 715 if (!dirName.isEmpty()) { 716 QByteArray ext = "_A.png"; 717 graphWin->savePNG(dirName, ext); 718 } 719 } 720 _mutex.unlock(); 183 } 721 184 } 722 185 … … 778 241 } 779 242 243 // 244 //////////////////////////////////////////////////////////////////////////// 245 void t_reqcAnalyze::updateQcSat(const t_qcObs& qcObs, t_qcSat& qcSat) { 246 if (qcObs._hasL1 && qcObs._hasL2) { 247 qcSat._numObs += 1; 248 } 249 if (qcObs._slipL1 && qcObs._slipL2) { 250 qcSat._numSlipsFlagged += 1; 251 } 252 } 253 254 // 255 //////////////////////////////////////////////////////////////////////////// 256 t_irc t_reqcAnalyze::setQcObs(const t_satObs& satObs, t_qcObs& qcObs) { 257 258 if (satObs._prn.system() == 'R') { 259 t_ephGlo* ephGlo = 0; 260 for (int ie = 0; ie < _ephs.size(); ie++) { 261 if (_ephs[ie]->prn() == satObs._prn) { 262 ephGlo = dynamic_cast<t_ephGlo*>(_ephs[ie]); 263 break; 264 } 265 } 266 if (ephGlo) { 267 qcObs._slotSet = true; 268 qcObs._slotNum = ephGlo->slotNum(); 269 } 270 } 271 272 bool okFlag = false; 273 274 // Availability and Slip Flags 275 // --------------------------- 276 double L1 = 0.0; 277 double L2 = 0.0; 278 double P1 = 0.0; 279 double P2 = 0.0; 280 281 for (unsigned iFrq = 0; iFrq < satObs._obs.size(); iFrq++) { 282 const t_frqObs* frqObs = satObs._obs[iFrq]; 283 if (frqObs->_rnxType2ch[0] == '1') { 284 if (frqObs->_phaseValid) { 285 L1 = frqObs->_phase; 286 qcObs._hasL1 = true; 287 qcObs._slipL1 = frqObs->_slip; 288 } 289 if (frqObs->_codeValid) { 290 P1 = frqObs->_code; 291 } 292 if (frqObs->_snrValid) { 293 qcObs._SNR1 = frqObs->_snr; 294 } 295 } 296 else if ( (satObs._prn.system() != 'E' && frqObs->_rnxType2ch[0] == '2') || 297 (satObs._prn.system() == 'E' && frqObs->_rnxType2ch[0] == '5') ) { 298 if (frqObs->_phaseValid) { 299 L2 = frqObs->_phase; 300 qcObs._hasL2 = true; 301 qcObs._slipL2 = frqObs->_slip; 302 } 303 if (frqObs->_codeValid) { 304 P2 = frqObs->_code; 305 } 306 if (frqObs->_snrValid) { 307 qcObs._SNR2 = frqObs->_snr; 308 } 309 } 310 } 311 312 // Compute the Multipath 313 // ---------------------- 314 if (L1 != 0.0 && L2 != 0.0) { 315 double f1 = 0.0; 316 double f2 = 0.0; 317 if (satObs._prn.system() == 'G') { 318 f1 = t_CST::freq(t_frequency::G1, 0); 319 f2 = t_CST::freq(t_frequency::G2, 0); 320 } 321 else if (satObs._prn.system() == 'R') { 322 f1 = t_CST::freq(t_frequency::R1, qcObs._slotNum); 323 f2 = t_CST::freq(t_frequency::R2, qcObs._slotNum); 324 } 325 else if (satObs._prn.system() == 'E') { 326 f1 = t_CST::freq(t_frequency::E1, 0); 327 f2 = t_CST::freq(t_frequency::E5, 0); 328 } 329 330 L1 = L1 * t_CST::c / f1; 331 L2 = L2 * t_CST::c / f2; 332 333 if (P1 != 0.0) { 334 qcObs._MP1 = P1 - L1 - 2.0*f2*f2/(f1*f1-f2*f2) * (L1 - L2); 335 okFlag = true; 336 } 337 if (P2 != 0.0) { 338 qcObs._MP2 = P2 - L2 - 2.0*f1*f1/(f1*f1-f2*f2) * (L1 - L2); 339 okFlag = true; 340 } 341 } 342 343 if (okFlag) { 344 return success; 345 } 346 else { 347 return failure; 348 } 349 } 350 351 // 352 //////////////////////////////////////////////////////////////////////////// 353 void t_reqcAnalyze::preparePlotData(const t_rnxObsFile* obsFile) { 354 355 ColumnVector xyzSta = obsFile->xyz(); 356 357 QVector<t_polarPoint*>* dataMP1 = new QVector<t_polarPoint*>; 358 QVector<t_polarPoint*>* dataMP2 = new QVector<t_polarPoint*>; 359 QVector<t_polarPoint*>* dataSNR1 = new QVector<t_polarPoint*>; 360 QVector<t_polarPoint*>* dataSNR2 = new QVector<t_polarPoint*>; 361 362 const double SLIPTRESH = 10.0; // cycle-slip threshold (meters) 363 const double chunkStep = 600.0; // 10 minutes 364 365 bncSettings settings; 366 QString reqSkyPlotSystems = settings.value("reqcSkyPlotSystems").toString(); 367 bool plotGPS = false; 368 bool plotGlo = false; 369 bool plotGal = false; 370 if (reqSkyPlotSystems == "GPS") { 371 plotGPS = true; 372 } 373 else if (reqSkyPlotSystems == "GLONASS") { 374 plotGlo = true; 375 } 376 else if (reqSkyPlotSystems == "Galileo") { 377 plotGal = true; 378 } 379 else { 380 plotGPS = true; 381 plotGlo = true; 382 plotGal = true; 383 } 384 385 // Loop over all satellites available 386 // ---------------------------------- 387 QMutableMapIterator<t_prn, t_qcSat> it(_qcFile._qcSat); 388 while (it.hasNext()) { 389 it.next(); 390 const t_prn& prn = it.key(); 391 t_qcSat& qcSat = it.value(); 392 393 // Loop over all Chunks of Data 394 // ---------------------------- 395 for (bncTime chunkStart = _qcFile._startTime; 396 chunkStart < _qcFile._endTime; chunkStart += chunkStep) { 397 398 // Chunk (sampled) Epoch 399 // --------------------- 400 _qcFile._qcEpoSampled.push_back(t_qcEpo()); 401 t_qcEpo& qcEpoSampled = _qcFile._qcEpoSampled.back(); 402 t_qcObs& qcObsSampled = qcEpoSampled._qcObs[prn]; 403 404 QVector<double> MP1; 405 QVector<double> MP2; 406 407 // Loop over all Epochs within one Chunk of Data 408 // --------------------------------------------- 409 bncTime prevTime; 410 for (int iEpo = 0; iEpo < _qcFile._qcEpo.size(); iEpo++) { 411 const t_qcEpo& qcEpo = _qcFile._qcEpo[iEpo]; 412 if (qcEpo._epoTime < chunkStart) { 413 continue; 414 } 415 if (!qcEpo._qcObs.contains(prn)) { 416 continue; 417 } 418 419 const t_qcObs& qcObs = qcEpo._qcObs[prn]; 420 421 // Compute the Azimuth and Zenith Distance 422 // --------------------------------------- 423 if (chunkStart == qcEpo._epoTime) { 424 qcEpoSampled._epoTime = qcEpo._epoTime; 425 qcEpoSampled._PDOP = qcEpo._PDOP; 426 427 if (qcObs._slotSet) { 428 qcObsSampled._slotSet = true; 429 qcObsSampled._slotNum = qcObs._slotNum; 430 } 431 if (xyzSta.size()) { 432 t_eph* eph = 0; 433 for (int ie = 0; ie < _ephs.size(); ie++) { 434 if (_ephs[ie]->prn() == prn) { 435 eph = _ephs[ie]; 436 break; 437 } 438 } 439 if (eph) { 440 ColumnVector xc(4); 441 ColumnVector vv(3); 442 if (eph->getCrd(qcEpo._epoTime, xc, vv, false) == success) { 443 double rho, eleSat, azSat; 444 topos(xyzSta(1), xyzSta(2), xyzSta(3), xc(1), xc(2), xc(3), rho, eleSat, azSat); 445 qcObsSampled._azDeg = azSat * 180.0/M_PI; 446 qcObsSampled._eleDeg = eleSat * 180.0/M_PI; 447 } 448 } 449 } 450 } 451 452 // Check Interval 453 // -------------- 454 if (prevTime.valid()) { 455 double dt = qcEpo._epoTime - prevTime; 456 if (dt > 1.5 * _qcFile._interval) { 457 qcObsSampled._gapL1 = true; 458 qcObsSampled._gapL2 = true; 459 } 460 } 461 prevTime = qcEpo._epoTime; 462 463 // Check L1 and L2 availability 464 // ---------------------------- 465 if (qcObs._hasL1) { 466 qcObsSampled._hasL1 = true; 467 } 468 if (qcObs._hasL2) { 469 qcObsSampled._hasL2 = true; 470 } 471 472 // Check Minimal Signal-to-Noise Ratio 473 // ----------------------------------- 474 if ( qcObs._SNR1 > 0 && (qcObsSampled._SNR1 == 0 || qcObsSampled._SNR1 > qcObs._SNR1) ) { 475 qcObsSampled._SNR1 = qcObs._SNR1; 476 } 477 if ( qcObs._SNR2 > 0 && (qcObsSampled._SNR2 == 0 || qcObsSampled._SNR2 > qcObs._SNR2) ) { 478 qcObsSampled._SNR2 = qcObs._SNR2; 479 } 480 481 // Check Slip Flags 482 // ---------------- 483 if (qcObs._slipL1) { 484 qcObsSampled._slipL1 = true; 485 } 486 if (qcObs._slipL2) { 487 qcObsSampled._slipL2 = true; 488 } 489 490 MP1 << qcObs._MP1; 491 MP2 << qcObs._MP2; 492 } 493 494 // Compute the Multipath 495 // --------------------- 496 if ( MP1.size() > 0 && MP2.size() > 0 && 497 ( (prn.system() == 'G' && plotGPS ) || 498 (prn.system() == 'R' && plotGlo && qcObsSampled._slotSet) || 499 (prn.system() == 'E' && plotGal ) ) ) { 500 501 double meanMP1 = 0.0; 502 double meanMP2 = 0.0; 503 for (int ii = 0; ii < MP1.size(); ii++) { 504 meanMP1 += MP1[ii]; 505 meanMP2 += MP2[ii]; 506 } 507 meanMP1 /= MP1.size(); 508 meanMP2 /= MP2.size(); 509 510 bool slipMP = false; 511 double stdMP1 = 0.0; 512 double stdMP2 = 0.0; 513 for (int ii = 0; ii < MP1.size(); ii++) { 514 double diff1 = MP1[ii] - meanMP1; 515 double diff2 = MP2[ii] - meanMP2; 516 if (fabs(diff1) > SLIPTRESH || fabs(diff2) > SLIPTRESH) { 517 slipMP = true; 518 break; 519 } 520 stdMP1 += diff1 * diff1; 521 stdMP1 += diff2 * diff2; 522 } 523 524 if (slipMP) { 525 qcObsSampled._slipL1 = true; 526 qcObsSampled._slipL2 = true; 527 qcSat._numSlipsFound += 1; 528 } 529 else { 530 stdMP1 = sqrt(stdMP1 / MP1.size()); 531 stdMP2 = sqrt(stdMP2 / MP2.size()); 532 (*dataMP1) << (new t_polarPoint(qcObsSampled._azDeg, 90.0 - qcObsSampled._eleDeg, stdMP1)); 533 (*dataMP2) << (new t_polarPoint(qcObsSampled._azDeg, 90.0 - qcObsSampled._eleDeg, stdMP2)); 534 } 535 } 536 537 // Signal-to-Noise Ratio Plot Data 538 // ------------------------------- 539 if ( (prn.system() == 'G' && plotGPS) || 540 (prn.system() == 'R' && plotGlo) || 541 (prn.system() == 'E' && plotGal) ) { 542 (*dataSNR1) << (new t_polarPoint(qcObsSampled._azDeg, 90.0 - qcObsSampled._eleDeg, qcObsSampled._SNR1)); 543 (*dataSNR2) << (new t_polarPoint(qcObsSampled._azDeg, 90.0 - qcObsSampled._eleDeg, qcObsSampled._SNR2)); 544 } 545 } 546 } 547 548 // Show the plots 549 // -------------- 550 if (BNC_CORE->GUIenabled()) { 551 QFileInfo fileInfo(obsFile->fileName()); 552 QByteArray title = fileInfo.fileName().toAscii(); 553 dspSkyPlot(obsFile->fileName(), "MP1", dataMP1, "MP2", dataMP2, "Meters", 2.0); 554 dspSkyPlot(obsFile->fileName(), "SNR1", dataSNR1, "SNR2", dataSNR2, "dbHz", 54.0); 555 dspAvailPlot(obsFile->fileName(), title); 556 } 557 else { 558 for (int ii = 0; ii < dataMP1->size(); ii++) { 559 delete dataMP1->at(ii); 560 } 561 delete dataMP1; 562 for (int ii = 0; ii < dataMP2->size(); ii++) { 563 delete dataMP2->at(ii); 564 } 565 delete dataMP2; 566 for (int ii = 0; ii < dataSNR1->size(); ii++) { 567 delete dataSNR1->at(ii); 568 } 569 delete dataSNR1; 570 for (int ii = 0; ii < dataSNR2->size(); ii++) { 571 delete dataSNR2->at(ii); 572 } 573 delete dataSNR2; 574 } 575 } 576 577 // 578 //////////////////////////////////////////////////////////////////////////// 579 void t_reqcAnalyze::dspSkyPlot(const QString& fileName, const QByteArray& title1, 580 QVector<t_polarPoint*>* data1, const QByteArray& title2, 581 QVector<t_polarPoint*>* data2, const QByteArray& scaleTitle, 582 double maxValue) { 583 584 if (BNC_CORE->GUIenabled()) { 585 586 if (maxValue == 0.0) { 587 if (data1) { 588 for (int ii = 0; ii < data1->size(); ii++) { 589 double val = data1->at(ii)->_value; 590 if (maxValue < val) { 591 maxValue = val; 592 } 593 } 594 } 595 if (data2) { 596 for (int ii = 0; ii < data2->size(); ii++) { 597 double val = data2->at(ii)->_value; 598 if (maxValue < val) { 599 maxValue = val; 600 } 601 } 602 } 603 } 604 605 QwtInterval scaleInterval(0.0, maxValue); 606 607 QVector<QWidget*> plots; 608 if (data1) { 609 t_polarPlot* plot1 = new t_polarPlot(QwtText(title1), scaleInterval, 610 BNC_CORE->mainWindow()); 611 plot1->addCurve(data1); 612 plots << plot1; 613 } 614 if (data2) { 615 t_polarPlot* plot2 = new t_polarPlot(QwtText(title2), scaleInterval, 616 BNC_CORE->mainWindow()); 617 plot2->addCurve(data2); 618 plots << plot2; 619 } 620 621 t_graphWin* graphWin = new t_graphWin(0, fileName, plots, 622 &scaleTitle, &scaleInterval); 623 624 graphWin->show(); 625 626 bncSettings settings; 627 QString dirName = settings.value("reqcPlotDir").toString(); 628 if (!dirName.isEmpty()) { 629 QByteArray ext = (scaleTitle == "Meters") ? "_M.png" : "_S.png"; 630 graphWin->savePNG(dirName, ext); 631 } 632 } 633 } 634 635 // 636 //////////////////////////////////////////////////////////////////////////// 637 void t_reqcAnalyze::dspAvailPlot(const QString& fileName, const QByteArray& title) { 638 639 if (BNC_CORE->GUIenabled()) { 640 t_availPlot* plotA = new t_availPlot(0, _qcFile._qcEpoSampled); 641 plotA->setTitle(title); 642 643 t_elePlot* plotZ = new t_elePlot(0, _qcFile._qcEpoSampled); 644 645 t_dopPlot* plotD = new t_dopPlot(0, _qcFile._qcEpoSampled); 646 647 QVector<QWidget*> plots; 648 plots << plotA << plotZ << plotD; 649 t_graphWin* graphWin = new t_graphWin(0, fileName, plots, 0, 0); 650 651 int ww = QFontMetrics(graphWin->font()).width('w'); 652 graphWin->setMinimumSize(120*ww, 40*ww); 653 654 graphWin->show(); 655 656 bncSettings settings; 657 QString dirName = settings.value("reqcPlotDir").toString(); 658 if (!dirName.isEmpty()) { 659 QByteArray ext = "_A.png"; 660 graphWin->savePNG(dirName, ext); 661 } 662 } 663 } 664 780 665 // Finish the report 781 666 //////////////////////////////////////////////////////////////////////////// 782 void t_reqcAnalyze::printReport(QVector<t_polarPoint*>* dataMP1, 783 QVector<t_polarPoint*>* dataMP2, 784 QVector<t_polarPoint*>* dataSNR1, 785 QVector<t_polarPoint*>* dataSNR2) { 667 void t_reqcAnalyze::printReport() { 786 668 787 669 if (!_log) { … … 789 671 } 790 672 791 *_log << "Marker name: " << _ obsStat._markerName << endl792 << "Receiver: " << _ obsStat._receiverType << endl793 << "Antenna: " << _ obsStat._antennaName << endl794 << "Start time: " << _ obsStat._startTime.datestr().c_str() << ' '795 << _ obsStat._startTime.timestr().c_str() << endl796 << "End time: " << _ obsStat._endTime.datestr().c_str() << ' '797 << _ obsStat._endTime.timestr().c_str() << endl798 << "Interval: " << _ obsStat._interval << endl799 << "# Sat.: " << _ obsStat._prnStat.size() << endl;673 *_log << "Marker name: " << _qcFile._markerName << endl 674 << "Receiver: " << _qcFile._receiverType << endl 675 << "Antenna: " << _qcFile._antennaName << endl 676 << "Start time: " << _qcFile._startTime.datestr().c_str() << ' ' 677 << _qcFile._startTime.timestr().c_str() << endl 678 << "End time: " << _qcFile._endTime.datestr().c_str() << ' ' 679 << _qcFile._endTime.timestr().c_str() << endl 680 << "Interval: " << _qcFile._interval << endl 681 << "# Sat.: " << _qcFile._qcSat.size() << endl; 800 682 801 683 int numObs = 0; 802 684 int numSlipsFlagged = 0; 803 685 int numSlipsFound = 0; 804 QMapIterator<t_prn, t_ prnStat> it(_obsStat._prnStat);686 QMapIterator<t_prn, t_qcSat> it(_qcFile._qcSat); 805 687 while (it.hasNext()) { 806 688 it.next(); 807 const t_ prnStat& prnStat = it.value();808 numObs += prnStat._numObs;809 numSlipsFlagged += prnStat._numSlipsFlagged;810 numSlipsFound += prnStat._numSlipsFound;689 const t_qcSat& qcSat = it.value(); 690 numObs += qcSat._numObs; 691 numSlipsFlagged += qcSat._numSlipsFlagged; 692 numSlipsFound += qcSat._numSlipsFound; 811 693 } 812 694 *_log << "# Obs.: " << numObs << endl … … 814 696 << "# Slips (found): " << numSlipsFound << endl; 815 697 816 for (int kk = 1; kk <= 4; kk++) {817 QVector<t_polarPoint*>* data = 0;818 QString text;819 if (kk == 1) {820 data = dataMP1;821 text = "Mean MP1: ";822 }823 else if (kk == 2) {824 data = dataMP2;825 text = "Mean MP2: ";826 }827 else if (kk == 3) {828 data = dataSNR1;829 text = "Mean SNR1: ";830 }831 else if (kk == 4) {832 data = dataSNR2;833 text = "Mean SNR2: ";834 }835 double mean = 0.0;836 for (int ii = 0; ii < data->size(); ii++) {837 const t_polarPoint* point = data->at(ii);838 mean += point->_value;839 }840 if (data->size() > 0) {841 mean /= data->size();842 }843 *_log << text << mean << endl;844 }845 846 698 _log->flush(); 847 699 }
Note:
See TracChangeset
for help on using the changeset viewer.