Normalize zero-based firmware satellite indices
This commit is contained in:
@@ -226,8 +226,9 @@ without logging out.
|
||||
positions are propagated from the cached ephemeris, then smoothly interpolated at 10 FPS.
|
||||
- The 3D Earth tab includes a `RINEX Guncelle` button for an immediate manual refresh. Its status
|
||||
line shows the system-local time of the last successful download or cache load.
|
||||
- Complete UART channel snapshots such as `tracked satellites=5 prns=[...]` replace the previous
|
||||
connected-PRN set, so satellites that were lost no longer remain green.
|
||||
- Complete UART channel snapshots such as `tracked satellites=5 prn_indices=[...]` replace the
|
||||
previous connected-PRN set, so satellites that were lost no longer remain green. Firmware
|
||||
channel indices are zero-based and are normalized for display (`0` is GPS PRN `G01`).
|
||||
- RINEX text is parsed once per download and retained as compact ephemeris records. The static
|
||||
globe is cached between camera changes, reducing CPU and allocation load during orbit animation.
|
||||
- The globe uses an embedded Natural Earth coastline mask with terrain-like land colouring,
|
||||
|
||||
+22
-8
@@ -234,10 +234,11 @@ QSet<QString> LocationParser::parseGpsPrns(const QString &line)
|
||||
QSet<QString> result;
|
||||
const auto addPrn = [&result](QString value, bool zeroBased = false) {
|
||||
value = value.trimmed().toUpper();
|
||||
if (value.startsWith(QLatin1Char('G'))) value.remove(0, 1);
|
||||
const bool explicitGpsPrn = value.startsWith(QLatin1Char('G'));
|
||||
if (explicitGpsPrn) value.remove(0, 1);
|
||||
bool ok = false;
|
||||
int number = value.toInt(&ok);
|
||||
if (ok && zeroBased) ++number;
|
||||
if (ok && zeroBased && !explicitGpsPrn) ++number;
|
||||
if (ok && number >= 1 && number <= 63) {
|
||||
result.insert(QStringLiteral("G%1").arg(number, 2, 10, QLatin1Char('0')));
|
||||
}
|
||||
@@ -249,18 +250,31 @@ QSet<QString> LocationParser::parseGpsPrns(const QString &line)
|
||||
auto gpsMatches = gpsToken.globalMatch(line);
|
||||
while (gpsMatches.hasNext()) addPrn(gpsMatches.next().captured(QStringLiteral("prn")));
|
||||
|
||||
static const QRegularExpression labeledList(
|
||||
QStringLiteral(R"((?<label>\bPRNS?\b|\bSVS?\b|\bSVNS?\b|\bSVIDS?\b)\s*(?:=|:|->)?\s*[\[(]?\s*(?<list>(?:G?\d{1,2})(?:\s*[,;/| ]\s*G?\d{1,2})*)\s*[\])]?)"),
|
||||
// Current firmware versions called their zero-based hardware channel values
|
||||
// "prns" in complete tracking snapshots. Keep accepting those messages while
|
||||
// newer firmware uses the unambiguous "prn_indices" label.
|
||||
static const QRegularExpression legacyTrackingIndices(
|
||||
QStringLiteral(R"(\btracked\s+satellites\s*=\s*\d+\s+prns?\s*=)"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
static const QRegularExpression number(QStringLiteral(R"(G?(\d{1,2}))"),
|
||||
const bool legacyZeroBasedPrns = legacyTrackingIndices.match(line).hasMatch();
|
||||
|
||||
static const QRegularExpression labeledList(
|
||||
QStringLiteral(R"((?<label>\bPRN[_ -]?INDICES\b|\bPRNS?\b|\bSVS?\b|\bSVNS?\b|\bSVIDS?\b)\s*(?:=|:|->)?\s*[\[(]?\s*(?<list>(?:G?\d{1,2})(?:\s*[,;/| ]\s*G?\d{1,2})*)\s*[\])]?)"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
static const QRegularExpression number(QStringLiteral(R"(G?\d{1,2})"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
auto listMatches = labeledList.globalMatch(line);
|
||||
while (listMatches.hasNext()) {
|
||||
const QRegularExpressionMatch listMatch = listMatches.next();
|
||||
const bool zeroBased = listMatch.captured(QStringLiteral("label")).startsWith(
|
||||
QStringLiteral("SVN"), Qt::CaseInsensitive);
|
||||
QString label = listMatch.captured(QStringLiteral("label")).toUpper();
|
||||
label.remove(QLatin1Char('_'));
|
||||
label.remove(QLatin1Char('-'));
|
||||
label.remove(QLatin1Char(' '));
|
||||
const bool zeroBased = label.startsWith(QStringLiteral("SVN"))
|
||||
|| label == QStringLiteral("PRNINDICES")
|
||||
|| (legacyZeroBasedPrns && label.startsWith(QStringLiteral("PRN")));
|
||||
auto values = number.globalMatch(listMatch.captured(QStringLiteral("list")));
|
||||
while (values.hasNext()) addPrn(values.next().captured(1), zeroBased);
|
||||
while (values.hasNext()) addPrn(values.next().captured(0), zeroBased);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+1
-1
@@ -653,7 +653,7 @@ void MainWindow::handleSerialLine(const QString &line)
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
static const QRegularExpression trackingSnapshotRegex(
|
||||
QStringLiteral(
|
||||
R"(\btracked\s+satellites\s*=\s*\d+\s+(?:prns?|svns?)\s*=\s*\[[^\]]*\])"),
|
||||
R"(\btracked\s+satellites\s*=\s*\d+\s+(?:prn[_ -]?indices|prns?|svns?)\s*=\s*\[[^\]]*\])"),
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
const bool solveStarted = solveStartRegex.match(line.trimmed()).hasMatch();
|
||||
const bool trackingSnapshot = trackingSnapshotRegex.match(line).hasMatch();
|
||||
|
||||
@@ -121,13 +121,13 @@ int main(int argc, char **argv)
|
||||
assert(std::abs(map->centerCoordinate().y() - 29.5) < 0.000001);
|
||||
map->clearPoints();
|
||||
|
||||
sendLine(window, QStringLiteral("[TRK] tracked satellites=2 prns=[3,8]"));
|
||||
sendLine(window, QStringLiteral("[TRK] tracked satellites=2 prn_indices=[2,7]"));
|
||||
assert(map != nullptr);
|
||||
auto *globe = window.findChild<GlobeWidget *>();
|
||||
assert(globe != nullptr);
|
||||
assert(globe->observedPrns()
|
||||
== QSet<QString>({QStringLiteral("G03"), QStringLiteral("G08")}));
|
||||
sendLine(window, QStringLiteral("[TRK] tracked satellites=1 prns=[14]"));
|
||||
sendLine(window, QStringLiteral("[TRK] tracked satellites=1 prn_indices=[13]"));
|
||||
assert(globe->observedPrns() == QSet<QString>({QStringLiteral("G14")}));
|
||||
|
||||
assert(QMetaObject::invokeMethod(map, "referenceLocationSelected", Qt::DirectConnection,
|
||||
|
||||
@@ -186,6 +186,25 @@ int main(int argc, char **argv)
|
||||
assert(prns == QSet<QString>({QStringLiteral("G01"), QStringLiteral("G32")}));
|
||||
}
|
||||
|
||||
{
|
||||
const QSet<QString> prns = LocationParser::parseGpsPrns(
|
||||
QStringLiteral("[TRK] tracked satellites=3 prn_indices=[0,7,31]"));
|
||||
assert(prns == QSet<QString>({QStringLiteral("G01"), QStringLiteral("G08"),
|
||||
QStringLiteral("G32")}));
|
||||
}
|
||||
|
||||
{
|
||||
const QSet<QString> prns = LocationParser::parseGpsPrns(
|
||||
QStringLiteral("[TRK] tracked satellites=2 prns=[0,7]"));
|
||||
assert(prns == QSet<QString>({QStringLiteral("G01"), QStringLiteral("G08")}));
|
||||
}
|
||||
|
||||
{
|
||||
const QSet<QString> prns = LocationParser::parseGpsPrns(
|
||||
QStringLiteral("[TRK] tracked satellites=2 prn_indices=[0,G08]"));
|
||||
assert(prns == QSet<QString>({QStringLiteral("G01"), QStringLiteral("G08")}));
|
||||
}
|
||||
|
||||
{
|
||||
const auto parsed = LocationParser::parseLine(QStringLiteral(
|
||||
"[OK] [NAV] DOP GDOP=7.0907891622 PDOP=5.6333862175 "
|
||||
|
||||
Reference in New Issue
Block a user