Changeset 11057 in ntrip for trunk/BNC/src/rinex
- Timestamp:
- Sep 30, 2026, 11:30:26 AM (10 days ago)
- Location:
- trunk/BNC/src/rinex
- Files:
-
- 5 edited
-
reqcanalyze.cpp (modified) (6 diffs)
-
reqcanalyze.h (modified) (2 diffs)
-
reqcedit.cpp (modified) (3 diffs)
-
reqcedit.h (modified) (2 diffs)
-
rnxobsfile.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/src/rinex/reqcanalyze.cpp
r11023 r11057 131 131 // ---------------- 132 132 t_reqcEdit::readEphemerides(_navFileNames, _ephs, _logStream, _checkEph); 133 t_reqcEdit::indexEphemerides(_ephs, _ephsByPrn); 133 134 134 135 // Loop over all RINEX Files … … 207 208 continue; 208 209 } 210 // observations of unhealthy satellites are excluded, as those 211 // below the elevation mask (see also setExpectedObs) 212 if (_navFileNames.size() && unhealthyAt(rnxSat.prn, _currEpo->tt)) { 213 continue; 214 } 209 215 t_satObs satObs; 210 216 t_rnxObsFile::setObsFromRnx(obsFile, _currEpo, rnxSat, satObs); … … 266 272 } 267 273 268 t_eph* eph = 0; 269 for (int ie = 0; ie < _ephs.size(); ie++) { 270 if (_ephs[ie]->prn() == prn) { 271 eph = _ephs[ie]; 272 break; 273 } 274 } 274 if (unhealthyAt(prn, _currEpo->tt)) { 275 continue; 276 } 277 t_eph* eph = ephForTime(prn, _currEpo->tt); 275 278 if (eph) { 276 279 ColumnVector xSat(6); … … 328 331 t_qcSat& qcSat) { 329 332 330 t_eph* eph = 0; 331 for (int ie = 0; ie < _ephs.size(); ie++) { 332 if (_ephs[ie]->prn() == satObs._prn) { 333 eph = _ephs[ie]; 334 break; 335 } 336 } 333 t_eph* eph = ephForTime(satObs._prn, epoTime); 337 334 if (eph) { 338 335 ColumnVector xc(6); … … 976 973 double interval, const ColumnVector& xyzSta) { 977 974 for(QMap<t_prn, int>::iterator it = _numExpObs.begin(); it != _numExpObs.end(); it++) { 978 t_eph* eph = 0;975 bool navAvail = false; 979 976 for (int ie = 0; ie < _ephs.size(); ie++) { 980 977 if (_ephs[ie]->prn() == it.key()) { 981 eph = _ephs[ie];978 navAvail = true; 982 979 break; 983 980 } 984 981 } 985 if ( eph) {982 if (navAvail) { 986 983 int numExpObs = 0; 987 984 bncTime epoTime; 988 985 for (epoTime = startTime - interval; epoTime < endTime; epoTime = epoTime + interval) { 986 // an observation is only expected if a valid ephemeris exists, 987 // the satellite is healthy (unhealthy satellite-epochs are also 988 // excluded from the observations, see analyzeFile) and above 989 // the elevation mask 990 if (unhealthyAt(it.key(), epoTime)) { 991 continue; 992 } 993 t_eph* eph = ephForTime(it.key(), epoTime, true); 994 if (!eph) { 995 continue; 996 } 989 997 ColumnVector xc(6); 990 998 ColumnVector vv(3); … … 1007 1015 } 1008 1016 } 1017 1018 // A satellite is considered unhealthy at epoch tt if the valid navigation 1019 // data set closest to tt is flagged unhealthy. Its orbit is not used then 1020 // (the geometry may be erroneous) and its observations are excluded. 1021 //////////////////////////////////////////////////////////////////////////// 1022 bool t_reqcAnalyze::unhealthyAt(const t_prn& prn, const bncTime& tt) const { 1023 t_eph* eph = ephForTime(prn, tt, true, true); 1024 return eph && eph->checkState() == t_eph::unhealthy; 1025 } 1026 1027 // Ephemeris of the given satellite for epoch tt, see t_reqcEdit::ephForTime 1028 //////////////////////////////////////////////////////////////////////////// 1029 t_eph* t_reqcAnalyze::ephForTime(const t_prn& prn, const bncTime& tt, 1030 bool validOnly, bool allowUnhealthy) const { 1031 return t_reqcEdit::ephForTime(_ephsByPrn.value(prn), prn, tt, validOnly, allowUnhealthy); 1032 } -
trunk/BNC/src/rinex/reqcanalyze.h
r11023 r11057 194 194 void setExpectedObs(const bncTime& startTime, const bncTime& endTime, 195 195 double interval, const ColumnVector& xyzSta); 196 197 t_eph* ephForTime(const t_prn& prn, const bncTime& tt, bool validOnly = false, 198 bool allowUnhealthy = false) const; 199 200 bool unhealthyAt(const t_prn& prn, const bncTime& tt) const; 196 201 197 202 void analyzeMultipath(); … … 219 224 QStringList _defaultSignalTypes; 220 225 QVector<t_eph*> _ephs; 226 QMap<t_prn, QVector<t_eph*> > _ephsByPrn; 221 227 t_rnxObsFile::t_rnxEpo* _currEpo; 222 228 t_qcFile _qcFile; -
trunk/BNC/src/rinex/reqcedit.cpp
r11023 r11057 230 230 if (_minEle > 0.0 && _ephs.isEmpty()) { 231 231 t_reqcEdit::readEphemerides(_navFileNames, _ephs, _logStream, _checkEph); 232 t_reqcEdit::indexEphemerides(_ephs, _ephsByPrn); 232 233 } 233 234 … … 546 547 const t_rnxObsFile::t_rnxSat& rnxSat = epo->rnxSat[iSat]; 547 548 548 t_eph* eph = 0; 549 for (int ie = 0; ie < _ephs.size(); ie++) { 550 if (_ephs[ie]->prn() == rnxSat.prn) { 551 eph = _ephs[ie]; 552 break; 553 } 554 } 549 t_eph* eph = ephForTime(_ephsByPrn.value(rnxSat.prn), rnxSat.prn, epo->tt); 555 550 if (eph) { 556 551 ColumnVector xc(6); … … 567 562 } 568 563 epo->rnxSat = keptSats; 564 } 565 566 // Ephemeris of the given satellite for epoch tt: the one with TOC closest 567 // to tt among those valid at tt (see outDatedBcep). If none is valid, 568 // return 0 when validOnly is set, otherwise the one with TOC closest to tt. 569 // Only ephemerides accepted by t_eph::getCrd are considered (not bad or 570 // outdated; unhealthy ones only if allowUnhealthy is set, to be used with 571 // getCrd(..., ignoreHealth = true)). 572 // Using the first ephemeris of the day for all epochs gives wrong 573 // geometry late in the day and, for GLONASS, integrations over many 574 // hours (t_ephGlo::position integrates from TOC on every call). 575 //////////////////////////////////////////////////////////////////////////// 576 t_eph* t_reqcEdit::ephForTime(const QVector<t_eph*>& ephs, const t_prn& prn, 577 const bncTime& tt, bool validOnly, 578 bool allowUnhealthy) { 579 t_eph* bestValid = 0; 580 t_eph* bestAny = 0; 581 double bestValidDt = 0.0; 582 double bestAnyDt = 0.0; 583 for (int ie = 0; ie < ephs.size(); ie++) { 584 t_eph* eph = ephs[ie]; 585 if (eph->prn() != prn) { 586 continue; 587 } 588 if (eph->checkState() == t_eph::bad || 589 eph->checkState() == t_eph::outdated || 590 (eph->checkState() == t_eph::unhealthy && !allowUnhealthy)) { 591 continue; 592 } 593 double dt = fabs(tt - eph->TOC()); 594 if (bestAny == 0 || dt < bestAnyDt) { 595 bestAny = eph; 596 bestAnyDt = dt; 597 } 598 if (!outDatedBcep(eph, tt) && (bestValid == 0 || dt < bestValidDt)) { 599 bestValid = eph; 600 bestValidDt = dt; 601 } 602 } 603 if (bestValid || validOnly) { 604 return bestValid; 605 } 606 return bestAny; 607 } 608 609 // Group ephemerides by satellite (speeds up ephForTime) 610 //////////////////////////////////////////////////////////////////////////// 611 void t_reqcEdit::indexEphemerides(const QVector<t_eph*>& ephs, 612 QMap<t_prn, QVector<t_eph*> >& ephsByPrn) { 613 ephsByPrn.clear(); 614 for (int ie = 0; ie < ephs.size(); ie++) { 615 ephsByPrn[ephs[ie]->prn()].append(ephs[ie]); 616 } 569 617 } 570 618 -
trunk/BNC/src/rinex/reqcedit.h
r11023 r11057 56 56 QVector<t_eph*>& ephs, 57 57 QTextStream* log, bool checkEph); 58 static void indexEphemerides(const QVector<t_eph*>& ephs, 59 QMap<t_prn, QVector<t_eph*> >& ephsByPrn); 60 static t_eph* ephForTime(const QVector<t_eph*>& ephs, const t_prn& prn, 61 const bncTime& tt, bool validOnly = false, 62 bool allowUnhealthy = false); 58 63 59 64 private: … … 82 87 QMap<QString, QMap<int, int> > _lli; 83 88 QVector<t_eph*> _ephs; 89 QMap<t_prn, QVector<t_eph*> > _ephsByPrn; 84 90 }; 85 91 -
trunk/BNC/src/rinex/rnxobsfile.cpp
r11023 r11057 349 349 } 350 350 else { 351 _obsTypes['G'] << "C1C" << "L1C" << "S1C" 352 << "C1W" << "L1W" << "S1W" 353 << "C2X" << "L2X" << "S2X" 354 << "C2W" << "L2W" << "S2W" 355 << "C5X" << "L5X" << "S5X"; 356 357 _obsTypes['J'] << "C1C" << "L1C" << "S1C" 358 << "C1Z" << "L1Z" << "S1Z" 359 << "C1X" << "L1X" << "S1X" 360 << "C2L" << "L2L" << "S2L" 361 << "C2X" << "L2X" << "S2X" 362 << "C5Q" << "L5Q" << "S5Q" 363 << "C5X" << "L5X" << "S5X" 364 << "C6L" << "L6L" << "S6L"; 365 366 _obsTypes['R'] << "C1C" << "L1C" << "S1C" 367 << "C1P" << "L1P" << "S1P" 368 << "C2C" << "L2C" << "S2C" 369 << "C2P" << "L2P" << "S2P" 370 << "C3I" << "L3I" << "S3I" 371 << "C4X" << "L4X" << "S4X" 372 << "C6X" << "L6X" << "S6X"; 373 374 _obsTypes['E'] << "C1C" << "L1C" << "S1C" 375 << "C1X" << "L1X" << "S1X" 376 << "C5Q" << "L5Q" << "S5Q" 377 << "C5X" << "L5X" << "S5X" 378 << "C6C" << "L6C" << "S6C" 379 << "C6X" << "L6X" << "S6X" 380 << "C7Q" << "L7Q" << "S7Q" 381 << "C7X" << "L7X" << "S7X" 382 << "C8Q" << "L8Q" << "S8Q" 383 << "C8X" << "L8X" << "S8X"; 384 385 _obsTypes['S'] << "C1C" << "L1C" << "S1C" 386 << "C5I" << "L5I" << "S5I" 387 << "C5Q" << "L5Q" << "S5Q" 388 << "C5X" << "L5X" << "S5X"; 389 390 _obsTypes['C'] << "C2I" << "L2I" << "S2I" 391 << "C2Q" << "L2Q" << "S2Q" 392 << "C2X" << "L2X" << "S2X" 393 << "C6I" << "L6I" << "S6I" 394 << "C6Q" << "L6Q" << "S6Q" 395 << "C6X" << "L6X" << "S6X" 396 << "C7I" << "L7I" << "S7I" 397 << "C7Q" << "L7Q" << "S7Q" 398 << "C7X" << "L7X" << "S7X"; 399 400 _obsTypes['I'] << "C5A" << "L5A" << "S5A" 401 << "C9A" << "L9A" << "S9A"; 351 // All signals the RTCM3 MSM decoder can deliver (see RTCM3Decoder.cpp), 352 // each with code, phase, Doppler and SNR. Empty observations are blank 353 // padded up to the last non-empty one of a record, so the order keeps 354 // records short: per system first the signals most receivers track 355 // (Q/C/L/P tracking modes), then the combined 'X' modes, then rarely 356 // used ones. 357 QMap<char, QStringList> sigCodes; 358 sigCodes['G'] << "1C" << "1W" << "2W" << "2L" << "2S" << "5Q" << "1L" 359 << "2X" << "5X" << "1X" 360 << "5I" << "1S" << "1P" << "2C" << "2P"; 361 sigCodes['R'] << "1C" << "1P" << "2C" << "2P" << "3Q" 362 << "3X" << "4X" << "6X" 363 << "3I" << "4A" << "4B" << "6A" << "6B"; 364 sigCodes['E'] << "1C" << "5Q" << "7Q" << "8Q" << "6C" 365 << "1X" << "5X" << "7X" << "8X" << "6X" 366 << "1B" << "5I" << "7I" << "8I" << "6B" << "1A" << "1Z" << "6A" << "6Z"; 367 sigCodes['J'] << "1C" << "2L" << "5Q" << "1L" 368 << "2X" << "5X" << "1X" 369 << "2S" << "5I" << "1S" << "1E" << "1Z" << "6L" << "6S" << "6X"; 370 sigCodes['C'] << "2I" << "7I" << "6I" << "5P" << "1P" << "7D" 371 << "2X" << "7X" << "6X" << "5X" << "1X" 372 << "2Q" << "7Q" << "6Q" << "5D" << "1D"; 373 sigCodes['S'] << "1C" << "5I" << "5Q" << "5X"; 374 sigCodes['I'] << "5A" << "9A"; 375 376 QMapIterator<char, QStringList> it(sigCodes); 377 while (it.hasNext()) { 378 it.next(); 379 for (int ii = 0; ii < it.value().size(); ii++) { 380 const QString& sig = it.value()[ii]; 381 _obsTypes[it.key()] << "C" + sig << "L" + sig << "D" + sig << "S" + sig; 382 } 383 } 402 384 } 403 385 } … … 1528 1510 char sys = rnxSat.prn.system(); 1529 1511 1512 // If all observation types are given as v3 types, a direct lookup is 1513 // equivalent to the (slow) matching loops below 1514 // -------------------------------------------------------------------- 1515 bool allTypesV3 = true; 1516 QMapIterator<QString, t_rnxObs> itChk(rnxSat.obs); 1517 while (itChk.hasNext() && allTypesV3) { 1518 itChk.next(); 1519 if (itChk.key().length() != 3 || type2to3(sys, itChk.key()) != itChk.key()) { 1520 allTypesV3 = false; 1521 } 1522 } 1523 1530 1524 std::vector <const t_rnxObs*> hlp(header.nTypes(sys)); 1531 1525 for (int iTypeV3 = 0; iTypeV3 < header.nTypes(sys); iTypeV3++) { 1532 1526 hlp[iTypeV3] = 0; 1533 1527 QString typeV3 = header.obsType(sys, iTypeV3); 1528 if (allTypesV3) { 1529 QMap<QString, t_rnxObs>::const_iterator itV3 = rnxSat.obs.constFind(typeV3); 1530 if (itV3 != rnxSat.obs.constEnd() && itV3.value().value != 0.0) { 1531 hlp[iTypeV3] = &itV3.value(); 1532 } 1533 continue; 1534 } 1534 1535 QMapIterator<QString, t_rnxObs> itObs(rnxSat.obs); 1535 1536 … … 1559 1560 1560 1561 if (header.nTypes(sys)) { 1561 *stream <<rnxSat.prn.toString().c_str();1562 QString record = rnxSat.prn.toString().c_str(); 1562 1563 for (int iTypeV3 = 0; iTypeV3 < header.nTypes(sys); iTypeV3++) { 1563 1564 const t_rnxObs* rnxObs = hlp[iTypeV3]; 1564 1565 if (rnxObs == 0) { 1565 *stream <<QString().leftJustified(16);1566 record += QString().leftJustified(16); 1566 1567 } 1567 1568 else { 1568 *stream <<QString("%1").arg(rnxObs->value, 14, 'f', 3);1569 record += QString("%1").arg(rnxObs->value, 14, 'f', 3); 1569 1570 if (rnxObs->lli != 0.0) { 1570 *stream <<QString("%1").arg(rnxObs->lli, 1);1571 record += QString("%1").arg(rnxObs->lli, 1); 1571 1572 } 1572 1573 else { 1573 *stream <<' ';1574 record += ' '; 1574 1575 } 1575 1576 if (rnxObs->snr != 0.0) { 1576 *stream <<QString("%1").arg(rnxObs->snr, 1);1577 record += QString("%1").arg(rnxObs->snr, 1); 1577 1578 } 1578 1579 else { 1579 *stream <<' ';1580 record += ' '; 1580 1581 } 1581 1582 } 1582 1583 } 1583 *stream << Qt::endl; 1584 // Trailing blanks can be removed from the records (RINEX 4.02, 4.) 1585 int len = record.length(); 1586 while (len > 3 && record[len-1] == ' ') { 1587 len--; 1588 } 1589 record.truncate(len); 1590 *stream << record << Qt::endl; 1584 1591 } 1585 1592 }
Note:
See TracChangeset
for help on using the changeset viewer.
