| | |
| | | </div> |
| | | |
| | | <div class="speed"> |
| | | <el-icon class="btnIcon" @click="speed = speed + 1"> |
| | | <el-icon class="btnIcon" @click="speed = speed === 15 ? 15 : speed + 1"> |
| | | <Plus /> |
| | | </el-icon> |
| | | <div> |
| | |
| | | <br /> |
| | | m/s |
| | | </div> |
| | | <el-icon class="btnIcon" @click="speed = speed - 1"> |
| | | <el-icon class="btnIcon" @click="speed = speed === 0 ? 0 : speed - 1"> |
| | | <Minus /> |
| | | </el-icon> |
| | | </div> |
| | |
| | | </div> |
| | | <!-- 指南针--> |
| | | <div class="compass"> |
| | | <ControlComPass /> |
| | | <ControlComPass :options="compassOptions" /> |
| | | </div> |
| | | |
| | | <div class="ptzControlBox"> |
| | |
| | | <div class="ptzControlBtnBox"> |
| | | <div class="ptzControlBtn b-r"> |
| | | <div |
| | | v-for="(item, index) in list5" |
| | | v-for="(item, index) in ptzBtns" |
| | | :style="item.style" |
| | | class="ptzControlItem" |
| | | @mousedown="onMouseDown(item.key)" |
| | |
| | | |
| | | <div |
| | | class="ptzControlItemIcon" |
| | | v-for="(item, index) in list5" |
| | | v-for="(item, index) in ptzBtns" |
| | | :style="{ transform: `rotate(${index * 90}deg)` }" |
| | | > |
| | | <el-icon> |
| | |
| | | </div> |
| | | |
| | | <div class="divider"></div> |
| | | <div v-for="arr in list4" class="info"> |
| | | <div v-for="arr in baseInfoList" class="info"> |
| | | <div v-for="item in arr" class="infoItem"> |
| | | <div class="infoName">{{ item.name }}</div> |
| | | <div class="infoValue">{{ item.value }}</div> |
| | | <div class="infoValue">{{ item.value + (item.unit || '') }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | import _ from 'lodash' |
| | | import BaseControl from '@/components/CurrentTaskDetails/ControlPanel/BaseControl.vue' |
| | | import EventBus from '@/event-bus' |
| | | import { getPayloadControlApi, ptzControlApi } from '@/api/payload' |
| | | import { getPayloadControlApi } from '@/api/payload' |
| | | import { directionMap } from '@/const/drc' |
| | | |
| | | const deviceOsdInfo = inject('deviceOsdInfo') |
| | | const host = computed(() => deviceOsdInfo?.value?.data?.host || {}) |
| | | const wsInfo = inject('wsInfo') |
| | | const device_osd_host = computed(() => wsInfo?.value?.device_osd?.data?.host || {}) |
| | | const dock_osd_host = computed(() => wsInfo?.value?.dock_osd?.data?.host || {}) |
| | | const taskDetails = inject('taskDetails') |
| | | const dockSn = inject('dockSn') |
| | | const droneSn = inject('droneSn') |
| | | const trueAltitude = inject('trueAltitude') |
| | | const client_id = inject('client_id') |
| | | const isBackDock = inject('isBackDock') |
| | | |
| | | const store = useStore() |
| | | const deviceTopicInfo = ref({ |
| | | pubTopic: '', |
| | | subTopic: '', |
| | | }) |
| | | const flightController = ref(false) |
| | | // 控制对象 |
| | | let manualControl = {} |
| | | const isAutoControl = inject('isAutoControl') |
| | | |
| | | const compassOptions = computed(() => { |
| | | return { |
| | | pitchAngle: pitchAngle.value.angle, |
| | | trueAltitude: trueAltitude.value, |
| | | yawAngle: yawAngle.value.angle, |
| | | } |
| | | }) |
| | | |
| | | let mqttState = null |
| | | const client_id = ref('') |
| | | const valueTime = ref('00:00:00') |
| | | let timer = null |
| | | let totalSeconds = 0 |
| | | |
| | | const workspace_id = computed(() => taskDetails?.value?.workspace_id) |
| | | const workspace_id = inject('workspace_id') |
| | | const list1 = [ |
| | | { key: KeyCode.KEY_Q, text: 'Q', icon: RefreshLeft }, |
| | | { key: KeyCode.KEY_W, text: 'W', icon: ArrowUp }, |
| | |
| | | const speed = ref(5) |
| | | provide('speed', speed) |
| | | |
| | | const list5 = [ |
| | | const ptzBtns = [ |
| | | { name: '上', key: KeyCode.ARROW_UP, operate: 'up', style: { top: '-70%' } }, |
| | | { name: '右', key: KeyCode.ARROW_RIGHT, operate: 'right', style: { left: '70%' } }, |
| | | { name: '下', key: KeyCode.ARROW_DOWN, operate: 'down', style: { top: '70%' } }, |
| | | { name: '左', key: KeyCode.ARROW_LEFT, operate: 'left', style: { left: '-70%' } }, |
| | | ] |
| | | |
| | | const list4 = computed(() => { |
| | | const { longitude, latitude, height, payloads } = host?.value || {} |
| | | const { gimbal_pitch } = payloads?.[0] || {} //俯仰角度 |
| | | return [ |
| | | [ |
| | | { name: '焦距倍数', value: '0' }, |
| | | { name: '俯仰角度', value: pitchAngle.value.angle }, |
| | | { name: '横向角度', value: yawAngle.value.angle }, |
| | | ], |
| | | [ |
| | | { name: '储存', value: '64.5G' }, |
| | | { name: '方向', value: pitchAngle.value.direction }, |
| | | { name: '方向', value: yawAngle.value.direction }, |
| | | ], |
| | | ] |
| | | }) |
| | | const baseInfoList = ref([ |
| | | [ |
| | | { name: '焦距倍数', value: 0 }, |
| | | { name: '俯仰角度', value: 0, unit: '°' }, |
| | | { name: '横向角度', value: 0, unit: '°' }, |
| | | ], |
| | | [ |
| | | { name: '储存', value: 0, unit: 'G' }, |
| | | { name: '方向', value: 0 }, |
| | | { name: '方向', value: 0 }, |
| | | ], |
| | | ]) |
| | | |
| | | const pitchAngle = computed(() => { |
| | | const { longitude, latitude, height, payloads } = host?.value || {} |
| | | const { payloads } = device_osd_host?.value || {} |
| | | const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0 |
| | | let direction = '' |
| | | if (gimbal_pitch > -2 && gimbal_pitch < 2) { |
| | |
| | | direction = '正下' |
| | | } |
| | | return { |
| | | angle: _.round(gimbal_pitch || 0, 1) + '°', |
| | | angle: _.round(gimbal_pitch || 0, 1), |
| | | direction, |
| | | } |
| | | }) |
| | | |
| | | const yawAngle = computed(() => { |
| | | let { longitude, latitude, height, payloads, attitude_head } = host?.value || {} |
| | | const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0 |
| | | let { payloads, attitude_head } = device_osd_host?.value || {} |
| | | const gimbal_yaw = payloads?.[0]?.gimbal_yaw || 0 |
| | | attitude_head = attitude_head || 0 |
| | | let yaw = '' |
| | |
| | | if ((yaw > -2 && yaw < 2) || parseInt(attitude_head) === parseInt(gimbal_yaw)) { |
| | | result = attitude_head < 0 ? 180 + (180 + attitude_head) : attitude_head |
| | | } |
| | | let direction = '' |
| | | const roundResult = Math.round(result) |
| | | if (roundResult === 0) { |
| | | direction = '正北' |
| | | } else if (roundResult > 0 && roundResult < 45) { |
| | | direction = '北偏东' |
| | | } else if (roundResult === 45) { |
| | | direction = '东北' |
| | | } else if (roundResult > 45 && roundResult < 90) { |
| | | direction = '北偏东' |
| | | } else if (roundResult === 90) { |
| | | direction = '正东' |
| | | } else if (roundResult > 90 && roundResult < 135) { |
| | | direction = '东偏南' |
| | | } else if (roundResult === 135) { |
| | | direction = '东南' |
| | | } else if (roundResult > 135 && roundResult < 180) { |
| | | direction = '南偏东' |
| | | } else if (roundResult === 180) { |
| | | direction = '正南' |
| | | } else if (roundResult > 180 && roundResult < 225) { |
| | | direction = '南偏西' |
| | | } else if (roundResult === 225) { |
| | | direction = '西南' |
| | | } else if (roundResult > 225 && roundResult < 270) { |
| | | direction = '西偏南' |
| | | } else if (roundResult === 270) { |
| | | direction = '正西' |
| | | } else if (roundResult > 270 && roundResult < 315) { |
| | | direction = '西偏北' |
| | | } else if (roundResult === 315) { |
| | | direction = '西北' |
| | | } else if (roundResult > 315 && roundResult < 360) { |
| | | direction = '北偏西' |
| | | } else if (roundResult === 360) { |
| | | direction = '正北' |
| | | let direction = '' |
| | | for (const item of directionMap) { |
| | | if (roundResult >= item.min && roundResult <= item.max) { |
| | | direction = item.value |
| | | break |
| | | } |
| | | } |
| | | return { |
| | | angle: _.round(result, 1) + '°', |
| | | angle: _.round(result, 1), |
| | | direction, |
| | | } |
| | | }) |
| | | |
| | | const deviceTopicInfo = ref({ |
| | | pubTopic: '', |
| | | subTopic: '', |
| | | }) |
| | | const flightController = ref(false) |
| | | // 控制对象 |
| | | let manualControl = {} |
| | | const isAutoControl = inject('isAutoControl') |
| | | const baseInfoChange = () => { |
| | | const newUsedStorage = dock_osd_host.value?.storage?.used |
| | | const zoom_factor = device_osd_host.value?.cameras?.[0]?.zoom_factor || 0 |
| | | const usedStorageGB = _.round(newUsedStorage / 1024 / 1024, 2) |
| | | baseInfoList.value[0][0].value = _.round(zoom_factor, 0) |
| | | baseInfoList.value[0][1].value = pitchAngle.value.angle |
| | | baseInfoList.value[0][2].value = yawAngle.value.angle |
| | | if (newUsedStorage !== undefined) baseInfoList.value[1][0].value = usedStorageGB |
| | | baseInfoList.value[1][1].value = pitchAngle.value.direction |
| | | baseInfoList.value[1][2].value = yawAngle.value.direction |
| | | } |
| | | |
| | | watch( |
| | | wsInfo, |
| | | () => { |
| | | baseInfoChange() |
| | | }, |
| | | { immediate: true, deep: true } |
| | | ) |
| | | |
| | | const timeStart = () => { |
| | | stop() // 避免重复启动 |
| | |
| | | function cancelControl() { |
| | | exitController({ client_id: client_id.value, dock_sn: dockSn.value }) |
| | | .then(res => { |
| | | flightController.value = false |
| | | deviceTopicInfo.value.subTopic = '' |
| | | deviceTopicInfo.value.pubTopic = '' |
| | | flightController.value = false |
| | | isAutoControl.value = true |
| | | ElMessage.success('退出飞行控制成功') |
| | | }) |
| | | .catch(e => {}) |
| | |
| | | }) |
| | | } |
| | | |
| | | |
| | | |
| | | // 返航 |
| | | function onBackDock() { |
| | | returnHome(dockSn?.value).then(res => { |
| | | ElMessage.success('返航操作成功') |
| | | }) |
| | | async function onBackDock() { |
| | | await returnHome(dockSn?.value) |
| | | ElMessage.success('返航操作成功') |
| | | isBackDock.value = true |
| | | isAutoControl.value = true |
| | | } |
| | | |
| | | // 取消返航 |
| | | function cancelBackDock() { |
| | | returnHomeCancel(dockSn?.value).then(res => { |
| | | ElMessage.success('取消返航成功') |
| | | }) |
| | | async function cancelBackDock() { |
| | | await returnHomeCancel({ dock_sn: dockSn?.value, client_id: client_id.value }) |
| | | ElMessage.success('取消返航成功') |
| | | isBackDock.value = false |
| | | isAutoControl.value = false |
| | | } |
| | | |
| | | // 创建mqtt连接 |
| | |
| | | |
| | | // 返航或取消返航 |
| | | const returnOrCancelReturn = () => { |
| | | if (deviceOsdInfo.value?.data?.host?.mode_code === 9) { |
| | | cancelBackDock() |
| | | } else { |
| | | onBackDock() |
| | | } |
| | | isBackDock.value ? cancelBackDock() : onBackDock() |
| | | } |
| | | |
| | | // useManualControl里面用的参数 |
| | |
| | | speed: speed.value, |
| | | })) |
| | | |
| | | watch( |
| | | () => workspace_id.value, |
| | | watch(workspace_id, |
| | | async () => { |
| | | if (workspace_id.value) { |
| | | if (workspace_id.value && mqttState === null && client_id.value === '') { |
| | | await createConnect() |
| | | // 使用控制 |
| | | manualControl = useManualControl(mqttState, deviceTopicInfo.value, flightController, paramsRef) |
| | |
| | | right: 0; |
| | | width: 1400px; |
| | | height: 217px; |
| | | background: linear-gradient(196deg, rgba(23, 23, 23, 0.11) 0%, rgba(6, 6, 6, 0.11) 100%); |
| | | background: rgba(31, 31, 31, 0.15); |
| | | backdrop-filter: blur(5px); |
| | | border-radius: 40px 0px 40px 40px; |
| | | display: flex; |
| | |
| | | box-shadow: 2px 4px 6px 0px rgba(0, 13, 26, 0.42); |
| | | border-radius: 8px 8px 8px 8px; |
| | | text-align: center; |
| | | padding: 5px 0; |
| | | padding: 10px 0; |
| | | |
| | | .btnIcon { |
| | | font-size: 20px; |
| | | cursor: pointer; |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | .divider { |
| | | position: absolute; |
| | | transform: translateX(90px); |
| | | transform: translateX(95px); |
| | | width: 0; |
| | | height: 137px; |
| | | border: 1px solid rgba(255, 255, 255, 0.07); |