Skip to content

feat(gps): Comprehensive GPS/RTK/NTRIP subsystem improvements#14112

Open
HTRamsey wants to merge 1 commit intomavlink:masterfrom
HTRamsey:feature/gps-updates
Open

feat(gps): Comprehensive GPS/RTK/NTRIP subsystem improvements#14112
HTRamsey wants to merge 1 commit intomavlink:masterfrom
HTRamsey:feature/gps-updates

Conversation

@HTRamsey
Copy link
Collaborator

Summary

Restructures and enhances the GPS subsystem with improved architecture, testability, and UI integration.

Architecture

  • Reorganized src/GPS/ into NTRIP/ and RTK/ subdirectories with clean separation of concerns
  • NTRIPTransport abstract base class with factory injection pattern for testability
  • RTCMRouter for multi-device RTCM distribution (vehicles via MAVLink + base stations via serial)
  • GPSTransport abstraction decoupling GPS provider from serial implementation
  • GPSEventModel for structured, queryable event logging

NTRIP

  • Exponential-backoff reconnect policy (NTRIPReconnectPolicy)
  • Connection statistics tracking (NTRIPConnectionStats)
  • GGA provider with configurable position source (NTRIPGgaProvider)
  • UDP RTCM forwarding (NTRIPUdpForwarder)
  • SSL/TLS error propagation (NTRIPError::SslError)
  • Transport config validation (NTRIPTransportConfig::isValid())
  • Fixed reconnect ordering bug where stopNTRIP() canceled pending reconnect timer
  • Fixed stopNTRIP() not canceling reconnect when called while idle with pending timer

RTK

  • RTCMMavlink MAVLink fragmentation with bandwidth tracking
  • RTKSatelliteModel for per-satellite signal strength display
  • GPSRTKFactGroup with survey-in progress, baseline, and heading facts

Vehicle Integration

  • New "RTK Corrections Status" section cross-referencing correction source (NTRIP/RTK base) with vehicle fix type
  • RTCM bandwidth and bytes-sent visible in both corrections status and NTRIP sections
  • 30-second warning when corrections flow but vehicle hasn't achieved RTK fix
  • Toolbar corrections dot: green when vehicle has RTK fix, orange when sending but no fix yet

UI

  • Unified GPS settings page (merged NTRIP settings into GPS settings)
  • Signal strength bar chart for RTK base satellites
  • Survey-in progress bar with accuracy convergence
  • Scrollable event log (QGCListView)
  • GPS 1/2 resilience sections via Repeater

Cleanup

  • Removed dead _MSC_VER < 1900 compatibility code
  • Changed _WIN32 to Q_OS_WIN for Qt convention consistency
  • Release-safe state guards (qCCritical replacing Q_ASSERT_X)

Tests

  • 213 tests across 22 suites, all passing
  • End-to-end tests with local TCP NTRIP caster (NTRIPEndToEndTest)
  • Full RTCM pipeline E2E: caster → transport → parser → router → MAVLink fragmentation
  • Mock infrastructure: MockNTRIPTransport, MockGPSRtk
  • Integration tests: NTRIPIntegrationTest, RTKIntegrationTest, SettingsLifecycleTest
  • RTCMTestHelper for building valid RTCM3 frames with correct CRC

Test plan

  • All 213 GPS unit/integration/E2E tests pass
  • Clean build with no warnings (-Werror)
  • Manual test: NTRIP connect/disconnect/reconnect cycle
  • Manual test: RTK base station survey-in and RTCM streaming
  • Manual test: Verify "RTK Corrections Status" section shows correct state
  • Manual test: Verify toolbar dot color changes with RTK fix status
  • Manual test: Settings page layout and functionality

@HTRamsey HTRamsey force-pushed the feature/gps-updates branch 2 times, most recently from bd106e6 to ace132e Compare March 12, 2026 15:36
@github-actions
Copy link
Contributor

github-actions bot commented Mar 12, 2026

Build Results

Platform Status

Platform Status Details
Linux Passed View
Windows Passed View
MacOS Passed View
Android Passed View

All builds passed.

Pre-commit

Check Status Details
pre-commit Failed (non-blocking) View

Pre-commit hooks: 4 passed, 32 failed, 7 skipped.

Test Results

linux-sanitizers: 88 passed, 0 skipped
linux_gcc_64: 88 passed, 0 skipped
Total: 176 passed, 0 skipped

Artifact Sizes

Artifact Size
QGroundControl 247.12 MB
QGroundControl 337.82 MB
QGroundControl-aarch64 176.97 MB
QGroundControl-installer-AMD64 134.84 MB
QGroundControl-installer-AMD64-ARM64 77.46 MB
QGroundControl-installer-ARM64 106.17 MB
QGroundControl-mac 188.53 MB
QGroundControl-windows 188.57 MB
QGroundControl-x86_64 172.10 MB
No baseline available for comparison---
Updated: 2026-03-25 17:11:02 UTC • Triggered by: Android

@HTRamsey HTRamsey force-pushed the feature/gps-updates branch 17 times, most recently from 10839e3 to 3c34872 Compare March 12, 2026 20:48
@HTRamsey HTRamsey marked this pull request as ready for review March 12, 2026 21:47
Copilot AI review requested due to automatic review settings March 12, 2026 21:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR substantially refactors and expands QGroundControl’s GPS subsystem, splitting responsibilities into RTK and NTRIP components, adding new abstractions for transports and routing, and integrating new status/controls into the UI and QML globals.

Changes:

  • Introduces new RTK/NTRIP architecture components (RTCM routing, MAVLink RTCM fragmentation + stats, reconnect policy, connection stats, UDP forwarder) and adds extensive unit/integration/E2E test coverage.
  • Extends vehicle GPS FactGroups and metadata (altitudes, accuracies, speeds, and GNSS integrity enums) and updates toolbar indicator behavior/badges.
  • Adds/updates QML settings pages and supporting reusable QML controls, plus new RTK base station map overlay.

Reviewed changes

Copilot reviewed 149 out of 152 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/QmlControls/QGroundControlQmlGlobal.h Exposes new GPS-related objects to QML (gpsManager, gpsRtk fact group, models).
src/QmlControls/QGroundControlQmlGlobal.cc Wires QML globals to GPSManager singletons and models in ctor.
src/GPS/GPSManager.h/.cc Implements multi-device RTK management, RTCM router/mavlink, and event log plumbing.
src/GPS/NTRIP/NTRIPReconnectPolicy.cc Adds exponential-backoff reconnect logic for NTRIP.
test/GPS/NTRIP/NTRIPHttpTransportTest.cc Updates whitelist tests and adds transport config validation tests.
src/GPS/RTK/RTKBaseStationMapItem.qml Adds map overlay for RTK base station marker/line.
src/UI/toolbar/GPSIndicator.qml Enhances GPS indicator coloring, badges, and click handling.
Comments suppressed due to low confidence (1)

test/GPS/NTRIP/NTRIPHttpTransportTest.cc:78

  • This assertion is logically equivalent to QVERIFY(t._rtcmParser.isWhitelisted(9999)); but the current !x == false form is hard to read and easy to misinterpret. Simplifying it will make the intent (empty whitelist accepts all IDs) clearer.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +118 to +124
QGCLabel {
anchors.centerIn: parent
text: "!"
color: "white"
font.bold: true
font.pixelSize: parent.height * 0.7
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interference badge label uses a hardcoded "white" text color. To keep theming consistent (light/dark palettes, custom themes), prefer using QGCPalette colors instead of literal color strings.

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +84
Q_PROPERTY(GPSManager* gpsManager READ gpsManager CONSTANT)
Q_PROPERTY(FactGroup* gpsRtk READ gpsRtkFactGroup CONSTANT)
#endif
Q_PROPERTY(RTKSatelliteModel* rtkSatelliteModel READ rtkSatelliteModel CONSTANT)
Q_PROPERTY(GPSEventModel* gpsEventModel READ gpsEventModel CONSTANT)
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gpsRtk, rtkSatelliteModel, and gpsEventModel are declared as CONSTANT, but their underlying pointers depend on runtime GPS device connections. If no RTK device is connected at startup, these will be nullptr and QML bindings won’t update when a device later connects. Consider making these Q_PROPERTY values non-constant with NOTIFY signals (emitted on device connect/disconnect/primary-device change), or expose them via GPSManager properties that notify changes.

Copilot uses AI. Check for mistakes.
if (_deviceMap.isEmpty()) {
return nullptr;
}
return _deviceMap.cbegin().value();
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_primaryDevice() selects the primary RTK device via QHash::cbegin(), but QHash iteration order is not deterministic. With multiple RTK devices connected, the chosen primary (and thus the fact group / satellite model / position source exposed to UI) can change unpredictably. Consider explicitly tracking a primary device (first-connected, user-selected, etc.) or using an ordered container.

Suggested change
return _deviceMap.cbegin().value();
// Select primary device deterministically by choosing the device with the
// lexicographically smallest key, instead of relying on QHash iteration order.
auto bestIt = _deviceMap.cbegin();
for (auto it = _deviceMap.cbegin(); it != _deviceMap.cend(); ++it) {
if (it.key() < bestIt.key()) {
bestIt = it;
}
}
return bestIt.value();

Copilot uses AI. Check for mistakes.
Comment on lines +34 to +37
int NTRIPReconnectPolicy::nextBackoffMs() const
{
return qMin(kMinReconnectMs * (1 << qMin(_attempts, 4)), kMaxReconnectMs);
}
Copy link

Copilot AI Mar 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nextBackoffMs() caps the exponent with qMin(_attempts, 4), so the backoff tops out at 16s (1s * 2^4) and will never reach kMaxReconnectMs (30s). If the intended max is 30s, allow attempts to grow until the computed backoff exceeds kMaxReconnectMs (then clamp), or adjust the cap accordingly.

Copilot uses AI. Check for mistakes.
@HTRamsey HTRamsey force-pushed the feature/gps-updates branch 2 times, most recently from be8e7f1 to 8492da8 Compare March 24, 2026 01:22
@HTRamsey HTRamsey force-pushed the feature/gps-updates branch 3 times, most recently from 8490048 to 6b29db1 Compare March 25, 2026 04:36
@HTRamsey HTRamsey force-pushed the feature/gps-updates branch 3 times, most recently from 71625a2 to 6b8ff2c Compare March 25, 2026 09:08
- Rewrite NTRIP subsystem with transport abstraction, reconnect policy,
  connection stats, and GGA provider
- Add RTK satellite model with per-satellite SNR/constellation tracking
- Extract QML components: RTKBaseStationStatus, RTKBaseStationMapItem,
  NTRIPConnectionStatus into GPS QML modules
- Move settings into domain modules: RTKSettings → GPS.RTK,
  NTRIPSettings → GPS.NTRIP, GCSPositionSettings → PositionManager
- Add 3-tab settings UI separating RTK, NTRIP, and GCS Position concerns
- Add connect/disconnect controls for RTK base station and NMEA GPS
- Add GPS event model and logging infrastructure
- Fix clang -Wunused-lambda-capture in GPSRtk
- Comprehensive null guards in RTKBaseStationStatus QML
@HTRamsey HTRamsey force-pushed the feature/gps-updates branch from 6b8ff2c to 869093f Compare March 25, 2026 15:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants