Commit 87c06bed authored by Don Gagne's avatar Don Gagne

Much better handling of missing facts

parent 5ae769a1
......@@ -635,7 +635,8 @@ SOURCES += \
# Fact System code
INCLUDEPATH += \
src/FactSystem
src/FactSystem \
src/FactSystem/FactControls \
HEADERS += \
src/FactSystem/Fact.h \
......@@ -644,6 +645,7 @@ HEADERS += \
src/FactSystem/FactSystem.h \
src/FactSystem/FactValidator.h \
src/FactSystem/ParameterLoader.h \
src/FactSystem/FactControls/FactPanelController.h \
SOURCES += \
src/FactSystem/Fact.cc \
......@@ -652,6 +654,7 @@ SOURCES += \
src/FactSystem/FactSystem.cc \
src/FactSystem/FactValidator.cc \
src/FactSystem/ParameterLoader.cc \
src/FactSystem/FactControls/FactPanelController.cc \
# Android
......
......@@ -9,6 +9,7 @@
<file alias="QmlTest.qml">src/QmlControls/QmlTest.qml</file>
<file alias="QGroundControl/FactControls/qmldir">src/FactSystem/FactControls/qmldir</file>
<file alias="QGroundControl/FactControls/FactPanel.qml">src/FactSystem/FactControls/FactPanel.qml</file>
<file alias="QGroundControl/FactControls/FactLabel.qml">src/FactSystem/FactControls/FactLabel.qml</file>
<file alias="QGroundControl/FactControls/FactTextField.qml">src/FactSystem/FactControls/FactTextField.qml</file>
<file alias="QGroundControl/FactControls/FactCheckBox.qml">src/FactSystem/FactControls/FactCheckBox.qml</file>
......
......@@ -31,125 +31,132 @@ import QGroundControl.Palette 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Controllers 1.0
Rectangle {
AirframeComponentController { id: controller }
QGCPalette { id: qgcPal; colorGroupEnabled: true }
FactPanel {
id: panel
color: qgcPal.window
AirframeComponentController { id: controller; factPanel: panel }
Column {
Rectangle {
anchors.fill: parent
QGCLabel {
text: "AIRFRAME CONFIG"
font.pointSize: 20
}
QGCPalette { id: qgcPal; colorGroupEnabled: true }
Item { height: 20; width: 10 } // spacer
color: qgcPal.window
Row {
width: parent.width
Column {
anchors.fill: parent
QGCLabel {
width: parent.width - applyButton.width
text: "Select you airframe type and specific vehicle bellow. Click 'Apply and Restart' when ready and your vehicle will be disconnected, rebooted to the new settings and re-connected."
wrapMode: Text.WordWrap
text: "AIRFRAME CONFIG"
font.pointSize: 20
}
QGCButton {
id: applyButton
text: "Apply and Restart"
onClicked: { controller.changeAutostart() }
}
}
Item { height: 20; width: 10 } // spacer
Item { height: 20; width: 10 } // spacer
Row {
width: parent.width
Flow {
width: parent.width
spacing: 10
QGCLabel {
width: parent.width - applyButton.width
text: "Select you airframe type and specific vehicle bellow. Click 'Apply and Restart' when ready and your vehicle will be disconnected, rebooted to the new settings and re-connected."
wrapMode: Text.WordWrap
}
ExclusiveGroup {
id: airframeTypeExclusive
QGCButton {
id: applyButton
text: "Apply and Restart"
onClicked: { controller.changeAutostart() }
}
}
Repeater {
model: controller.airframeTypes
Item { height: 20; width: 10 } // spacer
// Outer summary item rectangle
Rectangle {
readonly property real titleHeight: 30
readonly property real innerMargin: 10
Flow {
width: parent.width
spacing: 10
width: 250
height: 200
color: qgcPal.windowShade
ExclusiveGroup {
id: airframeTypeExclusive
}
Repeater {
model: controller.airframeTypes
// Outer summary item rectangle
Rectangle {
id: title
width: parent.width
height: parent.titleHeight
color: qgcPal.windowShadeDark
readonly property real titleHeight: 30
readonly property real innerMargin: 10
Text {
anchors.fill: parent
width: 250
height: 200
color: qgcPal.windowShade
color: qgcPal.buttonText
font.pixelSize: 12
text: modelData.name
Rectangle {
id: title
width: parent.width
height: parent.titleHeight
color: qgcPal.windowShadeDark
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
}
}
Text {
anchors.fill: parent
Image {
id: image
x: innerMargin
width: parent.width - (innerMargin * 2)
height: parent.height - title.height - combo.height - (innerMargin * 3)
anchors.topMargin: innerMargin
anchors.top: title.bottom
color: qgcPal.buttonText
font.pixelSize: 12
text: modelData.name
source: modelData.imageResource
fillMode: Image.PreserveAspectFit
smooth: true
verticalAlignment: TextEdit.AlignVCenter
horizontalAlignment: TextEdit.AlignHCenter
}
}
}
Image {
id: image
x: innerMargin
width: parent.width - (innerMargin * 2)
height: parent.height - title.height - combo.height - (innerMargin * 3)
anchors.topMargin: innerMargin
anchors.top: title.bottom
source: modelData.imageResource
fillMode: Image.PreserveAspectFit
smooth: true
QGCCheckBox {
id: airframeCheckBox
anchors.bottom: image.bottom
anchors.right: image.right
checked: modelData.name == controller.currentAirframeType
exclusiveGroup: airframeTypeExclusive
}
onCheckedChanged: {
if (checked && combo.currentIndex != -1) {
controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
QGCCheckBox {
id: airframeCheckBox
anchors.bottom: image.bottom
anchors.right: image.right
checked: modelData.name == controller.currentAirframeType
exclusiveGroup: airframeTypeExclusive
onCheckedChanged: {
if (checked && combo.currentIndex != -1) {
controller.autostartId = modelData.airframes[combo.currentIndex].autostartId
}
}
}
}
QGCComboBox {
id: combo
objectName: modelData.airframeType + "ComboBox"
x: innerMargin
anchors.topMargin: innerMargin
anchors.top: image.bottom
width: parent.width - (innerMargin * 2)
model: modelData.airframes
currentIndex: (modelData.name == controller.currentAirframeType) ? controller.currentVehicleIndex : 0
onCurrentIndexChanged: {
if (airframeCheckBox.checked) {
controller.autostartId = modelData.airframes[currentIndex].autostartId
QGCComboBox {
id: combo
objectName: modelData.airframeType + "ComboBox"
x: innerMargin
anchors.topMargin: innerMargin
anchors.top: image.bottom
width: parent.width - (innerMargin * 2)
model: modelData.airframes
currentIndex: (modelData.name == controller.currentAirframeType) ? controller.currentVehicleIndex : 0
onCurrentIndexChanged: {
if (airframeCheckBox.checked) {
controller.autostartId = modelData.airframes[currentIndex].autostartId
}
}
}
}
}
}
}
}
}
}
}
\ No newline at end of file
......@@ -37,19 +37,13 @@
bool AirframeComponentController::_typesRegistered = false;
AirframeComponentController::AirframeComponentController(QObject* parent) :
QObject(parent),
AirframeComponentController::AirframeComponentController(void) :
_uas(NULL),
_autoPilotPlugin(NULL),
_currentVehicleIndex(0),
_autostartId(0)
{
_uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(_uas);
_autoPilotPlugin = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(_uas);
Q_ASSERT(_autoPilotPlugin);
Q_ASSERT(_autoPilotPlugin->pluginReady());
if (!_typesRegistered) {
_typesRegistered = true;
......@@ -57,10 +51,16 @@ AirframeComponentController::AirframeComponentController(QObject* parent) :
qmlRegisterUncreatableType<Airframe>("QGroundControl.Controllers", 1, 0, "Aiframe", "Can only reference Airframe");
}
QStringList usedFacts;
usedFacts << "SYS_AUTOSTART" << "SYS_AUTOCONFIG";
if (!_allFactsExists(usedFacts)) {
return;
}
// Load up member variables
bool autostartFound = false;
_autostartId = _autoPilotPlugin->getParameterFact("SYS_AUTOSTART")->value().toInt();
_autostartId = _autopilot->getParameterFact("SYS_AUTOSTART")->value().toInt();
for (const AirframeComponentAirframes::AirframeType_t* pType=&AirframeComponentAirframes::rgAirframeTypes[0]; pType->name != NULL; pType++) {
AirframeType* airframeType = new AirframeType(pType->name, pType->imageResource, this);
......@@ -81,7 +81,7 @@ AirframeComponentController::AirframeComponentController(QObject* parent) :
_airframeTypes.append(QVariant::fromValue(airframeType));
}
if (_autostartId != 0) {
// FIXME: Should be a user error
Q_UNUSED(autostartFound);
......@@ -101,8 +101,8 @@ void AirframeComponentController::changeAutostart(void)
return;
}
_autoPilotPlugin->getParameterFact("SYS_AUTOSTART")->setValue(_autostartId);
_autoPilotPlugin->getParameterFact("SYS_AUTOCONFIG")->setValue(1);
_autopilot->getParameterFact("SYS_AUTOSTART")->setValue(_autostartId);
_autopilot->getParameterFact("SYS_AUTOCONFIG")->setValue(1);
qgcApp()->setOverrideCursor(Qt::WaitCursor);
......
......@@ -33,14 +33,15 @@
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
#include "FactPanelController.h"
/// MVC Controller for AirframeComponent.qml.
class AirframeComponentController : public QObject
class AirframeComponentController : public FactPanelController
{
Q_OBJECT
public:
AirframeComponentController(QObject* parent = NULL);
AirframeComponentController(void);
~AirframeComponentController();
Q_PROPERTY(QVariantList airframeTypes MEMBER _airframeTypes CONSTANT)
......@@ -63,7 +64,6 @@ private:
static bool _typesRegistered;
UASInterface* _uas;
AutoPilotPlugin* _autoPilotPlugin;
QVariantList _airframeTypes;
QString _currentAirframeType;
QString _currentVehicleName;
......
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Controllers 1.0
Column {
Fact { id: sysIdFact; name: "MAV_SYS_ID" }
Fact { id: sysAutoStartFact; name: "SYS_AUTOSTART" }
FactPanel {
id: panel
anchors.fill: parent
property bool autoStartSet: sysAutoStartFact.value != 0
AirframeComponentController { id: controller; factPanel: panel }
anchors.fill: parent
anchors.margins: 8
Fact { id: sysIdFact; name: "MAV_SYS_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: sysAutoStartFact; name: "SYS_AUTOSTART"; onFactMissing: showMissingFactOverlay(name) }
AirframeComponentController { id: controller }
property bool autoStartSet: sysAutoStartFact.value != 0
VehicleSummaryRow {
labelText: "System ID:"
valueText: sysIdFact.valueString
}
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Airframe type:"
valueText: autoStartSet ? controller.currentAirframeType : "Setup required"
}
VehicleSummaryRow {
labelText: "System ID:"
valueText: sysIdFact.valueString
}
VehicleSummaryRow {
labelText: "Airframe type:"
valueText: autoStartSet ? controller.currentAirframeType : "Setup required"
}
VehicleSummaryRow {
labelText: "Vehicle:"
valueText: autoStartSet ? controller.currentVehicleName : "Setup required"
VehicleSummaryRow {
labelText: "Vehicle:"
valueText: autoStartSet ? controller.currentVehicleName : "Setup required"
}
}
}
}
\ No newline at end of file
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
Column {
Fact { id: modeSwFact; name: "RC_MAP_MODE_SW" }
Fact { id: posCtlSwFact; name: "RC_MAP_POSCTL_SW" }
Fact { id: loiterSwFact; name: "RC_MAP_LOITER_SW" }
Fact { id: returnSwFact; name: "RC_MAP_RETURN_SW" }
FactPanel {
anchors.fill: parent
anchors.fill: parent
anchors.margins: 8
Fact { id: modeSwFact; name: "RC_MAP_MODE_SW"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: posCtlSwFact; name: "RC_MAP_POSCTL_SW"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: loiterSwFact; name: "RC_MAP_LOITER_SW"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: returnSwFact; name: "RC_MAP_RETURN_SW"; onFactMissing: showMissingFactOverlay(name) }
VehicleSummaryRow {
labelText: "Mode switch:"
valueText: modeSwFact.value == 0 ? "Setup required" : modeSwFact.valueString
}
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Position Ctl switch:"
valueText: posCtlSwFact.value == 0 ? "Disabled" : posCtlSwFact.valueString
}
VehicleSummaryRow {
labelText: "Mode switch:"
valueText: modeSwFact.value == 0 ? "Setup required" : modeSwFact.valueString
}
VehicleSummaryRow {
labelText: "Loiter switch:"
valueText: loiterSwFact.value == 0 ? "Disabled" : loiterSwFact.valueString
}
VehicleSummaryRow {
labelText: "Position Ctl switch:"
valueText: posCtlSwFact.value == 0 ? "Disabled" : posCtlSwFact.valueString
}
VehicleSummaryRow {
labelText: "Loiter switch:"
valueText: loiterSwFact.value == 0 ? "Disabled" : loiterSwFact.valueString
}
VehicleSummaryRow {
labelText: "Return switch:"
valueText: returnSwFact.value == 0 ? "Disabled" : returnSwFact.valueString
VehicleSummaryRow {
labelText: "Return switch:"
valueText: returnSwFact.value == 0 ? "Disabled" : returnSwFact.valueString
}
}
}
......@@ -27,32 +27,35 @@
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
Column {
Fact { id: batVChargedFact; name: "BAT_V_CHARGED" }
Fact { id: batVEmptyFact; name: "BAT_V_EMPTY" }
Fact { id: batCellsFact; name: "BAT_N_CELLS" }
FactPanel {
anchors.fill: parent
anchors.fill: parent
anchors.margins: 8
Fact { id: batVChargedFact; name: "BAT_V_CHARGED"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: batVEmptyFact; name: "BAT_V_EMPTY"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: batCellsFact; name: "BAT_N_CELLS"; onFactMissing: showMissingFactOverlay(name) }
VehicleSummaryRow {
labelText: "Battery Full:"
valueText: batVChargedFact.valueString
}
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Battery Empty:"
valueText: batVEmptyFact.valueString
}
VehicleSummaryRow {
labelText: "Battery Full:"
valueText: batVChargedFact.valueString
}
VehicleSummaryRow {
labelText: "Battery Empty:"
valueText: batVEmptyFact.valueString
}
VehicleSummaryRow {
labelText: "Number of Cells:"
valueText: batCellsFact.valueString
VehicleSummaryRow {
labelText: "Number of Cells:"
valueText: batCellsFact.valueString
}
}
}
}
\ No newline at end of file
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
Column {
Fact { id: mapRollFact; name: "RC_MAP_ROLL" }
Fact { id: mapPitchFact; name: "RC_MAP_PITCH" }
Fact { id: mapYawFact; name: "RC_MAP_YAW" }
Fact { id: mapThrottleFact; name: "RC_MAP_THROTTLE" }
Fact { id: mapFlapsFact; name: "RC_MAP_FLAPS" }
Fact { id: mapAux1Fact; name: "RC_MAP_AUX1" }
Fact { id: mapAux2Fact; name: "RC_MAP_AUX2" }
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Roll:"
valueText: mapRollFact.value == 0 ? "Setup required" : mapRollFact.valueString
}
VehicleSummaryRow {
labelText: "Pitch:"
valueText: mapPitchFact.value == 0 ? "Setup required" : mapPitchFact.valueString
}
VehicleSummaryRow {
labelText: "Yaw:"
valueText: mapYawFact.value == 0 ? "Setup required" : mapYawFact.valueString
}
VehicleSummaryRow {
labelText: "Throttle:"
valueText: mapThrottleFact.value == 0 ? "Setup required" : mapThrottleFact.valueString
}
VehicleSummaryRow {
labelText: "Flaps:"
valueText: mapFlapsFact.value == 0 ? "Disabled" : mapFlapsFact.valueString
}
VehicleSummaryRow {
labelText: "Aux1:"
valueText: mapAux1Fact.value == 0 ? "Disabled" : mapAux1Fact.valueString
}
VehicleSummaryRow {
labelText: "Aux2:"
valueText: mapAux2Fact.value == 0 ? "Disabled" : mapAux2Fact.valueString
FactPanel {
anchors.fill: parent
Fact { id: mapRollFact; name: "RC_MAP_ROLL"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapPitchFact; name: "RC_MAP_PITCH"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapYawFact; name: "RC_MAP_YAW"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapThrottleFact; name: "RC_MAP_THROTTLE"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapFlapsFact; name: "RC_MAP_FLAPS"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapAux1Fact; name: "RC_MAP_AUX1"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: mapAux2Fact; name: "RC_MAP_AUX2"; onFactMissing: showMissingFactOverlay(name) }
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Roll:"
valueText: mapRollFact.value == 0 ? "Setup required" : mapRollFact.valueString
}
VehicleSummaryRow {
labelText: "Pitch:"
valueText: mapPitchFact.value == 0 ? "Setup required" : mapPitchFact.valueString
}
VehicleSummaryRow {
labelText: "Yaw:"
valueText: mapYawFact.value == 0 ? "Setup required" : mapYawFact.valueString
}
VehicleSummaryRow {
labelText: "Throttle:"
valueText: mapThrottleFact.value == 0 ? "Setup required" : mapThrottleFact.valueString
}
VehicleSummaryRow {
labelText: "Flaps:"
valueText: mapFlapsFact.value == 0 ? "Disabled" : mapFlapsFact.valueString
}
VehicleSummaryRow {
labelText: "Aux1:"
valueText: mapAux1Fact.value == 0 ? "Disabled" : mapAux1Fact.valueString
}
VehicleSummaryRow {
labelText: "Aux2:"
valueText: mapAux2Fact.value == 0 ? "Disabled" : mapAux2Fact.valueString
}
}
}
import QtQuick 2.2
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QGroundControl.FactSystem 1.0
import QGroundControl.FactControls 1.0
import QGroundControl.Controls 1.0
Column {
Fact { id: returnAltFact; name: "RTL_RETURN_ALT" }
Fact { id: descendAltFact; name: "RTL_DESCEND_ALT" }
Fact { id: landDelayFact; name: "RTL_LAND_DELAY" }
Fact { id: commDLLossFact; name: "COM_DL_LOSS_EN" }
Fact { id: commRCLossFact; name: "COM_RC_LOSS_T" }
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "RTL min alt:"
valueText: returnAltFact.valueString
}
VehicleSummaryRow {
labelText: "RTL home alt:"
valueText: descendAltFact.valueString
}
VehicleSummaryRow {
labelText: "RTL loiter delay:"
valueText: landDelayFact.value < 0 ? "Disabled" : landDelayFact.valueString
}
VehicleSummaryRow {
labelText: "Telemetry loss RTL:"
valueText: commDLLossFact.value != -1 ? "Disabled" : commDLLossFact.valueString
}
VehicleSummaryRow {
labelText: "RC loss RTL (seconds):"
valueText: commRCLossFact.valueString
FactPanel {
anchors.fill: parent
Fact { id: returnAltFact; name: "RTL_RETURN_ALT"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: descendAltFact; name: "RTL_DESCEND_ALT"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: landDelayFact; name: "RTL_LAND_DELAY"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: commDLLossFact; name: "COM_DL_LOSS_EN"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: commRCLossFact; name: "COM_RC_LOSS_T"; onFactMissing: showMissingFactOverlay(name) }
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "RTL min alt:"
valueText: returnAltFact.valueString
}
VehicleSummaryRow {
labelText: "RTL home alt:"
valueText: descendAltFact.valueString
}
VehicleSummaryRow {
labelText: "RTL loiter delay:"
valueText: landDelayFact.value < 0 ? "Disabled" : landDelayFact.valueString
}