Browse Source

AGV ID 问题

jx-test
修宁 5 months ago
parent
commit
4ed9cde2a5
  1. 6
      src/core/ModelUtils.ts
  2. 11
      src/core/manager/EnvManager.ts
  3. 6
      src/core/manager/amr/AmrMessageManager.ts
  4. 41
      src/core/script/ModelManager.ts
  5. 5
      src/editor/widgets/monitor/MonitorView.vue
  6. 55
      src/modules/amr/ptr/PtrObject.ts
  7. 3
      src/types/Model.d.ts

6
src/core/ModelUtils.ts

@ -16,6 +16,10 @@ import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' import type InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts' import { MeshWrap } from '@/core/manager/InstanceMeshManager.ts'
export function getAgvItemNameById(agvId: string | number) {
return 'AGV_' + agvId
}
/** /**
* 2D * 2D
*/ */
@ -292,7 +296,7 @@ export function processModel(mesh: THREE.Mesh) {
-center.z -center.z
) )
geometry.applyMatrix4(translate) geometry.applyMatrix4(translate)
geometry.computeVertexNormals(); geometry.computeVertexNormals()
// 可选:验证最终包围盒 // 可选:验证最终包围盒
//@ts-ignore //@ts-ignore

11
src/core/manager/EnvManager.ts

@ -5,6 +5,7 @@ import type { ErrorWithReasonCode } from 'mqtt/src/lib/shared.ts'
import { Request } from '@ease-forge/shared' import { Request } from '@ease-forge/shared'
import AmrMessageManager from '@/core/manager/amr/AmrMessageManager' import AmrMessageManager from '@/core/manager/amr/AmrMessageManager'
import { AmrMsg } from '@/core/manager/amr/AmrMessageDefine' import { AmrMsg } from '@/core/manager/amr/AmrMessageDefine'
import { getAgvItemNameById } from '@/core/ModelUtils.ts'
export default class EnvManager { export default class EnvManager {
private amrMessageManager: AmrMessageManager = new AmrMessageManager() private amrMessageManager: AmrMessageManager = new AmrMessageManager()
@ -100,7 +101,7 @@ export default class EnvManager {
* *
*/ */
onDeviceStatusMessage(type, topic, data: AgvStatusVo) { onDeviceStatusMessage(type, topic, data: AgvStatusVo) {
const object3D = Model.find3D(data.id) const object3D = Model.find3D(getAgvItemNameById(data.id))
if (object3D) { if (object3D) {
object3D.agvStatusVo = data object3D.agvStatusVo = data
} }
@ -134,7 +135,7 @@ export default class EnvManager {
if (body.after != null) { if (body.after != null) {
// 将托盘挪到目标位置 // 将托盘挪到目标位置
const after = body.after const after = body.after
Model.createInv('pallet', body.lpn, after.rack, after.bay, after.level, after.cell) Model.createInv('pallet', body.lpn, after.rack, after.bay, after.level, after.cell, after.locCode)
} }
} }
@ -157,7 +158,7 @@ export default class EnvManager {
const lpn = row.lpn // : "LPN1" const lpn = row.lpn // : "LPN1"
const rack = row.rack // : "rack1" const rack = row.rack // : "rack1"
const container_type = row.container_type // : "pallet" const container_type = row.container_type // : "pallet"
Model.createInv(container_type, lpn, rack, bay, level, cell) Model.createInv(container_type, lpn, rack, bay, level, cell, loc_code)
} }
} }
@ -174,7 +175,7 @@ export default class EnvManager {
const deviceList: AgvStatusVo[] = deviceRes.data || [] const deviceList: AgvStatusVo[] = deviceRes.data || []
for (const agvState of deviceList) { for (const agvState of deviceList) {
const agvItem = Model.find(agvState.id) const agvItem = Model.find(getAgvItemNameById(agvState.id))
if (!agvItem) { if (!agvItem) {
// 还没加载到地图 // 还没加载到地图
const item = JSON.parse(agvState.virtualExecutorPayload) const item = JSON.parse(agvState.virtualExecutorPayload)
@ -197,6 +198,8 @@ export default class EnvManager {
item.tf[1][1] = 90 // 上方 item.tf[1][1] = 90 // 上方
break break
} }
item.id = getAgvItemNameById(agvState.id)
item.dt.vehicleId = agvState.id
Model.createExecutor(item) Model.createExecutor(item)
} }
} }

6
src/core/manager/amr/AmrMessageManager.ts

@ -1,6 +1,7 @@
import {AmrMsg, AmrMsg10010, AmrMsg10050, AmrMsg10060, AmrMsg10110, AmrMsg10120, AmrMsg20000Base, AmrMsg20020, AmrMsg20060} from '@/core/manager/amr/AmrMessageDefine' import {AmrMsg, AmrMsg10010, AmrMsg10050, AmrMsg10060, AmrMsg10110, AmrMsg10120, AmrMsg20000Base, AmrMsg20020, AmrMsg20060} from '@/core/manager/amr/AmrMessageDefine'
import Cl23dObject from '@/modules/amr/ptr/cl2/Cl23dObject' import Cl23dObject from '@/modules/amr/ptr/cl2/Cl23dObject'
import Viewport from '@/core/engine/Viewport' import Viewport from '@/core/engine/Viewport'
import { getAgvItemNameById } from '@/core/ModelUtils.ts'
export default class AmrMessageManager { export default class AmrMessageManager {
@ -9,9 +10,8 @@ export default class AmrMessageManager {
} }
handleMessage(topic, amrMsg: AmrMsg<any>) { handleMessage(topic, amrMsg: AmrMsg<any>) {
const vehicleId = parseInt(topic.replace('/wcs_server/', '')) const vehicleId = parseInt(topic.replace('/wcs_server/', ''))
const amrItem = this.viewport.entityManager.findObjectById(vehicleId + '') as Cl23dObject const amrItem = Model.find3D(getAgvItemNameById(vehicleId)) as Cl23dObject
switch (amrMsg.id) { switch (amrMsg.id) {
// AMR作业指令 10010 // AMR作业指令 10010
case 10010: case 10010:
@ -64,7 +64,7 @@ export default class AmrMessageManager {
handleStatusMessage(topic, amrMsg: AmrMsg<AmrMsg20000Base>) { handleStatusMessage(topic, amrMsg: AmrMsg<AmrMsg20000Base>) {
const vehicleId = amrMsg.content.VehicleId const vehicleId = amrMsg.content.VehicleId
const amrItem = this.viewport.entityManager.findObjectById(vehicleId + '') as Cl23dObject const amrItem = Model.find3D(getAgvItemNameById(vehicleId)) as Cl23dObject
switch (amrMsg.id) { switch (amrMsg.id) {
case 20020: case 20020:
amrItem.handle20020Message(amrMsg.content as AmrMsg20020) amrItem.handle20020Message(amrMsg.content as AmrMsg20020)

41
src/core/script/ModelManager.ts

@ -17,12 +17,12 @@ export default class ModelManager implements IControls, Model {
} }
getClx(id: string): ClxIf { getClx(id: string): ClxIf {
throw new Error("不支持 ClxIf"); throw new Error('不支持 ClxIf')
// return new ClxEntity(this.viewport, id) // return new ClxEntity(this.viewport, id)
} }
getFm600(id: string): Fm600If { getFm600(id: string): Fm600If {
throw new Error("不支持 Fm600If"); throw new Error('不支持 Fm600If')
// return new FM600Entity(this.viewport, id) // return new FM600Entity(this.viewport, id)
} }
@ -113,18 +113,33 @@ export default class ModelManager implements IControls, Model {
this.viewport.runtimeManager.addEntity(item) this.viewport.runtimeManager.addEntity(item)
} }
createInv(boxType: ContainerT, lpn: string, rack: string, bay?: number, level?: number, cell?: number): void { createInv(boxType: ContainerT, lpn: string, rack: string, bay?: number, level?: number, cell?: number, locCode?: string): void {
const scale = getRenderer(boxType).defaultScale const scale = getRenderer(boxType).defaultScale
this.viewport.runtimeManager.addEntity({ if (_.startsWith(locCode, 'AGV_')) {
id: lpn, // 库存在 AGV 上
t: boxType as string, this.viewport.runtimeManager.addEntity({
tf: [[-5000, -1, 0], [0, 0, 0], [scale.x, scale.y, scale.z]], id: lpn,
v: true, t: boxType as string,
dt: { tf: [[-5000, -1, 0], [0, 0, 0], [scale.x, scale.y, scale.z]],
in: [], out: [], center: [], v: true,
storeAt: { item: rack, bay, level, cell } dt: {
} in: [], out: [], center: [],
}) storeAt: { item: locCode, bay, level, cell }
}
})
}else {
this.viewport.runtimeManager.addEntity({
id: lpn,
t: boxType as string,
tf: [[-5000, -1, 0], [0, 0, 0], [scale.x, scale.y, scale.z]],
v: true,
dt: {
in: [], out: [], center: [],
storeAt: { item: rack, bay, level, cell }
}
})
}
// 这一段代码不要删除,他是用向正式环境提交数据用的 // 这一段代码不要删除,他是用向正式环境提交数据用的
/* /*

5
src/editor/widgets/monitor/MonitorView.vue

@ -73,6 +73,7 @@
<script> <script>
import IWidgets from '../IWidgets.js' import IWidgets from '../IWidgets.js'
import { worldModel } from '@/core/manager/WorldModel.js' import { worldModel } from '@/core/manager/WorldModel.js'
import { getAgvItemNameById } from '@/core/ModelUtils.js'
export default { export default {
name: 'MonitorView', name: 'MonitorView',
@ -103,7 +104,7 @@ export default {
if (deviceInfo.isOnline) { if (deviceInfo.isOnline) {
continue continue
} }
const view3DObject = Model.find3D(deviceInfo.id) const view3DObject = Model.find3D(getAgvItemNameById(deviceInfo.id))
if (typeof view3DObject.bootForMonitor === 'function') { if (typeof view3DObject.bootForMonitor === 'function') {
view3DObject.bootForMonitor() view3DObject.bootForMonitor()
} }
@ -136,6 +137,7 @@ export default {
onDeviceAliveMessage(type, topic, body) { onDeviceAliveMessage(type, topic, body) {
const deviceInfo = _.find(this.deviceList, device => device.id === body.id) const deviceInfo = _.find(this.deviceList, device => device.id === body.id)
if (!deviceInfo) { if (!deviceInfo) {
console.warn("device " + body.id + " not on list")
// //
this.deviceList.push({ this.deviceList.push({
id: body.id, id: body.id,
@ -155,6 +157,7 @@ export default {
onDeviceStatusMessage(type, topic, body) { onDeviceStatusMessage(type, topic, body) {
const deviceInfo = _.find(this.deviceList, device => device.id === body.id) const deviceInfo = _.find(this.deviceList, device => device.id === body.id)
if (!deviceInfo) { if (!deviceInfo) {
console.warn("device " + body.id + " not on list")
return return
} }
_.assign(deviceInfo, body) _.assign(deviceInfo, body)

55
src/modules/amr/ptr/PtrObject.ts

@ -15,13 +15,13 @@ import {
TaskStatusChangeData, TaskStatusChangeData,
TaskTypeChangeData TaskTypeChangeData
} from '@/core/manager/amr/AmrMessageDefine' } from '@/core/manager/amr/AmrMessageDefine'
import {worldModel} from '@/core/manager/WorldModel' import { worldModel } from '@/core/manager/WorldModel'
import Viewport from '@/core/engine/Viewport' import Viewport from '@/core/engine/Viewport'
import {Euler} from 'three/src/math/Euler' import { Euler } from 'three/src/math/Euler'
import gsap from 'gsap' import gsap from 'gsap'
import {MeshWrap} from "@/core/manager/InstanceMeshManager"; import { MeshWrap } from '@/core/manager/InstanceMeshManager'
import {getRenderer} from "@/core/manager/ModuleManager"; import { getRenderer } from '@/core/manager/ModuleManager'
import {MathUtils} from "three"; import { MathUtils } from 'three'
type CStepTaskType = 'MOVE' | 'MOVE_BACKWARD' | 'ROTATION' | 'LOAD' | 'UNLOAD' | 'CHARGE' type CStepTaskType = 'MOVE' | 'MOVE_BACKWARD' | 'ROTATION' | 'LOAD' | 'UNLOAD' | 'CHARGE'
@ -88,7 +88,7 @@ export default class PtrObject extends THREE.Object3D {
private __TaskStatus: CEventId = 0 private __TaskStatus: CEventId = 0
private __PickMode: CPickMode = 0 private __PickMode: CPickMode = 0
private agvStatusVo: AgvStatusVo; private agvStatusVo: AgvStatusVo
// 是否模拟设备 // 是否模拟设备
private isMonitoring: boolean = false private isMonitoring: boolean = false
@ -172,9 +172,9 @@ export default class PtrObject extends THREE.Object3D {
super() super()
this.viewport = viewport this.viewport = viewport
this.item = item this.item = item
this.vehicleId = parseInt(item.id) this.vehicleId = parseInt(item.dt.vehicleId)
this.viewport.addFrameTimerCallback(this.item.id, this.onFrameTimer.bind(this)) this.viewport.addFrameTimerCallback('' + this.vehicleId, this.onFrameTimer.bind(this))
window.agv3 = this window.agv3 = this
} }
@ -223,9 +223,8 @@ export default class PtrObject extends THREE.Object3D {
bootForShow() { bootForShow() {
this.isMonitoring = false this.isMonitoring = false
this.boot() this.boot()
this.subscribeMessage('/wcs_server/' + this.item.id) this.subscribeMessage('/wcs_server/' + this.vehicleId)
this.subscribeMessage('/agv_robot/status') this.subscribeMessage('/agv_robot/status')
} }
bootForMonitor() { bootForMonitor() {
@ -378,7 +377,7 @@ export default class PtrObject extends THREE.Object3D {
} }
subscribeMessage(topic: string) { subscribeMessage(topic: string) {
worldModel.envManager.client.subscribe(topic, {qos: 0}) worldModel.envManager.client.subscribe(topic, { qos: 0 })
} }
sendMessage(msg: AmrMsg<any>) { sendMessage(msg: AmrMsg<any>) {
@ -401,7 +400,7 @@ export default class PtrObject extends THREE.Object3D {
return return
} }
const content = new AmrMsg20100(this.vehicleId) const content = new AmrMsg20100(this.vehicleId)
content.Temperature = {Battery: this.Battery} content.Temperature = { Battery: this.Battery }
const m20100 = new AmrMsg<AmrMsg20100>(content) const m20100 = new AmrMsg<AmrMsg20100>(content)
worldModel.envManager.client.publish('/agv_robot/status', JSON.stringify(m20100)) worldModel.envManager.client.publish('/agv_robot/status', JSON.stringify(m20100))
} }
@ -536,16 +535,16 @@ export default class PtrObject extends THREE.Object3D {
const quat2 = new THREE.Quaternion().setFromEuler(euler) const quat2 = new THREE.Quaternion().setFromEuler(euler)
const angleDiff = quat1.angleTo(quat2) const angleDiff = quat1.angleTo(quat2)
if (p.distanceTo(this.position) < 0.5 && Math.abs(angleDiff) < Math.PI/4) { if (p.distanceTo(this.position) < 0.5 && Math.abs(angleDiff) < Math.PI / 4) {
return return
} }
this.position.set(p.x, 0, p.z) this.position.set(p.x, 0, p.z)
const transform = new Ammo.btTransform(); const transform = new Ammo.btTransform()
this.boxBody.getMotionState().getWorldTransform(transform); this.boxBody.getMotionState().getWorldTransform(transform)
transform.setOrigin(new Ammo.btVector3(p.x, 0, p.z)); // 设置新位置 transform.setOrigin(new Ammo.btVector3(p.x, 0, p.z)) // 设置新位置
this.boxBody.getMotionState().setWorldTransform(transform); this.boxBody.getMotionState().setWorldTransform(transform)
this.viewport.ammoModel.destroy(transform) this.viewport.ammoModel.destroy(transform)
this.rotation.set(0, r, 0) this.rotation.set(0, r, 0)
} }
@ -578,7 +577,7 @@ export default class PtrObject extends THREE.Object3D {
const linkCount = data.Link?.length || 0 const linkCount = data.Link?.length || 0
if (linkCount > 0) { if (linkCount > 0) {
let prevLink = {X: data.StartX, Y: data.StartY, Speed: 1000} let prevLink = { X: data.StartX, Y: data.StartY, Speed: 1000 }
for (let i = 0; i < data.Link.length; i++) { for (let i = 0; i < data.Link.length; i++) {
const link = data.Link[i] const link = data.Link[i]
if ((currentStepTask.X == link.X && currentStepTask.Y == link.Y) if ((currentStepTask.X == link.X && currentStepTask.Y == link.Y)
@ -877,6 +876,7 @@ export default class PtrObject extends THREE.Object3D {
keepSpeed: any keepSpeed: any
force: any force: any
stopD: number = 0.01 stopD: number = 0.01
// 走 // 走
addTravel(logicX: number, logicY: number, direction: number, speed: number = 1): Promise<void> { addTravel(logicX: number, logicY: number, direction: number, speed: number = 1): Promise<void> {
@ -912,13 +912,13 @@ export default class PtrObject extends THREE.Object3D {
this.keepSpeed.setValue(0, 0, speed) this.keepSpeed.setValue(0, 0, speed)
} }
if (this.viewport.registerPhysicsUpdateCallBack.has(this.item.id)) { if (this.viewport.registerPhysicsUpdateCallBack.has('' + this.vehicleId)) {
return null return null
} }
this.travelAnimation = 'asd' this.travelAnimation = 'asd'
this.viewport.registerPhysicsUpdateCallBack.set(this.item.id, () => { this.viewport.registerPhysicsUpdateCallBack.set('' + this.vehicleId, () => {
this.viewport.physicsWorld.stepSimulation(1 / 60, 10) this.viewport.physicsWorld.stepSimulation(1 / 60, 10)
@ -943,7 +943,8 @@ export default class PtrObject extends THREE.Object3D {
const stopVel = new this.viewport.ammoModel.btVector3(0, 0, 0) const stopVel = new this.viewport.ammoModel.btVector3(0, 0, 0)
this.boxBody.setLinearVelocity(stopVel) this.boxBody.setLinearVelocity(stopVel)
this.viewport.ammoModel.destroy(stopVel) this.viewport.ammoModel.destroy(stopVel)
this.viewport.registerPhysicsUpdateCallBack.delete(this.item.id)
this.viewport.registerPhysicsUpdateCallBack.delete('' + this.vehicleId)
this.viewport.ammoModel.destroy(this.force) this.viewport.ammoModel.destroy(this.force)
this.viewport.ammoModel.destroy(this.keepSpeed) this.viewport.ammoModel.destroy(this.keepSpeed)
this.position.set(this.__toPos.x, this.__toPos.y, this.__toPos.z) this.position.set(this.__toPos.x, this.__toPos.y, this.__toPos.z)
@ -977,17 +978,17 @@ export default class PtrObject extends THREE.Object3D {
if (cSpeed >= Math.abs(speed) || distance <= stopDistance) { if (cSpeed >= Math.abs(speed) || distance <= stopDistance) {
currentPhase = 'uniform' currentPhase = 'uniform'
} }
this.boxBody.setDamping(0, 0); this.boxBody.setDamping(0, 0)
break break
case 'uniform': case 'uniform':
currentPhase = 'uniform' currentPhase = 'uniform'
this.boxBody.setLinearVelocity(keepSpeed) this.boxBody.setLinearVelocity(keepSpeed)
this.boxBody.setDamping(0, 0); this.boxBody.setDamping(0, 0)
break break
case 'decelerate': case 'decelerate':
// 检测停止 // 检测停止
if (cSpeed > 0) { if (cSpeed > 0) {
this.boxBody.setDamping(sa, 0); this.boxBody.setDamping(sa, 0)
} }
this.boxBody.activate() this.boxBody.activate()
@ -1057,7 +1058,7 @@ export default class PtrObject extends THREE.Object3D {
this.OperationType = 4 this.OperationType = 4
this.animationUpFork(height + 0.2).then( this.animationUpFork(height + 0.2).then(
() => this.animationShowFork(1.35).then( () => this.animationShowFork(1.35).then(
()=>this.animationUpFork(height).then( () => this.animationUpFork(height).then(
() => { () => {
try { try {
const a = this.agvStatusVo.unloadBasLocationVo const a = this.agvStatusVo.unloadBasLocationVo
@ -1120,11 +1121,11 @@ export default class PtrObject extends THREE.Object3D {
const item = this.viewport.entityManager.findItemById(id) const item = this.viewport.entityManager.findItemById(id)
const wrap = this.viewport.entityManager.findObjectById(id) as MeshWrap const wrap = this.viewport.entityManager.findObjectById(id) as MeshWrap
if (!wrap || wrap.type !== 'MeshWrap') { if (!wrap || wrap.type !== 'MeshWrap') {
throw new Error(`无法拾取物品 ${id},它不是一个有效的 MeshWrap`) throw new Error(`无法拾取物品 ${id},它不是一个有效的 MeshWrap`)
} }
item.dt.storeAt = { item.dt.storeAt = {
item: this.id + "" item: this.id + ''
} }
const mesh = wrap.manager.wrapToObject3D(wrap) const mesh = wrap.manager.wrapToObject3D(wrap)
this.viewport.entityManager.replaceObject(id, mesh) this.viewport.entityManager.replaceObject(id, mesh)

3
src/types/Model.d.ts

@ -48,8 +48,9 @@ declare interface Model {
* @param bay , * @param bay ,
* @param level , * @param level ,
* @param cell , * @param cell ,
* @param locCode ,
*/ */
createInv(boxType: ContainerT, lpn: string, rack: string, bay: number = 0, level: number = 0, cell: number = 0): void createInv(boxType: ContainerT, lpn: string, rack: string, bay: number = 0, level: number = 0, cell: number = 0, locCode: string = ''): void
/** /**
* ID * ID

Loading…
Cancel
Save