diff --git a/libs/mavlink/include/mavlink/v2.0 b/libs/mavlink/include/mavlink/v2.0 index 908a3910ed4..8fbb24278b5 160000 --- a/libs/mavlink/include/mavlink/v2.0 +++ b/libs/mavlink/include/mavlink/v2.0 @@ -1 +1 @@ -Subproject commit 908a3910ed4070b9d08e01cbf3e467f413829f1f +Subproject commit 8fbb24278b561e126a0dfd7e9f69120469121563 diff --git a/qgcimages.qrc b/qgcimages.qrc index c42210b5d84..915c430e44a 100644 --- a/qgcimages.qrc +++ b/qgcimages.qrc @@ -96,6 +96,8 @@ src/AnalyzeView/GeoTagIcon.svg src/UI/toolbar/Images/Gps.svg src/UI/toolbar/Images/Hamburger.svg + src/UI/toolbar/Images/GpsAuthentication.svg + src/UI/toolbar/Images/GpsInterference.svg src/FlightMap/Images/Help.svg src/FlightMap/Images/HelpBlack.svg src/AutoPilotPlugins/PX4/Images/HITL.svg diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 9e8253038ed..329b98b12eb 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -13,6 +13,8 @@ src/UI/toolbar/TelemetryRSSIIndicator.qml src/UI/toolbar/VTOLModeIndicator.qml src/UI/toolbar/APMSupportForwardingIndicator.qml + src/UI/toolbar/GPSAuthenticationIndicator.qml + src/UI/toolbar/GPSInterferenceIndicator.qml src/FlightDisplay/DefaultChecklist.qml diff --git a/src/Comms/MockLink/MockLink.cc b/src/Comms/MockLink/MockLink.cc index 07be06552cd..57e533d7bd3 100644 --- a/src/Comms/MockLink/MockLink.cc +++ b/src/Comms/MockLink/MockLink.cc @@ -1323,7 +1323,7 @@ void MockLink::_sendGpsRawInt(void) 0, // Altitude uncertainty in meters * 1000 (positive for up). 0, // Speed uncertainty in meters * 1000 (positive for up). 0, // Heading / track uncertainty in degrees * 1e5. - 65535); // Yaw not provided + 65535); respondWithMavlinkMessage(msg); } diff --git a/src/FirmwarePlugin/FirmwarePlugin.cc b/src/FirmwarePlugin/FirmwarePlugin.cc index 4b8e9989eb4..764f621fe57 100644 --- a/src/FirmwarePlugin/FirmwarePlugin.cc +++ b/src/FirmwarePlugin/FirmwarePlugin.cc @@ -311,6 +311,8 @@ const QVariantList& FirmwarePlugin::toolIndicators(const Vehicle*) QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Controls/FlightModeIndicator.qml")), QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/MessageIndicator.qml")), QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSIndicator.qml")), + QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSInterferenceIndicator.qml")), + QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/GPSAuthenticationIndicator.qml")), QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/TelemetryRSSIIndicator.qml")), QVariant::fromValue(QUrl::fromUserInput("qrc:/toolbar/RCRSSIIndicator.qml")), QVariant::fromValue(QUrl::fromUserInput("qrc:/qml/QGroundControl/Controls/BatteryIndicator.qml")), diff --git a/src/QmlControls/QGCPalette.cc b/src/QmlControls/QGCPalette.cc index fedfa73b488..9f0b9ececd7 100644 --- a/src/QmlControls/QGCPalette.cc +++ b/src/QmlControls/QGCPalette.cc @@ -69,6 +69,7 @@ void QGCPalette::_buildMap() DECLARE_QGC_COLOR(mapIndicator, "#585858", "#be781c", "#585858", "#be781c") DECLARE_QGC_COLOR(mapIndicatorChild, "#585858", "#766043", "#585858", "#766043") DECLARE_QGC_COLOR(colorGreen, "#009431", "#009431", "#00e04b", "#00e04b") + DECLARE_QGC_COLOR(colorYellow, "#ffdb00", "#ffdb00", "#e1c100", "#e1c100") DECLARE_QGC_COLOR(colorOrange, "#b95604", "#b95604", "#de8500", "#de8500") DECLARE_QGC_COLOR(colorRed, "#ed3939", "#ed3939", "#f32836", "#f32836") DECLARE_QGC_COLOR(colorGrey, "#808080", "#808080", "#bfbfbf", "#bfbfbf") diff --git a/src/QmlControls/QGCPalette.h b/src/QmlControls/QGCPalette.h index ceb860a7196..388f0c14b93 100644 --- a/src/QmlControls/QGCPalette.h +++ b/src/QmlControls/QGCPalette.h @@ -138,6 +138,7 @@ class QGCPalette : public QObject DEFINE_QGC_COLOR(brandingPurple, setBrandingPurple) DEFINE_QGC_COLOR(brandingBlue, setBrandingBlue) DEFINE_QGC_COLOR(colorGreen, setColorGreen) + DEFINE_QGC_COLOR(colorYellow, setColorYellow) DEFINE_QGC_COLOR(colorOrange, setColorOrange) DEFINE_QGC_COLOR(colorRed, setColorRed) DEFINE_QGC_COLOR(colorGrey, setColorGrey) diff --git a/src/UI/toolbar/GPSAuthenticationIndicator.qml b/src/UI/toolbar/GPSAuthenticationIndicator.qml new file mode 100644 index 00000000000..1fb9e7af489 --- /dev/null +++ b/src/UI/toolbar/GPSAuthenticationIndicator.qml @@ -0,0 +1,68 @@ +/**************************************************************************** + * + * (c) 2009-2020 QGROUNDCONTROL PROJECT + * + * 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 +import QGroundControl.ScreenTools +import QGroundControl.Palette + +//------------------------------------------------------------------------- +//-- GPS Authentication Indicator +Item { + id: control + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + + property bool showIndicator: _activeVehicle.gps.authenticationState.value !== 0 + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + function authenticationIconColor() { + if (_activeVehicle.gps.authenticationState.value === 0) { + return qgcPal.colorGrey + } else if (_activeVehicle.gps.authenticationState.value === 1) { + return qgcPal.colorYellow + } else if (_activeVehicle.gps.authenticationState.value === 2) { + return qgcPal.colorRed + } else if (_activeVehicle.gps.authenticationState.value === 3) { + return qgcPal.colorGreen + } else if (_activeVehicle.gps.authenticationState.value === 4) { + return qgcPal.colorGrey + } + } + + QGCColoredImage { + id: gpsAuthenticationIcon + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "/qmlimages/GpsAuthentication.svg" + fillMode: Image.PreserveAspectFit + sourceSize.height: height + opacity: 1 + color: authenticationIconColor() + } + + MouseArea { + anchors.fill: parent + onClicked: mainWindow.showIndicatorDrawer(gpsIndicatorPage, control) + } + + Component { + id: gpsIndicatorPage + + GPSIndicatorPage { + + } + } +} diff --git a/src/UI/toolbar/GPSIndicator.qml b/src/UI/toolbar/GPSIndicator.qml index 36f159cda12..0fdc41c9931 100644 --- a/src/UI/toolbar/GPSIndicator.qml +++ b/src/UI/toolbar/GPSIndicator.qml @@ -37,7 +37,7 @@ Item { fillMode: Image.PreserveAspectFit sourceSize.height: height opacity: (_activeVehicle && _activeVehicle.gps.count.value >= 0) ? 1 : 0.5 - color: qgcPal.buttonText + color: (_activeVehicle && _activeVehicle.gps.systemErrors.value !== 0) ? qgcPal.colorRed : qgcPal.buttonText } Column { diff --git a/src/UI/toolbar/GPSInterferenceIndicator.qml b/src/UI/toolbar/GPSInterferenceIndicator.qml new file mode 100644 index 00000000000..87dbd932590 --- /dev/null +++ b/src/UI/toolbar/GPSInterferenceIndicator.qml @@ -0,0 +1,64 @@ +/**************************************************************************** + * + * (c) 2009-2024 QGROUNDCONTROL PROJECT + * + * 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 +import QGroundControl.ScreenTools +import QGroundControl.Palette + +//------------------------------------------------------------------------- +//-- GPS Interference Indicator +Item { + id: control + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + + property bool showIndicator: _activeVehicle.gps.authenticationState.value !== 0 + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + + function interferenceIconColor() { + if (_activeVehicle.gps.spoofingState.value === 1) { + return qgcPal.colorGreen + } else if (_activeVehicle.gps.spoofingState.value === 2) { + return qgcPal.colorRed + } else if (_activeVehicle.gps.spoofingState.value === 3) { + return qgcPal.colorBlue + } + } + + QGCColoredImage { + id: gpsSpoofingIcon + width: height + anchors.top: parent.top + anchors.bottom: parent.bottom + source: "/qmlimages/GpsInterference.svg" + fillMode: Image.PreserveAspectFit + sourceSize.height: height + opacity: 1 + color: interferenceIconColor() + } + + MouseArea { + anchors.fill: parent + onClicked: mainWindow.showIndicatorDrawer(gpsIndicatorPage, control) + } + + Component { + id: gpsIndicatorPage + + GPSIndicatorPage { + + } + } +} diff --git a/src/UI/toolbar/Images/GpsAuthentication.svg b/src/UI/toolbar/Images/GpsAuthentication.svg new file mode 100644 index 00000000000..68e0fd625a0 --- /dev/null +++ b/src/UI/toolbar/Images/GpsAuthentication.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/UI/toolbar/Images/GpsInterference.svg b/src/UI/toolbar/Images/GpsInterference.svg new file mode 100644 index 00000000000..35988aa90d4 --- /dev/null +++ b/src/UI/toolbar/Images/GpsInterference.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/Vehicle/FactGroups/GPSFact.json b/src/Vehicle/FactGroups/GPSFact.json index c02412eacde..3abd3e59135 100644 --- a/src/Vehicle/FactGroups/GPSFact.json +++ b/src/Vehicle/FactGroups/GPSFact.json @@ -51,6 +51,21 @@ "name": "count", "shortDesc": "Sat Count", "type": "uint32" +}, +{ + "name": "systemErrors", + "shortDesc": "General System Errors", + "type": "uint32" +}, +{ + "name": "spoofingState", + "shortDesc": "Signal Spoofing State", + "type": "uint8" +}, +{ + "name": "authenticationState", + "shortDesc": "Signal Authentication State", + "type": "uint8" } ] } diff --git a/src/Vehicle/FactGroups/VehicleGPSFactGroup.cc b/src/Vehicle/FactGroups/VehicleGPSFactGroup.cc index 963351cfefb..6b3e1c56d04 100644 --- a/src/Vehicle/FactGroups/VehicleGPSFactGroup.cc +++ b/src/Vehicle/FactGroups/VehicleGPSFactGroup.cc @@ -10,17 +10,21 @@ #include "VehicleGPSFactGroup.h" #include "Vehicle.h" #include "QGCGeo.h" +#include "development/mavlink_msg_gnss_integrity.h" VehicleGPSFactGroup::VehicleGPSFactGroup(QObject* parent) : FactGroup(1000, ":/json/Vehicle/GPSFact.json", parent) - , _latFact (0, _latFactName, FactMetaData::valueTypeDouble) - , _lonFact (0, _lonFactName, FactMetaData::valueTypeDouble) - , _mgrsFact (0, _mgrsFactName, FactMetaData::valueTypeString) - , _hdopFact (0, _hdopFactName, FactMetaData::valueTypeDouble) - , _vdopFact (0, _vdopFactName, FactMetaData::valueTypeDouble) - , _courseOverGroundFact (0, _courseOverGroundFactName, FactMetaData::valueTypeDouble) - , _countFact (0, _countFactName, FactMetaData::valueTypeInt32) - , _lockFact (0, _lockFactName, FactMetaData::valueTypeInt32) + , _latFact (0, _latFactName, FactMetaData::valueTypeDouble) + , _lonFact (0, _lonFactName, FactMetaData::valueTypeDouble) + , _mgrsFact (0, _mgrsFactName, FactMetaData::valueTypeString) + , _hdopFact (0, _hdopFactName, FactMetaData::valueTypeDouble) + , _vdopFact (0, _vdopFactName, FactMetaData::valueTypeDouble) + , _courseOverGroundFact (0, _courseOverGroundFactName, FactMetaData::valueTypeDouble) + , _countFact (0, _countFactName, FactMetaData::valueTypeInt32) + , _lockFact (0, _lockFactName, FactMetaData::valueTypeInt32) + , _systemErrorsFact (0, _systemErrorsFactName, FactMetaData::valueTypeUint32) + , _spoofingStateFact (0, _spoofingStateFactName, FactMetaData::valueTypeUint8) + , _authenticationStateFact (0, _authenticationStateFactName, FactMetaData::valueTypeUint8) { _addFact(&_latFact, _latFactName); _addFact(&_lonFact, _lonFactName); @@ -30,6 +34,9 @@ VehicleGPSFactGroup::VehicleGPSFactGroup(QObject* parent) _addFact(&_courseOverGroundFact, _courseOverGroundFactName); _addFact(&_lockFact, _lockFactName); _addFact(&_countFact, _countFactName); + _addFact(&_systemErrorsFact, _systemErrorsFactName); + _addFact(&_spoofingStateFact, _spoofingStateFactName); + _addFact(&_authenticationStateFact, _authenticationStateFactName); _latFact.setRawValue(std::numeric_limits::quiet_NaN()); _lonFact.setRawValue(std::numeric_limits::quiet_NaN()); @@ -51,6 +58,9 @@ void VehicleGPSFactGroup::handleMessage(Vehicle* /* vehicle */, mavlink_message_ case MAVLINK_MSG_ID_HIGH_LATENCY2: _handleHighLatency2(message); break; + case MAVLINK_MSG_ID_GNSS_INTEGRITY: + _handleGnssIntegrity(message); + break; default: break; } @@ -61,14 +71,14 @@ void VehicleGPSFactGroup::_handleGpsRawInt(mavlink_message_t& message) mavlink_gps_raw_int_t gpsRawInt; mavlink_msg_gps_raw_int_decode(&message, &gpsRawInt); - lat()->setRawValue (gpsRawInt.lat * 1e-7); - lon()->setRawValue (gpsRawInt.lon * 1e-7); - mgrs()->setRawValue (QGCGeo::convertGeoToMGRS(QGeoCoordinate(gpsRawInt.lat * 1e-7, gpsRawInt.lon * 1e-7))); - count()->setRawValue (gpsRawInt.satellites_visible == 255 ? 0 : gpsRawInt.satellites_visible); - hdop()->setRawValue (gpsRawInt.eph == UINT16_MAX ? qQNaN() : gpsRawInt.eph / 100.0); - vdop()->setRawValue (gpsRawInt.epv == UINT16_MAX ? qQNaN() : gpsRawInt.epv / 100.0); - courseOverGround()->setRawValue (gpsRawInt.cog == UINT16_MAX ? qQNaN() : gpsRawInt.cog / 100.0); - lock()->setRawValue (gpsRawInt.fix_type); + lat()->setRawValue (gpsRawInt.lat * 1e-7); + lon()->setRawValue (gpsRawInt.lon * 1e-7); + mgrs()->setRawValue (QGCGeo::convertGeoToMGRS(QGeoCoordinate(gpsRawInt.lat * 1e-7, gpsRawInt.lon * 1e-7))); + count()->setRawValue (gpsRawInt.satellites_visible == 255 ? 0 : gpsRawInt.satellites_visible); + hdop()->setRawValue (gpsRawInt.eph == UINT16_MAX ? qQNaN() : gpsRawInt.eph / 100.0); + vdop()->setRawValue (gpsRawInt.epv == UINT16_MAX ? qQNaN() : gpsRawInt.epv / 100.0); + courseOverGround()->setRawValue (gpsRawInt.cog == UINT16_MAX ? qQNaN() : gpsRawInt.cog / 100.0); + lock()->setRawValue (gpsRawInt.fix_type); } void VehicleGPSFactGroup::_handleHighLatency(mavlink_message_t& message) @@ -104,3 +114,13 @@ void VehicleGPSFactGroup::_handleHighLatency2(mavlink_message_t& message) hdop()->setRawValue (highLatency2.eph == UINT8_MAX ? qQNaN() : highLatency2.eph / 10.0); vdop()->setRawValue (highLatency2.epv == UINT8_MAX ? qQNaN() : highLatency2.epv / 10.0); } + +void VehicleGPSFactGroup::_handleGnssIntegrity(mavlink_message_t& message) +{ + mavlink_gnss_integrity_t gnssIntegrity; + mavlink_msg_gnss_integrity_decode(&message, &gnssIntegrity); + + systemErrors()->setRawValue (gnssIntegrity.system_errors); + spoofingState()->setRawValue (gnssIntegrity.spoofing_state); + authenticationState()->setRawValue(gnssIntegrity.authentication_state); +} \ No newline at end of file diff --git a/src/Vehicle/FactGroups/VehicleGPSFactGroup.h b/src/Vehicle/FactGroups/VehicleGPSFactGroup.h index 868ed8d42c4..8795a8c25a4 100644 --- a/src/Vehicle/FactGroups/VehicleGPSFactGroup.h +++ b/src/Vehicle/FactGroups/VehicleGPSFactGroup.h @@ -19,31 +19,38 @@ class VehicleGPSFactGroup : public FactGroup public: VehicleGPSFactGroup(QObject* parent = nullptr); - Q_PROPERTY(Fact* lat READ lat CONSTANT) - Q_PROPERTY(Fact* lon READ lon CONSTANT) - Q_PROPERTY(Fact* mgrs READ mgrs CONSTANT) - Q_PROPERTY(Fact* hdop READ hdop CONSTANT) - Q_PROPERTY(Fact* vdop READ vdop CONSTANT) - Q_PROPERTY(Fact* courseOverGround READ courseOverGround CONSTANT) - Q_PROPERTY(Fact* count READ count CONSTANT) - Q_PROPERTY(Fact* lock READ lock CONSTANT) + Q_PROPERTY(Fact* lat READ lat CONSTANT) + Q_PROPERTY(Fact* lon READ lon CONSTANT) + Q_PROPERTY(Fact* mgrs READ mgrs CONSTANT) + Q_PROPERTY(Fact* hdop READ hdop CONSTANT) + Q_PROPERTY(Fact* vdop READ vdop CONSTANT) + Q_PROPERTY(Fact* courseOverGround READ courseOverGround CONSTANT) + Q_PROPERTY(Fact* count READ count CONSTANT) + Q_PROPERTY(Fact* lock READ lock CONSTANT) + Q_PROPERTY(Fact* systemErrors READ systemErrors CONSTANT) + Q_PROPERTY(Fact* spoofingState READ spoofingState CONSTANT) + Q_PROPERTY(Fact* authenticationState READ authenticationState CONSTANT) - Fact* lat () { return &_latFact; } - Fact* lon () { return &_lonFact; } - Fact* mgrs () { return &_mgrsFact; } - Fact* hdop () { return &_hdopFact; } - Fact* vdop () { return &_vdopFact; } - Fact* courseOverGround () { return &_courseOverGroundFact; } - Fact* count () { return &_countFact; } - Fact* lock () { return &_lockFact; } + Fact* lat () { return &_latFact; } + Fact* lon () { return &_lonFact; } + Fact* mgrs () { return &_mgrsFact; } + Fact* hdop () { return &_hdopFact; } + Fact* vdop () { return &_vdopFact; } + Fact* courseOverGround () { return &_courseOverGroundFact; } + Fact* count () { return &_countFact; } + Fact* lock () { return &_lockFact; } + Fact* systemErrors () { return &_systemErrorsFact; } + Fact* spoofingState () { return &_spoofingStateFact; } + Fact* authenticationState () { return &_authenticationStateFact; } // Overrides from FactGroup virtual void handleMessage(Vehicle* vehicle, mavlink_message_t& message) override; protected: - void _handleGpsRawInt (mavlink_message_t& message); - void _handleHighLatency (mavlink_message_t& message); - void _handleHighLatency2(mavlink_message_t& message); + void _handleGpsRawInt (mavlink_message_t& message); + void _handleHighLatency (mavlink_message_t& message); + void _handleHighLatency2 (mavlink_message_t& message); + void _handleGnssIntegrity(mavlink_message_t& message); const QString _latFactName = QStringLiteral("lat"); const QString _lonFactName = QStringLiteral("lon"); @@ -53,6 +60,9 @@ class VehicleGPSFactGroup : public FactGroup const QString _courseOverGroundFactName = QStringLiteral("courseOverGround"); const QString _countFactName = QStringLiteral("count"); const QString _lockFactName = QStringLiteral("lock"); + const QString _systemErrorsFactName = QStringLiteral("systemErrors"); + const QString _spoofingStateFactName = QStringLiteral("spoofingState"); + const QString _authenticationStateFactName = QStringLiteral("authenticationState"); Fact _latFact; Fact _lonFact; @@ -62,4 +72,7 @@ class VehicleGPSFactGroup : public FactGroup Fact _courseOverGroundFact; Fact _countFact; Fact _lockFact; + Fact _systemErrorsFact; + Fact _spoofingStateFact; + Fact _authenticationStateFact; }; diff --git a/src/ui/toolbar/CMakeLists.txt b/src/ui/toolbar/CMakeLists.txt new file mode 100644 index 00000000000..828ab07c513 --- /dev/null +++ b/src/ui/toolbar/CMakeLists.txt @@ -0,0 +1,26 @@ +find_package(Qt6 REQUIRED COMPONENTS Core Qml) + +add_custom_target(UiToolbarQml + SOURCES + ArmedIndicator.qml + BatteryIndicator.qml + FlightModeMenuIndicator.qml + GPSAuthenticationIndicator.qml + GPSInterferenceIndicator.qml + GPSIndicator.qml + GPSIndicatorPage.qml + GPSRTKIndicator.qml + JoystickIndicator.qml + LinkIndicator.qml + MainStatusIndicator.qml + MessageIndicator.qml + ModeIndicator.qml + MultiVehicleSelector.qml + RCRSSIIndicator.qml + RemoteIDIndicator.qml + RemoteIDIndicatorPage.qml + SignalStrength.qml + TelemetryRSSIIndicator.qml + FlyViewToolBar.qml + PlanViewToolBar.qml +)