地面站终端 App
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

438 lines
23 KiB

/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
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
/// This provides the smarts behind the guided mode commands, minus the user interface. This way you can change UI
/// without affecting the underlying functionality.
Item {
id: _root
property var missionController
property var confirmDialog
property var actionList
property var altitudeSlider
property var orbitMapCircle
readonly property string emergencyStopTitle: qsTr("EMERGENCY STOP")
readonly property string armTitle: qsTr("Arm")
readonly property string disarmTitle: qsTr("Disarm")
readonly property string rtlTitle: qsTr("Return")
readonly property string takeoffTitle: qsTr("Takeoff")
readonly property string landTitle: qsTr("Land")
readonly property string startMissionTitle: qsTr("Start Mission")
readonly property string mvStartMissionTitle: qsTr("Start Mission (MV)")
readonly property string continueMissionTitle: qsTr("Continue Mission")
readonly property string resumeMissionUploadFailTitle: qsTr("Resume FAILED")
readonly property string pauseTitle: qsTr("Pause")
readonly property string mvPauseTitle: qsTr("Pause (MV)")
readonly property string changeAltTitle: qsTr("Change Altitude")
readonly property string orbitTitle: qsTr("Orbit")
readonly property string landAbortTitle: qsTr("Land Abort")
readonly property string setWaypointTitle: qsTr("Set Waypoint")
readonly property string gotoTitle: qsTr("Go To Location")
readonly property string vtolTransitionTitle: qsTr("VTOL Transition")
readonly property string roiTitle: qsTr("ROI")
readonly property string armMessage: qsTr("Arm the vehicle.")
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 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")
readonly property string landMessage: qsTr("Land the vehicle at the current position.")
readonly property string rtlMessage: qsTr("Return to the launch position of the vehicle.")
readonly property string changeAltMessage: qsTr("Change the altitude of the vehicle up or down.")
readonly property string gotoMessage: qsTr("Move the vehicle to the specified location.")
property string setWaypointMessage: qsTr("Adjust current waypoint to %1.").arg(_actionData)
readonly property string orbitMessage: qsTr("Orbit the vehicle around the specified location.")
readonly property string landAbortMessage: qsTr("Abort the landing sequence.")
readonly property string pauseMessage: qsTr("Pause the vehicle at it's current position, adjusting altitude up or down as needed.")
readonly property string mvPauseMessage: qsTr("Pause all vehicles at their current position.")
readonly property string vtolTransitionFwdMessage: qsTr("Transition VTOL to fixed wing flight.")
readonly property string vtolTransitionMRMessage: qsTr("Transition VTOL to multi-rotor flight.")
readonly property string roiMessage: qsTr("Make the specified location a Region Of Interest.")
readonly property int actionRTL: 1
readonly property int actionLand: 2
readonly property int actionTakeoff: 3
readonly property int actionArm: 4
readonly property int actionDisarm: 5
readonly property int actionEmergencyStop: 6
readonly property int actionChangeAlt: 7
readonly property int actionGoto: 8
readonly property int actionSetWaypoint: 9
readonly property int actionOrbit: 10
readonly property int actionLandAbort: 11
readonly property int actionStartMission: 12
readonly property int actionContinueMission: 13
readonly property int actionResumeMission: 14
readonly property int _actionUnused: 15
readonly property int actionResumeMissionUploadFail: 16
readonly property int actionPause: 17
readonly property int actionMVPause: 18
readonly property int actionMVStartMission: 19
readonly property int actionVtolTransitionToFwdFlight: 20
readonly property int actionVtolTransitionToMRFlight: 21
readonly property int actionROI: 22
property bool showEmergenyStop: _guidedActionsEnabled && !_hideEmergenyStop && _vehicleArmed && _vehicleFlying
property bool showArm: _guidedActionsEnabled && !_vehicleArmed
property bool showDisarm: _guidedActionsEnabled && _vehicleArmed && !_vehicleFlying
property bool showRTL: _guidedActionsEnabled && _vehicleArmed && activeVehicle.guidedModeSupported && _vehicleFlying && !_vehicleInRTLMode
property bool showTakeoff: _guidedActionsEnabled && activeVehicle.takeoffVehicleSupported && !_vehicleFlying
property bool showLand: _guidedActionsEnabled && activeVehicle.guidedModeSupported && _vehicleArmed && !activeVehicle.fixedWing && !_vehicleInLandMode
property bool showStartMission: _guidedActionsEnabled && _missionAvailable && !_missionActive && !_vehicleFlying
property bool showContinueMission: _guidedActionsEnabled && _missionAvailable && !_missionActive && _vehicleArmed && _vehicleFlying && (_currentMissionIndex < _missionItemCount - 1)
property bool showPause: _guidedActionsEnabled && _vehicleArmed && activeVehicle.pauseVehicleSupported && _vehicleFlying && !_vehiclePaused && !_fixedWingOnApproach
property bool showChangeAlt: _guidedActionsEnabled && _vehicleFlying && activeVehicle.guidedModeSupported && _vehicleArmed && !_missionActive
property bool showOrbit: _guidedActionsEnabled && !_hideOrbit && _vehicleFlying && activeVehicle.orbitModeSupported && !_missionActive
property bool showROI: _guidedActionsEnabled && !_hideROI && _vehicleFlying && activeVehicle.roiModeSupported && !_missionActive
property bool showLandAbort: _guidedActionsEnabled && _vehicleFlying && _fixedWingOnApproach
property bool showGotoLocation: _guidedActionsEnabled && _vehicleFlying
// Note: The '_missionItemCount - 2' is a hack to not trigger resume mission when a mission ends with an RTL item
property bool showResumeMission: activeVehicle && !_vehicleArmed && _vehicleWasFlying && _missionAvailable && _resumeMissionIndex > 0 && (_resumeMissionIndex < _missionItemCount - 2)
property bool guidedUIVisible: guidedActionConfirm.visible || guidedActionList.visible
property var _corePlugin: QGroundControl.corePlugin
property bool _guidedActionsEnabled: (!ScreenTools.isDebug && QGroundControl.corePlugin.options.guidedActionsRequireRCRSSI && activeVehicle) ? _rcRSSIAvailable : activeVehicle
property string _flightMode: activeVehicle ? activeVehicle.flightMode : ""
property bool _missionAvailable: missionController.containsItems
property bool _missionActive: activeVehicle ? _vehicleArmed && (_vehicleInLandMode || _vehicleInRTLMode || _vehicleInMissionMode) : false
property bool _vehicleArmed: activeVehicle ? activeVehicle.armed : false
property bool _vehicleFlying: activeVehicle ? activeVehicle.flying : false
property bool _vehicleLanding: activeVehicle ? activeVehicle.landing : false
property bool _vehiclePaused: false
property bool _vehicleInMissionMode: false
property bool _vehicleInRTLMode: false
property bool _vehicleInLandMode: false
property int _missionItemCount: missionController.missionItemCount
property int _currentMissionIndex: missionController.currentMissionIndex
property int _resumeMissionIndex: missionController.resumeMissionIndex
property bool _hideEmergenyStop: !QGroundControl.corePlugin.options.guidedBarShowEmergencyStop
property bool _hideOrbit: !QGroundControl.corePlugin.options.guidedBarShowOrbit
property bool _hideROI: !QGroundControl.corePlugin.options.guidedBarShowOrbit
property bool _vehicleWasFlying: false
property bool _rcRSSIAvailable: activeVehicle ? activeVehicle.rcRSSI > 0 && activeVehicle.rcRSSI <= 100 : false
property bool _fixedWingOnApproach: activeVehicle ? activeVehicle.fixedWing && _vehicleLanding : false
// You can turn on log output for GuidedActionsController by turning on GuidedActionsControllerLog category
property bool __guidedModeSupported: activeVehicle ? activeVehicle.guidedModeSupported : false
property bool __pauseVehicleSupported: activeVehicle ? activeVehicle.pauseVehicleSupported : false
property bool __flightMode: _flightMode
function _outputState() {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log(qsTr("activeVehicle(%1) _vehicleArmed(%2) guidedModeSupported(%3) _vehicleFlying(%4) _vehicleWasFlying(%5) _vehicleInRTLMode(%6) pauseVehicleSupported(%7) _vehiclePaused(%8) _flightMode(%9) _missionItemCount(%10)").arg(activeVehicle ? 1 : 0).arg(_vehicleArmed ? 1 : 0).arg(__guidedModeSupported ? 1 : 0).arg(_vehicleFlying ? 1 : 0).arg(_vehicleWasFlying ? 1 : 0).arg(_vehicleInRTLMode ? 1 : 0).arg(__pauseVehicleSupported ? 1 : 0).arg(_vehiclePaused ? 1 : 0).arg(_flightMode).arg(_missionItemCount))
}
}
Connections {
target: mainWindow
onActiveVehicleChanged: {
_outputState()
}
}
Component.onCompleted: _outputState()
on_VehicleArmedChanged: _outputState()
on_VehicleInRTLModeChanged: _outputState()
on_VehiclePausedChanged: _outputState()
on__FlightModeChanged: _outputState()
on__GuidedModeSupportedChanged: _outputState()
on__PauseVehicleSupportedChanged: _outputState()
on_MissionItemCountChanged: _outputState()
on_CurrentMissionIndexChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("_currentMissionIndex", _currentMissionIndex)
}
}
on_ResumeMissionIndexChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("_resumeMissionIndex", _resumeMissionIndex)
}
}
onShowResumeMissionChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("showResumeMission", showResumeMission)
}
_outputState()
}
onShowStartMissionChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("showStartMission", showStartMission)
}
_outputState()
}
onShowContinueMissionChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("showContinueMission", showContinueMission)
}
_outputState()
}
onShowRTLChanged: {
if (_corePlugin.guidedActionsControllerLogging()) {
console.log("showRTL", showRTL)
}
_outputState()
}
// End of hack
on_VehicleFlyingChanged: {
_outputState()
if (!_vehicleFlying) {
// We use _vehicleWasFLying to help trigger Resume Mission only if the vehicle actually flew and came back down.
// Otherwise it may trigger during the Start Mission sequence due to signal ordering or armed and resume mission index.
_vehicleWasFlying = true
}
}
property var _actionData
on_FlightModeChanged: {
_vehiclePaused = activeVehicle ? _flightMode === activeVehicle.pauseFlightMode : false
_vehicleInRTLMode = activeVehicle ? _flightMode === activeVehicle.rtlFlightMode || _flightMode === activeVehicle.smartRTLFlightMode : false
_vehicleInLandMode = activeVehicle ? _flightMode === activeVehicle.landFlightMode : false
_vehicleInMissionMode = activeVehicle ? _flightMode === activeVehicle.missionFlightMode : false // Must be last to get correct signalling for showStartMission popups
}
// Called when an action is about to be executed in order to confirm
function confirmAction(actionCode, actionData, mapIndicator) {
var showImmediate = true
closeAll()
confirmDialog.action = actionCode
confirmDialog.actionData = actionData
confirmDialog.hideTrigger = true
confirmDialog.mapIndicator = mapIndicator
confirmDialog.optionText = ""
_actionData = actionData
switch (actionCode) {
case actionArm:
if (_vehicleFlying || !_guidedActionsEnabled) {
return
}
confirmDialog.title = armTitle
confirmDialog.message = armMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showArm })
break;
case actionDisarm:
if (_vehicleFlying) {
return
}
confirmDialog.title = disarmTitle
confirmDialog.message = disarmMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showDisarm })
break;
case actionEmergencyStop:
confirmDialog.title = emergencyStopTitle
confirmDialog.message = emergencyStopMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showEmergenyStop })
break;
case actionTakeoff:
confirmDialog.title = takeoffTitle
confirmDialog.message = takeoffMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showTakeoff })
altitudeSlider.setToMinimumTakeoff()
altitudeSlider.visible = true
break;
case actionStartMission:
showImmediate = false
confirmDialog.title = startMissionTitle
confirmDialog.message = startMissionMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showStartMission })
break;
case actionMVStartMission:
confirmDialog.title = mvStartMissionTitle
confirmDialog.message = startMissionMessage
confirmDialog.hideTrigger = true
break;
case actionContinueMission:
showImmediate = false
confirmDialog.title = continueMissionTitle
confirmDialog.message = continueMissionMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showContinueMission })
break;
case actionResumeMission:
// Resume Mission is handled in mission end dialog
return
case actionResumeMissionUploadFail:
confirmDialog.title = resumeMissionUploadFailTitle
confirmDialog.message = resumeMissionUploadFailMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showResumeMission })
break;
case actionLand:
confirmDialog.title = landTitle
confirmDialog.message = landMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showLand })
break;
case actionRTL:
confirmDialog.title = rtlTitle
confirmDialog.message = rtlMessage
if (activeVehicle.supportsSmartRTL) {
confirmDialog.optionText = qsTr("Smart RTL")
confirmDialog.optionChecked = false
}
confirmDialog.hideTrigger = Qt.binding(function() { return !showRTL })
break;
case actionChangeAlt:
confirmDialog.title = changeAltTitle
confirmDialog.message = changeAltMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showChangeAlt })
altitudeSlider.reset()
altitudeSlider.visible = true
break;
case actionGoto:
confirmDialog.title = gotoTitle
confirmDialog.message = gotoMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showGotoLocation })
break;
case actionSetWaypoint:
confirmDialog.title = setWaypointTitle
confirmDialog.message = setWaypointMessage
break;
case actionOrbit:
confirmDialog.title = orbitTitle
confirmDialog.message = orbitMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showOrbit })
altitudeSlider.reset()
altitudeSlider.visible = true
break;
case actionLandAbort:
confirmDialog.title = landAbortTitle
confirmDialog.message = landAbortMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showLandAbort })
break;
case actionPause:
confirmDialog.title = pauseTitle
confirmDialog.message = pauseMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showPause })
altitudeSlider.reset()
altitudeSlider.visible = true
break;
case actionMVPause:
confirmDialog.title = mvPauseTitle
confirmDialog.message = mvPauseMessage
confirmDialog.hideTrigger = true
break;
case actionVtolTransitionToFwdFlight:
confirmDialog.title = vtolTransitionTitle
confirmDialog.message = vtolTransitionFwdMessage
confirmDialog.hideTrigger = true
break
case actionVtolTransitionToMRFlight:
confirmDialog.title = vtolTransitionTitle
confirmDialog.message = vtolTransitionMRMessage
confirmDialog.hideTrigger = true
break
case actionROI:
confirmDialog.title = roiTitle
confirmDialog.message = roiMessage
confirmDialog.hideTrigger = Qt.binding(function() { return !showROI })
break;
default:
console.warn("Unknown actionCode", actionCode)
return
}
confirmDialog.show(showImmediate)
}
// Executes the specified action
function executeAction(actionCode, actionData, actionAltitudeChange, optionChecked) {
var i;
var rgVehicle;
switch (actionCode) {
case actionRTL:
activeVehicle.guidedModeRTL(optionChecked)
break
case actionLand:
activeVehicle.guidedModeLand()
break
case actionTakeoff:
activeVehicle.guidedModeTakeoff(actionAltitudeChange)
break
case actionResumeMission:
case actionResumeMissionUploadFail:
missionController.resumeMission(missionController.resumeMissionIndex)
break
case actionStartMission:
case actionContinueMission:
activeVehicle.startMission()
break
case actionMVStartMission:
rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (i = 0; i < rgVehicle.count; i++) {
rgVehicle.get(i).startMission()
}
break
case actionArm:
activeVehicle.armed = true
break
case actionDisarm:
activeVehicle.armed = false
break
case actionEmergencyStop:
activeVehicle.emergencyStop()
break
case actionChangeAlt:
activeVehicle.guidedModeChangeAltitude(actionAltitudeChange)
break
case actionGoto:
activeVehicle.guidedModeGotoLocation(actionData)
break
case actionSetWaypoint:
activeVehicle.setCurrentMissionSequence(actionData)
break
case actionOrbit:
activeVehicle.guidedModeOrbit(orbitMapCircle.center, orbitMapCircle.radius() * (orbitMapCircle.clockwiseRotation ? 1 : -1), activeVehicle.altitudeAMSL.rawValue + actionAltitudeChange)
break
case actionLandAbort:
activeVehicle.abortLanding(50) // hardcoded value for climbOutAltitude that is currently ignored
break
case actionPause:
activeVehicle.pauseVehicle()
activeVehicle.guidedModeChangeAltitude(actionAltitudeChange)
break
case actionMVPause:
rgVehicle = QGroundControl.multiVehicleManager.vehicles
for (i = 0; i < rgVehicle.count; i++) {
rgVehicle.get(i).pauseVehicle()
}
break
case actionVtolTransitionToFwdFlight:
activeVehicle.vtolInFwdFlight = true
break
case actionVtolTransitionToMRFlight:
activeVehicle.vtolInFwdFlight = false
break
case actionROI:
activeVehicle.guidedModeROI(actionData)
break
default:
console.warn(qsTr("Internal error: unknown actionCode"), actionCode)
break
}
}
}