Changeset 11061 in ntrip
- Timestamp:
- Oct 1, 2026, 6:34:50 PM (5 hours ago)
- Location:
- trunk/BNC/src
- Files:
-
- 3 edited
-
bnchelp.html (modified) (1 diff)
-
combination/bnccomb.cpp (modified) (4 diffs)
-
combination/bnccomb.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/BNC/src/bnchelp.html
r11058 r11061 7843 7843 - despite the fact, that the delivered code biases of an AC may contain contributions from other biases, also phase 7844 7844 biases. 7845 </p> 7846 <p> 7847 <b>Consistency of code biases and clocks:</b> 7848 This procedure requires that the code biases of an AC are consistent with its clocks. An AC is free to estimate 7849 its clocks from signals other than the reference signals; its code biases of the reference signals must then 7850 refer to exactly these clocks, i.e. they have to be estimated together with them or aligned to the same clock 7851 datum. If an AC combines its clocks with code biases from another source (e.g. a SINEX Bias file of another 7852 analysis), the ionosphere-free linear combination B_IF of these biases does not belong to the clocks. The clocks 7853 are then shifted per satellite by the wrong amount before the combination. 7854 </p> 7855 <p> 7856 In the combination (method 'Filter') such errors are absorbed by the satellite-specific clock offsets estimated 7857 for each AC, which consequently follow B_IF of that AC from satellite to satellite. BNC uses this to check the 7858 consistency, separately for each AC and system: 7859 </p> 7860 <ul> 7861 <li>Every 5 minutes (the first check 5 minutes after the start), the AC's satellite offsets of the current epoch 7862 are regressed against its B_IF.</li> 7863 <li>Only satellites with code biases for both reference signals are used; at least 5 satellites are required.</li> 7864 <li>B_IF must vary noticeably between the satellites (standard deviation of at least 3 cm). Otherwise, e.g. for 7865 GPS where B_IF of most ACs is close to zero, an inconsistency is not detectable and the check is skipped.</li> 7866 <li>An inconsistency is reported if the offsets clearly follow B_IF: regression slope at least 0.3 and correlation 7867 coefficient at least 0.7. Since the error is shared between the inconsistent AC and the others, a slope of about 7868 0.5 is to be expected with two ACs; with more ACs it approaches 1. The ACs with consistent biases show no 7869 correlation with their own B_IF.</li> 7870 </ul> 7871 <p> 7872 The result of each positive check is written to the combination logfile, a warning to the BNC logfile at most once 7873 per hour per AC and system, e.g. 7874 </p> 7875 <pre> 7876 bncComb: BKG E code biases (C1C/C5Q) seem inconsistent with its clocks: satellite offsets follow the bias 7877 combination B_IF (27 satellites, B_IF spread 0.084 m, slope 0.60, correlation 0.88) 7878 </pre> 7879 <p> 7880 The AC is still used in the combination, its offsets absorb most of the error. Nevertheless, the code biases 7881 sent out by this AC should be corrected by its provider: either biases estimated together with the clocks 7882 should be used, or the external biases have to be aligned to the clocks per satellite (b' = b - B_IF of the 7883 reference signals, SSR sign convention). The check is not applied with the 'Single-Epoch' method. 7845 7884 </p> 7846 7885 <p> -
trunk/BNC/src/combination/bnccomb.cpp
r11059 r11061 899 899 _newCorr->_satCodeBiasIF += codeCoeff * codeBiasesRefSig[frqType]; 900 900 } 901 if (codeBiasesRefSig.size() == 2) { 902 _acBiasIF[acName][prnStr.mid(0,3)] = _newCorr->_satCodeBiasIF; 903 } 904 else { 905 _acBiasIF[acName].remove(prnStr.mid(0,3)); 906 } 901 907 _newCorr->_satCodeBias._bias.clear(); 902 908 } … … 1079 1085 out.flush(); 1080 1086 } 1087 if (_method == filter) { 1088 checkBiasConsistency(epoTime, sys, out); 1089 } 1081 1090 printResults(epoTime, out, masterCorr); 1082 1091 dumpResults(epoTime, masterCorr); … … 1144 1153 if (pp->type == cmbParam::offACSat && 1145 1154 pp->AC == corrs(sys)[maxResIndex-1]->_acName && 1146 pp->prn == corrs(sys)[maxResIndex-1]->_prn .mid(0,3)) {1155 pp->prn == corrs(sys)[maxResIndex-1]->_prn) { 1147 1156 QQ_sav.Row(iPar) = 0.0; 1148 1157 QQ_sav.Column(iPar) = 0.0; … … 1174 1183 1175 1184 return success; 1185 } 1186 1187 // Check the consistency of the AC code biases with the AC clocks 1188 //////////////////////////////////////////////////////////////////////////// 1189 // An AC's clocks refer to its own clock signals; the code biases of the 1190 // reference signals refer them to the reference signals (B_IF, ionosphere- 1191 // free combination of these biases, added to the AC clocks). If the code 1192 // biases do not belong to the clocks (e.g. taken from another product), the 1193 // error B_IF is absorbed by the AC's satellite offsets. The satellite offsets 1194 // of each AC are therefore regressed against its B_IF every 5 minutes (from 1195 // 5 minutes after the start); a warning is issued (at most once per hour per 1196 // AC and system) if B_IF varies noticeably between the satellites and the 1197 // offsets clearly follow it. 1198 //////////////////////////////////////////////////////////////////////////// 1199 void bncComb::checkBiasConsistency(bncTime epoTime, char sys, QTextStream& out) { 1200 1201 const double CHECK_INT = 300.0; // [s] check interval, first check after start 1202 const unsigned MIN_SAT = 5; 1203 const double MIN_SPREAD = 0.03; // [m] minimum std. deviation of B_IF 1204 const double MIN_SLOPE = 0.3; // 0.5 expected for 2 ACs, -> 1 for more ACs 1205 const double MIN_CORR = 0.7; 1206 1207 if (!_biasCheckStart[sys].valid()) { 1208 _biasCheckStart[sys] = epoTime; 1209 _biasCheckLast[sys] = epoTime; 1210 return; 1211 } 1212 if (epoTime - _biasCheckLast[sys] < CHECK_INT) { 1213 return; 1214 } 1215 _biasCheckLast[sys] = epoTime; 1216 1217 QListIterator<cmbAC*> itAc(_ACs); 1218 while (itAc.hasNext()) { 1219 const QString& acName = itAc.next()->name; 1220 if (!_acBiasIF.contains(acName)) { 1221 continue; 1222 } 1223 const QMap<QString, double>& biasIF = _acBiasIF[acName]; 1224 1225 // satellites of this AC in the current epoch with B_IF available 1226 QVector<double> xx, yy; 1227 for (int ii = 0; ii < corrs(sys).size(); ii++) { 1228 const cmbCorr* corr = corrs(sys)[ii]; 1229 if (corr->_acName != acName || !biasIF.contains(corr->_prn.mid(0,3))) { 1230 continue; 1231 } 1232 for (int iPar = 1; iPar <= _params[sys].size(); iPar++) { 1233 const cmbParam* pp = _params[sys][iPar-1]; 1234 if (pp->type == cmbParam::offACSat && pp->AC == acName && pp->prn == corr->_prn) { 1235 xx.push_back(biasIF[corr->_prn.mid(0,3)]); 1236 yy.push_back(pp->xx); 1237 break; 1238 } 1239 } 1240 } 1241 unsigned nn = xx.size(); 1242 if (nn < MIN_SAT) { 1243 continue; 1244 } 1245 double mx = 0.0, my = 0.0; 1246 for (unsigned ii = 0; ii < nn; ii++) { 1247 mx += xx[ii] / nn; 1248 my += yy[ii] / nn; 1249 } 1250 double sxx = 0.0, syy = 0.0, sxy = 0.0; 1251 for (unsigned ii = 0; ii < nn; ii++) { 1252 sxx += (xx[ii] - mx) * (xx[ii] - mx); 1253 syy += (yy[ii] - my) * (yy[ii] - my); 1254 sxy += (xx[ii] - mx) * (yy[ii] - my); 1255 } 1256 double spread = sqrt(sxx / nn); 1257 if (spread < MIN_SPREAD || syy <= 0.0) { 1258 continue; 1259 } 1260 double slope = sxy / sxx; 1261 double corrCoeff = sxy / sqrt(sxx * syy); 1262 if (slope < MIN_SLOPE || corrCoeff < MIN_CORR) { 1263 continue; 1264 } 1265 1266 QString refSig; 1267 for (unsigned ii = 1; ii < cmbRefSig::cIF; ii++) { 1268 t_frequency::type frqType = cmbRefSig::toFreq(sys, static_cast<cmbRefSig::type>(ii)); 1269 refSig += QString("%1C%2%3").arg(ii > 1 ? "/" : "").arg(t_frequency::toString(frqType)[1]) 1270 .arg(cmbRefSig::toAttrib(sys, static_cast<cmbRefSig::type>(ii))); 1271 } 1272 QString msg = QString("%1 %2 code biases (%3) seem inconsistent with its clocks: " 1273 "satellite offsets follow the bias combination B_IF " 1274 "(%4 satellites, B_IF spread %5 m, slope %6, correlation %7)") 1275 .arg(acName).arg(sys).arg(refSig).arg(nn) 1276 .arg(spread, 0, 'f', 3).arg(slope, 0, 'f', 2).arg(corrCoeff, 0, 'f', 2); 1277 out << epoTime.datestr().c_str() << " " << epoTime.timestr().c_str() 1278 << " " << msg << "\n"; 1279 QString key = acName + sys; 1280 bncTime& warned = _biasCheckWarned[key]; 1281 if (!warned.valid() || epoTime - warned >= 3600.0) { 1282 warned = epoTime; 1283 emit newMessage("bncComb: " + msg.toLatin1(), true); 1284 } 1285 } 1176 1286 } 1177 1287 -
trunk/BNC/src/combination/bnccomb.h
r11059 r11061 270 270 QMap<QString, bncTime> _refBiasWarned; // last warning per AC and system 271 271 QMap<char, bncTime> _singleACWarned; // last 'fewer than 2 ACs' message per system 272 QMap<QString, QMap<QString, double> > _acBiasIF; // latest B_IF of the reference signals per AC and satellite 273 QMap<char, bncTime> _biasCheckStart; // first combined epoch per system 274 QMap<char, bncTime> _biasCheckLast; // last bias/clock consistency check per system 275 QMap<QString, bncTime> _biasCheckWarned; // last inconsistency warning per AC and system 276 void checkBiasConsistency(bncTime epoTime, char sys, QTextStream& out); 272 277 bool allACsBeyond(const bncTime& epoTime) const; 273 278 bncTime _resTime;
Note:
See TracChangeset
for help on using the changeset viewer.
