Browse Source

pallet 无法出现的问题

master
修宁 6 months ago
parent
commit
6ce2cc8775
  1. 1
      src/core/ModelUtils.ts
  2. 4
      src/core/base/BaseRenderer.ts
  3. 16
      src/core/manager/EnvManager.ts
  4. 7
      src/core/script/LCCScript.ts
  5. 112
      src/editor/widgets/monitor/MonitorView.vue
  6. 43
      src/modules/pallet/PalletRenderer.ts
  7. 46
      src/modules/tote/ToteRenderer.ts
  8. 45
      src/types/LCC.d.ts

1
src/core/ModelUtils.ts

@ -292,6 +292,7 @@ export function processModel(mesh: THREE.Mesh) {
-center.z -center.z
) )
geometry.applyMatrix4(translate) geometry.applyMatrix4(translate)
geometry.computeVertexNormals();
// 可选:验证最终包围盒 // 可选:验证最终包围盒
//@ts-ignore //@ts-ignore

4
src/core/base/BaseRenderer.ts

@ -136,7 +136,7 @@ export default abstract class BaseRenderer {
// 由基础类创造一个属于自己的点演示 // 由基础类创造一个属于自己的点演示
const point = this.createPointBasic(item, option) const point = this.createPointBasic(item, option)
const matrix = this.calcMeshMatrix(item, option) const matrix = this.calcMeshMatrix(item, option)
point.applyMatrix4(matrix) point.setMatrix4(matrix)
point.visible = ((typeof item.v !== 'undefined') ? item.v : true) point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
return point return point
@ -262,7 +262,7 @@ export default abstract class BaseRenderer {
// point.manager.syncMeshObject3D(point) // point.manager.syncMeshObject3D(point)
// } // }
const matrix = this.calcMeshMatrix(item, option) const matrix = this.calcMeshMatrix(item, option)
point.applyMatrix4(matrix) point.setMatrix4(matrix)
point.visible = ((typeof item.v !== 'undefined') ? item.v : true) point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
return point return point

16
src/core/manager/EnvManager.ts

@ -7,7 +7,6 @@ import AmrMessageManager from '@/core/manager/amr/AmrMessageManager'
import { AmrMsg } from '@/core/manager/amr/AmrMessageDefine' import { AmrMsg } from '@/core/manager/amr/AmrMessageDefine'
export default class EnvManager { export default class EnvManager {
private viewport: Viewport
private amrMessageManager: AmrMessageManager = new AmrMessageManager() private amrMessageManager: AmrMessageManager = new AmrMessageManager()
public client: mqtt.MqttClient = null public client: mqtt.MqttClient = null
@ -105,9 +104,10 @@ export default class EnvManager {
this.client = null this.client = null
} }
this.clearExecutors() if (window['viewport']) {
this.clearInv() const viewport = window['viewport'] as Viewport
this.viewport?.runtimeManager?.clear() viewport?.runtimeManager?.clear()
}
} finally { } finally {
system.clearLoading() system.clearLoading()
@ -115,14 +115,6 @@ export default class EnvManager {
} }
} }
clearInv() {
}
clearExecutors() {
}
/** /**
* *
* @param worldId ID * @param worldId ID

7
src/core/script/LCCScript.ts

@ -66,6 +66,13 @@ export default class LCCScript implements LCC {
}) })
} }
queryDeviceInfoList(): Promise<ServerResponse<DeviceVo[]>> {
return Request.request.post('/api/workbench/LccController@queryDeviceInfoList', {
projectUUID: worldModel.state.project_uuid,
envId: worldModel.state.runState.currentEnvId
})
}
// 从后台读取所有车 // 从后台读取所有车
async loadExecutor(): Promise<ExecutorVo> { async loadExecutor(): Promise<ExecutorVo> {
const res = await Request.request.post('/api/workbench/LccController@loadExecutor', { const res = await Request.request.post('/api/workbench/LccController@loadExecutor', {

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

@ -52,8 +52,8 @@
p-id="22185" fill="#ffffff"></path></svg> p-id="22185" fill="#ffffff"></path></svg>
</span> </span>
<div class="progress"> <div class="progress">
<span :style="{width:'55%'}"></span> <span :style="{width:getTaskProcessPercent(deviceInfo)+'%'}"></span>
<div class="text">55%</div> <div class="text"> {{ getTaskProcessPercent(deviceInfo) }} %</div>
</div> </div>
</div> </div>
<div class="data-infor"> <div class="data-infor">
@ -105,71 +105,31 @@ export default {
return { return {
searchKeyword: '', searchKeyword: '',
selectedId: '', selectedId: '',
/*
设备列表, 数据展示为:
[
{
id: 'device-id',
type: 'device-type',
online: true,
x: 0,
y: 0,
z: 0,
logicX: 0,
logicY: 0,
direction: 'up',
orientation: 0,
soc: 100,
mode: 'AMR_FREE_MODE',
taskStatus: 'IDLE',
isBlocked: false,
taskCompleted: 0,
taskTotalCount: 10
}
]
*/
/** /**
* 设备列表数据 * 设备列表数据
* @type {Array<{ * @type {Array<DeviceVo>}
id: string,
type: string,
online: boolean,
x: number,
y: number,
z: number,
logicX: number,
logicY: number,
direction: string,
orientation: number,
soc: number,
mode: 'AMR_FREE_MODE' |
'AMR_INIT_MODE' |
'AMR_TASK_MODE' |
'AMR_SINGLE_ACTION_MODE' |
'AMR_MANUAL_MODE' |
'AMR_HANDSET_MODE' |
'AMR_CHARGE_MODE' |
'AMR_TASK_INTERRUPT_MODE' |
'AMR_CUSTOMIZE_MODE',
taskStatus: string,
isBlocked: boolean,
taskCompleted: number,
taskTotalCount: number
// ID
bizTaskId: string
// : / / / /
bizTaskType: '' | 'MOVE' |'CHARGE' |'CARRY' |'LOAD' |'UNLOAD'
// WAY_1_1 Rack1/0/0/0
bizTaskFrom: string
// WAY_1_1 Rack1/0/0/0 charge1
bizTaskTo: string
}>}
*/ */
deviceList: [] deviceList: []
} }
}, },
mounted() {
window['MonitorView'] = this
},
unmounted() {
window['MonitorView'] = null
this.undescribe()
},
methods: { methods: {
/** /**
* 获取任务进度百分比
*/
getTaskProcessPercent(deviceInfo) {
if (deviceInfo == null || deviceInfo.taskTotalCount === 0) {
return 0
}
return Math.round((deviceInfo.taskCompleted / deviceInfo.taskTotalCount) * 100)
},
/**
* 处理设备存活消息 * 处理设备存活消息
* @type {(type: BackendTopicType, topic: string, body: { * @type {(type: BackendTopicType, topic: string, body: {
* id: string * id: string
@ -207,35 +167,11 @@ export default {
}, },
async subscribe() { async subscribe() {
this.deviceList = [] this.deviceList = []
const list = await LCC.loadExecutor() const res = await LCC.queryDeviceInfoList()
this.deviceList = _.map(list, executorVo => { if (!res.success) {
const row = { return
online: false }
} this.deviceList = res.data
return {
id: executorVo.executor_id,
type: row.type,
online: row.online,
x: row.x,
y: row.y,
z: row.z,
logicX: row.logicX,
logicY: row.logicY,
direction: row.direction,
orientation: row.orientation,
soc: row.soc,
mode: row.mode,
taskStatus: row.taskStatus,
isBlocked: row.isBlocked,
taskCompleted: row.taskCompleted || 0,
taskTotalCount: row.taskTotalCount || 0,
bizTaskId: row.bizTaskId || '',
bizTaskType: row.bizTaskType || '',
bizTaskFrom: row.bizTaskFrom || '',
bizTaskTo: row.bizTaskTo || ''
}
})
// //
LCC.subscribe('DeviceAlive', this.onDeviceAliveMessage) LCC.subscribe('DeviceAlive', this.onDeviceAliveMessage)

43
src/modules/pallet/PalletRenderer.ts

@ -8,7 +8,7 @@ import { loadGlbModule, loadTexture, processModel } from '@/core/ModelUtils.ts'
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/** /**
* *
*/ */
export default class PalletRenderer extends BaseRenderer { export default class PalletRenderer extends BaseRenderer {
static POINT_NAME = 'pallet_point' static POINT_NAME = 'pallet_point'
@ -24,34 +24,38 @@ export default class PalletRenderer extends BaseRenderer {
} }
palletGeometry: THREE.BufferGeometry palletGeometry: THREE.BufferGeometry
palletMaterial: THREE.Material palletMaterial: THREE.MeshPhongMaterial
private _isInitialized = false
async init() {
await super.init()
init() { const [glbGroup, palletTexture] = await Promise.all([
return Promise.all([
super.init(),
loadGlbModule(MODULE_PALLET_GLB), loadGlbModule(MODULE_PALLET_GLB),
loadTexture(MODULE_PALLET_TEX) loadTexture(MODULE_PALLET_TEX)
])
]).then(([_, glbGroup, palletTexture]) => { const mesh = glbGroup.children[0] as THREE.Mesh
const mesh = glbGroup.children[0] as THREE.Mesh
this.palletGeometry = processModel(mesh) this.palletGeometry = processModel(mesh)
this.palletMaterial = new THREE.MeshPhongMaterial({ color: 0x2b5d94 }) this.palletMaterial = new THREE.MeshPhongMaterial({ color: 0x2b5d94 })
palletTexture.flipY = true palletTexture.flipY = true
palletTexture.wrapS = THREE.RepeatWrapping palletTexture.wrapS = THREE.RepeatWrapping
palletTexture.wrapT = THREE.RepeatWrapping palletTexture.wrapT = THREE.RepeatWrapping
palletTexture.repeat.set(0.5, 0.5) palletTexture.repeat.set(0.5, 0.5)
//@ts-ignore this.palletMaterial.color.set(this.defaultUserData.color)
this.palletMaterial.color.set(this.defaultUserData.color) this.palletMaterial.map = palletTexture
//@ts-ignore this.palletMaterial.needsUpdate = true
this.palletMaterial.normalMap = palletTexture
}) this._isInitialized = true
} }
createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike { createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
if (!this._isInitialized) {
throw new Error('Renderer not initialized')
}
return this.pointManager.createByItem(item) return this.pointManager.createByItem(item)
} }
@ -59,6 +63,9 @@ export default class PalletRenderer extends BaseRenderer {
if (!this.tempViewport) { if (!this.tempViewport) {
throw new Error('tempViewport is not set.') throw new Error('tempViewport is not set.')
} }
if (!this._isInitialized) {
throw new Error('Renderer not ready')
}
return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () => return this.tempViewport.getOrCreateMeshManager(this.itemTypeName, () =>
// 构建 InstanceMesh 代理对象 // 构建 InstanceMesh 代理对象
new InstanceMeshManager(this.itemTypeName, new InstanceMeshManager(this.itemTypeName,

46
src/modules/tote/ToteRenderer.ts

@ -8,7 +8,7 @@ import { load3DModule, loadByUrl, loadTexture, processModel } from '@/core/Model
import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts' import InstanceMeshManager from '@/core/manager/InstanceMeshManager.ts'
/** /**
* *
*/ */
export default class PalletRenderer extends BaseRenderer { export default class PalletRenderer extends BaseRenderer {
static POINT_NAME = 'pallet_point' static POINT_NAME = 'pallet_point'
@ -26,50 +26,6 @@ export default class PalletRenderer extends BaseRenderer {
toteGeometry: THREE.BufferGeometry toteGeometry: THREE.BufferGeometry
toteMaterial: THREE.Material toteMaterial: THREE.Material
//
// processModel(mesh: THREE.Mesh) {
// const geometry = mesh.geometry.clone() as THREE.BufferGeometry
// geometry.rotateX(-Math.PI / 2)
//
// // 获取原始包围盒
// //@ts-ignore
// const box = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
// const size = new THREE.Vector3()
// box.getSize(size)
//
// // 计算缩放因子:让整个包围盒变成 1x1x1 的立方体
// const scaleX = 1 / size.x
// const scaleY = 1 / size.y
// const scaleZ = 1 / size.z
//
// // 缩放几何体到 1x1x1 立方体(保持原点不变)
// geometry.scale(scaleX, scaleY, scaleZ)
//
// // 更新包围盒
// //@ts-ignore
// const scaledBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
// const center = new THREE.Vector3()
// scaledBox.getCenter(center)
//
// // 平移:让中心在 (0, height/2, 0),底部贴地
// const translate = new THREE.Matrix4().makeTranslation(
// -center.x,
// -scaledBox.min.y, // 保证底部贴地
// -center.z
// )
// geometry.applyMatrix4(translate)
//
// // 可选:验证最终包围盒
// //@ts-ignore
// const finalBox = new THREE.Box3().setFromBufferAttribute(geometry.attributes.position)
// const finalSize = new THREE.Vector3()
// finalBox.getSize(finalSize)
// console.log('最终包围盒大小:', finalSize) // 应该是 (1, 1, 1)
// console.log('包围盒底部 Y 值:', finalBox.min.y) // 应该是 0
//
// return geometry
// }
init() { init() {
return Promise.all([ return Promise.all([
super.init(), super.init(),

45
src/types/LCC.d.ts

@ -46,6 +46,11 @@ declare interface LCC {
* @param eventHandler * @param eventHandler
*/ */
unsubscribe(topicType: BackendTopicType, eventHandler: BackendMessageHandler); unsubscribe(topicType: BackendTopicType, eventHandler: BackendMessageHandler);
/**
*
*/
queryDeviceInfoList(): Promise<ServerResponse<DeviceVo[]>>
} }
/** /**
@ -54,17 +59,32 @@ declare interface LCC {
type BackendTopicType = 'ServerState' | 'ClientState' | 'TaskUpdate' | 'InvUpdate' | type BackendTopicType = 'ServerState' | 'ClientState' | 'TaskUpdate' | 'InvUpdate' |
'DeviceStatus' | 'DeviceAlive' | 'Logs' | 'Alarm' | 'ScriptUpdate' 'DeviceStatus' | 'DeviceAlive' | 'Logs' | 'Alarm' | 'ScriptUpdate'
type DeviceAliveFn = (type: BackendTopicType, topic: string, body: { type DeviceAliveFn = (type: BackendTopicType, topic: string, body: DeviceAliveVo) => void
type DeviceStatusFn = (type: BackendTopicType, topic: string, body: DeviceVo) => void
/**
*
*/
type BackendMessageHandler = (type: BackendTopicType, topic: string, message: any) => void
type ContainerT = 'pallet' | 'tote' | 'carton' | 'box'
interface DeviceAliveVo {
id: string id: string
type: string type: string
online: boolean online: boolean
}) => void }
type DeviceStatusFn = (type: BackendTopicType, topic: string, body: { interface DeviceVo {
// 设备 ID // 设备 ID
id: string id: string
// 设备类型 // 设备类型
type: string type: string
// 是否在线
isOnline: boolean
// 是否系统托管
isSystemManaged: boolean
// 设备x,y,z坐标 // 设备x,y,z坐标
x: number x: number
y: number y: number
@ -88,15 +108,7 @@ type DeviceStatusFn = (type: BackendTopicType, topic: string, body: {
// AMR_CHARGE_MODE=充电模式; // AMR_CHARGE_MODE=充电模式;
// AMR_TASK_INTERRUPT_MODE=任务被中断模式; // AMR_TASK_INTERRUPT_MODE=任务被中断模式;
// AMR_CUSTOMIZE_MODE=自定义模式; // AMR_CUSTOMIZE_MODE=自定义模式;
mode: 'AMR_FREE_MODE' | mode: 'AMR_FREE_MODE' | 'AMR_INIT_MODE' | 'AMR_TASK_MODE' | 'AMR_SINGLE_ACTION_MODE' | 'AMR_MANUAL_MODE' | 'AMR_HANDSET_MODE' | 'AMR_CHARGE_MODE' | 'AMR_TASK_INTERRUPT_MODE' | 'AMR_CUSTOMIZE_MODE'
'AMR_INIT_MODE' |
'AMR_TASK_MODE' |
'AMR_SINGLE_ACTION_MODE' |
'AMR_MANUAL_MODE' |
'AMR_HANDSET_MODE' |
'AMR_CHARGE_MODE' |
'AMR_TASK_INTERRUPT_MODE' |
'AMR_CUSTOMIZE_MODE'
// 任务状态 ID: IDLE / PAUSED / EXECUTING // 任务状态 ID: IDLE / PAUSED / EXECUTING
taskStatus: string taskStatus: string
// 是否阻挡 // 是否阻挡
@ -117,14 +129,7 @@ type DeviceStatusFn = (type: BackendTopicType, topic: string, body: {
bizTaskTo: string bizTaskTo: string
// 搬运托盘号 // 搬运托盘号
bizLpn: string bizLpn: string
}) => void }
/**
*
*/
type BackendMessageHandler = (type: BackendTopicType, topic: string, message: any) => void
type ContainerT = 'pallet' | 'tote' | 'carton' | 'box'
interface InvVo { interface InvVo {
lpn: string lpn: string

Loading…
Cancel
Save