Changeset 11091 in ntrip for trunk/BNC/src/ssrQc.cpp


Ignore:
Timestamp:
Oct 16, 2026, 11:22:26 AM (39 hours ago)
Author:
stuerze
Message:

ssrqs: consider if an AC has more than one solution

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/src/ssrQc.cpp

    r11087 r11091  
    172172
    173173// Analysis center of a stream: the 3 characters of the AC in mountpoints
    174 // like SSRA00CNE1, otherwise the stream name itself
     174// like SSRA00CNE1 or OSBC00WHU1, otherwise the stream name itself
    175175////////////////////////////////////////////////////////////////////////////
    176176QString t_ssrQc::acOf(const QString& staID) {
    177   static const QRegularExpression re("^SSR[AC][0-9]{2}([A-Z0-9]{3})[0-9]$");
     177  static const QRegularExpression re("^(?:SSR|OSB)[AC][0-9]{2}([A-Z0-9]{3})[0-9]$");
    178178  QRegularExpressionMatch mm = re.match(staID);
    179179  return mm.hasMatch() ? mm.captured(1) : staID;
     180}
     181
     182// Solution of an AC: AC and the two digits of the mountpoint, e.g. GFZ00 for
     183// SSRA00GFZ0/SSRC00GFZ1 and GFZ01 for SSRA01GFZ0; the streams of a solution
     184// (formats, APC/CoM) have one vote in the consensus
     185////////////////////////////////////////////////////////////////////////////
     186QString t_ssrQc::solOf(const QString& staID) {
     187  static const QRegularExpression re("^(?:SSR|OSB)[AC]([0-9]{2})([A-Z0-9]{3})[0-9]$");
     188  QRegularExpressionMatch mm = re.match(staID);
     189  return mm.hasMatch() ? mm.captured(2) + mm.captured(1) : staID;
     190}
     191
     192// AC of a solution (GFZ01 -> GFZ)
     193////////////////////////////////////////////////////////////////////////////
     194QString t_ssrQc::acOfSol(const QString& sol) {
     195  static const QRegularExpression re("^([A-Z0-9]{3})[0-9]{2}$");
     196  QRegularExpressionMatch mm = re.match(sol);
     197  return mm.hasMatch() ? mm.captured(1) : sol;
    180198}
    181199
    … …  
    505523    }
    506524    if (_reference == "CONSENSUS") {
    507       if (!votes(sta) || acOf(sta) == acOf(staID) || (!onlyAC.isEmpty() && acOf(sta) != onlyAC)) {
     525      if (!votes(sta)) {
     526        continue;
     527      }
     528      if (onlyAC.isEmpty() ? (acOf(sta) == acOf(staID))
     529                           : (solOf(sta) != onlyAC || solOf(sta) == solOf(staID))) {
    508530        continue;
    509531      }
    … …  
    521543    for (auto it = bb.constBegin(); it != bb.constEnd(); ++it) {
    522544      if (it.key() != base) {
    523         acDcbs[acOf(sta)][it.key()].append(bb[base] - it.value());
     545        acDcbs[solOf(sta)][it.key()].append(bb[base] - it.value());
    524546      }
    525547    }
    … …  
    668690    QSet<QString> acs;
    669691    for (auto itS = _cbLast.constBegin(); itS != _cbLast.constEnd(); ++itS) {
    670       if (itS.key() != staID && votes(itS.key()) && acOf(itS.key()) != acOf(staID)) {
    671         acs.insert(acOf(itS.key()));
     692      if (itS.key() != staID && votes(itS.key()) && solOf(itS.key()) != solOf(staID)) {
     693        acs.insert(solOf(itS.key()));
    672694      }
    673695    }
    … …  
    683705        continue;
    684706      }
    685       numACs++;
    686707      bases.unite(cc.bases);
    687708      items << QString("%1 RMS %2 m, opposite sign %3/%4").arg(ac).arg(cc.rms(), 0, 'f', 2)
    688709                                                         .arg(cc.numOpp).arg(cc.numSign);
    689       if (cc.opposite()) {
    690         oppACs << ac;
    691       }
    692     }
    693     if (numACs > 0) {
     710      // the sign rule counts the solutions of other ACs only
     711      if (acOfSol(ac) != acOf(staID)) {
     712        numACs++;
     713        if (cc.opposite()) {
     714          oppACs << ac;
     715        }
     716      }
     717    }
     718    if (!items.isEmpty()) {
    694719      QStringList ll = bases.values();
    695720      ll.sort();
    696       lines << QString("code biases compared with the other ACs (DCBs to %1): %2").arg(ll.join("/")).arg(items.join("; "));
     721      lines << QString("code biases compared with the other solutions (DCBs to %1): %2").arg(ll.join("/")).arg(items.join("; "));
    697722      if (numACs >= 2 && oppACs.size() > numACs / 2) {
    698         lines << QString("code biases with the opposite sign of %1 of %2 other ACs (%3) - "
     723        lines << QString("code biases with the opposite sign of %1 of %2 solutions of other ACs (%3) - "
    699724                         "SINEX sign convention instead of the SSR one?")
    700725                 .arg(oppACs.size()).arg(numACs).arg(oppACs.join(" "));
    701726      }
    702       deviating(compare(1, QString()), QString("the median of the other ACs (at least %1 ACs)").arg(MIN_VOTE));
     727      deviating(compare(1, QString()), QString("the median of the other ACs (at least %1 solutions)").arg(MIN_VOTE));
    703728    }
    704729  }
    … …  
    828853        if (!votes(oo) || !crd[oo].contains(prn) || !crd[oo][prn].clkOK) continue;
    829854        if (useOff && !off.contains(oo)) continue;
    830         perAC[acOf(oo)] << crd[oo][prn].clk - (useOff ? off[oo] : 0.0);
     855        perAC[solOf(oo)] << crd[oo][prn].clk - (useOff ? off[oo] : 0.0);
    831856      }
    832857      QMap<QString, double> res;
    … …  
    879904          while (itA.hasNext()) {
    880905            itA.next();
    881             if (itA.key() != ownAC) clks << itA.value();
     906            if (acOfSol(itA.key()) != ownAC) clks << itA.value();
    882907          }
    883908          // orbits: per AC the median of its streams with the same reference point
    … …  
    887912            const t_satCrd& rc = crd[oo][prn];
    888913            if (rc.refPoint != sc.refPoint || sc.refPoint == '?') continue;
    889             for (int ii = 0; ii < 3; ii++) perAC[ii][acOf(oo)] << rc.xx[ii];
     914            for (int ii = 0; ii < 3; ii++) perAC[ii][solOf(oo)] << rc.xx[ii];
    890915          }
    891916          for (const QString& ac : perAC[0].keys()) {
Note: See TracChangeset for help on using the changeset viewer.