Changeset 11079 in ntrip
- Timestamp:
- Oct 8, 2026, 11:47:35 AM (65 minutes ago)
- Location:
- trunk/BNC
- Files:
-
- 12 edited
-
src/bncantex.cpp (modified) (2 diffs)
-
src/bncantex.h (modified) (1 diff)
-
src/bnchelp.html (modified) (2 diffs)
-
src/combination/bnccomb.cpp (modified) (6 diffs)
-
src/combination/bnccomb.h (modified) (1 diff)
-
src/pppMain.cpp (modified) (1 diff)
-
src/src.pri (modified) (2 diffs)
-
src/ssrQc.cpp (modified) (2 diffs)
-
src/ssrQc.h (modified) (1 diff)
-
tests/cases/combi/expected/Combi.log.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/CombiPPP.log.gz (modified) ( previous)
-
tests/cases/combi_ppp/expected/FFMJ00DEU_20262780000_01D_01S.ppp.gz (modified) ( previous)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/src/bncantex.cpp
r11066 r11079 778 778 const ColumnVector& xSat, 779 779 const ColumnVector& vSat, ColumnVector& dx, 780 e_attMode mode, double externalYaw) { 780 e_attMode mode, double externalYaw, 781 const QString& stateKey) { 782 783 // separate yaw model states per caller (stateKey), each called in time order 784 QString yawKey = stateKey.isEmpty() ? prn : stateKey + ":" + prn; 781 785 782 786 t_frequency::type frqType = t_frequency::dummy; … … 836 840 837 841 if (mode == ATT_COMPUTED && prn[0] == 'R' && vSat.size() == 3) { 838 psiEff = glonassYawAngle( prn, Mjd, xSat, vSat, xSun);842 psiEff = glonassYawAngle(yawKey, Mjd, xSat, vSat, xSun); 839 843 useVelocityFrame = true; 840 844 } 841 845 else if (mode == ATT_COMPUTED && prn[0] == 'G' && vSat.size() == 3 842 846 && !map->blockType.isEmpty()) { 843 psiEff = gpsYawAngle( prn, map->blockType, Mjd, xSat, vSat, xSun);847 psiEff = gpsYawAngle(yawKey, map->blockType, Mjd, xSat, vSat, xSun); 844 848 useVelocityFrame = true; 845 849 } 846 850 else if (mode == ATT_COMPUTED && prn[0] == 'E' && vSat.size() == 3 847 851 && !map->blockType.isEmpty()) { 848 psiEff = galileoYawAngle( prn, map->blockType, Mjd, xSat, vSat, xSun);852 psiEff = galileoYawAngle(yawKey, map->blockType, Mjd, xSat, vSat, xSun); 849 853 useVelocityFrame = true; 850 854 } 851 855 else if (mode == ATT_COMPUTED && prn[0] == 'C' && vSat.size() == 3 852 856 && !map->blockType.isEmpty()) { 853 psiEff = bdsYawAngle( prn, map->blockType, Mjd, xSat, vSat, xSun);857 psiEff = bdsYawAngle(yawKey, map->blockType, Mjd, xSat, vSat, xSun); 854 858 useVelocityFrame = true; 855 859 } -
trunk/BNC/src/bncantex.h
r11066 r11079 66 66 ColumnVector& dx, 67 67 e_attMode mode = ATT_COMPUTED, 68 double externalYaw = 0.0); 68 double externalYaw = 0.0, 69 const QString& stateKey = QString()); 69 70 70 71 // Drain and return diagnostic logs accumulated by the yaw models. -
trunk/BNC/src/bnchelp.html
r11076 r11079 6323 6323 </p> 6324 6324 <p> 6325 Whether the orbit corrections refer to the satellite's Antenna Phase Center (APC) or to its Center of Mass (CoM) is 6326 derived from the name of the correction stream or file: names beginning with 'SSRA' refer to the APC, the combined 6327 corrections 'INTERNAL' always refer to the APC as well; all others are taken as CoM. For APC corrections, only the 6328 differences of the satellite antenna offsets to that of the reference frequency are applied. 6329 </p> 6330 <p> 6325 6331 Default value for 'ANTEX file' is an empty option field, meaning that you do not want to correct observations for 6326 6332 Antenna Phase Center offsets and variations. … … 8096 8102 - despite the fact, that the delivered code biases of an AC may contain contributions from other biases, also phase 8097 8103 biases. 8104 </p> 8105 <p> 8106 <b>APC and CoM streams:</b> The orbits of Broadcast Correction streams refer either to the satellite's Antenna Phase 8107 Center (APC, stream names 'SSRA...', reference frequency of the IGS-SSR and RTCM-SSR conventions) or to its Center 8108 of Mass (CoM, 'SSRC...'). If streams of both kinds are combined and an ANTEX file is specified ('Upload 8109 Corrections' panel), the combination is done in the CoM frame: the orbits of the APC streams are converted to CoM 8110 with the satellite antenna offsets of the ANTEX file and the attitude model selected for the AC ('Computed', 'SSR' 8111 or 'Nominal'). The result is converted to the APC for upload streams referring to the APC and for the combined 8112 corrections passed on to BNC's PPP ('INTERNAL'), which always refer to the APC. As most ACs provide 8113 both kinds of streams, combining CoM streams is recommended: the combined SP3 and CoM results then do not depend on 8114 BNC's attitude model and ANTEX file, only the uploaded APC streams do. Without an ANTEX file, or if all streams 8115 are of one kind, the combination is done in the frame of the master AC; streams of the other kind are not 8116 combined, which is reported in the logfile at most once per hour per AC and system. 8098 8117 </p> 8099 8118 <p> -
trunk/BNC/src/combination/bnccomb.cpp
r11067 r11079 296 296 } 297 297 298 // Reference point of the combination: with ACs of both kinds (APC streams 299 // 'SSRA...', CoM streams 'SSRC...') and an ANTEX file, the combination is 300 // done in the CoM frame and the orbits of the APC ACs are converted to 301 // CoM; otherwise in the frame of the master AC (ACs of the other kind are 302 // not used) 303 // ------------------------------------------------------------------------ 304 bool hasAPC = false, hasCoM = false; 305 for (const cmbAC* AC : _ACs) { 306 if (AC->isAPC) hasAPC = true; else hasCoM = true; 307 } 308 _cmbCoM = (_antex && hasAPC && hasCoM); 309 if (_cmbCoM) { 310 for (QMap<char, bool>::iterator it = _masterIsAPC.begin(); it != _masterIsAPC.end(); ++it) { 311 it.value() = false; 312 } 313 emit newMessage("bncComb: APC and CoM streams configured - combination in the CoM frame, " 314 "orbits of the APC streams converted to CoM", true); 315 } 316 else if (hasAPC && hasCoM) { 317 emit newMessage("bncComb: APC and CoM streams configured, but no ANTEX file - only the streams " 318 "with the reference point of the master AC are combined", true); 319 } 320 if (!_antex && hasCoM) { 321 emit newMessage("bncComb: CoM streams configured, but no ANTEX file - the combined orbits (INTERNAL) " 322 "may refer to the CoM, while the PPP assumes the APC", true); 323 } 324 298 325 299 326 // Bias SINEX File … … 610 637 } 611 638 } 612 if (acName.isEmpty() || 613 isAPC != _masterIsAPC[sys] || 614 excludeSat(newClk._prn, excludeSats)) { 639 if (acName.isEmpty() || excludeSat(newClk._prn, excludeSats)) { 640 continue; 641 } 642 if (!_cmbCoM && isAPC != _masterIsAPC[sys]) { 643 bncTime& warned = _refPointWarned[acName + sys]; 644 if (!warned.valid() || newClk._time - warned >= 3600.0) { 645 warned = newClk._time; 646 emit newMessage("bncComb: " + acName.toLatin1() + " " + QByteArray(1, sys) + " not combined: its orbits refer to the " + 647 (isAPC ? "APC" : "CoM") + ", those of the master AC " + _masterOrbitAC[sys].toLatin1() + 648 " to the " + (isAPC ? "CoM" : "APC") + 649 " (an ANTEX file allows to combine both in the CoM frame)", true); 650 } 615 651 continue; 616 652 } … … 949 985 } 950 986 987 // Orbits of an APC AC in a combination in the CoM frame 988 // ------------------------------------------------------ 989 if (_cmbCoM) { 990 const cmbAC* AC = 0; 991 for (const cmbAC* ac : _ACs) { 992 if (ac->name == acName) { 993 AC = ac; 994 break; 995 } 996 } 997 if (AC && AC->isAPC && convertApcToCoM(_newCorr, AC) != success) { 998 delete _newCorr; _newCorr = 0; 999 continue; 1000 } 1001 } 1002 951 1003 // Store correction into the buffer 952 1004 // -------------------------------- … … 1047 1099 << AC->name.toLatin1().data() << "\n"; 1048 1100 _masterOrbitAC[sys] = AC->name; 1049 _masterIsAPC[sys] = AC->isAPC; 1101 _masterIsAPC[sys] = _cmbCoM ? false : AC->isAPC; 1050 1102 break; 1051 1103 } … … 1320 1372 } 1321 1373 1374 // Convert the orbit correction of an APC AC to the satellite's CoM: the 1375 // antenna offset (ANTEX, single reference frequency, attitude as configured 1376 // for the AC) is added to the correction in radial, along-track and 1377 // cross-track direction. The clock correction is not affected. 1378 //////////////////////////////////////////////////////////////////////////// 1379 t_irc bncComb::convertApcToCoM(cmbCorr* corr, const cmbAC* AC) { 1380 corr->_eph->setOrbCorr(&corr->_orbCorr); 1381 corr->_eph->setClkCorr(&corr->_clkCorr); 1382 ColumnVector xc(6), vv(3); 1383 if (corr->_eph->getCrd(corr->_time, xc, vv, true) != success) { 1384 return failure; 1385 } 1386 bncAntex::e_attMode attMode = bncAntex::ATT_COMPUTED; 1387 double extYaw = 0.0; 1388 if (AC->attitudeSource == "SSR" && corr->_satYawAngleValid) { 1389 attMode = bncAntex::ATT_EXTERNAL; 1390 extYaw = corr->_satYawAngle; 1391 } 1392 else if (AC->attitudeSource == "Nominal") { 1393 attMode = bncAntex::ATT_NOMINAL; 1394 } 1395 double Mjd = corr->_time.mjd() + corr->_time.daysec() / 86400.0; 1396 ColumnVector dx(3); dx = 0.0; 1397 if (_antex->satCoMcorrection(corr->_prn, Mjd, xc.Rows(1,3), vv, dx, attMode, extYaw, AC->name) != success) { 1398 if (_antex->warnNoSatEntry(corr->_prn, corr->_time)) { 1399 emit newMessage("bncComb: no satellite antenna entry valid at " + 1400 QByteArray(corr->_time.datestr().c_str()) + " " + QByteArray(corr->_time.timestr().c_str()) + 1401 " for " + corr->_prn.mid(0,3).toLatin1() + 1402 " in ANTEX file - APC orbit of " + AC->name.toLatin1() + " not converted to CoM, not combined", true); 1403 } 1404 return failure; 1405 } 1406 // X = X_brdc - RSW(xr): X_CoM = X_APC - dx => xr_CoM = xr_APC + RSW(dx) 1407 ColumnVector dRAO(3); 1408 XYZ_to_RSW(xc.Rows(1,3), vv, dx, dRAO); 1409 corr->_orbCorr._xr += dRAO; 1410 return success; 1411 } 1412 1322 1413 // Report AC satellites rejected as outliers in most epochs 1323 1414 //////////////////////////////////////////////////////////////////////////// … … 1544 1635 apc(2) = xc(2)+dx(2); 1545 1636 apc(3) = xc(3)+dx(3); 1637 } 1638 1639 // The combined corrections passed on to the PPP (INTERNAL) always refer 1640 // to the APC: orbits combined in the CoM frame are converted 1641 if (!masterIsAPC && _antex) { 1642 ColumnVector dRAO(3); 1643 XYZ_to_RSW(xc.Rows(1,3), vv, dx, dRAO); 1644 orbCorrections.back()._xr -= dRAO; 1546 1645 } 1547 1646 -
trunk/BNC/src/combination/bnccomb.h
r11075 r11079 280 280 void checkBiasConsistency(bncTime epoTime, char sys, QTextStream& out); 281 281 void checkPersistentOutliers(bncTime epoTime, char sys, QTextStream& out); 282 t_irc convertApcToCoM(cmbCorr* corr, const cmbAC* AC); 283 bool _cmbCoM; // combination in the CoM frame, APC ACs converted 284 QMap<QString, bncTime> _refPointWarned; // last 'APC/CoM differs from master' warning per AC 282 285 struct t_outlierStat { 283 286 t_outlierStat() : numEpo(0) {} -
trunk/BNC/src/pppMain.cpp
r11057 r11079 213 213 if (_realTime) { 214 214 opt->_corrMount.assign(settings.value("PPP/corrMount").toString().toStdString()); 215 opt->_isAPC = (opt->_corrMount.substr(0,4)=="SSRA"); 215 // the combined corrections (INTERNAL) always refer to the APC 216 opt->_isAPC = (opt->_corrMount.substr(0,4)=="SSRA" || opt->_corrMount == "INTERNAL"); 216 217 opt->_biasMount.assign(settings.value("PPP/biasMount").toString().toStdString()); 217 218 opt->_ionoMount.assign(settings.value("PPP/ionoMount").toString().toStdString()); -
trunk/BNC/src/src.pri
r10917 r11079 47 47 -lnewmat -lqwtpolar -lqwt 48 48 49 HEADERS = bnchelp.html bncgetthread.h bncwindow.h bnctabledlg.h \ 49 HEADERS = bnchelp.html bncgetthread.h ssrQc.h bncwindow.h bnctabledlg.h \ 50 50 bnccaster.h bncrinex.h bnccore.h bncutils.h bnchlpdlg.h \ 51 51 bncconst.h bnchtml.h bnctableitem.h bnczerodecoder.h \ … … 89 89 win32:HEADERS += serial/win_qextserialport.h 90 90 91 SOURCES = bncgetthread.cpp bncwindow.cpp bnctabledlg.cpp \ 91 SOURCES = bncgetthread.cpp ssrQc.cpp bncwindow.cpp bnctabledlg.cpp \ 92 92 bnccaster.cpp bncrinex.cpp bnccore.cpp bncutils.cpp \ 93 93 bncconst.cpp bnchtml.cpp bnchlpdlg.cpp bnctableitem.cpp \ -
trunk/BNC/src/ssrQc.cpp
r11075 r11079 106 106 _dirName = dirName; 107 107 _reference = reference.isEmpty() ? QString("CONSENSUS") : reference; 108 bncSettings settings;109 QStringList cmbStreams = settings.value("cmbStreams").toStringList();110 if (!cmbStreams.isEmpty()) {111 _cmbMaster = cmbStreams[0].split(' ', Qt::SkipEmptyParts).value(0);112 }113 108 _interval = interval > 0.0 ? interval : 3600.0; 114 109 for (const QString& sta : streams) { … … 398 393 399 394 // Reference point of the orbits of a stream: APC (SSRA...), CoM (SSRC...); 400 // the combined stream INTERNAL refers to that of its master AC (the first 401 // AC of the combination) 395 // the combined stream INTERNAL refers to the APC 402 396 //////////////////////////////////////////////////////////////////////////// 403 397 char t_ssrQc::refPoint(const QString& staID) const { 404 QString sta = (staID == "INTERNAL") ? _cmbMaster : staID; 398 if (staID == "INTERNAL") { 399 return 'A'; // the combined corrections always refer to the APC 400 } 401 const QString& sta = staID; 405 402 if (sta.startsWith("SSRA")) return 'A'; 406 403 if (sta.startsWith("SSRC")) return 'C'; -
trunk/BNC/src/ssrQc.h
r11075 r11079 107 107 char refPoint(const QString& staID) const; 108 108 QString _reference; // "CONSENSUS" or stream name 109 QString _cmbMaster; // mountpoint of the combination's first AC110 109 bncTime _nextCmpEpoch; 111 110 QMap<QString, QMap<QString, QMap<double, t_orbCorr> > > _orbHist; // stream, PRN (internal), time
Note:
See TracChangeset
for help on using the changeset viewer.
