diff --git a/qgcresources.qrc b/qgcresources.qrc
index dcfc66ccf6b..5c714bbed29 100644
--- a/qgcresources.qrc
+++ b/qgcresources.qrc
@@ -58,6 +58,12 @@
src/AutoPilotPlugins/PX4/Images/LandMode.svg
src/AutoPilotPlugins/PX4/Images/LandModeCopter.svg
src/AutoPilotPlugins/APM/Images/LightsComponentIcon.png
+ src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png
+ src/AutoPilotPlugins/APM/Images/bluerov-frame.png
+ src/AutoPilotPlugins/APM/Images/vectored-frame.png
+ src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png
+ src/AutoPilotPlugins/APM/Images/simple3-frame.png
+ src/AutoPilotPlugins/APM/Images/simple4-frame.png
src/AnalyzeView/LogDownloadIcon.svg
src/AutoPilotPlugins/PX4/Images/LowBattery.svg
src/AutoPilotPlugins/PX4/Images/LowBatteryLight.svg
diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro
index 4fa119de466..3560594152e 100644
--- a/qgroundcontrol.pro
+++ b/qgroundcontrol.pro
@@ -796,6 +796,7 @@ APMFirmwarePlugin {
src/AutoPilotPlugins/APM/APMFlightModesComponent.h \
src/AutoPilotPlugins/APM/APMFlightModesComponentController.h \
src/AutoPilotPlugins/APM/APMLightsComponent.h \
+ src/AutoPilotPlugins/APM/APMSubFrameComponent.h \
src/AutoPilotPlugins/APM/APMPowerComponent.h \
src/AutoPilotPlugins/APM/APMRadioComponent.h \
src/AutoPilotPlugins/APM/APMSafetyComponent.h \
@@ -822,6 +823,7 @@ APMFirmwarePlugin {
src/AutoPilotPlugins/APM/APMFlightModesComponent.cc \
src/AutoPilotPlugins/APM/APMFlightModesComponentController.cc \
src/AutoPilotPlugins/APM/APMLightsComponent.cc \
+ src/AutoPilotPlugins/APM/APMSubFrameComponent.cc \
src/AutoPilotPlugins/APM/APMPowerComponent.cc \
src/AutoPilotPlugins/APM/APMRadioComponent.cc \
src/AutoPilotPlugins/APM/APMSafetyComponent.cc \
diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc
index 618e2a7ab77..4edebf5de4d 100644
--- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc
+++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.cc
@@ -27,6 +27,7 @@
#include "MotorComponent.h"
#include "APMCameraComponent.h"
#include "APMLightsComponent.h"
+#include "APMSubFrameComponent.h"
#include "ESP8266Component.h"
/// This is the AutoPilotPlugin implementatin for the MAV_AUTOPILOT_ARDUPILOT type.
@@ -36,6 +37,7 @@ APMAutoPilotPlugin::APMAutoPilotPlugin(Vehicle* vehicle, QObject* parent)
, _airframeComponent(NULL)
, _cameraComponent(NULL)
, _lightsComponent(NULL)
+ , _subFrameComponent(NULL)
, _flightModesComponent(NULL)
, _powerComponent(NULL)
#if 0
@@ -109,6 +111,13 @@ const QVariantList& APMAutoPilotPlugin::vehicleComponents(void)
_lightsComponent = new APMLightsComponent(_vehicle, this);
_lightsComponent->setupTriggerSignals();
_components.append(QVariant::fromValue((VehicleComponent*)_lightsComponent));
+
+ qWarning() << "ArduSub Version Detected:" << _vehicle->firmwareMajorVersion() << _vehicle->firmwareMinorVersion();
+ if(_vehicle->firmwareMajorVersion() > 3 || (_vehicle->firmwareMajorVersion() == 3 && _vehicle->firmwareMinorVersion() >= 5)) {
+ _subFrameComponent = new APMSubFrameComponent(_vehicle, this);
+ _subFrameComponent->setupTriggerSignals();
+ _components.append(QVariant::fromValue((VehicleComponent*)_subFrameComponent));
+ }
}
//-- Is there an ESP8266 Connected?
diff --git a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h
index 6bd6031526b..8ac267b4266 100644
--- a/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h
+++ b/src/AutoPilotPlugins/APM/APMAutoPilotPlugin.h
@@ -25,6 +25,7 @@ class APMPowerComponent;
class MotorComponent;
class APMCameraComponent;
class APMLightsComponent;
+class APMSubFrameComponent;
class ESP8266Component;
/// This is the APM specific implementation of the AutoPilot class.
@@ -42,6 +43,7 @@ class APMAutoPilotPlugin : public AutoPilotPlugin
APMAirframeComponent* airframeComponent (void) const { return _airframeComponent; }
APMCameraComponent* cameraComponent (void) const { return _cameraComponent; }
APMLightsComponent* lightsComponent (void) const { return _lightsComponent; }
+ APMSubFrameComponent* subFrameComponent (void) const { return _subFrameComponent; }
APMFlightModesComponent* flightModesComponent(void) const { return _flightModesComponent; }
APMPowerComponent* powerComponent (void) const { return _powerComponent; }
#if 0
@@ -61,6 +63,7 @@ class APMAutoPilotPlugin : public AutoPilotPlugin
APMAirframeComponent* _airframeComponent;
APMCameraComponent* _cameraComponent;
APMLightsComponent* _lightsComponent;
+ APMSubFrameComponent* _subFrameComponent;
APMFlightModesComponent* _flightModesComponent;
APMPowerComponent* _powerComponent;
#if 0
diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc b/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc
new file mode 100644
index 00000000000..95506a14c82
--- /dev/null
+++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.cc
@@ -0,0 +1,78 @@
+/****************************************************************************
+ *
+ * (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 Jacob Walser
+
+#include "APMSubFrameComponent.h"
+#include "QGCQmlWidgetHolder.h"
+#include "APMAutoPilotPlugin.h"
+#include "APMAirframeComponent.h"
+
+APMSubFrameComponent::APMSubFrameComponent(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent)
+ : VehicleComponent(vehicle, autopilot, parent)
+ , _name(tr("Frame"))
+{
+}
+
+QString APMSubFrameComponent::name(void) const
+{
+ return _name;
+}
+
+QString APMSubFrameComponent::description(void) const
+{
+ return tr("Frame setup allows you to choose your vehicle's motor configuration. Install clockwise" \
+ "\npropellers on the green thrusters and counter-clockwise propellers on the blue thrusters" \
+ "\n(or vice-versa). The flight controller will need to be rebooted to apply changes.");
+}
+
+QString APMSubFrameComponent::iconResource(void) const
+{
+ return QStringLiteral("/qmlimages/SubFrameComponentIcon.png");
+}
+
+bool APMSubFrameComponent::requiresSetup(void) const
+{
+ return false;
+}
+
+bool APMSubFrameComponent::setupComplete(void) const
+{
+ return true;
+}
+
+QStringList APMSubFrameComponent::setupCompleteChangedTriggerList(void) const
+{
+ return QStringList();
+}
+
+QUrl APMSubFrameComponent::setupSource(void) const
+{
+ return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMSubFrameComponent.qml"));
+}
+
+QUrl APMSubFrameComponent::summaryQmlSource(void) const
+{
+ return QUrl::fromUserInput(QStringLiteral("qrc:/qml/APMSubFrameComponentSummary.qml"));
+}
+
+QString APMSubFrameComponent::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/APMSubFrameComponent.h b/src/AutoPilotPlugins/APM/APMSubFrameComponent.h
new file mode 100644
index 00000000000..68b3eabb1fa
--- /dev/null
+++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.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 APMSubFrameComponent_H
+#define APMSubFrameComponent_H
+
+#include "VehicleComponent.h"
+
+class APMSubFrameComponent : public VehicleComponent
+{
+ Q_OBJECT
+
+public:
+ APMSubFrameComponent(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/APMSubFrameComponent.qml b/src/AutoPilotPlugins/APM/APMSubFrameComponent.qml
new file mode 100644
index 00000000000..df06fec6959
--- /dev/null
+++ b/src/AutoPilotPlugins/APM/APMSubFrameComponent.qml
@@ -0,0 +1,151 @@
+/****************************************************************************
+ *
+ * (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: subFramePage
+ pageComponent: subFramePageComponent
+
+ Component {
+ id: subFramePageComponent
+
+ Column {
+ id: mainColumn
+ width: availableWidth
+
+ FactPanelController { id: controller; factPanel: subFramePage.viewPanel }
+
+ QGCPalette { id: palette; colorGroupEnabled: true }
+
+ property Fact _frameConfig: controller.getParameterFact(-1, "FRAME_CONFIG")
+
+ function setFrameConfig(frame) {
+ _frameConfig.value = frame;
+ }
+
+ property real _minW: ScreenTools.defaultFontPixelWidth * 30
+ property real _boxWidth: _minW
+ property real _boxSpace: ScreenTools.defaultFontPixelWidth
+
+ onWidthChanged: {
+ computeDimensions()
+ }
+
+ Component.onCompleted: computeDimensions()
+
+ function computeDimensions() {
+ var sw = 0
+ var rw = 0
+ var idx = Math.floor(mainColumn.width / (_minW + ScreenTools.defaultFontPixelWidth))
+ if(idx < 1) {
+ _boxWidth = mainColumn.width
+ _boxSpace = 0
+ } else {
+ _boxSpace = 0
+ if(idx > 1) {
+ _boxSpace = ScreenTools.defaultFontPixelWidth
+ sw = _boxSpace * (idx - 1)
+ }
+ rw = mainColumn.width - sw
+ _boxWidth = rw / idx
+ }
+ }
+
+ ListModel {
+ id: subFrameModel
+
+ ListElement {
+ name: "BlueROV1"
+ resource: "qrc:///qmlimages/Frames/BlueROV1.png"
+ paramValue: 0
+ }
+
+ ListElement {
+ name: "BlueROV2/Vectored"
+ resource: "qrc:///qmlimages/Frames/Vectored.png"
+ paramValue: 1
+ }
+
+ ListElement {
+ name: "Vectored-6DOF"
+ resource: "qrc:///qmlimages/Frames/Vectored6DOF.png"
+ paramValue: 2
+ }
+
+ ListElement {
+ name: "SimpleROV-3"
+ resource: "qrc:///qmlimages/Frames/SimpleROV-3.png"
+ paramValue: 4
+ }
+
+ ListElement {
+ name: "SimpleROV-4"
+ resource: "qrc:///qmlimages/Frames/SimpleROV-4.png"
+ paramValue: 5
+ }
+ }
+
+ Flow {
+ id: flowView
+ width: parent.width
+ spacing: _boxSpace
+
+ Repeater {
+ model: subFrameModel
+
+ Rectangle {
+ width: _boxWidth
+ height: ScreenTools.defaultFontPixelHeight * 14
+ color: qgcPal.window
+
+ QGCLabel {
+ id: title
+ text: subFrameModel.get(index).name
+ }
+
+ Rectangle {
+ anchors.topMargin: ScreenTools.defaultFontPixelHeight / 2
+ anchors.top: title.bottom
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ color: subFrameModel.get(index).paramValue == _frameConfig.value ? qgcPal.buttonHighlight: qgcPal.windowShade
+
+ Image {
+ anchors.margins: ScreenTools.defaultFontPixelWidth
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ mipmap: true
+ source: subFrameModel.get(index).resource
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: setFrameConfig(subFrameModel.get(index).paramValue)
+ }
+ }
+ }
+ }// Repeater
+ }// Flow
+ } // Column
+ } // Component
+} // SetupPage
diff --git a/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml b/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml
new file mode 100644
index 00000000000..6dcf659fd76
--- /dev/null
+++ b/src/AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml
@@ -0,0 +1,57 @@
+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.Controllers 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 frameFact: controller.getParameterFact(-1, "FRAME_CONFIG")
+
+ function frameName() {
+ switch(frameFact.value) {
+ case 0:
+ return "BlueROV1"
+ case 1:
+ return "Vectored/BlueROV2"
+ case 2:
+ return "Vectored 6DOF"
+ case 3:
+ return "Vectored 6DOF 90Degree"
+ case 4:
+ return "SimpleROV-3"
+ case 5:
+ return "SimpleROV-4"
+ case 6:
+ return "SimpleROV-5"
+ case 7:
+ return "Custom"
+ default:
+ return "Unknown"
+ }
+ }
+
+ Column {
+ anchors.fill: parent
+ VehicleSummaryRow {
+ id: nameRow;
+ labelText: qsTr("Frame Type:")
+ valueText: frameName()
+ }
+
+ VehicleSummaryRow {
+ labelText: qsTr("Firmware Version:")
+ valueText: activeVehicle.firmwareMajorVersion == -1 ? qsTr("Unknown") : activeVehicle.firmwareMajorVersion + "." + activeVehicle.firmwareMinorVersion + "." + activeVehicle.firmwarePatchVersion + "-" + activeVehicle.firmwareVersionTypeString
+ }
+ }
+}
diff --git a/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png b/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png
new file mode 100644
index 00000000000..6401e093c85
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/SubFrameComponentIcon.png differ
diff --git a/src/AutoPilotPlugins/APM/Images/bluerov-frame.png b/src/AutoPilotPlugins/APM/Images/bluerov-frame.png
new file mode 100644
index 00000000000..5a5edaf360c
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/bluerov-frame.png differ
diff --git a/src/AutoPilotPlugins/APM/Images/simple3-frame.png b/src/AutoPilotPlugins/APM/Images/simple3-frame.png
new file mode 100644
index 00000000000..c7368a3e228
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/simple3-frame.png differ
diff --git a/src/AutoPilotPlugins/APM/Images/simple4-frame.png b/src/AutoPilotPlugins/APM/Images/simple4-frame.png
new file mode 100644
index 00000000000..793b36521c2
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/simple4-frame.png differ
diff --git a/src/AutoPilotPlugins/APM/Images/vectored-frame.png b/src/AutoPilotPlugins/APM/Images/vectored-frame.png
new file mode 100644
index 00000000000..aa1c3cf9edf
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/vectored-frame.png differ
diff --git a/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png b/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png
new file mode 100644
index 00000000000..c690be96964
Binary files /dev/null and b/src/AutoPilotPlugins/APM/Images/vectored6dof-frame.png differ
diff --git a/src/FirmwarePlugin/APM/APMResources.qrc b/src/FirmwarePlugin/APM/APMResources.qrc
index 9e0cb0c8beb..4ca53d7fc40 100644
--- a/src/FirmwarePlugin/APM/APMResources.qrc
+++ b/src/FirmwarePlugin/APM/APMResources.qrc
@@ -8,6 +8,8 @@
../../AutoPilotPlugins/APM/APMFlightModesComponentSummary.qml
../../AutoPilotPlugins/APM/APMLightsComponent.qml
../../AutoPilotPlugins/APM/APMLightsComponentSummary.qml
+ ../../AutoPilotPlugins/APM/APMSubFrameComponent.qml
+ ../../AutoPilotPlugins/APM/APMSubFrameComponentSummary.qml
../../AutoPilotPlugins/APM/APMNotSupported.qml
../../AutoPilotPlugins/APM/APMPowerComponent.qml
../../AutoPilotPlugins/APM/APMPowerComponentSummary.qml