-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Add GPS resilience monitoring with GNSS_INTEGRITY message #13812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
5beae41
Add GPS resilience icons
Tory9 c701042
Extend GPS fact groups with integrity fields
Tory9 07ac51a
Add GPS2 integrity message handling
Tory9 eee7f61
Create GPS aggregate fact group
Tory9 b2a3bb6
Wire GPS aggregate into Vehicle class
Tory9 79c089d
Add GPS resilience toolbar indicator
Tory9 f8c97ad
Add GPS system errors to existing GPS indicator page
Tory9 ebf3a91
Copilot review follow-up: Remove trailing whitespace
Tory9 4c5332f
Copilot review follow-up: Remove redundant code in GPS aggregate hand…
Tory9 20b869e
Copilot review follow-up: Improve GPS resilience code clarity
Tory9 4af4e38
Add signal emission on GNSS_INTEGRITY message receipt for stale timer
Tory9 74b49e8
Refine GPS resilience details visibility
Tory9 b9c531e
Simplify GNSS Integrity ID handling
Tory9 34a7f52
Switch to using JSON metadata for facts
Tory9 64eae2a
Simplify signal connections
Tory9 507556e
Introduce AuthState enum for clearer authentication merge logic
Tory9 5b5eb52
Updated GPS detail visibility
Tory9 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| /**************************************************************************** | ||
| * | ||
| * (c) 2009-2024 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org> | ||
| * | ||
| * QGroundControl is licensed according to the terms in the file | ||
| * COPYING.md in the root of the source code directory. | ||
| * | ||
| ****************************************************************************/ | ||
|
|
||
| import QtQuick | ||
| import QtQuick.Layouts | ||
|
|
||
| import QGroundControl | ||
| import QGroundControl.Controls | ||
|
|
||
| //------------------------------------------------------------------------- | ||
| //-- GPS Resilience Indicator | ||
| Item { | ||
| id: control | ||
| width: height | ||
| anchors.top: parent.top | ||
| anchors.bottom: parent.bottom | ||
| visible: showIndicator | ||
|
|
||
| property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle | ||
| property var _gpsAggregate: _activeVehicle ? _activeVehicle.gpsAggregate : null | ||
|
|
||
| property var qgcPal: QGroundControl.globalPalette | ||
|
|
||
| property bool showIndicator: _activeVehicle && _gpsAggregate && ( | ||
| (_gpsAggregate.authenticationState.value > 0 && _gpsAggregate.authenticationState.value < 255) || | ||
| (_gpsAggregate.spoofingState.value > 0 && _gpsAggregate.spoofingState.value < 255) || | ||
| (_gpsAggregate.jammingState.value > 0 && _gpsAggregate.jammingState.value < 255) | ||
| ) | ||
|
|
||
| // Authentication Icon (Outer/Bottom Layer) | ||
| QGCColoredImage { | ||
| id: authIcon | ||
| width: parent.height * 0.95 | ||
| height: parent.height * 0.95 | ||
| anchors.centerIn: parent | ||
| source: "/qmlimages/GpsAuthentication.svg" | ||
| fillMode: Image.PreserveAspectFit | ||
| sourceSize.height: height | ||
| color: _authColor() | ||
| visible: _gpsAggregate && _gpsAggregate.authenticationState.value > 0 && _gpsAggregate.authenticationState.value < 255 | ||
| } | ||
|
|
||
| // Interference Icon (Inner/Top Layer) | ||
| QGCColoredImage { | ||
| id: interfIcon | ||
| width: parent.height * 0.55 | ||
| height: parent.height * 0.55 | ||
| anchors.centerIn: parent | ||
| source: "/qmlimages/GpsInterference.svg" | ||
| fillMode: Image.PreserveAspectFit | ||
| sourceSize.height: height | ||
| color: _interfColor() | ||
| visible: _gpsAggregate && (Math.max(_gpsAggregate.spoofingState.value, _gpsAggregate.jammingState.value) > 0) && (Math.max(_gpsAggregate.spoofingState.value, _gpsAggregate.jammingState.value) < 255) | ||
| } | ||
|
|
||
| function _authColor() { | ||
| if (!_gpsAggregate) return qgcPal.colorGrey; | ||
| switch (_gpsAggregate.authenticationState.value) { | ||
| case 1: return qgcPal.colorYellow; // Initializing | ||
| case 2: return qgcPal.colorRed; // Error | ||
| case 3: return qgcPal.colorGreen; // OK | ||
| default: return qgcPal.colorGrey; // Unknown or Disabled | ||
| } | ||
| } | ||
|
|
||
| function _interfColor() { | ||
| if (!_gpsAggregate) return qgcPal.colorGrey; | ||
| let maxState = Math.max(_gpsAggregate.spoofingState.value, _gpsAggregate.jammingState.value); | ||
| switch (maxState) { | ||
| case 1: return qgcPal.colorGreen; // Not spoofed/jammed | ||
| case 2: return qgcPal.colorOrange; // Mitigated | ||
| case 3: return qgcPal.colorRed; // Detected | ||
| default: return qgcPal.colorGrey; // Unknown | ||
| } | ||
| } | ||
|
|
||
| MouseArea { | ||
| anchors.fill: parent | ||
| onClicked: mainWindow.showIndicatorDrawer(resiliencePopup, control) | ||
| } | ||
|
|
||
| Component { | ||
| id: resiliencePopup | ||
| ToolIndicatorPage { | ||
| showExpand: expandedComponent ? true : false | ||
| contentComponent: resilienceContent | ||
| } | ||
| } | ||
|
|
||
| Component { | ||
| id: resilienceContent | ||
| ColumnLayout { | ||
| spacing: ScreenTools.defaultFontPixelHeight / 2 | ||
|
|
||
| // Unified GPS Resilience Status | ||
| SettingsGroupLayout { | ||
| heading: qsTr("GPS Resilience Status") | ||
| showDividers: true | ||
|
|
||
| LabelledLabel { | ||
| label: qsTr("GPS Jamming") | ||
| labelText: _gpsAggregate ? (_gpsAggregate.jammingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _gpsAggregate && _gpsAggregate.jammingState.value > 0 && _gpsAggregate.jammingState.value < 255 | ||
| } | ||
|
|
||
| LabelledLabel { | ||
| label: qsTr("GPS Spoofing") | ||
| labelText: _gpsAggregate ? (_gpsAggregate.spoofingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _gpsAggregate && _gpsAggregate.spoofingState.value > 0 && _gpsAggregate.spoofingState.value < 255 | ||
| } | ||
|
|
||
| LabelledLabel { | ||
| label: qsTr("GPS Authentication") | ||
| labelText: _gpsAggregate ? (_gpsAggregate.authenticationState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _gpsAggregate && _gpsAggregate.authenticationState.value > 0 && _gpsAggregate.authenticationState.value < 255 | ||
| } | ||
| } | ||
|
|
||
| // GPS 1 Details | ||
| SettingsGroupLayout { | ||
| heading: qsTr("GPS 1 Details") | ||
| showDividers: true | ||
| visible: _activeVehicle && _activeVehicle.gps && ( | ||
| (_activeVehicle.gps.jammingState.value > 0 && _activeVehicle.gps.jammingState.value < 255) || | ||
| (_activeVehicle.gps.spoofingState.value > 0 && _activeVehicle.gps.spoofingState.value < 255) || | ||
| (_activeVehicle.gps.authenticationState.value > 0 && _activeVehicle.gps.authenticationState.value < 255) | ||
| ) | ||
|
|
||
| LabelledLabel { | ||
| label: qsTr("Jamming") | ||
| labelText: (_activeVehicle && _activeVehicle.gps) ? (_activeVehicle.gps.jammingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps.jammingState.value > 0 && _activeVehicle.gps.jammingState.value < 255 | ||
| } | ||
| LabelledLabel { | ||
| label: qsTr("Spoofing") | ||
| labelText: (_activeVehicle && _activeVehicle.gps) ? (_activeVehicle.gps.spoofingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps.spoofingState.value > 0 && _activeVehicle.gps.spoofingState.value < 255 | ||
| } | ||
| LabelledLabel { | ||
| label: qsTr("Authentication") | ||
| labelText: (_activeVehicle && _activeVehicle.gps) ? (_activeVehicle.gps.authenticationState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps.authenticationState.value > 0 && _activeVehicle.gps.authenticationState.value < 255 | ||
| } | ||
| } | ||
|
|
||
| // GPS 2 Details | ||
| SettingsGroupLayout { | ||
| heading: qsTr("GPS 2 Details") | ||
| showDividers: true | ||
| visible: _activeVehicle && _activeVehicle.gps2 && ( | ||
| (_activeVehicle.gps2.jammingState.value > 0 && _activeVehicle.gps2.jammingState.value < 255) || | ||
| (_activeVehicle.gps2.spoofingState.value > 0 && _activeVehicle.gps2.spoofingState.value < 255) || | ||
| (_activeVehicle.gps2.authenticationState.value > 0 && _activeVehicle.gps2.authenticationState.value < 255) | ||
| ) | ||
|
|
||
| LabelledLabel { | ||
| label: qsTr("Jamming") | ||
| labelText: (_activeVehicle && _activeVehicle.gps2) ? (_activeVehicle.gps2.jammingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps2.jammingState.value > 0 && _activeVehicle.gps2.jammingState.value < 255 | ||
| } | ||
| LabelledLabel { | ||
| label: qsTr("Spoofing") | ||
| labelText: (_activeVehicle && _activeVehicle.gps2) ? (_activeVehicle.gps2.spoofingState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps2.spoofingState.value > 0 && _activeVehicle.gps2.spoofingState.value < 255 | ||
| } | ||
| LabelledLabel { | ||
| label: qsTr("Authentication") | ||
| labelText: (_activeVehicle && _activeVehicle.gps2) ? (_activeVehicle.gps2.authenticationState.enumStringValue || qsTr("n/a")) : qsTr("n/a") | ||
| visible: _activeVehicle.gps2.authenticationState.value > 0 && _activeVehicle.gps2.authenticationState.value < 255 | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
systemErrorsfield appears to be a bitmask (values are powers of 2: 1, 2, 4, 8, 16, 32, 64), but the switch statement handles only exact single-bit values. When multiple errors occur simultaneously (e.g., value = 3 for bits 0 and 1 set), it will fall through to "Multiple errors" without identifying which specific errors are present. Consider implementing proper bit-flag checking to handle combinations of errors, or at least document this behavior if it's intentional.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This does need to be addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I intentionally grouped multiple errors into a single "Multiple errors" message to keep the UI clean, as there isn't much space to list several error strings like "Incoming correction, Configuration" without cluttering the display. Since these are exceptional situations, and having multiple at once is even rarer, a simple summary seemed like the best trade-off, especially since investigation would be required anyway. However, if you think seeing every individual error is critical, I can add the bit-flag checking