| | |
| | | <template> |
| | | <div class="drone-control-wrapper"> |
| | | <div class="drone-control-header">无人机飞行控制</div> |
| | | <div class="drone-control-wrapper" v-if="modelValue"> |
| | | <div class="drone-control-header width-100 flex-display flex-align-center flex-justify-between"> |
| | | <span>无人机飞行控制</span> |
| | | <span @click="closeDrone"> |
| | | <CloseOutlined /> |
| | | </span> |
| | | </div> |
| | | <div class="drone-control-box"> |
| | | <div class="box"> |
| | | <div class="row"> |
| | |
| | | <template #formContent> |
| | | <div class="form-content"> |
| | | <div> |
| | | <span class="form-label">latitude:</span> |
| | | <span class="form-label">纬度:</span> |
| | | <a-input-number v-model:value="flyToPointPopoverData.latitude"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">longitude:</span> |
| | | <span class="form-label">经度:</span> |
| | | <a-input-number v-model:value="flyToPointPopoverData.longitude"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">height(m):</span> |
| | | <span class="form-label">高度(m):</span> |
| | | <a-input-number v-model:value="flyToPointPopoverData.height"/> |
| | | </div> |
| | | </div> |
| | |
| | | <template #formContent> |
| | | <div class="form-content"> |
| | | <div> |
| | | <span class="form-label">latitude:</span> |
| | | <span class="form-label">纬度:</span> |
| | | <a-input-number v-model:value="takeoffToPointPopoverData.latitude"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">longitude:</span> |
| | | <span class="form-label">经度:</span> |
| | | <a-input-number v-model:value="takeoffToPointPopoverData.longitude"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">height(m):</span> |
| | | <span class="form-label">高度(m):</span> |
| | | <a-input-number v-model:value="takeoffToPointPopoverData.height"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">Safe Takeoff Altitude(m):</span> |
| | | <span class="form-label">安全起飞高度(m):</span> |
| | | <a-input-number v-model:value="takeoffToPointPopoverData.securityTakeoffHeight"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">Return-to-Home Altitude(m):</span> |
| | | <span class="form-label">返回原点高度(m):</span> |
| | | <a-input-number v-model:value="takeoffToPointPopoverData.rthAltitude"/> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">Lost Action:</span> |
| | | <span class="form-label">失控操作:</span> |
| | | <a-select |
| | | v-model:value="takeoffToPointPopoverData.rcLostAction" |
| | | style="width: 120px" |
| | |
| | | ></a-select> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">Wayline Lost Action:</span> |
| | | <span class="form-label">线路丢失操作:</span> |
| | | <a-select |
| | | v-model:value="takeoffToPointPopoverData.exitWaylineWhenRcLost" |
| | | style="width: 120px" |
| | |
| | | </div> |
| | | </template> |
| | | <Button size="small" ghost @click="onShowTakeoffToPointPopover" > |
| | | <span>起飞</span> |
| | | <span>一键起飞</span> |
| | | </Button> |
| | | </DroneControlPopover> |
| | | <Button :loading="cmdItem.loading" size="small" ghost @click="sendControlCmd(cmdItem, 0)"> |
| | |
| | | <div class="row"> |
| | | <Select v-model:value="payloadSelectInfo.value" style="width: 110px; marginRight: 5px" :options="payloadSelectInfo.options" @change="handlePayloadChange"/> |
| | | <div class="drone-control"> |
| | | <Button type="primary" size="small" @click="onAuthPayload">有效载荷控制</Button> |
| | | <Button type="primary" size="small" @click="onAuthPayload">负载控制</Button> |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | |
| | | <template #formContent> |
| | | <div class="form-content"> |
| | | <div> |
| | | <span class="form-label">reset mode:</span> |
| | | <span class="form-label">重置模式:</span> |
| | | <a-select |
| | | v-model:value="gimbalResetPopoverData.resetMode" |
| | | style="width: 180px" |
| | |
| | | <template #formContent> |
| | | <div class="form-content"> |
| | | <div> |
| | | <span class="form-label">camera type:</span> |
| | | <span class="form-label">相机类型:</span> |
| | | <a-select |
| | | v-model:value="zoomFactorPopoverData.cameraType" |
| | | style="width: 120px" |
| | |
| | | ></a-select> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">zoom factor:</span> |
| | | <span class="form-label">缩放:</span> |
| | | <a-input-number v-model:value="zoomFactorPopoverData.zoomFactor" :min="2" :max="200" /> |
| | | </div> |
| | | </div> |
| | |
| | | <template #formContent> |
| | | <div class="form-content"> |
| | | <div> |
| | | <span class="form-label">camera type:</span> |
| | | <span class="form-label">相机类型:</span> |
| | | <a-select |
| | | v-model:value="cameraAimPopoverData.cameraType" |
| | | style="width: 120px" |
| | |
| | | ></a-select> |
| | | </div> |
| | | <div> |
| | | <span class="form-label">locked:</span> |
| | | <span class="form-label">锁定:</span> |
| | | <a-switch v-model:checked="cameraAimPopoverData.locked"/> |
| | | </div> |
| | | <div> |
| | |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { defineProps, reactive, ref, watch, computed, onMounted, watchEffect } from 'vue' |
| | | import { defineProps, reactive, ref, watch, computed, onMounted, watchEffect, defineEmits } from 'vue' |
| | | import { Select, message, Button } from 'ant-design-vue' |
| | | import { PayloadInfo, DeviceInfoType, ControlSource, DeviceOsdCamera, DrcStateEnum } from '/@/types/device' |
| | | import { useMyStore } from '/@/store' |
| | | import { postDrcEnter, postDrcExit } from '/@/api/drc' |
| | | import { useMqtt, DeviceTopicInfo } from './use-mqtt' |
| | | import { DownOutlined, UpOutlined, LeftOutlined, RightOutlined, PauseCircleOutlined, UndoOutlined, RedoOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons-vue' |
| | | import { DownOutlined, UpOutlined, LeftOutlined, RightOutlined, PauseCircleOutlined, UndoOutlined, RedoOutlined, ArrowUpOutlined, ArrowDownOutlined, CloseOutlined } from '@ant-design/icons-vue' |
| | | import { useManualControl, KeyCode } from './use-manual-control' |
| | | import { usePayloadControl } from './use-payload-control' |
| | | import { CameraMode, CameraType, CameraTypeOptions, ZoomCameraTypeOptions, CameraListItem } from '/@/types/live-stream' |
| | |
| | | const props = defineProps<{ |
| | | sn: string, |
| | | deviceInfo: DeviceInfoType, |
| | | payloads: null | PayloadInfo[] |
| | | payloads: null | PayloadInfo[], |
| | | modelValue: Boolean, |
| | | }>() |
| | | |
| | | const store = useMyStore() |
| | |
| | | |
| | | const initCmdList = baseCmdList.find(item => item.cmdKey === DeviceCmd.ReturnHome) as DeviceCmdItem |
| | | const cmdItem = ref(initCmdList) |
| | | console.log(cmdItem, 'cmdItem') |
| | | |
| | | const { |
| | | sendDockControlCmd |
| | |
| | | action: cmdItem.action |
| | | }, false) |
| | | if (result && flightController.value) { |
| | | message.success('Return home successful') |
| | | message.success('返航成功') |
| | | exitFlightCOntrol() |
| | | } else { |
| | | message.error('Failed to return home') |
| | | message.warn('请先进入控制!') |
| | | } |
| | | cmdItem.loading = false |
| | | } |
| | | |
| | | const emits = defineEmits(['update:modelValue']) |
| | | // 关闭弹窗 |
| | | const closeDrone = () => { |
| | | emits('update:modelValue', false) |
| | | } |
| | | const { flyToPoint, stopFlyToPoint, takeoffToPoint } = useDroneControl() |
| | | const MAX_SPEED = 14 |
| | | |
| | |
| | | async function onFlyToConfirm (confirm: boolean) { |
| | | if (confirm) { |
| | | if (!flyToPointPopoverData.height || !flyToPointPopoverData.latitude || !flyToPointPopoverData.longitude) { |
| | | message.error('Input error') |
| | | message.error('输入错误') |
| | | return |
| | | } |
| | | try { |
| | |
| | | const takeoffToPointPopoverData = reactive({ |
| | | visible: false, |
| | | loading: false, |
| | | latitude: null as null | number, |
| | | longitude: null as null | number, |
| | | height: null as null | number, |
| | | securityTakeoffHeight: null as null | number, |
| | | latitude: 28.62426114 as null | number, |
| | | longitude: 115.85657177 as null | number, |
| | | height: 120 as null | number, |
| | | securityTakeoffHeight: 100 as null | number, |
| | | maxSpeed: MAX_SPEED, |
| | | rthAltitude: null as null | number, |
| | | rthAltitude: 100 as null | number, |
| | | rcLostAction: LostControlActionInCommandFLight.RETURN_HOME, |
| | | exitWaylineWhenRcLost: WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION |
| | | }) |
| | |
| | | function onShowTakeoffToPointPopover () { |
| | | takeoffToPointPopoverData.visible = !takeoffToPointPopoverData.visible |
| | | takeoffToPointPopoverData.loading = false |
| | | takeoffToPointPopoverData.latitude = null |
| | | takeoffToPointPopoverData.longitude = null |
| | | takeoffToPointPopoverData.securityTakeoffHeight = null |
| | | takeoffToPointPopoverData.rthAltitude = null |
| | | takeoffToPointPopoverData.latitude = 28.62426114 |
| | | takeoffToPointPopoverData.longitude = 115.85657177 |
| | | takeoffToPointPopoverData.securityTakeoffHeight = 100 |
| | | takeoffToPointPopoverData.rthAltitude = 100 |
| | | takeoffToPointPopoverData.rcLostAction = LostControlActionInCommandFLight.RETURN_HOME |
| | | takeoffToPointPopoverData.exitWaylineWhenRcLost = WaylineLostControlActionInCommandFlight.EXEC_LOST_ACTION |
| | | } |
| | |
| | | !takeoffToPointPopoverData.longitude || |
| | | !takeoffToPointPopoverData.securityTakeoffHeight || |
| | | !takeoffToPointPopoverData.rthAltitude) { |
| | | message.error('Input error') |
| | | message.error('输入错误') |
| | | return |
| | | } |
| | | try { |
| | |
| | | } |
| | | enterFlightControl() |
| | | } |
| | | |
| | | // 进入飞行控制 |
| | | async function enterFlightControl () { |
| | | try { |
| | |
| | | if (droneControlSource.value !== ControlSource.A) { |
| | | await postFlightAuth(props.sn) |
| | | } |
| | | message.success('Get flight control successfully') |
| | | message.success('获取飞行控制成功') |
| | | } |
| | | } catch (error: any) { |
| | | } |
| | |
| | | flightController.value = false |
| | | deviceTopicInfo.subTopic = '' |
| | | deviceTopicInfo.pubTopic = '' |
| | | message.success('Exit flight control') |
| | | message.success('退出飞行控制成功') |
| | | } |
| | | } catch (error: any) { |
| | | } |
| | |
| | | async function onGimbalResetConfirm (confirm: boolean) { |
| | | if (confirm) { |
| | | if (gimbalResetPopoverData.resetMode === null) { |
| | | message.error('Please select reset mode') |
| | | message.error('请选择重置模式') |
| | | return |
| | | } |
| | | gimbalResetPopoverData.loading = true |
| | |
| | | async function onZoomFactorConfirm (confirm: boolean) { |
| | | if (confirm) { |
| | | if (!zoomFactorPopoverData.zoomFactor || zoomFactorPopoverData.cameraType === null) { |
| | | message.error('Please input Zoom Factor') |
| | | message.error('请输入缩放程度') |
| | | return |
| | | } |
| | | zoomFactorPopoverData.loading = true |
| | |
| | | async function onCameraAimConfirm (confirm: boolean) { |
| | | if (confirm) { |
| | | if (cameraAimPopoverData.cameraType === null || cameraAimPopoverData.x === null || cameraAimPopoverData.y === null) { |
| | | message.error('Input error') |
| | | message.error('输入错误') |
| | | return |
| | | } |
| | | try { |
| | |
| | | |
| | | <style lang='scss' scoped> |
| | | .drone-control-wrapper{ |
| | | // border-bottom: 1px solid #515151; |
| | | position: absolute; |
| | | background: #000; |
| | | color: #fff; |
| | | left: calc( 100% + 10px); |
| | | width: 480px; |
| | | top: 0; |
| | | |
| | | .drone-control-header{ |
| | | font-size: 14px; |