From e666acf924aa1c83518d8d3251d3dea48690cc8d Mon Sep 17 00:00:00 2001 From: Gus Grubba Date: Fri, 7 Feb 2020 13:49:25 -0500 Subject: [PATCH] Bringing preflight checklist to mainline QGC --- qgroundcontrol.qrc | 9 ++ src/FlightDisplay/DefaultChecklist.qml | 92 +++++++++++++ src/FlightDisplay/FixedWingChecklist.qml | 92 +++++++++++++ src/FlightDisplay/MultiRotorChecklist.qml | 87 +++++++++++++ src/FlightDisplay/PreFlightCheckList.qml | 149 ++++++++++++++++++++++ src/FlightDisplay/RoverChecklist.qml | 81 ++++++++++++ src/FlightDisplay/SubChecklist.qml | 82 ++++++++++++ src/FlightDisplay/VTOLChecklist.qml | 119 +++++++++++++++++ src/api/QGCOptions.h | 4 +- 9 files changed, 713 insertions(+), 2 deletions(-) create mode 100644 src/FlightDisplay/DefaultChecklist.qml create mode 100644 src/FlightDisplay/FixedWingChecklist.qml create mode 100644 src/FlightDisplay/MultiRotorChecklist.qml create mode 100644 src/FlightDisplay/PreFlightCheckList.qml create mode 100644 src/FlightDisplay/RoverChecklist.qml create mode 100644 src/FlightDisplay/SubChecklist.qml create mode 100644 src/FlightDisplay/VTOLChecklist.qml diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 4234f1b44..181621741 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -19,6 +19,14 @@ src/ui/toolbar/TelemetryRSSIIndicator.qml src/ui/toolbar/VTOLModeIndicator.qml + + src/FlightDisplay/DefaultChecklist.qml + src/FlightDisplay/MultiRotorChecklist.qml + src/FlightDisplay/FixedWingChecklist.qml + src/FlightDisplay/VTOLChecklist.qml + src/FlightDisplay/RoverChecklist.qml + src/FlightDisplay/SubChecklist.qml + src/QmlControls/HeightIndicator.qml src/QmlControls/QGCDynamicObjectManager.qml @@ -65,6 +73,7 @@ src/PlanView/PlanToolBar.qml src/PlanView/PlanToolBarIndicators.qml src/PlanView/PlanView.qml + src/FlightDisplay/PreFlightCheckList.qml src/VehicleSetup/PX4FlowSensor.qml src/FlightMap/Widgets/QGCInstrumentWidget.qml src/FlightMap/Widgets/QGCInstrumentWidgetAlternate.qml diff --git a/src/FlightDisplay/DefaultChecklist.qml b/src/FlightDisplay/DefaultChecklist.qml new file mode 100644 index 000000000..47ff95d15 --- /dev/null +++ b/src/FlightDisplay/DefaultChecklist.qml @@ -0,0 +1,92 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("Generic Initial checks") + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("Props mounted? Wings secured? Tail secured?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Actuators") + manualText: qsTr("Move all control surfaces. Did they work properly?") + } + + PreFlightCheckButton { + name: qsTr("Motors") + manualText: qsTr("Propellers free? Then throttle up gently. Working properly?") + } + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + PreFlightCheckButton { + name: qsTr("Wind & weather") + manualText: qsTr("OK for your platform? Lauching into the wind?") + } + + PreFlightCheckButton { + name: qsTr("Flight area") + manualText: qsTr("Launch area and path free of obstacles/people?") + } + } + } +} + diff --git a/src/FlightDisplay/FixedWingChecklist.qml b/src/FlightDisplay/FixedWingChecklist.qml new file mode 100644 index 000000000..895df23cf --- /dev/null +++ b/src/FlightDisplay/FixedWingChecklist.qml @@ -0,0 +1,92 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("Fixed Wing Initial Checks") + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("Props mounted? Wings secured? Tail secured?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Actuators") + manualText: qsTr("Move all control surfaces. Did they work properly?") + } + + PreFlightCheckButton { + name: qsTr("Motors") + manualText: qsTr("Propellers free? Then throttle up gently. Working properly?") + } + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + PreFlightCheckButton { + name: qsTr("Wind & weather") + manualText: qsTr("OK for your platform? Lauching into the wind?") + } + + PreFlightCheckButton { + name: qsTr("Flight area") + manualText: qsTr("Launch area and path free of obstacles/people?") + } + } + } +} + diff --git a/src/FlightDisplay/MultiRotorChecklist.qml b/src/FlightDisplay/MultiRotorChecklist.qml new file mode 100644 index 000000000..6968e53c9 --- /dev/null +++ b/src/FlightDisplay/MultiRotorChecklist.qml @@ -0,0 +1,87 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("Multirotor Initial Checks") + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("Props mounted and secured?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Motors") + manualText: qsTr("Propellers free? Then throttle up gently. Working properly?") + } + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + PreFlightCheckButton { + name: qsTr("Wind & weather") + manualText: qsTr("OK for your platform?") + } + + PreFlightCheckButton { + name: qsTr("Flight area") + manualText: qsTr("Launch area and path free of obstacles/people?") + } + } + } +} + diff --git a/src/FlightDisplay/PreFlightCheckList.qml b/src/FlightDisplay/PreFlightCheckList.qml new file mode 100644 index 000000000..04b783a84 --- /dev/null +++ b/src/FlightDisplay/PreFlightCheckList.qml @@ -0,0 +1,149 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Rectangle { + width: mainColumn.width + ScreenTools.defaultFontPixelWidth * 3 + height: mainColumn.height + ScreenTools.defaultFontPixelHeight + color: qgcPal.windowShade + radius: 3 + + Loader { + id: modelContainer + source: "/checklists/DefaultChecklist.qml" + } + + property bool _passed: false + + function _handleGroupPassedChanged(index, passed) { + if (passed) { + // Collapse current group + var group = checkListRepeater.itemAt(index) + group._checked = false + // Expand next group + if (index + 1 < checkListRepeater.count) { + group = checkListRepeater.itemAt(index + 1) + group.enabled = true + group._checked = true + } + } + _passed = passed + } + + //-- Pick a checklist model that matches the current airframe type (if any) + function _updateModel() { + if(activeVehicle) { + if(activeVehicle.multiRotor) { + modelContainer.source = "/checklists/MultiRotorChecklist.qml" + } else if(activeVehicle.vtol) { + modelContainer.source = "/checklists/VTOLChecklist.qml" + } else if(activeVehicle.rover) { + modelContainer.source = "/checklists/RoverChecklist.qml" + } else if(activeVehicle.sub) { + modelContainer.source = "/checklists/SubChecklist.qml" + } else if(activeVehicle.fixedWing) { + modelContainer.source = "/checklists/FixedWingChecklist.qml" + } else { + modelContainer.source = "/checklists/DefaultChecklist.qml" + } + return + } + modelContainer.source = "/checklists/DefaultChecklist.qml" + } + + Component.onCompleted: { + _updateModel() + } + + onVisibleChanged: { + if(activeVehicle) { + if(visible) { + _updateModel() + } else { + if(modelContainer.item.model.isPassed()) { + activeVehicle.checkListState = Vehicle.CheckListPassed + } else { + activeVehicle.checkListState = Vehicle.CheckListFailed + } + } + } + } + + // We delay the updates when a group passes so the user can see all items green for a moment prior to hiding + Timer { + id: delayedGroupPassed + interval: 750 + + property int index + + onTriggered: _handleGroupPassedChanged(index, true /* passed */) + } + + Column { + id: mainColumn + width: 40 * ScreenTools.defaultFontPixelWidth + spacing: 0.8 * ScreenTools.defaultFontPixelWidth + anchors.left: parent.left + anchors.top: parent.top + anchors.topMargin: 0.6 * ScreenTools.defaultFontPixelWidth + anchors.leftMargin: 1.5 * ScreenTools.defaultFontPixelWidth + + function groupPassedChanged(index, passed) { + if (passed) { + delayedGroupPassed.index = index + delayedGroupPassed.restart() + } else { + _handleGroupPassedChanged(index, passed) + } + } + + // Header/title of checklist + Item { + width: parent.width + height: 1.75 * ScreenTools.defaultFontPixelHeight + + QGCLabel { + text: qsTr("Pre-Flight Checklist %1").arg(_passed ? qsTr("(passed)") : "") + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + font.pointSize: ScreenTools.mediumFontPointSize + } + QGCButton { + width: 1.2 * ScreenTools.defaultFontPixelHeight + height: 1.2 * ScreenTools.defaultFontPixelHeight + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + tooltip: qsTr("Reset the checklist (e.g. after a vehicle reboot)") + + onClicked: checkListRepeater.model.reset() + + QGCColoredImage { + source: "/qmlimages/MapSyncBlack.svg" + color: qgcPal.buttonText + anchors.fill: parent + } + } + } + + // All check list items + Repeater { + id: checkListRepeater + model: modelContainer.item.model + } + } +} diff --git a/src/FlightDisplay/RoverChecklist.qml b/src/FlightDisplay/RoverChecklist.qml new file mode 100644 index 000000000..a17fbc4f9 --- /dev/null +++ b/src/FlightDisplay/RoverChecklist.qml @@ -0,0 +1,81 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("Rover Initial Checks") + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("Battery mounted and secured?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + PreFlightCheckButton { + name: qsTr("Wind & weather") + manualText: qsTr("OK for your platform?") + } + + PreFlightCheckButton { + name: qsTr("Mission area") + manualText: qsTr("Mission area and path free of obstacles/people?") + } + } + } +} diff --git a/src/FlightDisplay/SubChecklist.qml b/src/FlightDisplay/SubChecklist.qml new file mode 100644 index 000000000..b777baf27 --- /dev/null +++ b/src/FlightDisplay/SubChecklist.qml @@ -0,0 +1,82 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("Submarine Initial checks") + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("All seals in place?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Actuators") + manualText: qsTr("Move all control surfaces. Did they work properly?") + } + + PreFlightCheckButton { + name: qsTr("Motors") + manualText: qsTr("Propellers free? Then throttle up gently. Working properly?") + } + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + } + } +} diff --git a/src/FlightDisplay/VTOLChecklist.qml b/src/FlightDisplay/VTOLChecklist.qml new file mode 100644 index 000000000..40aa5ace4 --- /dev/null +++ b/src/FlightDisplay/VTOLChecklist.qml @@ -0,0 +1,119 @@ +/**************************************************************************** + * + * (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.11 +import QtQuick.Controls 2.4 +import QtQml.Models 2.1 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.FlightDisplay 1.0 +import QGroundControl.Vehicle 1.0 + +import CustomQuickInterface 1.0 + +Item { + property var model: listModel + PreFlightCheckModel { + id: listModel + PreFlightCheckGroup { + name: qsTr("VTOL Initial Checks") + + // Standard check list items (group 0) - Available from the start + Rectangle { + width: ScreenTools.defaultFontPixelWidth * 40 + height: testFlight.height + ScreenTools.defaultFontPixelHeight + color: qgcPal.button + property bool passed: true + function reset() { + if(activeVehicle) { + CustomQuickInterface.testFlight = false + activeVehicle.checkListState = Vehicle.CheckListNotSetup + } + } + QGCCheckBox { + id: testFlight + text: "Test Flight" + enabled: !CustomQuickInterface.debugBuild + checked: CustomQuickInterface.testFlight + anchors.centerIn: parent + onClicked: CustomQuickInterface.testFlight = checked + Component.onCompleted: { + CustomQuickInterface.testFlight = false + } + } + } + + PreFlightCheckButton { + name: qsTr("Hardware") + manualText: qsTr("Props mounted? Wings secured? Tail secured?") + } + + PreFlightBatteryCheck { + failurePercent: 40 + allowFailurePercentOverride: false + } + + PreFlightSensorsHealthCheck { + } + + PreFlightGPSCheck { + failureSatCount: 9 + allowOverrideSatCount: true + } + + PreFlightRCCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Please arm the vehicle here") + + PreFlightCheckButton { + name: qsTr("Actuators") + manualText: qsTr("Move all control surfaces. Did they work properly?") + } + + PreFlightCheckButton { + name: qsTr("Motors") + manualText: qsTr("Propellers free? Then throttle up gently. Working properly?") + } + + PreFlightCheckButton { + name: qsTr("Mission") + manualText: qsTr("Please confirm mission is valid (waypoints valid, no terrain collision).") + } + + PreFlightSoundCheck { + } + } + + PreFlightCheckGroup { + name: qsTr("Last preparations before launch") + + // Check list item group 2 - Final checks before launch + PreFlightCheckButton { + name: qsTr("Payload") + manualText: qsTr("Configured and started? Payload lid closed?") + } + + PreFlightCheckButton { + name: "Wind & weather" + manualText: qsTr("OK for your platform? Lauching into the wind?") + } + + PreFlightCheckButton { + name: qsTr("Flight area") + manualText: qsTr("Launch area and path free of obstacles/people?") + } + } + } +} + diff --git a/src/api/QGCOptions.h b/src/api/QGCOptions.h index acd72f9cb..9099cdd6d 100644 --- a/src/api/QGCOptions.h +++ b/src/api/QGCOptions.h @@ -90,8 +90,8 @@ public: /// Allows access to the full fly view window virtual QUrl flyViewOverlay () const { return QUrl(); } - /// Provides an optional preflight checklist - virtual QUrl preFlightChecklistUrl () const { return QUrl(); } + /// Provides an optional, custom preflight checklist + virtual QUrl preFlightChecklistUrl () const { return QUrl::fromUserInput("qrc:/qml/PreFlightCheckList.qml"); } /// Allows replacing the Main toolbar virtual QUrl mainToolbarUrl () const; -- 2.22.0