Browse Source

Merge pull request #1537 from DonLakeFlyer/MissingFacts

Much better handling of missing parameters
QGC4.4
Don Gagne 10 years ago
parent
commit
3520241ef8
  1. 5
      QGCApplication.pro
  2. 1
      qgroundcontrol.qrc
  3. 177
      src/AutoPilotPlugins/PX4/AirframeComponent.qml
  4. 22
      src/AutoPilotPlugins/PX4/AirframeComponentController.cc
  5. 6
      src/AutoPilotPlugins/PX4/AirframeComponentController.h
  6. 44
      src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml
  7. 50
      src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml
  8. 41
      src/AutoPilotPlugins/PX4/PowerComponentSummary.qml
  9. 96
      src/AutoPilotPlugins/PX4/RadioComponentSummary.qml
  10. 71
      src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml
  11. 41
      src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml
  12. 60
      src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml
  13. 5
      src/FactSystem/Fact.h
  14. 35
      src/FactSystem/FactBinder.cc
  15. 10
      src/FactSystem/FactBinder.h
  16. 61
      src/FactSystem/FactControls/FactPanel.qml
  17. 108
      src/FactSystem/FactControls/FactPanelController.cc
  18. 71
      src/FactSystem/FactControls/FactPanelController.h
  19. 1
      src/FactSystem/FactControls/qmldir
  20. 2
      src/FactSystem/FactSystem.cc
  21. 3
      src/FactSystem/ParameterLoader.cc
  22. 30
      src/QGCApplication.cc
  23. 14
      src/QGCApplication.h

5
QGCApplication.pro

@ -625,7 +625,8 @@ SOURCES += \ @@ -625,7 +625,8 @@ SOURCES += \
# Fact System code
INCLUDEPATH += \
src/FactSystem
src/FactSystem \
src/FactSystem/FactControls \
HEADERS += \
src/FactSystem/Fact.h \
@ -634,6 +635,7 @@ HEADERS += \ @@ -634,6 +635,7 @@ HEADERS += \
src/FactSystem/FactSystem.h \
src/FactSystem/FactValidator.h \
src/FactSystem/ParameterLoader.h \
src/FactSystem/FactControls/FactPanelController.h \
SOURCES += \
src/FactSystem/Fact.cc \
@ -642,6 +644,7 @@ SOURCES += \ @@ -642,6 +644,7 @@ SOURCES += \
src/FactSystem/FactSystem.cc \
src/FactSystem/FactValidator.cc \
src/FactSystem/ParameterLoader.cc \
src/FactSystem/FactControls/FactPanelController.cc \
# Android

1
qgroundcontrol.qrc

@ -9,6 +9,7 @@ @@ -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>

177
src/AutoPilotPlugins/PX4/AirframeComponent.qml

@ -31,125 +31,132 @@ import QGroundControl.Palette 1.0 @@ -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
}
}
}
}
}
}
}
}
}
}
}

22
src/AutoPilotPlugins/PX4/AirframeComponentController.cc

@ -37,19 +37,13 @@ @@ -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) : @@ -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) : @@ -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) @@ -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);

6
src/AutoPilotPlugins/PX4/AirframeComponentController.h

@ -33,14 +33,15 @@ @@ -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: @@ -63,7 +64,6 @@ private:
static bool _typesRegistered;
UASInterface* _uas;
AutoPilotPlugin* _autoPilotPlugin;
QVariantList _airframeTypes;
QString _currentAirframeType;
QString _currentVehicleName;

44
src/AutoPilotPlugins/PX4/AirframeComponentSummary.qml

@ -1,35 +1,39 @@ @@ -1,35 +1,39 @@
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"
}
}
}
}

50
src/AutoPilotPlugins/PX4/FlightModesComponentSummary.qml

@ -1,36 +1,40 @@ @@ -1,36 +1,40 @@
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
}
}
}

41
src/AutoPilotPlugins/PX4/PowerComponentSummary.qml

@ -27,32 +27,35 @@ @@ -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
}
}
}
}

96
src/AutoPilotPlugins/PX4/RadioComponentSummary.qml

@ -1,54 +1,58 @@ @@ -1,54 +1,58 @@
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
}
}
}

71
src/AutoPilotPlugins/PX4/SafetyComponentSummary.qml

@ -1,43 +1,46 @@ @@ -1,43 +1,46 @@
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
}
VehicleSummaryRow {
labelText: "Telemetry loss RTL:"
valueText: commDLLossFact.value != -1 ? "Disabled" : commDLLossFact.valueString
}
VehicleSummaryRow {
labelText: "RC loss RTL (seconds):"
valueText: commRCLossFact.valueString
}
}
}

41
src/AutoPilotPlugins/PX4/SensorsComponentSummary.qml

@ -3,32 +3,37 @@ import QtQuick.Controls 1.2 @@ -3,32 +3,37 @@ 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
/*
IMPORTANT NOTE: Any changes made here must also be made to SensorsComponentSummary.qml
*/
Column {
Fact { id: mag0IdFact; name: "CAL_MAG0_ID" }
Fact { id: gyro0IdFact; name: "CAL_GYRO0_ID" }
Fact { id: accel0IdFact; name: "CAL_ACC0_ID" }
FactPanel {
anchors.fill: parent
anchors.fill: parent
anchors.margins: 8
Fact { id: mag0IdFact; name: "CAL_MAG0_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: gyro0IdFact; name: "CAL_GYRO0_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: accel0IdFact; name: "CAL_ACC0_ID"; onFactMissing: showMissingFactOverlay(name) }
VehicleSummaryRow {
labelText: "Compass:"
valueText: mag0IdFact.value == 0 ? "Setup required" : "Ready"
}
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Gyro:"
valueText: gyro0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Compass:"
valueText: mag0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Gyro:"
valueText: gyro0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Accelerometer:"
valueText: accel0IdFact.value == 0 ? "Setup required" : "Ready"
VehicleSummaryRow {
labelText: "Accelerometer:"
valueText: accel0IdFact.value == 0 ? "Setup required" : "Ready"
}
}
}
}

60
src/AutoPilotPlugins/PX4/SensorsComponentSummaryFixedWing.qml

@ -1,40 +1,44 @@ @@ -1,40 +1,44 @@
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
/*
IMPORTANT NOTE: Any changes made here must also be made to SensorsComponentSummary.qml
*/
Column {
Fact { id: mag0IdFact; name: "CAL_MAG0_ID" }
Fact { id: gyro0IdFact; name: "CAL_GYRO0_ID" }
Fact { id: accel0IdFact; name: "CAL_ACC0_ID" }
Fact { id: dPressOffFact; name: "SENS_DPRES_OFF" }
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Compass:"
valueText: mag0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Gyro:"
valueText: gyro0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Accelerometer:"
valueText: accel0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Airspeed:"
valueText: dPressOffFact.value == 0 ? "Setup required" : "Ready"
FactPanel {
anchors.fill: parent
Fact { id: mag0IdFact; name: "CAL_MAG0_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: gyro0IdFact; name: "CAL_GYRO0_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: accel0IdFact; name: "CAL_ACC0_ID"; onFactMissing: showMissingFactOverlay(name) }
Fact { id: dPressOffFact; name: "SENS_DPRES_OFF"; onFactMissing: showMissingFactOverlay(name) }
Column {
anchors.fill: parent
anchors.margins: 8
VehicleSummaryRow {
labelText: "Compass:"
valueText: mag0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Gyro:"
valueText: gyro0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Accelerometer:"
valueText: accel0IdFact.value == 0 ? "Setup required" : "Ready"
}
VehicleSummaryRow {
labelText: "Airspeed:"
valueText: dPressOffFact.value == 0 ? "Setup required" : "Ready"
}
}
}

5
src/FactSystem/Fact.h

@ -35,16 +35,11 @@ @@ -35,16 +35,11 @@
#include <QDebug>
/// @brief A Fact is used to hold a single value within the system.
///
/// Along with the value property is a set of meta data which further describes the Fact. This information is
/// exposed through QObject Properties such that you can bind to it from QML as well as use it within C++ code.
/// Since the meta data is common to all instances of the same Fact, it is acually stored once in a seperate object.
class Fact : public QObject
{
Q_OBJECT
public:
//Fact(int componentId, QString name = "", FactMetaData::ValueType_t type = FactMetaData::valueTypeInt32, QObject* parent = NULL);
Fact(int componentId, QString name, FactMetaData::ValueType_t type, QObject* parent = NULL);
// Property system methods

35
src/FactSystem/FactBinder.cc

@ -34,7 +34,8 @@ @@ -34,7 +34,8 @@
FactBinder::FactBinder(void) :
_autopilotPlugin(NULL),
_fact(NULL),
_componentId(FactSystem::defaultComponentId)
_componentId(FactSystem::defaultComponentId),
_factMissingSignalConnected(false)
{
UASInterface* uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(uas);
@ -85,8 +86,12 @@ void FactBinder::setName(const QString& name) @@ -85,8 +86,12 @@ void FactBinder::setName(const QString& name)
emit nameChanged();
emit metaDataChanged();
} else {
QString panicMessage("Required parameter (component id: %1, name: %2), is missing from vehicle. QGroundControl cannot operate with this firmware revision. QGroundControl will now shut down.");
qgcApp()->panicShutdown(panicMessage.arg(_componentId).arg(parsedName));
qgcApp()->reportMissingFact(name);
if (_factMissingSignalConnected) {
emit factMissing(name);
} else {
_missedFactMissingSignals << name;
}
}
}
}
@ -208,3 +213,27 @@ bool FactBinder::valueEqualsDefault(void) @@ -208,3 +213,27 @@ bool FactBinder::valueEqualsDefault(void)
return false;
}
}
void FactBinder::connectNotify(const QMetaMethod & signal)
{
if (signal == QMetaMethod::fromSignal(&FactBinder::factMissing)) {
_factMissingSignalConnected = true;
if (_missedFactMissingSignals.count()) {
QTimer::singleShot(10, this, &FactBinder::_delayedFactMissing);
}
}
}
void FactBinder::disconnectNotify(const QMetaMethod & signal)
{
if (signal == QMetaMethod::fromSignal(&FactBinder::factMissing)) {
_factMissingSignalConnected = false;
}
}
void FactBinder::_delayedFactMissing(void)
{
foreach (QString name, _missedFactMissingSignals) {
emit factMissing(name);
}
}

10
src/FactSystem/FactBinder.h

@ -78,14 +78,24 @@ public: @@ -78,14 +78,24 @@ public:
QString group(void);
signals:
void factMissing(const QString& name);
void nameChanged(void);
void valueChanged(void);
void metaDataChanged(void);
private slots:
void _delayedFactMissing(void);
private:
// Overrides from QObject
void connectNotify(const QMetaMethod & signal);
void disconnectNotify(const QMetaMethod & signal);
AutoPilotPlugin* _autopilotPlugin;
Fact* _fact;
int _componentId;
bool _factMissingSignalConnected;
QStringList _missedFactMissingSignals;
};
#endif

61
src/FactSystem/FactControls/FactPanel.qml

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
/// @file
/// @author Don Gagne <don@thegagnes.com>
import QtQuick 2.3
import QtQuick.Controls 1.3
import QGroundControl.FactSystem 1.0
import QGroundControl.Controls 1.0
import QGroundControl.Palette 1.0
Item {
property string __missingFacts: ""
function showMissingFactOverlay(missingFactName) {
if (__missingFacts.length != 0) {
__missingFacts = __missingFacts.concat(", ")
}
__missingFacts = __missingFacts.concat(missingFactName)
__missingFactOverlay.visible = true
}
Rectangle {
QGCPalette { id: __qgcPal; colorGroupEnabled: true }
id: __missingFactOverlay
anchors.fill: parent
z: 9999
visible: false
color: __qgcPal.window
opacity: 0.85
QGCLabel {
anchors.fill: parent
wrapMode: Text.WordWrap
text: "Fact(s) missing: " + __missingFacts
}
}
}

108
src/FactSystem/FactControls/FactPanelController.cc

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "FactPanelController.h"
#include "UASManager.h"
#include "AutoPilotPluginManager.h"
#include "QGCMessageBox.h"
/// @file
/// @author Don Gagne <don@thegagnes.com>
FactPanelController::FactPanelController(void) :
_autopilot(NULL),
_factPanel(NULL)
{
UASInterface* uas = UASManager::instance()->getActiveUAS();
Q_ASSERT(uas);
_autopilot = AutoPilotPluginManager::instance()->getInstanceForAutoPilotPlugin(uas);
Q_ASSERT(_autopilot);
Q_ASSERT(_autopilot->pluginReady());
// Do a delayed check for the _factPanel finally being set correctly from Qml
QTimer::singleShot(1000, this, &FactPanelController::_checkForMissingFactPanel);
}
QQuickItem* FactPanelController::factPanel(void)
{
return _factPanel;
}
void FactPanelController::setFactPanel(QQuickItem* panel)
{
// Once we finally have the _factPanel member set send any
// missing fact notices that were waiting to go out
_factPanel = panel;
foreach (QString missingFact, _delayedMissingFacts) {
_notifyPanelMissingFact(missingFact);
}
_delayedMissingFacts.clear();
}
void FactPanelController::_notifyPanelMissingFact(const QString& missingFact)
{
QVariant returnedValue;
QMetaObject::invokeMethod(_factPanel,
"showMissingFactOverlay",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, missingFact));
}
void FactPanelController::_reportMissingFact(const QString& missingFact)
{
qgcApp()->reportMissingFact(missingFact);
// If missing facts a reported from the constructor of a derived class we
// will not have access to _factPanel yet. Just record list of missing facts
// in that case instead of notify. Once _factPanel is available they will be
// send out for real.
if (_factPanel) {
_notifyPanelMissingFact(missingFact);
} else {
_delayedMissingFacts += missingFact;
}
}
bool FactPanelController::_allFactsExists(QStringList factList)
{
bool noMissingFacts = true;
foreach (QString fact, factList) {
if (!_autopilot->parameterExists(fact)) {
_reportMissingFact(fact);
noMissingFacts = false;
}
}
return noMissingFacts;
}
void FactPanelController::_checkForMissingFactPanel(void)
{
if (!_factPanel) {
QGCMessageBox::critical("Incorrect FactPanel Qml implementation", "FactPanelController used without passing in factPanel. This could lead to non-functioning user interface being displayed.");
}
}

71
src/FactSystem/FactControls/FactPanelController.h

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef FactPanelController_H
#define FactPanelController_H
/// @file
/// @author Don Gagne <don@thegagnes.com>
#include <QObject>
#include <QQuickItem>
#include "UASInterface.h"
#include "AutoPilotPlugin.h"
#include "UASManagerInterface.h"
/// FactPanelController is used in combination with the FactPanel Qml control for handling
/// missing Facts from C++ code.
class FactPanelController : public QObject
{
Q_OBJECT
public:
FactPanelController(void);
Q_PROPERTY(QQuickItem* factPanel READ factPanel WRITE setFactPanel)
QQuickItem* factPanel(void);
void setFactPanel(QQuickItem* panel);
protected:
/// Checks for existence of the specified facts
/// @return true: all facts exists, false: facts missing and reported
bool _allFactsExists(QStringList factList);
/// Report a missing fact to the FactPanel Qml element
void _reportMissingFact(const QString& missingFact);
AutoPilotPlugin* _autopilot;
private slots:
void _checkForMissingFactPanel(void);
private:
void _notifyPanelMissingFact(const QString& missingFact);
QQuickItem* _factPanel;
QStringList _delayedMissingFacts;
};
#endif

1
src/FactSystem/FactControls/qmldir

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
Module QGroundControl.FactControls
FactPanel 1.0 FactPanel.qml
FactLabel 1.0 FactLabel.qml
FactTextField 1.0 FactTextField.qml
FactCheckBox 1.0 FactCheckBox.qml

2
src/FactSystem/FactSystem.cc

@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
#include "QGCApplication.h"
#include "VehicleComponent.h"
#include "FactBinder.h"
#include "FactPanelController.h"
#include <QtQml>
@ -40,6 +41,7 @@ FactSystem::FactSystem(QObject* parent) : @@ -40,6 +41,7 @@ FactSystem::FactSystem(QObject* parent) :
QGCSingleton(parent)
{
qmlRegisterType<FactBinder>(_factSystemQmlUri, 1, 0, "Fact");
qmlRegisterType<FactPanelController>(_factSystemQmlUri, 1, 0, "FactPanelController");
qmlRegisterUncreatableType<VehicleComponent>(_factSystemQmlUri, 1, 0, "VehicleComponent", "Can only reference, cannot create");
}

3
src/FactSystem/ParameterLoader.cc

@ -386,8 +386,7 @@ Fact* ParameterLoader::getFact(int componentId, const QString& name) @@ -386,8 +386,7 @@ Fact* ParameterLoader::getFact(int componentId, const QString& name)
componentId = _actualComponentId(componentId);
if (!_mapParameterName2Variant.contains(componentId) || !_mapParameterName2Variant[componentId].contains(name)) {
QString panicMessage("Required parameter (component id: %1, name: %2), is missing from vehicle. QGroundControl cannot operate with this firmware revision. QGroundControl will now shut down.");
qgcApp()->panicShutdown(panicMessage.arg(componentId).arg(name));
return NULL;
}
Fact* fact = _mapParameterName2Variant[componentId][name].value<Fact*>();

30
src/QGCApplication.cc

@ -180,6 +180,10 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) : @@ -180,6 +180,10 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) :
#endif
#endif
// Set up timer for delayed missing fact display
_missingFactDelayedDisplayTimer.setSingleShot(true);
_missingFactDelayedDisplayTimer.setInterval(_missingFactDelayedDisplayTimerTimeout);
connect(&_missingFactDelayedDisplayTimer, &QTimer::timeout, this, &QGCApplication::_missingFactsDisplay);
// Set application information
if (_runningUnitTests) {
@ -677,8 +681,28 @@ void QGCApplication::_reconnect(void) @@ -677,8 +681,28 @@ void QGCApplication::_reconnect(void)
_reconnectLinkConfig = NULL;
}
void QGCApplication::panicShutdown(const QString& panicMessage)
void QGCApplication::reportMissingFact(const QString& name)
{
QGCMessageBox::critical("Panic Shutdown", panicMessage);
::exit(0);
_missingFacts += name;
_missingFactDelayedDisplayTimer.start();
}
/// Called when the delay timer fires to show the missing facts warning
void QGCApplication::_missingFactsDisplay(void)
{
Q_ASSERT(_missingFacts.count());
QString facts;
foreach (QString fact, _missingFacts) {
if (facts.isEmpty()) {
facts += fact;
} else {
facts += QString(", %1").arg(fact);
}
}
_missingFacts.clear();
QGCMessageBox::critical("Missing Parameters",
QString("Parameters missing from firmware: %1.\n\n"
"You should quit QGroundControl immediately and update your firmware.").arg(facts));
}

14
src/QGCApplication.h

@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
#define QGCAPPLICATION_H
#include <QApplication>
#include <QTimer>
#include "LinkConfiguration.h"
@ -98,9 +99,9 @@ public: @@ -98,9 +99,9 @@ public:
/// Disconnects the current link and waits for the specified number of seconds before reconnecting.
void reconnectAfterWait(int waitSeconds);
/// Used to shutdown the app if a fatal condition occurs from which it cannot recover
/// @param panicMessage Message to display to user
void panicShutdown(const QString& panicMessage);
/// Used to report a missing Fact. Warning will be displayed to user. Method may be called
/// multiple times.
void reportMissingFact(const QString& name);
public slots:
/// You can connect to this slot to show an information message box from a different thread.
@ -143,6 +144,7 @@ public: @@ -143,6 +144,7 @@ public:
private slots:
void _reconnect(void);
void _missingFactsDisplay(void);
private:
void _createSingletons(void);
@ -165,7 +167,11 @@ private: @@ -165,7 +167,11 @@ private:
static const char* _lightStyleFile;
bool _styleIsDark; ///< true: dark style, false: light style
LinkConfiguration* _reconnectLinkConfig; ///< Configuration to reconnect for reconnectAfterWai
LinkConfiguration* _reconnectLinkConfig; ///< Configuration to reconnect for reconnectAfterWait
static const int _missingFactDelayedDisplayTimerTimeout = 1000; ///< Timeout to wait for next missing fact to come in before display
QTimer _missingFactDelayedDisplayTimer; ///< Timer use to delay missing fact display
QStringList _missingFacts; ///< List of missing facts to be displayed
/// Unit Test have access to creating and destroying singletons
friend class UnitTest;

Loading…
Cancel
Save