diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index fa2c4b21ee6d31e22b6b7072445c39bd2e59e7e4..7c3ff1d968e795e9a7a23581e1dedca023d6e4a1 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -695,6 +695,7 @@ HEADERS += \ src/Vehicle/MAVLinkLogManager.h \ src/Vehicle/MultiVehicleManager.h \ src/Vehicle/StateMachine.h \ + src/Vehicle/SysStatusSensorInfo.h \ src/Vehicle/TerrainFactGroup.h \ src/Vehicle/TerrainProtocolHandler.h \ src/Vehicle/TrajectoryPoints.h \ @@ -914,6 +915,7 @@ SOURCES += \ src/Vehicle/MAVLinkLogManager.cc \ src/Vehicle/MultiVehicleManager.cc \ src/Vehicle/StateMachine.cc \ + src/Vehicle/SysStatusSensorInfo.cc \ src/Vehicle/TerrainFactGroup.cc \ src/Vehicle/TerrainProtocolHandler.cc \ src/Vehicle/TrajectoryPoints.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 93c3e0b8376a4c4848d8bce6e1e96cd342af9c6f..5c19b2258f1614833cbf3821de72010dcd7b48e4 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -49,7 +49,6 @@ src/PlanView/FWLandingPatternEditor.qml src/ui/preferences/GeneralSettings.qml src/AnalyzeView/GeoTagPage.qml - src/FlightMap/Widgets/HealthPageWidget.qml src/ui/preferences/HelpSettings.qml src/VehicleSetup/JoystickConfig.qml src/VehicleSetup/JoystickConfigAdvanced.qml @@ -106,6 +105,7 @@ src/QmlControls/JoystickThumbPad.qml src/QmlControls/KMLOrSHPFileDialog.qml src/QmlControls/LogReplayStatusBar.qml + src/ui/toolbar/MainStatusIndicator.qml src/ui/toolbar/MainToolBar.qml src/QmlControls/MainWindowSavedState.qml src/QmlControls/MAVLinkChart.qml diff --git a/src/FlightMap/Widgets/HealthPageWidget.qml b/src/FlightMap/Widgets/HealthPageWidget.qml deleted file mode 100644 index 1862cc533176e80e768f981ff3536a1c3211535c..0000000000000000000000000000000000000000 --- a/src/FlightMap/Widgets/HealthPageWidget.qml +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** - * - * (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 2.3 -import QtQuick.Layouts 1.2 - -import QGroundControl 1.0 -import QGroundControl.Controls 1.0 -import QGroundControl.ScreenTools 1.0 - -/// Health page for Instrument Panel PageWidget -Column { - width: pageWidth - - property bool showSettingsIcon: false - - property var _unhealthySensors: QGroundControl.multiVehicleManager.activeVehicle ? QGroundControl.multiVehicleManager.activeVehicle.unhealthySensors : [ ] - - QGCLabel { - width: parent.width - horizontalAlignment: Text.AlignHCenter - text: qsTr("All systems healthy") - visible: healthRepeater.count == 0 - } - - Repeater { - id: healthRepeater - model: _unhealthySensors - - Row { - Image { - source: "/qmlimages/Yield.svg" - height: ScreenTools.defaultFontPixelHeight - sourceSize.height: height - fillMode: Image.PreserveAspectFit - } - - QGCLabel { - text: modelData - } - } - } -} diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir index b39eb1994bab741afeb9c219ec6e902d395304ae..8f83594dc4c94595cecb334de0b4386ff9ebf142 100644 --- a/src/QmlControls/QGroundControl/Controls/qmldir +++ b/src/QmlControls/QGroundControl/Controls/qmldir @@ -31,6 +31,7 @@ InstrumentValueEditDialog 1.0 InstrumentValueEditDialog.qml JoystickThumbPad 1.0 JoystickThumbPad.qml KMLOrSHPFileDialog 1.0 KMLOrSHPFileDialog.qml LogReplayStatusBar 1.0 LogReplayStatusBar.qml +MainStatusIndicator 1.0 MainStatusIndicator.qml MainToolBar 1.0 MainToolBar.qml MainWindowSavedState 1.0 MainWindowSavedState.qml MAVLinkMessageButton 1.0 MAVLinkMessageButton.qml diff --git a/src/Vehicle/SysStatusSensorInfo.cc b/src/Vehicle/SysStatusSensorInfo.cc new file mode 100644 index 0000000000000000000000000000000000000000..25d238db186e32694b0dcc9cd08d00399d1bb4da --- /dev/null +++ b/src/Vehicle/SysStatusSensorInfo.cc @@ -0,0 +1,124 @@ +/**************************************************************************** + * + * (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. + * + ****************************************************************************/ + +#include "SysStatusSensorInfo.h" + +#include + +SysStatusSensorInfo::SysStatusSensorInfo(QObject* parent) + : QObject(parent) +{ + +} + +void SysStatusSensorInfo::update(const mavlink_sys_status_t& sysStatus) +{ + bool dirty = false; + + // Walk the bits + for (int bitPosition=0; bitPosition<32; bitPosition++) { + MAV_SYS_STATUS_SENSOR sensorBitMask = static_cast(1 << bitPosition); + if (sysStatus.onboard_control_sensors_present & sensorBitMask) { + if (_sensorInfoMap.contains(sensorBitMask)) { + SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + bool newEnabled = sysStatus.onboard_control_sensors_enabled & sensorBitMask; + if (sensorInfo.enabled != newEnabled) { + dirty = true; + sensorInfo.enabled = newEnabled; + } + + bool newHealthy = sysStatus.onboard_control_sensors_health & sensorBitMask; + if (sensorInfo.healthy != newHealthy) { + dirty = true; + sensorInfo.healthy = newHealthy; + } + } else { + dirty = true; + SensorInfo_t sensorInfo = { !!(sysStatus.onboard_control_sensors_enabled & sensorBitMask), !!(sysStatus.onboard_control_sensors_health & sensorBitMask) }; + _sensorInfoMap[sensorBitMask] = sensorInfo; + } + } else { + if (_sensorInfoMap.contains(sensorBitMask)) { + dirty = true; + _sensorInfoMap.remove(sensorBitMask); + } + } + } + + if (dirty) { + emit sensorInfoChanged(); + } +} + +QStringList SysStatusSensorInfo::sensorNames (void) const +{ + QStringList rgNames; + + // List ordering is unhealthy, healthy, disabled + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (sensorInfo.enabled && !sensorInfo.healthy) { + rgNames.append(QGCMAVLink::mavSysStatusSensorToString(sensorBitMask)); + } + } + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (sensorInfo.enabled && sensorInfo.healthy) { + rgNames.append(QGCMAVLink::mavSysStatusSensorToString(sensorBitMask)); + } + } + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (!sensorInfo.enabled) { + rgNames.append(QGCMAVLink::mavSysStatusSensorToString(sensorBitMask)); + } + } + + return rgNames; +} + +QStringList SysStatusSensorInfo::sensorStatus(void) const +{ + QStringList rgStatus; + + // List ordering is unhealthy, healthy, disabled + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (sensorInfo.enabled && !sensorInfo.healthy) { + rgStatus.append(tr("Error")); + } + } + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (sensorInfo.enabled && sensorInfo.healthy) { + rgStatus.append(tr("Normal")); + } + } + for (int i=0; i<_sensorInfoMap.keys().count(); i++) { + const MAV_SYS_STATUS_SENSOR sensorBitMask = _sensorInfoMap.keys()[i]; + const SensorInfo_t& sensorInfo = _sensorInfoMap[sensorBitMask]; + + if (!sensorInfo.enabled) { + rgStatus.append(tr("Disabled")); + } + } + + return rgStatus; +} diff --git a/src/Vehicle/SysStatusSensorInfo.h b/src/Vehicle/SysStatusSensorInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..a791cb45b2207489c50d9946b9a8008c6877d015 --- /dev/null +++ b/src/Vehicle/SysStatusSensorInfo.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * + * (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. + * + ****************************************************************************/ + +#pragma once + +#include "QGCMAVLink.h" +#include "QmlObjectListModel.h" + +#include + +/// Class which represents sensor info from the SYS_STATUS mavlink message +class SysStatusSensorInfo : public QObject +{ + Q_OBJECT + +public: + SysStatusSensorInfo(QObject* parent = nullptr); + + Q_PROPERTY(QStringList sensorNames READ sensorNames NOTIFY sensorInfoChanged) + Q_PROPERTY(QStringList sensorStatus READ sensorStatus NOTIFY sensorInfoChanged) + + void update (const mavlink_sys_status_t& sysStatus); + QStringList sensorNames (void) const; + QStringList sensorStatus(void) const; + +signals: + void sensorInfoChanged(void); + +private: + typedef struct { + bool enabled; + bool healthy; + } SensorInfo_t; + + QMap _sensorInfoMap; +}; diff --git a/src/Vehicle/Vehicle.cc b/src/Vehicle/Vehicle.cc index 41a87832717384c20747f62f5693f4daa60655f8..793b77b1164d65d99702bdaea68675f109859b88 100644 --- a/src/Vehicle/Vehicle.cc +++ b/src/Vehicle/Vehicle.cc @@ -1429,7 +1429,6 @@ void Vehicle::_handleHighLatency2(mavlink_message_t& message) _onboardControlSensorsEnabled = newOnboardControlSensorsEnabled; _onboardControlSensorsPresent = newOnboardControlSensorsEnabled; _onboardControlSensorsUnhealthy = 0; - emit unhealthySensorsChanged(); } } @@ -1652,6 +1651,27 @@ void Vehicle::_handleSysStatus(mavlink_message_t& message) mavlink_sys_status_t sysStatus; mavlink_msg_sys_status_decode(&message, &sysStatus); + _sysStatusSensorInfo.update(sysStatus); + + if (sysStatus.onboard_control_sensors_enabled & MAV_SYS_STATUS_PREARM_CHECK) { + if (!_readyToFlyAvailable) { + _readyToFlyAvailable = true; + emit readyToFlyAvailableChanged(true); + } + + bool newReadyToFly = sysStatus.onboard_control_sensors_health & MAV_SYS_STATUS_PREARM_CHECK; + if (newReadyToFly != _readyToFly) { + _readyToFly = newReadyToFly; + emit readyToFlyChanged(_readyToFly); + } + } + + bool newAllSensorsHealthy = (sysStatus.onboard_control_sensors_enabled & sysStatus.onboard_control_sensors_health) == sysStatus.onboard_control_sensors_enabled; + if (newAllSensorsHealthy != _allSensorsHealthy) { + _allSensorsHealthy = newAllSensorsHealthy; + emit allSensorsHealthyChanged(_allSensorsHealthy); + } + if (_onboardControlSensorsPresent != sysStatus.onboard_control_sensors_present) { _onboardControlSensorsPresent = sysStatus.onboard_control_sensors_present; emit sensorsPresentBitsChanged(_onboardControlSensorsPresent); @@ -1675,7 +1695,6 @@ void Vehicle::_handleSysStatus(mavlink_message_t& message) uint32_t newSensorsUnhealthy = _onboardControlSensorsEnabled & ~_onboardControlSensorsHealth; if (newSensorsUnhealthy != _onboardControlSensorsUnhealthy) { _onboardControlSensorsUnhealthy = newSensorsUnhealthy; - emit unhealthySensorsChanged(); emit sensorsUnhealthyBitsChanged(_onboardControlSensorsUnhealthy); } @@ -3579,58 +3598,6 @@ QString Vehicle::brandImageOutdoor() const return _firmwarePlugin->brandImageOutdoor(this); } -QStringList Vehicle::unhealthySensors() const -{ - QStringList sensorList; - - struct sensorInfo_s { - uint32_t bit; - QString sensorName; - }; - - static const sensorInfo_s rgSensorInfo[] = { - { MAV_SYS_STATUS_SENSOR_3D_GYRO, tr("Gyro") }, - { MAV_SYS_STATUS_SENSOR_3D_ACCEL, tr("Accelerometer") }, - { MAV_SYS_STATUS_SENSOR_3D_MAG, tr("Magnetometer") }, - { MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE, tr("Absolute pressure") }, - { MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE, tr("Differential pressure") }, - { MAV_SYS_STATUS_SENSOR_GPS, tr("GPS") }, - { MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW, tr("Optical flow") }, - { MAV_SYS_STATUS_SENSOR_VISION_POSITION, tr("Computer vision position") }, - { MAV_SYS_STATUS_SENSOR_LASER_POSITION, tr("Laser based position") }, - { MAV_SYS_STATUS_SENSOR_EXTERNAL_GROUND_TRUTH, tr("External ground truth") }, - { MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL, tr("Angular rate control") }, - { MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION, tr("Attitude stabilization") }, - { MAV_SYS_STATUS_SENSOR_YAW_POSITION, tr("Yaw position") }, - { MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL, tr("Z/altitude control") }, - { MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL, tr("X/Y position control") }, - { MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS, tr("Motor outputs / control") }, - { MAV_SYS_STATUS_SENSOR_RC_RECEIVER, tr("RC receiver") }, - { MAV_SYS_STATUS_SENSOR_3D_GYRO2, tr("Gyro 2") }, - { MAV_SYS_STATUS_SENSOR_3D_ACCEL2, tr("Accelerometer 2") }, - { MAV_SYS_STATUS_SENSOR_3D_MAG2, tr("Magnetometer 2") }, - { MAV_SYS_STATUS_GEOFENCE, tr("GeoFence") }, - { MAV_SYS_STATUS_AHRS, tr("AHRS") }, - { MAV_SYS_STATUS_TERRAIN, tr("Terrain") }, - { MAV_SYS_STATUS_REVERSE_MOTOR, tr("Motors reversed") }, - { MAV_SYS_STATUS_LOGGING, tr("Logging") }, - { MAV_SYS_STATUS_SENSOR_BATTERY, tr("Battery") }, - { MAV_SYS_STATUS_SENSOR_PROXIMITY, tr("Proximity") }, - { MAV_SYS_STATUS_SENSOR_SATCOM, tr("Satellite Communication") }, - { MAV_SYS_STATUS_PREARM_CHECK, tr("Pre-Arm Check") }, - { MAV_SYS_STATUS_OBSTACLE_AVOIDANCE, tr("Avoidance/collision prevention") }, - }; - - for (size_t i=0; ibit) && !(_onboardControlSensorsHealth & pSensorInfo->bit)) { - sensorList << pSensorInfo->sensorName; - } - } - - return sensorList; -} - void Vehicle::setOfflineEditingDefaultComponentId(int defaultComponentId) { if (_offlineEditingVehicle) { diff --git a/src/Vehicle/Vehicle.h b/src/Vehicle/Vehicle.h index f45a86b755c85169bd2ac58b38850eaab0151d03..6d7805353f0c680e297d0bcb76fa037e6922afc7 100644 --- a/src/Vehicle/Vehicle.h +++ b/src/Vehicle/Vehicle.h @@ -25,6 +25,7 @@ #include "SettingsFact.h" #include "QGCMapCircle.h" #include "TerrainFactGroup.h" +#include "SysStatusSensorInfo.h" class UAS; class UASInterface; @@ -596,7 +597,6 @@ public: Q_PROPERTY(bool isOfflineEditingVehicle READ isOfflineEditingVehicle CONSTANT) Q_PROPERTY(QString brandImageIndoor READ brandImageIndoor NOTIFY firmwareTypeChanged) Q_PROPERTY(QString brandImageOutdoor READ brandImageOutdoor NOTIFY firmwareTypeChanged) - Q_PROPERTY(QStringList unhealthySensors READ unhealthySensors NOTIFY unhealthySensorsChanged) Q_PROPERTY(int sensorsPresentBits READ sensorsPresentBits NOTIFY sensorsPresentBitsChanged) Q_PROPERTY(int sensorsEnabledBits READ sensorsEnabledBits NOTIFY sensorsEnabledBitsChanged) Q_PROPERTY(int sensorsHealthBits READ sensorsHealthBits NOTIFY sensorsHealthBitsChanged) @@ -643,6 +643,10 @@ public: Q_PROPERTY(bool gimbalData READ gimbalData NOTIFY gimbalDataChanged) Q_PROPERTY(bool isROIEnabled READ isROIEnabled NOTIFY isROIEnabledChanged) Q_PROPERTY(CheckList checkListState READ checkListState WRITE setCheckListState NOTIFY checkListStateChanged) + Q_PROPERTY(bool readyToFlyAvailable READ readyToFlyAvailable NOTIFY readyToFlyAvailableChanged) ///< true: readyToFly signalling is available on this vehicle + Q_PROPERTY(bool readyToFly READ readyToFly NOTIFY readyToFlyChanged) + Q_PROPERTY(QObject* sysStatusSensorInfo READ sysStatusSensorInfo CONSTANT) + Q_PROPERTY(bool allSensorsHealthy READ allSensorsHealthy NOTIFY allSensorsHealthyChanged) //< true: all sensors in SYS_STATUS reported as healthy // The following properties relate to Orbit status Q_PROPERTY(bool orbitActive READ orbitActive NOTIFY orbitActiveChanged) @@ -940,7 +944,6 @@ public: bool isOfflineEditingVehicle () const { return _offlineEditingVehicle; } QString brandImageIndoor () const; QString brandImageOutdoor () const; - QStringList unhealthySensors () const; int sensorsPresentBits () const { return static_cast(_onboardControlSensorsPresent); } int sensorsEnabledBits () const { return static_cast(_onboardControlSensorsEnabled); } int sensorsHealthBits () const { return static_cast(_onboardControlSensorsHealth); } @@ -968,6 +971,10 @@ public: bool highLatencyLink () const { return _highLatencyLink; } bool orbitActive () const { return _orbitActive; } QGCMapCircle* orbitMapCircle () { return &_orbitMapCircle; } + bool readyToFlyAvailable () { return _readyToFlyAvailable; } + bool readyToFly () { return _readyToFly; } + bool allSensorsHealthy () { return _allSensorsHealthy; } + QObject* sysStatusSensorInfo () { return &_sysStatusSensorInfo; } /// Get the maximum MAVLink protocol version supported /// @return the maximum version @@ -1178,7 +1185,6 @@ signals: void vtolInFwdFlightChanged (bool vtolInFwdFlight); void prearmErrorChanged (const QString& prearmError); void soloFirmwareChanged (bool soloFirmware); - void unhealthySensorsChanged (); void defaultCruiseSpeedChanged (double cruiseSpeed); void defaultHoverSpeedChanged (double hoverSpeed); void firmwareTypeChanged (); @@ -1223,6 +1229,9 @@ signals: void sensorsHealthBitsChanged (int sensorsHealthBits); void sensorsUnhealthyBitsChanged (int sensorsUnhealthyBits); void orbitActiveChanged (bool orbitActive); + void readyToFlyAvailableChanged (bool readyToFlyAvailable); + void readyToFlyChanged (bool readyToFy); + void allSensorsHealthyChanged (bool allSensorsHealthy); void firmwareVersionChanged (); void firmwareCustomVersionChanged (); @@ -1421,9 +1430,9 @@ private: uint32_t _onboardControlSensorsEnabled; uint32_t _onboardControlSensorsHealth; uint32_t _onboardControlSensorsUnhealthy; - bool _gpsRawIntMessageAvailable = false; - bool _globalPositionIntMessageAvailable = false; - bool _altitudeMessageAvailable = false; + bool _gpsRawIntMessageAvailable = false; + bool _globalPositionIntMessageAvailable = false; + bool _altitudeMessageAvailable = false; double _defaultCruiseSpeed; double _defaultHoverSpeed; int _telemetryRRSSI; @@ -1433,14 +1442,19 @@ private: uint32_t _telemetryTXBuffer; int _telemetryLNoise; int _telemetryRNoise; - bool _mavlinkProtocolRequestComplete = false; - unsigned _mavlinkProtocolRequestMaxProtoVersion = 0; - unsigned _maxProtoVersion = 0; - bool _capabilityBitsKnown = false; + bool _mavlinkProtocolRequestComplete = false; + unsigned _mavlinkProtocolRequestMaxProtoVersion = 0; + unsigned _maxProtoVersion = 0; + bool _capabilityBitsKnown = false; uint64_t _capabilityBits; bool _highLatencyLink; bool _receivingAttitudeQuaternion; - CheckList _checkListState = CheckListNotSetup; + CheckList _checkListState = CheckListNotSetup; + bool _readyToFlyAvailable = false; + bool _readyToFly = false; + bool _allSensorsHealthy = true; + + SysStatusSensorInfo _sysStatusSensorInfo; QGCCameraManager* _cameras; diff --git a/src/api/QGCCorePlugin.cc b/src/api/QGCCorePlugin.cc index 7ae9ea4dc7bc1de96540ac5628df4d80b55bf0a5..4e0e365bec11dbffe9d84a6745836ddb33974cd0 100644 --- a/src/api/QGCCorePlugin.cc +++ b/src/api/QGCCorePlugin.cc @@ -100,7 +100,6 @@ public: QmlComponentInfo* valuesPageWidgetInfo = nullptr; QmlComponentInfo* cameraPageWidgetInfo = nullptr; QmlComponentInfo* videoPageWidgetInfo = nullptr; - QmlComponentInfo* healthPageWidgetInfo = nullptr; QmlComponentInfo* vibrationPageWidgetInfo = nullptr; QGCOptions* defaultOptions = nullptr; @@ -206,10 +205,6 @@ void QGCCorePlugin::_resetInstrumentPages() _p->videoPageWidgetInfo = nullptr; } #endif - if(_p->healthPageWidgetInfo) { - _p->healthPageWidgetInfo->deleteLater(); - _p->healthPageWidgetInfo = nullptr; - } if(_p->vibrationPageWidgetInfo) { _p->vibrationPageWidgetInfo->deleteLater(); _p->vibrationPageWidgetInfo = nullptr; @@ -287,7 +282,6 @@ QVariantList& QGCCorePlugin::instrumentPages() _p->videoPageWidgetInfo = new QmlComponentInfo(tr("Video Stream"), QUrl::fromUserInput("qrc:/qml/VideoPageWidget.qml")); } #endif - _p->healthPageWidgetInfo = new QmlComponentInfo(tr("Health"), QUrl::fromUserInput("qrc:/qml/HealthPageWidget.qml")); _p->vibrationPageWidgetInfo = new QmlComponentInfo(tr("Vibration"), QUrl::fromUserInput("qrc:/qml/VibrationPageWidget.qml")); _p->instrumentPageWidgetList.append(QVariant::fromValue(_p->valuesPageWidgetInfo)); @@ -295,7 +289,6 @@ QVariantList& QGCCorePlugin::instrumentPages() #if defined(QGC_GST_STREAMING) _p->instrumentPageWidgetList.append(QVariant::fromValue(_p->videoPageWidgetInfo)); #endif - _p->instrumentPageWidgetList.append(QVariant::fromValue(_p->healthPageWidgetInfo)); _p->instrumentPageWidgetList.append(QVariant::fromValue(_p->vibrationPageWidgetInfo)); } return _p->instrumentPageWidgetList; diff --git a/src/api/QGCOptions.cc b/src/api/QGCOptions.cc index d8555d1e8268c95a7080ebb0debb115820159bf6..2e2c05c38a2cf924aec37660833c9b7a9d1679bf 100644 --- a/src/api/QGCOptions.cc +++ b/src/api/QGCOptions.cc @@ -23,12 +23,12 @@ QGCOptions::QGCOptions(QObject* parent) QColor QGCOptions::toolbarBackgroundLight() const { - return QColor(255,255,255,204); + return QColor(255,255,255); } QColor QGCOptions::toolbarBackgroundDark() const { - return QColor(0,0,0,192); + return QColor(0,0,0); } QGCFlyViewOptions* QGCOptions::flyViewOptions(void) diff --git a/src/comm/QGCMAVLink.cc b/src/comm/QGCMAVLink.cc index 24b2f81dd5df21b0cc2854358543d7f1f65e92bf..162803b21a969599aba3cbaa32036ff3b669cea3 100644 --- a/src/comm/QGCMAVLink.cc +++ b/src/comm/QGCMAVLink.cc @@ -10,6 +10,7 @@ #include "QGCMAVLink.h" #include +#include constexpr QGCMAVLink::FirmwareClass_t QGCMAVLink::FirmwareClassPX4; constexpr QGCMAVLink::FirmwareClass_t QGCMAVLink::FirmwareClassArduPilot; @@ -145,7 +146,7 @@ QString QGCMAVLink::vehicleClassToString(VehicleClass_t vehicleClass) } } -QString QGCMAVLink::mavResultToString(MAV_RESULT result) +QString QGCMAVLink::mavResultToString(MAV_RESULT result) { switch (result) { case MAV_RESULT_ACCEPTED: @@ -165,6 +166,58 @@ QString QGCMAVLink::mavResultToString(MAV_RESULT result) } } +QString QGCMAVLink::mavSysStatusSensorToString(MAV_SYS_STATUS_SENSOR sysStatusSensor) +{ + struct sensorInfo_s { + uint32_t bit; + QString sensorName; + }; + + static const sensorInfo_s rgSensorInfo[] = { + { MAV_SYS_STATUS_SENSOR_3D_GYRO, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Gyro") }, + { MAV_SYS_STATUS_SENSOR_3D_ACCEL, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Accelerometer") }, + { MAV_SYS_STATUS_SENSOR_3D_MAG, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Magnetometer") }, + { MAV_SYS_STATUS_SENSOR_ABSOLUTE_PRESSURE, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Absolute pressure") }, + { MAV_SYS_STATUS_SENSOR_DIFFERENTIAL_PRESSURE, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Differential pressure") }, + { MAV_SYS_STATUS_SENSOR_GPS, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "GPS") }, + { MAV_SYS_STATUS_SENSOR_OPTICAL_FLOW, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Optical flow") }, + { MAV_SYS_STATUS_SENSOR_VISION_POSITION, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Computer vision position") }, + { MAV_SYS_STATUS_SENSOR_LASER_POSITION, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Laser based position") }, + { MAV_SYS_STATUS_SENSOR_EXTERNAL_GROUND_TRUTH, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "External ground truth") }, + { MAV_SYS_STATUS_SENSOR_ANGULAR_RATE_CONTROL, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Angular rate control") }, + { MAV_SYS_STATUS_SENSOR_ATTITUDE_STABILIZATION, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Attitude stabilization") }, + { MAV_SYS_STATUS_SENSOR_YAW_POSITION, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Yaw position") }, + { MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Z/altitude control") }, + { MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "X/Y position control") }, + { MAV_SYS_STATUS_SENSOR_MOTOR_OUTPUTS, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Motor outputs / control") }, + { MAV_SYS_STATUS_SENSOR_RC_RECEIVER, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "RC receiver") }, + { MAV_SYS_STATUS_SENSOR_3D_GYRO2, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Gyro 2") }, + { MAV_SYS_STATUS_SENSOR_3D_ACCEL2, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Accelerometer 2") }, + { MAV_SYS_STATUS_SENSOR_3D_MAG2, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Magnetometer 2") }, + { MAV_SYS_STATUS_GEOFENCE, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "GeoFence") }, + { MAV_SYS_STATUS_AHRS, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "AHRS") }, + { MAV_SYS_STATUS_TERRAIN, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Terrain") }, + { MAV_SYS_STATUS_REVERSE_MOTOR, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Motors reversed") }, + { MAV_SYS_STATUS_LOGGING, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Logging") }, + { MAV_SYS_STATUS_SENSOR_BATTERY, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Battery") }, + { MAV_SYS_STATUS_SENSOR_PROXIMITY, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Proximity") }, + { MAV_SYS_STATUS_SENSOR_SATCOM, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Satellite Communication") }, + { MAV_SYS_STATUS_PREARM_CHECK, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Pre-Arm Check") }, + { MAV_SYS_STATUS_OBSTACLE_AVOIDANCE, QT_TRANSLATE_NOOP("MAVLink SYS_STATUS_SENSOR value", "Avoidance/collision prevention") }, + }; + + for (size_t i=0; ibit) { + return pSensorInfo->sensorName; + } + } + + qWarning() << "QGCMAVLink::mavSysStatusSensorToString: Unknown sensor" << sysStatusSensor; + + return QT_TRANSLATE_NOOP("MAVLink unknown SYS_STATUS_SENSOR value", "Unknown sensor"); +} + QString MavlinkFTP::opCodeToString(OpCode_t opCode) { switch (opCode) { @@ -238,3 +291,4 @@ QString MavlinkFTP::errorCodeToString(ErrorCode_t errorCode) return "Unknown Error"; } + diff --git a/src/comm/QGCMAVLink.h b/src/comm/QGCMAVLink.h index 3450173fd99233bfcf7ae79f3c458c0e06c86889..5a56e010423389977bd0191c3f2315becc79199b 100644 --- a/src/comm/QGCMAVLink.h +++ b/src/comm/QGCMAVLink.h @@ -63,25 +63,26 @@ public: static constexpr VehicleClass_t VehicleClassVTOL = MAV_TYPE_VTOL_QUADROTOR; static constexpr VehicleClass_t VehicleClassGeneric = MAV_TYPE_GENERIC; - static bool isPX4FirmwareClass (MAV_AUTOPILOT autopilot) { return autopilot == MAV_AUTOPILOT_PX4; } - static bool isArduPilotFirmwareClass(MAV_AUTOPILOT autopilot) { return autopilot == MAV_AUTOPILOT_ARDUPILOTMEGA; } - static bool isGenericFirmwareClass (MAV_AUTOPILOT autopilot) { return !isPX4FirmwareClass(autopilot) && ! isArduPilotFirmwareClass(autopilot); } - static FirmwareClass_t firmwareClass (MAV_AUTOPILOT autopilot); - static MAV_AUTOPILOT firmwareClassToAutopilot(FirmwareClass_t firmwareClass) { return static_cast(firmwareClass); } - static QString firmwareClassToString (FirmwareClass_t firmwareClass); - static QList allFirmwareClasses (void); - - static bool isFixedWing (MAV_TYPE mavType); - static bool isRoverBoat (MAV_TYPE mavType); - static bool isSub (MAV_TYPE mavType); - static bool isMultiRotor (MAV_TYPE mavType); - static bool isVTOL (MAV_TYPE mavType); - static VehicleClass_t vehicleClass (MAV_TYPE mavType); - static MAV_TYPE vehicleClassToMavType (VehicleClass_t vehicleClass) { return static_cast(vehicleClass); } - static QString vehicleClassToString (VehicleClass_t vehicleClass); - static QList allVehicleClasses (void); - - static QString mavResultToString (MAV_RESULT result); + static bool isPX4FirmwareClass (MAV_AUTOPILOT autopilot) { return autopilot == MAV_AUTOPILOT_PX4; } + static bool isArduPilotFirmwareClass (MAV_AUTOPILOT autopilot) { return autopilot == MAV_AUTOPILOT_ARDUPILOTMEGA; } + static bool isGenericFirmwareClass (MAV_AUTOPILOT autopilot) { return !isPX4FirmwareClass(autopilot) && ! isArduPilotFirmwareClass(autopilot); } + static FirmwareClass_t firmwareClass (MAV_AUTOPILOT autopilot); + static MAV_AUTOPILOT firmwareClassToAutopilot (FirmwareClass_t firmwareClass) { return static_cast(firmwareClass); } + static QString firmwareClassToString (FirmwareClass_t firmwareClass); + static QList allFirmwareClasses (void); + + static bool isFixedWing (MAV_TYPE mavType); + static bool isRoverBoat (MAV_TYPE mavType); + static bool isSub (MAV_TYPE mavType); + static bool isMultiRotor (MAV_TYPE mavType); + static bool isVTOL (MAV_TYPE mavType); + static VehicleClass_t vehicleClass (MAV_TYPE mavType); + static MAV_TYPE vehicleClassToMavType (VehicleClass_t vehicleClass) { return static_cast(vehicleClass); } + static QString vehicleClassToString (VehicleClass_t vehicleClass); + static QList allVehicleClasses (void); + + static QString mavResultToString (MAV_RESULT result); + static QString mavSysStatusSensorToString (MAV_SYS_STATUS_SENSOR sysStatusSensor); }; class MavlinkFTP { diff --git a/src/ui/MainRootWindow.qml b/src/ui/MainRootWindow.qml index 1efee825e68527eff9b017271df6a14baa215cba..18579c2784d545c4d3aacb45ea10f7e8981c3b65 100644 --- a/src/ui/MainRootWindow.qml +++ b/src/ui/MainRootWindow.qml @@ -526,15 +526,6 @@ ApplicationWindow { source: "AnalyzeView.qml" } - //------------------------------------------------------------------------- - // @brief Loader helper for any child, no matter how deep, to display elements - // on top of the main window. - // This is DEPRECATED. Use Popup instead. - Loader { - id: rootLoader - anchors.centerIn: parent - } - //------------------------------------------------------------------------- //-- Vehicle Messages @@ -781,7 +772,7 @@ ApplicationWindow { Popup { id: indicatorDropdown - y: ScreenTools.defaultFontPixelHeight + padding: ScreenTools.defaultFontPixelWidth * 0.75 modal: true focus: true closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside diff --git a/src/ui/toolbar/MainStatusIndicator.qml b/src/ui/toolbar/MainStatusIndicator.qml new file mode 100644 index 0000000000000000000000000000000000000000..2b8ce97f8726a999a46fb6e13bb17f94470225a1 --- /dev/null +++ b/src/ui/toolbar/MainStatusIndicator.qml @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * (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 2.11 +import QtQuick.Layouts 1.11 + +import QGroundControl 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.MultiVehicleManager 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Palette 1.0 + +Item { + id: _root + Layout.preferredWidth: mainStatusLabel.contentWidth + ScreenTools.defaultFontPixelWidth + + property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property real _margins: ScreenTools.defaultFontPixelWidth + + Component { + id: mainStatusInfo + + Rectangle { + width: mainLayout.width + (_margins * 2) + height: mainLayout.height + (_margins * 2) + radius: ScreenTools.defaultFontPixelHeight * 0.5 + color: qgcPal.window + border.color: qgcPal.text + + GridLayout { + id: mainLayout + anchors.margins: _margins + anchors.top: parent.top + anchors.left: parent.left + rowSpacing: ScreenTools.defaultFontPixelWidth / 2 + columnSpacing: rowSpacing + rows: _activeVehicle.sysStatusSensorInfo.sensorNames.length + flow: GridLayout.TopToBottom + + Repeater { + model: _activeVehicle.sysStatusSensorInfo.sensorNames + + QGCLabel { + text: modelData + } + } + + Repeater { + model: _activeVehicle.sysStatusSensorInfo.sensorStatus + + QGCLabel { + text: modelData + } + } + } + } + } + + QGCLabel { + id: mainStatusLabel + text: mainStatusText() + font.pointSize: ScreenTools.largeFontPointSize + anchors.verticalCenter: parent.verticalCenter + + property string _commLostText: qsTr("Communication Lost") + property string _readyToFlyText: qsTr("Ready To Fly") + property string _notReadyToFlyText: qsTr("Not Ready") + property string _disconnectedText: qsTr("Disconnected") + property string _armedText: qsTr("Armed") + property string _flyingText: qsTr("Flying") + property string _landingText: qsTr("Landing") + + function mainStatusText() { + var statusText + if (_activeVehicle) { + if (_communicationLost) { + _mainStatusBGColor = "red" + return mainStatusLabel._commLostText + } + if (_activeVehicle.armed) { + _mainStatusBGColor = "green" + if (_activeVehicle.flying) { + return mainStatusLabel._flyingText + } else if (_activeVehicle.landing) { + return mainStatusLabel._landingText + } else { + return mainStatusLabel._armedText + } + } else { + if (_activeVehicle.readyToFlyAvailable) { + if (_activeVehicle.readyToFly) { + _mainStatusBGColor = "green" + return mainStatusLabel._readyToFlyText + } else { + _mainStatusBGColor = "yellow" + return mainStatusLabel._notReadyToFlyText + } + } else { + // Best we can do is determine readiness based on AutoPilot component setup and health indicators from SYS_STATUS + if (_activeVehicle.allSensorsHealthy && _activeVehicle.autopilot.setupComplete) { + _mainStatusBGColor = "green" + return mainStatusLabel._readyToFlyText + } else { + _mainStatusBGColor = "yellow" + return mainStatusLabel._notReadyToFlyText + } + } + } + } else { + _mainStatusBGColor = qgcPal.brandingPurple + return mainStatusLabel._disconnectedText + } + } + } + + MouseArea { + anchors.fill: parent + enabled: _activeVehicle + onClicked: { + mainWindow.showPopUp(_root, mainStatusInfo) + } + } +} diff --git a/src/ui/toolbar/MainToolBar.qml b/src/ui/toolbar/MainToolBar.qml index 47d480a60994d1e0ce7a4e3dcd678573c944a535..bbe9633cdb9f1ca61d208ecf742cd67d41ade1c9 100644 --- a/src/ui/toolbar/MainToolBar.qml +++ b/src/ui/toolbar/MainToolBar.qml @@ -7,7 +7,7 @@ * ****************************************************************************/ -import QtQuick 2.11 +import QtQuick 2.12 import QtQuick.Controls 2.4 import QtQuick.Layouts 1.11 import QtQuick.Dialogs 1.3 @@ -31,6 +31,7 @@ Rectangle { property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _communicationLost: _activeVehicle ? _activeVehicle.connectionLost : false + property color _mainStatusBGColor: qgcPal.brandingPurple Component.onCompleted: toolbar.viewButtonClicked(flyButton) @@ -66,6 +67,18 @@ Rectangle { visible: qgcPal.globalTheme === QGCPalette.Light } + Rectangle { + anchors.fill: viewButtonRow + visible: currentToolbar === flyViewToolbar + + gradient: Gradient { + orientation: Gradient.Horizontal + GradientStop { position: 0; color: _mainStatusBGColor } + GradientStop { position: currentButton.x + currentButton.width; color: _mainStatusBGColor } + GradientStop { position: 1; color: _root.color } + } + } + RowLayout { id: viewButtonRow anchors.bottomMargin: 1 @@ -78,26 +91,29 @@ Rectangle { Layout.fillHeight: true onClicked: viewSelectDrawer.visible = true } - } - Rectangle { - id: separator1 - anchors.margins: ScreenTools.defaultFontPixelHeight / 2 - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: viewButtonRow.right - width: 1 - color: qgcPal.text + MainStatusIndicator { + Layout.fillHeight: true + visible: currentToolbar === flyViewToolbar + } + + QGCButton { + id: disconnectButton + Layout.alignment: Qt.AlignVCenter + text: qsTr("Disconnect") + onClicked: _activeVehicle.disconnectInactiveVehicle() + visible: _activeVehicle && _communicationLost && currentToolbar === flyViewToolbar + } } QGCFlickable { id: toolsFlickable anchors.leftMargin: ScreenTools.defaultFontPixelHeight / 2 - anchors.left: separator1.right + anchors.left: viewButtonRow.right anchors.bottomMargin: 1 anchors.top: parent.top anchors.bottom: parent.bottom - anchors.right: connectionStatus.visible ? connectionStatus.left : parent.right + anchors.right: parent.right contentWidth: indicatorLoader.x + indicatorLoader.width flickableDirection: Flickable.HorizontalFlick clip: !valueArea.settingsUnlocked @@ -232,47 +248,4 @@ Rectangle { onClicked: largeProgressBar._userHide = true } } - - //------------------------------------------------------------------------- - //-- Waiting for a vehicle - QGCLabel { - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - text: qsTr("Waiting For Vehicle Connection") - font.pointSize: ScreenTools.mediumFontPointSize - font.family: ScreenTools.demiboldFontFamily - color: qgcPal.colorRed - visible: currentToolbar !== planViewToolbar && !_activeVehicle - } - - //------------------------------------------------------------------------- - //-- Connection Status - Row { - id: connectionStatus - anchors.rightMargin: ScreenTools.defaultFontPixelWidth - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - layoutDirection: Qt.RightToLeft - spacing: ScreenTools.defaultFontPixelWidth - visible: currentToolbar !== planViewToolbar && _activeVehicle && _communicationLost - - QGCButton { - id: disconnectButton - anchors.verticalCenter: parent.verticalCenter - text: qsTr("Disconnect") - primary: true - onClicked: _activeVehicle.disconnectInactiveVehicle() - } - - QGCLabel { - id: connectionLost - anchors.verticalCenter: parent.verticalCenter - text: qsTr("COMMUNICATION LOST") - font.pointSize: ScreenTools.largeFontPointSize - font.family: ScreenTools.demiboldFontFamily - color: qgcPal.colorRed - } - } }