feat: 处理轮询时地图刷新的问题
This commit is contained in:
parent
2159b7f228
commit
f5b1b70274
@ -100,7 +100,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="video-container">
|
<div class="video-container">
|
||||||
<div v-if="activeMode === 'auto' || activeController === 1" class="map-container">
|
<div v-if="activeMode === 'auto' || activeController === 1" class="map-container">
|
||||||
<MapCanvas v-if="robotList.length > 0" :clearMap="true" :robotList="currentRobot" ref="mapCanvasRef" />
|
<MapCanvas v-if="robotList.length > 0" :robotList="currentRobot" ref="mapCanvasRef" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="activeMode === 'artificial' && activeController === 2" class="model-container">
|
<div v-if="activeMode === 'artificial' && activeController === 2" class="model-container">
|
||||||
<UrdfViewer ref="urdfViewerRef" modelPath="/inspection/elfin10/elfin10.urdf.xacro" />
|
<UrdfViewer ref="urdfViewerRef" modelPath="/inspection/elfin10/elfin10.urdf.xacro" />
|
||||||
|
|||||||
@ -28,16 +28,11 @@ import {
|
|||||||
import { getMapJson } from '@/api/inspection/robot'
|
import { getMapJson } from '@/api/inspection/robot'
|
||||||
import { useInspectionStore } from "@/store/modules/inspection";
|
import { useInspectionStore } from "@/store/modules/inspection";
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { clear } from 'ace-builds/src-noconflict/ext-code_lens';
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
robotList: {
|
robotList: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => []
|
default: () => []
|
||||||
},
|
|
||||||
clearMap: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -78,6 +73,9 @@ const applicationState = {
|
|||||||
let mapCanvas; // 主渲染画布 DOM 元素
|
let mapCanvas; // 主渲染画布 DOM 元素
|
||||||
let canvasCtx; // 2D 渲染上下文
|
let canvasCtx; // 2D 渲染上下文
|
||||||
|
|
||||||
|
let animationFrameId;
|
||||||
|
let mapLoadVersion = 0;
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
mapCanvas = document.getElementById('map-canvas');
|
mapCanvas = document.getElementById('map-canvas');
|
||||||
canvasCtx = mapCanvas.getContext('2d');
|
canvasCtx = mapCanvas.getContext('2d');
|
||||||
@ -191,7 +189,7 @@ function renderFrame(timestamp) {
|
|||||||
|
|
||||||
// 如果地图未加载,跳过绘制
|
// 如果地图未加载,跳过绘制
|
||||||
if (!applicationState.isMapLoaded) {
|
if (!applicationState.isMapLoaded) {
|
||||||
requestAnimationFrame(renderFrame); // 继续请求下一帧
|
animationFrameId = requestAnimationFrame(renderFrame); // 继续请求下一帧
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +239,7 @@ function renderFrame(timestamp) {
|
|||||||
drawMapBoundary(canvasCtx, map);
|
drawMapBoundary(canvasCtx, map);
|
||||||
|
|
||||||
// 请求下一帧渲染
|
// 请求下一帧渲染
|
||||||
requestAnimationFrame(renderFrame);
|
animationFrameId = requestAnimationFrame(renderFrame);
|
||||||
}
|
}
|
||||||
|
|
||||||
const drawAllRobots = (ctx) => {
|
const drawAllRobots = (ctx) => {
|
||||||
@ -354,14 +352,25 @@ const centerCanvasView = () => {
|
|||||||
inspectionStore.camera.centerY = (map.originY + map.maxY) / 2;
|
inspectionStore.camera.centerY = (map.originY + map.maxY) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadSourceMap = async () => {
|
const getConnectedRobot = (robotList = props.robotList) => {
|
||||||
const connectedRobot = props.robotList.find(item => item.connectStatus == 1);
|
return robotList.find(item => item?.connectStatus == 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getMapIdentity = (robotList = props.robotList) => {
|
||||||
|
const robot = getConnectedRobot(robotList)
|
||||||
|
return robot ? `${robot.id ?? ''}:${robot.robotMapName ?? ''}` : ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadSourceMap = async (connectedRobot = getConnectedRobot()) => {
|
||||||
if (!connectedRobot) return;
|
if (!connectedRobot) return;
|
||||||
|
|
||||||
|
const currentLoadVersion = ++mapLoadVersion;
|
||||||
|
|
||||||
const res = await getMapJson({
|
const res = await getMapJson({
|
||||||
robotId: connectedRobot.id,
|
robotId: connectedRobot.id,
|
||||||
mapName: connectedRobot.robotMapName
|
mapName: connectedRobot.robotMapName
|
||||||
});
|
});
|
||||||
|
if (currentLoadVersion !== mapLoadVersion) return;
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
try {
|
try {
|
||||||
const rawJsonObject = JSON.parse(res.data); // 解析 JSON
|
const rawJsonObject = JSON.parse(res.data); // 解析 JSON
|
||||||
@ -373,20 +382,6 @@ const loadSourceMap = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param id 机器人编号
|
|
||||||
* @param name 机器人名称
|
|
||||||
* @param angleRad 角度
|
|
||||||
* @param color 颜色
|
|
||||||
*/
|
|
||||||
const addRobot = (id, name,x, y, angleRad, color) => {
|
|
||||||
const map = applicationState.parsedMap;
|
|
||||||
// 放置于地图中央附近
|
|
||||||
const robot = new MobileRobot(id, name, x, y, angleRad, color);
|
|
||||||
applicationState.robots.push(robot);
|
|
||||||
}
|
|
||||||
|
|
||||||
const parseRobotPosition = (currentPosition) => {
|
const parseRobotPosition = (currentPosition) => {
|
||||||
if (!currentPosition) return null
|
if (!currentPosition) return null
|
||||||
const values = String(currentPosition).split(',').map(Number)
|
const values = String(currentPosition).split(',').map(Number)
|
||||||
@ -394,60 +389,58 @@ const parseRobotPosition = (currentPosition) => {
|
|||||||
return values
|
return values
|
||||||
}
|
}
|
||||||
|
|
||||||
const moveRobot = (robot, dx, dy, dtheta = 0) => {
|
const syncRobots = (robotList) => {
|
||||||
robot.x += dx;
|
const previousRobots = new Map(applicationState.robots.map(robot => [robot.id, robot]));
|
||||||
robot.y += dy;
|
const nextRobots = [];
|
||||||
robot.angle += dtheta;
|
|
||||||
|
robotList.forEach(item => {
|
||||||
|
const position = parseRobotPosition(item.currentPosition)
|
||||||
|
if (!position) return
|
||||||
|
|
||||||
|
const [x, y, angle] = position
|
||||||
|
const robot = previousRobots.get(item.id)
|
||||||
|
if (robot) {
|
||||||
|
robot.name = item.robotName
|
||||||
|
robot.x = x
|
||||||
|
robot.y = y
|
||||||
|
robot.angle = angle
|
||||||
|
nextRobots.push(robot)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
nextRobots.push(new MobileRobot(
|
||||||
|
item.id,
|
||||||
|
item.robotName,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
angle,
|
||||||
|
colorList[nextRobots.length % colorList.length]
|
||||||
|
))
|
||||||
|
})
|
||||||
|
|
||||||
|
applicationState.robots = nextRobots
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init()
|
init()
|
||||||
if (props.robotList.length > 0) {
|
window.addEventListener('resize', resizeCanvasToContainer);
|
||||||
loadSourceMap()
|
resizeCanvasToContainer();
|
||||||
requestAnimationFrame(renderFrame);
|
bindEvent()
|
||||||
window.addEventListener('resize', resizeCanvasToContainer); // 监听窗口大小变化
|
syncRobots(props.robotList)
|
||||||
resizeCanvasToContainer(); // 初始调用一次
|
loadSourceMap()
|
||||||
setTimeout(() => {
|
animationFrameId = requestAnimationFrame(renderFrame);
|
||||||
bindEvent()
|
|
||||||
props.robotList.forEach(item => {
|
|
||||||
const position = parseRobotPosition(item.currentPosition)
|
|
||||||
if (!position) return
|
|
||||||
const [x, y, angle] = position
|
|
||||||
addRobot(item.id, item.robotName, x, y, angle, colorList[applicationState.robots.length % colorList.length])
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const colorList = ['#00D4FF', '#FFB300', '#00FF88', '#ff5100', '#fff', '#15ff00', '#ff00d4', '#00d4ff']
|
const colorList = ['#00D4FF', '#FFB300', '#00FF88', '#ff5100', '#fff', '#15ff00', '#ff00d4', '#00d4ff']
|
||||||
|
|
||||||
watch(() => props.robotList,
|
// 轮询只同步机器人实例,不重新请求、解析或重置地图。
|
||||||
(newVal) => {
|
watch(() => props.robotList, syncRobots)
|
||||||
if (newVal.length > 0) {
|
|
||||||
if (props.clearMap) {
|
|
||||||
applicationState.robots = []
|
|
||||||
}
|
|
||||||
loadSourceMap()
|
|
||||||
|
|
||||||
const ids = applicationState.robots.map(r => r.id);
|
// 只有用于加载地图的机器人或地图名称改变时,才重新加载底图。
|
||||||
props.robotList.forEach(item => {
|
watch(
|
||||||
const position = parseRobotPosition(item.currentPosition)
|
() => getMapIdentity(props.robotList),
|
||||||
if (!position) return
|
(newIdentity, oldIdentity) => {
|
||||||
const [x, y, angle] = position
|
if (newIdentity && newIdentity !== oldIdentity) loadSourceMap()
|
||||||
if (!ids.includes(item.id)) {
|
|
||||||
addRobot(item.id, item.robotName, x, y, angle, colorList[applicationState.robots.length % colorList.length])
|
|
||||||
} else {
|
|
||||||
applicationState.robots.forEach(robot => {
|
|
||||||
if (robot.id === item.id) {
|
|
||||||
// moveRobot(robot, parseFloat(x) - robot.x, parseFloat(y) - robot.y, parseFloat(angle) - robot.angle)
|
|
||||||
robot.x = x
|
|
||||||
robot.y = y
|
|
||||||
robot.angle = angle
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -458,6 +451,8 @@ defineExpose({
|
|||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
window.removeEventListener('resize', resizeCanvasToContainer)
|
window.removeEventListener('resize', resizeCanvasToContainer)
|
||||||
|
cancelAnimationFrame(animationFrameId)
|
||||||
|
mapLoadVersion += 1
|
||||||
canvasCtx = null
|
canvasCtx = null
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user