From 14e9b94b1bfad0086a7ee8e5830b44cd12535f3a Mon Sep 17 00:00:00 2001 From: DieBorr Date: Sun, 14 May 2023 12:30:08 +0200 Subject: [PATCH] Add Frontend UI for GripperAction Feature Now the user can release and grab the gripper while the UAV has motors armed with the action button and also while the motors are disarmed in a specific toolbar option. --- qgcresources.qrc | 3 + qgroundcontrol.qrc | 3 + resources/Gripper.svg | 20 ++++++ resources/GripperGrab.svg | 27 ++++++++ resources/GripperRelease.svg | 27 ++++++++ src/FlightDisplay/CMakeLists.txt | 2 + src/FlightDisplay/FlyView.qml | 1 + src/FlightDisplay/FlyViewToolStripActionList.qml | 3 +- src/FlightDisplay/FlyViewWidgetLayer.qml | 5 ++ src/FlightDisplay/GripperMenu.qml | 71 ++++++++++++++++++++++ src/FlightDisplay/GuidedActionGripper.qml | 24 ++++++++ src/FlightDisplay/GuidedActionList.qml | 6 ++ src/FlightDisplay/GuidedActionsController.qml | 15 +++++ src/QmlControls/QGCColumnButton.qml | 63 +++++++++++++++++++ src/QmlControls/QGroundControl/Controls/qmldir | 1 + .../QGroundControl/FlightDisplay/qmldir | 2 + 16 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 resources/Gripper.svg create mode 100644 resources/GripperGrab.svg create mode 100644 resources/GripperRelease.svg create mode 100644 src/FlightDisplay/GripperMenu.qml create mode 100644 src/FlightDisplay/GuidedActionGripper.qml create mode 100644 src/QmlControls/QGCColumnButton.qml diff --git a/qgcresources.qrc b/qgcresources.qrc index 3b4fb80..be6ac2c 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -55,6 +55,9 @@ resources/XDelete.svg resources/XDeleteBlack.svg resources/waypoint.svg + resources/Gripper.svg + resources/GripperRelease.svg + resources/GripperGrab.svg resources/icons/qgroundcontrol.ico diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 4eeb642..9d4aeae 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -132,6 +132,7 @@ src/QmlControls/PreFlightCheckGroup.qml src/QmlControls/PreFlightCheckModel.qml src/QmlControls/QGCButton.qml + src/QmlControls/QGCColumnButton.qml src/QmlControls/AutotuneUI.qml src/QmlControls/QGCCheckBox.qml src/QmlControls/QGCColoredImage.qml @@ -221,6 +222,8 @@ src/FlightDisplay/GuidedActionLand.qml src/FlightDisplay/GuidedActionList.qml src/FlightDisplay/GuidedActionTakeoff.qml + src/FlightDisplay/GuidedActionGripper.qml + src/FlightDisplay/GripperMenu.qml src/FlightDisplay/GuidedActionPause.qml src/FlightDisplay/GuidedActionRTL.qml src/FlightDisplay/GuidedValueSlider.qml diff --git a/resources/Gripper.svg b/resources/Gripper.svg new file mode 100644 index 0000000..fd4d69e --- /dev/null +++ b/resources/Gripper.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/GripperGrab.svg b/resources/GripperGrab.svg new file mode 100644 index 0000000..d375fb0 --- /dev/null +++ b/resources/GripperGrab.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/resources/GripperRelease.svg b/resources/GripperRelease.svg new file mode 100644 index 0000000..d0b4797 --- /dev/null +++ b/resources/GripperRelease.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/FlightDisplay/CMakeLists.txt b/src/FlightDisplay/CMakeLists.txt index b0920d2..89c1e48 100644 --- a/src/FlightDisplay/CMakeLists.txt +++ b/src/FlightDisplay/CMakeLists.txt @@ -26,6 +26,8 @@ add_custom_target(FligthDisplayQml GuidedActionRTL.qml GuidedActionsController.qml GuidedActionTakeoff.qml + GuidedActionGripper.qml + GripperMenu.qml GuidedValueSlider.qml GuidedToolStripAction.qml MultiRotorChecklist.qml diff --git a/src/FlightDisplay/FlyView.qml b/src/FlightDisplay/FlyView.qml index 77081f9..b70dea3 100644 --- a/src/FlightDisplay/FlyView.qml +++ b/src/FlightDisplay/FlyView.qml @@ -52,6 +52,7 @@ Item { property var _guidedController: guidedActionsController property var _guidedActionList: guidedActionList property var _guidedValueSlider: guidedValueSlider + property var _widgetLayer: widgetLayer property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75 property rect _centerViewport: Qt.rect(0, 0, width, height) property real _rightPanelWidth: ScreenTools.defaultFontPixelWidth * 30 diff --git a/src/FlightDisplay/FlyViewToolStripActionList.qml b/src/FlightDisplay/FlyViewToolStripActionList.qml index 451a482..331aaea 100644 --- a/src/FlightDisplay/FlyViewToolStripActionList.qml +++ b/src/FlightDisplay/FlyViewToolStripActionList.qml @@ -28,6 +28,7 @@ ToolStripActionList { GuidedActionLand { }, GuidedActionRTL { }, GuidedActionPause { }, - GuidedActionActionList { } + GuidedActionActionList { }, + GuidedActionGripper { } ] } diff --git a/src/FlightDisplay/FlyViewWidgetLayer.qml b/src/FlightDisplay/FlyViewWidgetLayer.qml index 86876a6..434d305 100644 --- a/src/FlightDisplay/FlyViewWidgetLayer.qml +++ b/src/FlightDisplay/FlyViewWidgetLayer.qml @@ -48,6 +48,7 @@ Item { property real _toolsMargin: ScreenTools.defaultFontPixelWidth * 0.75 property rect _centerViewport: Qt.rect(0, 0, width, height) property real _rightPanelWidth: ScreenTools.defaultFontPixelWidth * 30 + property alias _gripperMenu: gripperOptions QGCToolInsets { id: _totalToolInsets @@ -258,6 +259,10 @@ Item { property real leftInset: x + width } + GripperMenu { + id: gripperOptions + } + FlyViewAirspaceIndicator { anchors.top: parent.top anchors.topMargin: ScreenTools.defaultFontPixelHeight * 0.25 diff --git a/src/FlightDisplay/GripperMenu.qml b/src/FlightDisplay/GripperMenu.qml new file mode 100644 index 0000000..b1c863e --- /dev/null +++ b/src/FlightDisplay/GripperMenu.qml @@ -0,0 +1,71 @@ + +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Dialogs 1.2 +import QtLocation 5.3 +import QtPositioning 5.3 +import QtQuick.Layouts 1.2 + +import QGroundControl 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Vehicle 1.0 +import QGroundControl.FlightMap 1.0 + +Component { + id: messageDialogComponent + QGCPopupDialog { + title: "Select one action" + property var acceptFunction: null + buttons: StandardButton.Cancel + + onRejected:{ + _guidedController._gripperFunction = Vehicle.Invalid_option + _guidedController.closeAll() + close() + } + + onAccepted: { + if (acceptFunction) { + _guidedController._gripperFunction = Vehicle.Invalid_option + close() + } + } + + RowLayout { + QGCColumnButton { + id: grabButton + text: "Grab" + iconSource: "/res/GripperGrab.svg" + pointSize: ScreenTools.defaultFontPointSize * 3.5 + backRadius: width / 40 + heightFactor: 0.75 + Layout.preferredHeight: releaseButton.height + Layout.preferredWidth: releaseButton.width + + onClicked: { + _guidedController._gripperFunction = Vehicle.Gripper_grab + close() + } + } + + QGCColumnButton { + id: releaseButton + text: "Release" + iconSource: "/res/GripperRelease.svg" + pointSize: ScreenTools.defaultFontPointSize * 3.5 + backRadius: width / 40 + heightFactor: 0.75 + Layout.preferredWidth: ScreenTools.defaultFontPixelWidth * 27 + Layout.preferredHeight: Layout.preferredWidth / 1.20 + + onClicked: { + _guidedController._gripperFunction = Vehicle.Gripper_release + close() + } + } + } + } +} diff --git a/src/FlightDisplay/GuidedActionGripper.qml b/src/FlightDisplay/GuidedActionGripper.qml new file mode 100644 index 0000000..cddb3c4 --- /dev/null +++ b/src/FlightDisplay/GuidedActionGripper.qml @@ -0,0 +1,24 @@ +/**************************************************************************** + * + * (c) 2009-2020 QGROUNDCONTROL PROJECT + * + * QGroundControl is licensed according to the terms in the file + * COPYING.md in the root of the source code directory. + * + ****************************************************************************/ + +import QGroundControl.FlightDisplay 1.0 +import QGroundControl 1.0 + +GuidedToolStripAction { + property var activeVehicle: QGroundControl.multiVehicleManager.activeVehicle + property bool _initialConnectComplete: activeVehicle ? activeVehicle.initialConnectComplete : false + property bool _grip_enable: _initialConnectComplete ? activeVehicle.hasGripper : false + property bool _isVehicleArmed: _initialConnectComplete ? activeVehicle.armed : false + + text: "Gripper" + iconSource: "/res/Gripper.svg" + visible: !_isVehicleArmed && _grip_enable // in this way if the pilot it's on the ground can release the cargo without actions tool + enabled: _grip_enable + actionID: _guidedController.actionGripper +} diff --git a/src/FlightDisplay/GuidedActionList.qml b/src/FlightDisplay/GuidedActionList.qml index 035b887..6b494d7 100644 --- a/src/FlightDisplay/GuidedActionList.qml +++ b/src/FlightDisplay/GuidedActionList.qml @@ -69,6 +69,12 @@ Rectangle { text: guidedController.changeSpeedMessage, action: guidedController.actionChangeSpeed, visible: guidedController.showChangeSpeed + }, + { + title: guidedController.gripperTitle, + text: guidedController.gripperMessage, + action: guidedController.actionGripper, + visible: guidedController.showGripper } ] diff --git a/src/FlightDisplay/GuidedActionsController.qml b/src/FlightDisplay/GuidedActionsController.qml index 541e4b3..6f65023 100644 --- a/src/FlightDisplay/GuidedActionsController.qml +++ b/src/FlightDisplay/GuidedActionsController.qml @@ -39,6 +39,7 @@ Item { readonly property string disarmTitle: qsTr("Disarm") readonly property string rtlTitle: qsTr("Return") readonly property string takeoffTitle: qsTr("Takeoff") + readonly property string gripperTitle: qsTr("Gripper Function") readonly property string landTitle: qsTr("Land") readonly property string startMissionTitle: qsTr("Start Mission") readonly property string mvStartMissionTitle: qsTr("Start Mission (MV)") @@ -62,6 +63,7 @@ Item { readonly property string disarmMessage: qsTr("Disarm the vehicle") readonly property string emergencyStopMessage: qsTr("WARNING: THIS WILL STOP ALL MOTORS. IF VEHICLE IS CURRENTLY IN THE AIR IT WILL CRASH.") readonly property string takeoffMessage: qsTr("Takeoff from ground and hold position.") + readonly property string gripperMessage: qsTr("Grab or Release the cargo") readonly property string startMissionMessage: qsTr("Takeoff from ground and start the current mission.") readonly property string continueMissionMessage: qsTr("Continue the mission from the current waypoint.") readonly property string resumeMissionUploadFailMessage: qsTr("Upload of resume mission failed. Confirm to retry upload") @@ -105,6 +107,7 @@ Item { readonly property int actionActionList: 23 readonly property int actionForceArm: 24 readonly property int actionChangeSpeed: 25 + readonly property int actionGripper: 26 property var _activeVehicle: QGroundControl.multiVehicleManager.activeVehicle property bool _useChecklist: QGroundControl.settingsManager.appSettings.useChecklist.rawValue && QGroundControl.corePlugin.options.preFlightChecklistUrl.toString().length @@ -113,6 +116,7 @@ Item { property bool _canArm: _activeVehicle ? (_checklistPassed && (!_activeVehicle.healthAndArmingCheckReport.supported || _activeVehicle.healthAndArmingCheckReport.canArm)) : false property bool _canTakeoff: _activeVehicle ? (_checklistPassed && (!_activeVehicle.healthAndArmingCheckReport.supported || _activeVehicle.healthAndArmingCheckReport.canTakeoff)) : false property bool _canStartMission: _activeVehicle ? (_checklistPassed && (!_activeVehicle.healthAndArmingCheckReport.supported || _activeVehicle.healthAndArmingCheckReport.canStartMission)) : false + property bool _initialConnectComplete: _activeVehicle ? _activeVehicle.initialConnectComplete : false property bool showEmergenyStop: _guidedActionsEnabled && !_hideEmergenyStop && _vehicleArmed && _vehicleFlying property bool showArm: _guidedActionsEnabled && !_vehicleArmed && _canArm @@ -131,6 +135,7 @@ Item { property bool showLandAbort: _guidedActionsEnabled && _vehicleFlying && _fixedWingOnApproach property bool showGotoLocation: _guidedActionsEnabled && _vehicleFlying property bool showActionList: _guidedActionsEnabled && (showStartMission || showResumeMission || showChangeAlt || showLandAbort || actionList.hasCustomActions) + property bool showGripper: _initialConnectComplete ? _activeVehicle.hasGripper : false property string changeSpeedTitle: _fixedWing ? changeAirspeedTitle : changeCruiseSpeedTitle property string changeSpeedMessage: _fixedWing ? changeAirspeedMessage : changeCruiseSpeedMessage @@ -163,6 +168,7 @@ Item { property bool _fixedWingOnApproach: _activeVehicle ? _activeVehicle.fixedWing && _vehicleLanding : false property bool _fixedWing: _activeVehicle ? _activeVehicle.fixedWing || _activeVehicle.vtolInFwdFlight : false property bool _speedLimitsAvailable: _activeVehicle && ((_fixedWing && _activeVehicle.haveFWSpeedLimits) || (!_fixedWing && _activeVehicle.haveMRSpeedLimits)) + property var _gripperFunction: undefined // You can turn on log output for GuidedActionsController by turning on GuidedActionsControllerLog category property bool __guidedModeSupported: _activeVehicle ? _activeVehicle.guidedModeSupported : false @@ -496,6 +502,12 @@ Item { confirmDialog.message = changeSpeedMessage guidedValueSlider.visible = true break + case actionGripper: + confirmDialog.hideTrigger = true + confirmDialog.title = gripperTitle + confirmDialog.message = gripperMessage + _widgetLayer._gripperMenu.createObject(mainWindow).open() + break default: console.warn("Unknown actionCode", actionCode) return @@ -585,6 +597,9 @@ Item { } } break + case actionGripper: + _gripperFunction === undefined ? _activeVehicle.sendGripperAction(Vehicle.Invalid_option) : _activeVehicle.sendGripperAction(_gripperFunction) + break default: console.warn(qsTr("Internal error: unknown actionCode"), actionCode) break diff --git a/src/QmlControls/QGCColumnButton.qml b/src/QmlControls/QGCColumnButton.qml new file mode 100644 index 0000000..02721fb --- /dev/null +++ b/src/QmlControls/QGCColumnButton.qml @@ -0,0 +1,63 @@ +import QtQuick 2.5 +import QtQuick.Controls 2.12 +import QtQuick.Controls.Styles 1.4 +import QtQuick.Layouts 1.2 + +import QGroundControl.Palette 1.0 +import QGroundControl.ScreenTools 1.0 + +QGCButton { + id: control //This is a button rework from DonLakeFlyer's QGCButton that allows to contain a text and an Icon with a column look and the same capabilites + + background: Rectangle { + id: backRect + width: control.width + height: control.height + radius: backRadius + border.width: showBorder ? 1 : 0 + border.color: qgcPal.buttonText + color: _showHighlight ? + qgcPal.buttonHighlight : + (primary ? qgcPal.primaryButton : qgcPal.button) + } + + contentItem: Item { + id: contItem + implicitWidth: Math.max(textLabel.implicitWidth , icon.implicitWidth ) * 1.1 + implicitHeight: iconSource === "" ? textLabel.implicitHeight : textLabel.implicitHeight * 2.5 + ColumnLayout { + anchors.fill: parent + QGCColoredImage { + id: icon + Layout.fillWidth: true + Layout.fillHeight: true + Layout.maximumHeight: parent.height - textLabelContainer.height + Layout.alignment: control.text !== "" ? Qt.AlignTop : Qt.AlignHCenter | Qt.AlignVCenter + source: control.iconSource + color: qgcPal.text + fillMode: Image.PreserveAspectFit + sourceSize.height: height + sourceSize.width: width + visible: control.iconSource !== "" ? true : false + } + + Item { + id: textLabelContainer + Layout.alignment: icon.visible ? Qt.AlignBottom | Qt.AlignHCenter : Qt.AlignCenter + visible: control.text !== "" ? true : false + Layout.preferredWidth: parent.width + Layout.preferredHeight: textLabel.baselineOffset + QGCLabel { + id: textLabel + text: control.text + font.family: ScreenTools.normalFontFamily + font.pointSize: control.pointSize + color: _showHighlight ? qgcPal.buttonHighlightText : (primary ? qgcPal.primaryButtonText : qgcPal.buttonText) + anchors.baseline: iconSource !== "" ? parent.bottom : undefined + anchors.centerIn: iconSource === "" ? parent : undefined + anchors.horizontalCenter: parent.horizontalCenter + } + } + } + } +} diff --git a/src/QmlControls/QGroundControl/Controls/qmldir b/src/QmlControls/QGroundControl/Controls/qmldir index 75341ec..0ac432d 100644 --- a/src/QmlControls/QGroundControl/Controls/qmldir +++ b/src/QmlControls/QGroundControl/Controls/qmldir @@ -55,6 +55,7 @@ PreFlightCheckButton 1.0 PreFlightCheckButton.qml PreFlightCheckGroup 1.0 PreFlightCheckGroup.qml PreFlightCheckModel 1.0 PreFlightCheckModel.qml QGCButton 1.0 QGCButton.qml +QGCColumnButton 1.0 QGCColumnButton.qml AutotuneUI 1.0 AutotuneUI.qml QGCCheckBox 1.0 QGCCheckBox.qml QGCColoredImage 1.0 QGCColoredImage.qml diff --git a/src/QmlControls/QGroundControl/FlightDisplay/qmldir b/src/QmlControls/QGroundControl/FlightDisplay/qmldir index d6f6d62..12db3bc 100644 --- a/src/QmlControls/QGroundControl/FlightDisplay/qmldir +++ b/src/QmlControls/QGroundControl/FlightDisplay/qmldir @@ -21,6 +21,7 @@ GuidedActionPause 1.0 GuidedActionPause.qml GuidedActionRTL 1.0 GuidedActionRTL.qml GuidedValueSlider 1.0 GuidedValueSlider.qml GuidedActionTakeoff 1.0 GuidedActionTakeoff.qml +GuidedActionGripper 1.0 GuidedActionGripper.qml GuidedToolStripAction 1.0 GuidedToolStripAction.qml MultiVehicleList 1.0 MultiVehicleList.qml PreFlightBatteryCheck 1.0 PreFlightBatteryCheck.qml @@ -36,3 +37,4 @@ VehicleWarnings 1.0 VehicleWarnings.qml ObstacleDistanceOverlay 1.0 ObstacleDistanceOverlay.qml ObstacleDistanceOverlayMap 1.0 ObstacleDistanceOverlayMap.qml ObstacleDistanceOverlayVideo 1.0 ObstacleDistanceOverlayVideo.qml +GripperMenu 1.0 GripperMenu.qml