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