diff --git a/qgcresources.qrc b/qgcresources.qrc index 23b8afa32c3db2d7f8c0a76feeb324cce3621b27..70f2a6585981d67ed21162cbb7666c56826ea822 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -57,6 +57,7 @@ src/AnalyzeView/GeoTagIcon.png src/AutoPilotPlugins/PX4/Images/LandMode.svg src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg + src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png src/AnalyzeView/LogDownloadIcon.png src/AutoPilotPlugins/PX4/Images/LowBattery.svg src/AutoPilotPlugins/PX4/Images/LowBatteryLight.svg diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index 28bb36268f78f4d731dd220217a32f23c5ed2d27..9dfad863f037d1c97aaa31f5a6a1e1ce778c5e52 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -667,6 +667,7 @@ HEADERS+= \ src/AutoPilotPlugins/APM/APMAirframeComponentController.h \ src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.h \ src/AutoPilotPlugins/APM/APMCameraComponent.h \ + src/AutoPilotPlugins/APM/APMLightsComponent.h \ src/AutoPilotPlugins/APM/APMCompassCal.h \ src/AutoPilotPlugins/APM/APMFlightModesComponent.h \ src/AutoPilotPlugins/APM/APMFlightModesComponentController.h \ @@ -730,6 +731,7 @@ SOURCES += \ src/AutoPilotPlugins/APM/APMAirframeComponent.cc \ src/AutoPilotPlugins/APM/APMAirframeComponentController.cc \ src/AutoPilotPlugins/APM/APMCameraComponent.cc \ + src/AutoPilotPlugins/APM/APMLightsComponent.cc \ src/AutoPilotPlugins/APM/APMCompassCal.cc \ src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \ src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 5a9a2a37e3a81eb4ccf3236464164bd3c9fb4732..69dd1d0bf73292f2b8bf40a543271a75c1f722b3 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -143,15 +143,19 @@ src/AutoPilotPlugins/APM/APMNotSupported.qml src/AutoPilotPlugins/APM/APMCameraComponent.qml src/AutoPilotPlugins/APM/APMCameraComponentSummary.qml + src/AutoPilotPlugins/APM/APMLightsComponent.qml + src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml src/AutoPilotPlugins/APM/APMPowerComponent.qml src/AutoPilotPlugins/APM/APMPowerComponentSummary.qml src/AutoPilotPlugins/APM/APMRadioComponentSummary.qml src/AutoPilotPlugins/APM/APMSafetyComponentCopter.qml src/AutoPilotPlugins/APM/APMSafetyComponentPlane.qml src/AutoPilotPlugins/APM/APMSafetyComponentRover.qml + src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml src/AutoPilotPlugins/APM/APMSafetyComponentSummaryCopter.qml src/AutoPilotPlugins/APM/APMSafetyComponentSummaryPlane.qml src/AutoPilotPlugins/APM/APMSafetyComponentSummaryRover.qml + src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml src/AutoPilotPlugins/APM/APMTuningComponentCopter.qml src/AutoPilotPlugins/PX4/CameraComponent.qml src/AutoPilotPlugins/PX4/CameraComponentSummary.qml diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc index ece082b9707e7c73286777c1c49576be6f8ce4ef..9b8b70245592a1e20e7b45a42639d6b6a8a9b988 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc @@ -27,6 +27,7 @@ #include "APMPowerComponent.h" #include "MotorComponent.h" #include "APMCameraComponent.h" +#include "APMLightsComponent.h" #include "ESP8266Component.h" /// This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_ARDUPILOT type. @@ -35,6 +36,7 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent) , _incorrectParameterVersion(false) , _airframeComponent(NULL) , _cameraComponent(NULL) + , _lightsComponent(NULL) , _flightModesComponent(NULL) , _powerComponent(NULL) #if 0 @@ -104,6 +106,12 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void) _cameraComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_cameraComponent)); + if (_vehicle->sub()) { + _lightsComponent = new APMLightsComponent(_vehicle, this); + _lightsComponent->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_lightsComponent)); + } + //-- Is there an ESP8266 Connected? if(_vehicle->parameterManager()->parameterExists(MAV_COMP_ID_UDP_BRIDGE, "SW_VER")) { _esp8266Component = new ESP8266Component(_vehicle, this); diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h index 62ffbdf061b0e5279c3c9ac3496d1ff12df257c3..6bd6031526bad7d82075be43285452f538b0e286 100644 --- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h +++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h @@ -24,6 +24,7 @@ class APMSensorsComponent; class APMPowerComponent; class MotorComponent; class APMCameraComponent; +class APMLightsComponent; class ESP8266Component; /// This is the APM specific implementation of the AutoPilot class. @@ -40,6 +41,7 @@ public: APMAirframeComponent* airframeComponent (void) const { return _airframeComponent; } APMCameraComponent* cameraComponent (void) const { return _cameraComponent; } + APMLightsComponent* lightsComponent (void) const { return _lightsComponent; } APMFlightModesComponent* flightModesComponent(void) const { return _flightModesComponent; } APMPowerComponent* powerComponent (void) const { return _powerComponent; } #if 0 @@ -58,6 +60,7 @@ private: APMAirframeComponent* _airframeComponent; APMCameraComponent* _cameraComponent; + APMLightsComponent* _lightsComponent; APMFlightModesComponent* _flightModesComponent; APMPowerComponent* _powerComponent; #if 0 diff --git a/src/AutoPilotPlugins/APM/APMLightsComponent.cc b/src/AutoPilotPlugins/APM/APMLightsComponent.cc new file mode 100644 index 0000000000000000000000000000000000000000..6c6d62219ddd192e95dcf762e2a4bc73aa14eeaf --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMLightsComponent.cc @@ -0,0 +1,76 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +/// @file +/// @author Don Gagne +/// @author Rustom Jehangir + +#include "APMLightsComponent.h" +#include "QGCQmlWidgetHolder.h" +#include "APMAutoPilotPlugin.h" +#include "APMAirframeComponent.h" + +APMLightsComponent::APMLightsComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) + : VehicleComponent(vehicle, autopilot, parent) + , _name(tr("Lights")) +{ +} + +QString APMLightsComponent::name(void) const +{ + return _name; +} + +QString APMLightsComponent::description(void) const +{ + return tr("Lights setup is used to adjust light output channels."); +} + +QString APMLightsComponent::iconResource(void) const +{ + return QStringLiteral("/qmlimages/LightsComponentIcon.png"); +} + +bool APMLightsComponent::requiresSetup(void) const +{ + return false; +} + +bool APMLightsComponent::setupComplete(void) const +{ + return true; +} + +QStringList APMLightsComponent::setupCompleteChangedTriggerList(void) const +{ + return QStringList(); +} + +QUrl APMLightsComponent::setupSource(void) const +{ + return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMLightsComponent.qml")); +} + +QUrl APMLightsComponent::summaryQmlSource(void) const +{ + return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMLightsComponentSummary.qml")); +} + +QString APMLightsComponent::prerequisiteSetup(void) const +{ + APMAutoPilotPlugin* plugin = dynamic_cast(_autopilot); + Q_ASSERT(plugin); + + if (!plugin->airframeComponent()->setupComplete()) { + return plugin->airframeComponent()->name(); + } + + return QString(); +} diff --git a/src/AutoPilotPlugins/APM/APMLightsComponent.h b/src/AutoPilotPlugins/APM/APMLightsComponent.h new file mode 100644 index 0000000000000000000000000000000000000000..0369aae877c02de8823759c950c444d72d6774f6 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMLightsComponent.h @@ -0,0 +1,40 @@ +/**************************************************************************** + * + * (c) 2009-2016 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + + +#ifndef APMLightsComponent_H +#define APMLightsComponent_H + +#include "VehicleComponent.h" + +class APMLightsComponent : public VehicleComponent +{ + Q_OBJECT + +public: + APMLightsComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL); + + // Virtuals from VehicleComponent + QStringList setupCompleteChangedTriggerList(void) const final; + + // Virtuals from VehicleComponent + QString name(void) const final; + QString description(void) const final; + QString iconResource(void) const final; + bool requiresSetup(void) const final; + bool setupComplete(void) const final; + QUrl setupSource(void) const final; + QUrl summaryQmlSource(void) const final; + QString prerequisiteSetup(void) const final; + +private: + const QString _name; +}; + +#endif diff --git a/src/AutoPilotPlugins/APM/APMLightsComponent.qml b/src/AutoPilotPlugins/APM/APMLightsComponent.qml new file mode 100644 index 0000000000000000000000000000000000000000..42c76d1a24b18e20b533fa56d6e49c234b83765c --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMLightsComponent.qml @@ -0,0 +1,190 @@ +/**************************************************************************** + * + * (c) 2009-2016 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.5 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +SetupPage { + id: lightsPage + pageComponent: lightsPageComponent + + Component { + id: lightsPageComponent + + Column { + spacing: _margins + width: availableWidth + + FactPanelController { id: controller; factPanel: lightsPage.viewPanel } + + QGCPalette { id: palette; colorGroupEnabled: true } + + property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") + property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") + property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") + property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") + property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") + property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") + property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + + readonly property real _margins: ScreenTools.defaultFontPixelHeight + readonly property int _rcFunctionDisabled: 0 + readonly property int _rcFunctionRCIN9: 59 + readonly property int _rcFunctionRCIN10: 60 + readonly property int _firstLightsOutChannel: 5 + readonly property int _lastLightsOutChannel: 14 + + Component.onCompleted: { + calcLightOutValues() + } + + /// Light output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// to find them and setup the ui accordindly. + function calcLightOutValues() { + lightsLoader.lights1OutIndex = 0 + lightsLoader.lights2OutIndex = 0 + for (var channel=_firstLightsOutChannel; channel<=_lastLightsOutChannel; channel++) { + var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + if (functionFact.value == _rcFunctionRCIN9) { + lightsLoader.lights1OutIndex = channel - 4 + } else if (functionFact.value == _rcFunctionRCIN10) { + lightsLoader.lights2OutIndex = channel - 4 + } + } + } + + function setRCFunction(channel, rcFunction) { + // First clear any previous settings for this function + for (var index=_firstLightsOutChannel; index<=_lastLightsOutChannel; index++) { + var functionFact = controller.getParameterFact(-1, "RC" + index + "_FUNCTION") + if (functionFact.value != _rcFunctionDisabled && functionFact.value == rcFunction) { + functionFact.value = _rcFunctionDisabled + } + } + + // Now set the function into the new channel + if (channel != 0) { + var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + functionFact.value = rcFunction + } + } + + // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for light output channels again + Connections { target: _rc5Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc6Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc7Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc8Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc9Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc10Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc11Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc12Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc13Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc14Function; onValueChanged: calcLightOutValues() } + + ListModel { + id: lightsOutModel + ListElement { text: qsTr("Disabled"); value: 0 } + ListElement { text: qsTr("Channel 5"); value: 5 } + ListElement { text: qsTr("Channel 6"); value: 6 } + ListElement { text: qsTr("Channel 7"); value: 7 } + ListElement { text: qsTr("Channel 8"); value: 8 } + ListElement { text: qsTr("Channel 9"); value: 9 } + ListElement { text: qsTr("Channel 10"); value: 10 } + ListElement { text: qsTr("Channel 11"); value: 11 } + ListElement { text: qsTr("Channel 12"); value: 12 } + ListElement { text: qsTr("Channel 13"); value: 13 } + ListElement { text: qsTr("Channel 14"); value: 14 } + } + + Component { + id: lightSettings + + Item { + width: rectangle.x + rectangle.width + height: rectangle.y + rectangle.height + + QGCLabel { + id: settingsLabel + text: qsTr("Light Output Channels") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: rectangle + anchors.topMargin: _margins / 2 + anchors.top: settingsLabel.bottom + width: lights1Combo.x + lights1Combo.width + _margins + height: lights2Combo.y + lights2Combo.height + _margins + color: palette.windowShade + + QGCLabel { + id: lights1Label + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: lights1Combo.baseline + text: qsTr("Lights 1:") + } + + QGCComboBox { + id: lights1Combo + anchors.margins: _margins + anchors.top: parent.top + anchors.left: lights1Label.right + width: ScreenTools.defaultFontPixelWidth * 15 + model: lightsOutModel + currentIndex: lights1OutIndex + + onActivated: setRCFunction(lightsOutModel.get(index).value, lights1Function) + } + + QGCLabel { + id: lights2Label + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: lights2Combo.baseline + text: qsTr("Lights 2:") + } + + QGCComboBox { + id: lights2Combo + anchors.margins: _margins + anchors.top: lights1Combo.bottom + anchors.left: lights2Label.right + width: lights1Combo.width + model: lightsOutModel + currentIndex: lights2OutIndex + + onActivated: setRCFunction(lightsOutModel.get(index).value, lights2Function) + } + } // Rectangle + } // Item + } // Component - lightSettings + + Loader { + id: lightsLoader + sourceComponent: lightSettings + + property int lights1OutIndex: 0 + property int lights2OutIndex: 0 + property int lights1Function: _rcFunctionRCIN9 + property int lights2Function: _rcFunctionRCIN10 + } + } // Column + } // Component +} // SetupPage diff --git a/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml b/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml new file mode 100644 index 0000000000000000000000000000000000000000..3eb129d28a14139ace27fd6c94346a00fa525e46 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMLightsComponentSummary.qml @@ -0,0 +1,101 @@ +import QtQuick 2.5 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 + +FactPanel { + id: panel + anchors.fill: parent + color: qgcPal.windowShadeDark + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + FactPanelController { id: controller; factPanel: panel } + + property Fact _rc5Function: controller.getParameterFact(-1, "RC5_FUNCTION") + property Fact _rc6Function: controller.getParameterFact(-1, "RC6_FUNCTION") + property Fact _rc7Function: controller.getParameterFact(-1, "RC7_FUNCTION") + property Fact _rc8Function: controller.getParameterFact(-1, "RC8_FUNCTION") + property Fact _rc9Function: controller.getParameterFact(-1, "RC9_FUNCTION") + property Fact _rc10Function: controller.getParameterFact(-1, "RC10_FUNCTION") + property Fact _rc11Function: controller.getParameterFact(-1, "RC11_FUNCTION") + property Fact _rc12Function: controller.getParameterFact(-1, "RC12_FUNCTION") + property Fact _rc13Function: controller.getParameterFact(-1, "RC13_FUNCTION") + property Fact _rc14Function: controller.getParameterFact(-1, "RC14_FUNCTION") + + readonly property int _rcFunctionRCIN9: 59 + readonly property int _rcFunctionRCIN10: 60 + readonly property int _firstLightsOutChannel: 5 + readonly property int _lastLightsOutChannel: 14 + + Component.onCompleted: { + calcLightOutValues() + } + + /// Light output channels are stored in RC#_FUNCTION parameters. We need to loop through those + /// to find them and setup the ui accordindly. + function calcLightOutValues() { + lightsLoader.lights1OutIndex = 0 + lightsLoader.lights2OutIndex = 0 + for (var channel=_firstLightsOutChannel; channel<=_lastLightsOutChannel; channel++) { + var functionFact = controller.getParameterFact(-1, "RC" + channel + "_FUNCTION") + if (functionFact.value == _rcFunctionRCIN9) { + lightsLoader.lights1OutIndex = channel - 4 + } else if (functionFact.value == _rcFunctionRCIN10) { + lightsLoader.lights2OutIndex = channel - 4 + } + } + } + + // Whenever any RC#_FUNCTION parameters chagnes we need to go looking for light output channels again + Connections { target: _rc5Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc6Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc7Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc8Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc9Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc10Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc11Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc12Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc13Function; onValueChanged: calcLightOutValues() } + Connections { target: _rc14Function; onValueChanged: calcLightOutValues() } + + ListModel { + id: lightsOutModel + ListElement { text: qsTr("Disabled"); value: 0 } + ListElement { text: qsTr("Channel 5"); value: 5 } + ListElement { text: qsTr("Channel 6"); value: 6 } + ListElement { text: qsTr("Channel 7"); value: 7 } + ListElement { text: qsTr("Channel 8"); value: 8 } + ListElement { text: qsTr("Channel 9"); value: 9 } + ListElement { text: qsTr("Channel 10"); value: 10 } + ListElement { text: qsTr("Channel 11"); value: 11 } + ListElement { text: qsTr("Channel 12"); value: 12 } + ListElement { text: qsTr("Channel 13"); value: 13 } + ListElement { text: qsTr("Channel 14"); value: 14 } + } + + Loader { + id: lightsLoader + + property int lights1OutIndex: 0 + property int lights2OutIndex: 0 + property int lights1Function: _rcFunctionRCIN9 + property int lights2Function: _rcFunctionRCIN10 + } + + Column { + anchors.fill: parent + + VehicleSummaryRow { + labelText: qsTr("Lights Output 1:") + valueText: lightsOutModel.get(lightsLoader.lights1OutIndex).text + } + + VehicleSummaryRow { + labelText: qsTr("Lights Output 2:") + valueText: lightsOutModel.get(lightsLoader.lights2OutIndex).text + } + } +} diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc index d97d522c47cd30f74e2b2420e4baa7b57cd29880..02da238fbed897efb5ceab24a185de0384ff99d8 100644 --- a/src/AutoPilotPlugins/APM/APMSafetyComponent.cc +++ b/src/AutoPilotPlugins/APM/APMSafetyComponent.cc @@ -29,7 +29,22 @@ QString APMSafetyComponent::name(void) const QString APMSafetyComponent::description(void) const { - return tr("Safety Setup is used to setup triggers for Return to Land as well as the settings for Return to Land itself."); + switch (_vehicle->vehicleType()) { + case MAV_TYPE_SUBMARINE: + return tr("Safety Setup is used to setup failsafe actions, geofence limits, leak detection, and arming checks."); + break; + case MAV_TYPE_GROUND_ROVER: + case MAV_TYPE_FIXED_WING: + case MAV_TYPE_QUADROTOR: + case MAV_TYPE_COAXIAL: + case MAV_TYPE_HELICOPTER: + case MAV_TYPE_HEXAROTOR: + case MAV_TYPE_OCTOROTOR: + case MAV_TYPE_TRICOPTER: + default: + return tr("Safety Setup is used to setup triggers for Return to Land as well as the settings for Return to Land itself."); + break; + } } QString APMSafetyComponent::iconResource(void) const @@ -69,6 +84,9 @@ QUrl APMSafetyComponent::setupSource(void) const case MAV_TYPE_TRICOPTER: qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentCopter.qml"); break; + case MAV_TYPE_SUBMARINE: + qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentSub.qml"); + break; case MAV_TYPE_GROUND_ROVER: qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentRover.qml"); break; @@ -96,6 +114,9 @@ QUrl APMSafetyComponent::summaryQmlSource(void) const case MAV_TYPE_TRICOPTER: qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentSummaryCopter.qml"); break; + case MAV_TYPE_SUBMARINE: + qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentSummarySub.qml"); + break; case MAV_TYPE_GROUND_ROVER: qmlFile = QStringLiteral("qrc:/qml/APMSafetyComponentSummaryRover.qml"); break; diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml b/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml new file mode 100644 index 0000000000000000000000000000000000000000..affae197ece8f2ec909bd67d77e3846887d878cb --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSafetyComponentSub.qml @@ -0,0 +1,266 @@ +/**************************************************************************** + * + * (c) 2009-2016 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.5 +import QtQuick.Controls 1.2 +import QtGraphicalEffects 1.0 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 + +SetupPage { + id: safetyPage + pageComponent: safetyPageComponent + + Component { + id: safetyPageComponent + + Flow { + id: flowLayout + width: availableWidth + spacing: _margins + + FactPanelController { id: controller; factPanel: safetyPage.viewPanel } + + QGCPalette { id: ggcPal; colorGroupEnabled: true } + + property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE") + property Fact _failsafeLeakEnable: controller.getParameterFact(-1, "FS_LEAK_ENABLE") + property Fact _failsafePressureEnable: controller.getParameterFact(-1, "FS_PRESS_ENABLE") + property Fact _failsafePressureValue: controller.getParameterFact(-1, "FS_PRESS_MAX") + property Fact _failsafeTempEnable: controller.getParameterFact(-1, "FS_TEMP_ENABLE") + property Fact _failsafeTempValue: controller.getParameterFact(-1, "FS_TEMP_MAX") + + property Fact _fenceAction: controller.getParameterFact(-1, "FENCE_ACTION") + property Fact _fenceAltMax: controller.getParameterFact(-1, "FENCE_ALT_MAX") + property Fact _fenceEnable: controller.getParameterFact(-1, "FENCE_ENABLE") + property Fact _fenceMargin: controller.getParameterFact(-1, "FENCE_MARGIN") + property Fact _fenceType: controller.getParameterFact(-1, "FENCE_TYPE") + + property Fact _leakPin: controller.getParameterFact(-1, "LEAK1_PIN") + property Fact _leakLogic: controller.getParameterFact(-1, "LEAK1_LOGIC") + + property Fact _armingCheck: controller.getParameterFact(-1, "ARMING_CHECK") + + property real _margins: ScreenTools.defaultFontPixelHeight + property bool _showIcon: !ScreenTools.isTinyScreen + + ExclusiveGroup { id: fenceActionRadioGroup } + + Column { + spacing: _margins / 2 + + QGCLabel { + id: failsafeLabel + text: qsTr("Failsafe Actions") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: failsafeSettings + width: leakEnableCombo.x + leakEnableCombo.width + _margins + height: leakEnableCombo.y + leakEnableCombo.height + _margins + color: ggcPal.windowShade + + QGCLabel { + id: gcsEnableLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: gcsEnableCombo.baseline + text: qsTr("Ground Station failsafe:") + } + + FactComboBox { + id: gcsEnableCombo + anchors.margins: _margins + anchors.left: gcsEnableLabel.right + anchors.top: parent.top + width: ScreenTools.defaultFontPixelWidth*15 + fact: _failsafeGCSEnable + indexModel: false + } + + QGCLabel { + id: leakEnableLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.baseline: leakEnableCombo.baseline + text: qsTr("Leak failsafe:") + } + + FactComboBox { + id: leakEnableCombo + anchors.topMargin: _margins + anchors.left: gcsEnableCombo.left + anchors.top: gcsEnableCombo.bottom + width: ScreenTools.defaultFontPixelWidth*15 + fact: _failsafeLeakEnable + indexModel: false + } + } // Rectangle - Failsafe Settings + } // Column - Failsafe Settings + + Column { + spacing: _margins / 2 + + QGCLabel { + id: geoFenceLabel + text: qsTr("GeoFence") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: geoFenceSettings + width: fenceAltMaxField.x + fenceAltMaxField.width + _margins + height: fenceAltMaxField.y + fenceAltMaxField.height + _margins + color: ggcPal.windowShade + + QGCCheckBox { + id: altitudeGeo + anchors.margins: _margins + anchors.left: parent.left + anchors.top: parent.top + text: qsTr("Depth GeoFence enabled\n(report only)") + checked: _fenceEnable.value != 0 && _fenceType.value & 1 + + onClicked: { + if (checked) { + if (_fenceEnable.value == 1) { + _fenceType.value |= 1 + } else { + _fenceEnable.value = 1 + _fenceType.value = 1 + } + } else { + _fenceEnable.value = 0 + _fenceType.value = 0 + } + } + } + + QGCLabel { + id: fenceAltMaxLabel + anchors.left: altitudeGeo.left + anchors.baseline: fenceAltMaxField.baseline + text: qsTr("Max depth:") + } + + FactTextField { + id: fenceAltMaxField + anchors.topMargin: _margins / 2 + anchors.leftMargin: _margins + anchors.left: fenceAltMaxLabel.right + anchors.top: altitudeGeo.bottom + fact: _fenceAltMax + showUnits: true + } + } // Rectangle - GeoFence Settings + } // Column - GeoFence Settings + + Column { + spacing: _margins / 2 + + QGCLabel { + id: leakDetectorLabel + text: qsTr("Leak detector") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + id: leakDetectorSettings + width: leakLogicCombo.x + leakLogicCombo.width + _margins + height: leakLogicCombo.y + leakLogicCombo.height + _margins + color: ggcPal.windowShade + + QGCLabel { + id: leakPinLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.top: parent.top + text: qsTr("Pin:") + } + + FactComboBox { + id: leakPinCombo + anchors.margins: _margins + anchors.left: leakLogicLabel.right + anchors.baseline: leakPinLabel.baseline + width: ScreenTools.defaultFontPixelWidth*15 + fact: _leakPin + indexModel: false + } + + QGCLabel { + id: leakLogicLabel + anchors.margins: _margins + anchors.left: parent.left + anchors.top: leakPinLabel.bottom + text: qsTr("Logic:") + } + + FactComboBox { + id: leakLogicCombo + anchors.margins: _margins + anchors.left: leakLogicLabel.right + anchors.baseline: leakLogicLabel.baseline + width: ScreenTools.defaultFontPixelWidth*15 + fact: _leakLogic + indexModel: false + } + } // Rectangle - Leak Detector Settings + } // Column - Leak Detector Settings + + Column { + spacing: _margins / 2 + + QGCLabel { + text: qsTr("Arming Checks") + font.family: ScreenTools.demiboldFontFamily + } + + Rectangle { + width: flowLayout.width + height: armingCheckInnerColumn.height + (_margins * 2) + color: ggcPal.windowShade + + Column { + id: armingCheckInnerColumn + anchors.margins: _margins + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + spacing: _margins + + FactBitmask { + id: armingCheckBitmask + anchors.left: parent.left + anchors.right: parent.right + firstEntryIsAll: true + fact: _armingCheck + } + + QGCLabel { + id: armingCheckWarning + anchors.left: parent.left + anchors.right: parent.right + wrapMode: Text.WordWrap + color: qgcPal.warningText + text: qsTr("Warning: Turning off arming checks can lead to loss of Vehicle control.") + visible: _armingCheck.value != 1 + } + } + } // Rectangle - Arming checks + } // Column - Arming Checks + } // Flow + } // Component - safetyPageComponent +} // SetupView diff --git a/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml b/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml new file mode 100644 index 0000000000000000000000000000000000000000..7bab272be5f2bddd208df850f985fc34ff7c9161 --- /dev/null +++ b/src/AutoPilotPlugins/APM/APMSafetyComponentSummarySub.qml @@ -0,0 +1,94 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 + +FactPanel { + id: panel + anchors.fill: parent + color: qgcPal.windowShadeDark + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + FactPanelController { id: controller; factPanel: panel } + + property Fact _failsafeGCSEnable: controller.getParameterFact(-1, "FS_GCS_ENABLE") + property Fact _failsafeLeakEnable: controller.getParameterFact(-1, "FS_LEAK_ENABLE") + + property Fact _fenceAction: controller.getParameterFact(-1, "FENCE_ACTION") + property Fact _fenceEnable: controller.getParameterFact(-1, "FENCE_ENABLE") + property Fact _fenceType: controller.getParameterFact(-1, "FENCE_TYPE") + + property Fact _leakPin: controller.getParameterFact(-1, "LEAK1_PIN") + + property Fact _armingCheck: controller.getParameterFact(-1, "ARMING_CHECK") + + property string _failsafeGCSEnableText + + Component.onCompleted: { + setFailsafeGCSEnableText() + } + + Connections { + target: _failsafeGCSEnable + + onValueChanged: setFailsafeGCSEnableText() + } + + function setFailsafeGCSEnableText() { + switch (_failsafeGCSEnable.value) { + case 0: + _failsafeGCSEnableText = qsTr("Disabled") + break + case 1: + _failsafeGCSEnableText = qsTr("Always RTL") + break + case 2: + _failsafeGCSEnableText = qsTr("Continue with Mission in Auto Mode") + break + default: + _failsafeGCSEnableText = qsTr("Unknown") + } + } + + Column { + anchors.fill: parent + + VehicleSummaryRow { + labelText: qsTr("Arming Checks:") + valueText: _armingCheck.value & 1 ? qsTr("Enabled") : qsTr("Some disabled") + } + + VehicleSummaryRow { + labelText: qsTr("GCS failsafe:") + valueText: _failsafeGCSEnableText + } + + VehicleSummaryRow { + labelText: qsTr("Leak failsafe:") + valueText: _failsafeLeakEnable.value ? qsTr("Enabled") : qsTr("Disabled") + } + + VehicleSummaryRow { + labelText: qsTr("Leak detector:") + valueText: _leakPin.value > 0 ? qsTr("Enabled") : qsTr("Disabled") + } + + VehicleSummaryRow { + labelText: qsTr("GeoFence:") + valueText: _fenceEnable.value == 0 || _fenceType == 0 ? + qsTr("Disabled") : + (_fenceType.value == 1 ? + qsTr("Depth") : + (_fenceType.value == 2 ? qsTr("Circle") : qsTr("Depth,Circle"))) + } + + VehicleSummaryRow { + labelText: qsTr("GeoFence:") + valueText: qsTr("Report only") + visible: _fenceEnable.value != 0 + } + } +} diff --git a/src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png b/src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..71c05680207280e505ba40c6b3c0b04a852a9c43 Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png differ