初始化位置
This commit is contained in:
@@ -45,6 +45,11 @@ createApp({
|
|||||||
agvMoveInterval: null,
|
agvMoveInterval: null,
|
||||||
agvCameraUrl: API + '/api/camera/refresh',
|
agvCameraUrl: API + '/api/camera/refresh',
|
||||||
agvCameraTimer: null,
|
agvCameraTimer: null,
|
||||||
|
// 初始化定位
|
||||||
|
initPoseLoading: false,
|
||||||
|
initPoseMsg: '',
|
||||||
|
initAmclPoseLoading: false,
|
||||||
|
initAmclPoseMsg: '',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -146,6 +151,8 @@ createApp({
|
|||||||
const { resolution, origin } = this.mapMeta
|
const { resolution, origin } = this.mapMeta
|
||||||
const wx = origin[0] + px * resolution * this.mapMeta.width
|
const wx = origin[0] + px * resolution * this.mapMeta.width
|
||||||
const wy = origin[1] + (1 - py) * resolution * this.mapMeta.height
|
const wy = origin[1] + (1 - py) * resolution * this.mapMeta.height
|
||||||
|
// 确认框
|
||||||
|
if (!confirm(`确定导航到坐标 (${wx.toFixed(2)}, ${wy.toFixed(2)}) 吗?`)) return
|
||||||
try {
|
try {
|
||||||
const res = await fetch(API + '/api/navigate/to', {
|
const res = await fetch(API + '/api/navigate/to', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -639,6 +646,44 @@ createApp({
|
|||||||
alert('❌ 复位请求失败: ' + e.message)
|
alert('❌ 复位请求失败: ' + e.message)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async initPose() {
|
||||||
|
if (!this.agvConnected) { alert('AGV 未连接'); return }
|
||||||
|
if (!confirm('确定要将 AMCL 初始位置设为 (0,0,0) 吗?这会重置定位。')) return
|
||||||
|
this.initPoseLoading = true
|
||||||
|
this.initPoseMsg = ''
|
||||||
|
try {
|
||||||
|
const res = await fetch(API + '/api/mission/init_pose', { method: 'POST' })
|
||||||
|
const data = await res.json()
|
||||||
|
if (data.ok) {
|
||||||
|
this.initPoseMsg = '✅ ' + (data.message || '初始化成功')
|
||||||
|
} else {
|
||||||
|
this.initPoseMsg = '❌ ' + (data.error || '初始化失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.initPoseMsg = '❌ 请求失败: ' + e.message
|
||||||
|
}
|
||||||
|
this.initPoseLoading = false
|
||||||
|
setTimeout(() => { this.initPoseMsg = '' }, 5000)
|
||||||
|
},
|
||||||
|
async initAmclPose() {
|
||||||
|
if (!this.agvConnected) { alert('AGV 未连接'); return }
|
||||||
|
if (!confirm('确定要将 AMCL 初始位置设为 (0,0,0) 吗?这会重置定位。')) return
|
||||||
|
this.initAmclPoseLoading = true
|
||||||
|
this.initAmclPoseMsg = ''
|
||||||
|
try {
|
||||||
|
const res = await fetch(API + '/api/mission/init_pose', { method: 'POST' })
|
||||||
|
const data = await res.json()
|
||||||
|
if (data.ok) {
|
||||||
|
this.initAmclPoseMsg = '✅ ' + (data.message || '初始化成功')
|
||||||
|
} else {
|
||||||
|
this.initAmclPoseMsg = '❌ ' + (data.error || '初始化失败')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
this.initAmclPoseMsg = '❌ 请求失败: ' + e.message
|
||||||
|
}
|
||||||
|
this.initAmclPoseLoading = false
|
||||||
|
setTimeout(() => { this.initAmclPoseMsg = '' }, 5000)
|
||||||
|
},
|
||||||
|
|
||||||
getPointAt(pointRow, col) {
|
getPointAt(pointRow, col) {
|
||||||
var positions = this.missionConfig.positions || []
|
var positions = this.missionConfig.positions || []
|
||||||
|
|||||||
@@ -48,22 +48,33 @@
|
|||||||
<p v-if="mapMsg" class="hint">{% raw %}{{ mapMsg }}{% endraw %}</p>
|
<p v-if="mapMsg" class="hint">{% raw %}{{ mapMsg }}{% endraw %}</p>
|
||||||
</section>
|
</section>
|
||||||
<section class="card" v-if="mapLoaded" style="margin-top:16px">
|
<section class="card" v-if="mapLoaded" style="margin-top:16px">
|
||||||
<h2>地图可视化</h2>
|
<div style="display:flex;align-items:center;justify-content:space-between">
|
||||||
|
<h2>地图可视化</h2>
|
||||||
|
<div style="display:flex;gap:8px;align-items:center">
|
||||||
|
<span style="font-size:12px;color:#888">旋转:</span>
|
||||||
|
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" @click="rotateMap(-90)">↶ 90°</button>
|
||||||
|
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" @click="rotateMap(90)">↷ 90°</button>
|
||||||
|
<button class="btn btn-secondary" style="padding:4px 10px;font-size:12px" @click="resetMapView">重置</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="map-container" style="position:relative;background:#111;border-radius:8px;overflow:hidden">
|
<div class="map-container" style="position:relative;background:#111;border-radius:8px;overflow:hidden">
|
||||||
<img :src="mapImageUrl" @error="onMapError" @click="onMapClick" style="width:100%;display:block;cursor:crosshair" title="点击地图导航到该位置">
|
<!-- 地图旋转 wrapper -->
|
||||||
<!-- 地图覆盖层:显示点位坐标 -->
|
<div :style="{ transform: 'rotate(' + mapRotation + 'deg)', transition: 'transform 0.3s ease' }">
|
||||||
<div class="map-overlay">
|
<img :src="mapImageUrl" @error="onMapError" @click="onMapClick" style="width:100%;display:block;cursor:crosshair" title="点击地图导航到该位置">
|
||||||
<!-- AGV 实时位置 -->
|
<!-- 地图覆盖层:显示点位坐标 -->
|
||||||
<div v-if="navCurrentPos && nav2Available"
|
<div class="map-overlay">
|
||||||
class="map-dot agv-dot"
|
<!-- AGV 实时位置 -->
|
||||||
:style="{ left: getMapX(navCurrentPos) + '%', top: getMapY(navCurrentPos) + '%' }"
|
<div v-if="navCurrentPos && nav2Available"
|
||||||
title="AGV 当前位置">
|
class="map-dot agv-dot"
|
||||||
</div>
|
:style="{ left: getMapX(navCurrentPos) + '%', top: getMapY(navCurrentPos) + '%' }"
|
||||||
<!-- 点位坐标点 -->
|
title="AGV 当前位置">
|
||||||
<div v-for="(p, pi) in missionConfig.positions" :key="'pdot-'+mapVersion+'-'+pi"
|
</div>
|
||||||
class="map-dot point-dot"
|
<!-- 点位坐标点 -->
|
||||||
:style="{ left: getMapX(p.coords) + '%', top: getMapY(p.coords) + '%' }"
|
<div v-for="(p, pi) in missionConfig.positions" :key="'pdot-'+mapVersion+'-'+pi"
|
||||||
:title="p.coords ? p.coords.map(c => c.toFixed(2)).join(', ') : ''">
|
class="map-dot point-dot"
|
||||||
|
:style="{ left: getMapX(p.coords) + '%', top: getMapY(p.coords) + '%' }"
|
||||||
|
:title="p.coords ? p.coords.map(c => c.toFixed(2)).join(', ') : ''">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user