Changeset 11061 in ntrip for trunk/BNC/src/combination


Ignore:
Timestamp:
Oct 1, 2026, 6:34:50 PM (4 weeks ago)
Author:
stuerze
Message:

some more fixes

Location:
trunk/BNC/src/combination
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/src/combination/bnccomb.cpp

    r11059 r11061  
    899899          _newCorr->_satCodeBiasIF += codeCoeff * codeBiasesRefSig[frqType];
    900900        }
     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        }
    901907        _newCorr->_satCodeBias._bias.clear();
    902908      }
    … …  
    10791085      out.flush();
    10801086    }
     1087    if (_method == filter) {
     1088      checkBiasConsistency(epoTime, sys, out);
     1089    }
    10811090    printResults(epoTime, out, masterCorr);
    10821091    dumpResults(epoTime, masterCorr);
    … …  
    11441153        if (pp->type == cmbParam::offACSat            &&
    11451154            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) {
    11471156          QQ_sav.Row(iPar)    = 0.0;
    11481157          QQ_sav.Column(iPar) = 0.0;
    … …  
    11741183
    11751184  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////////////////////////////////////////////////////////////////////////////
     1199void 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  }
    11761286}
    11771287
  • trunk/BNC/src/combination/bnccomb.h

    r11059 r11061  
    270270  QMap<QString, bncTime>                     _refBiasWarned; // last warning per AC and system
    271271  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);
    272277  bool allACsBeyond(const bncTime& epoTime) const;
    273278  bncTime                                    _resTime;
Note: See TracChangeset for help on using the changeset viewer.