From 3703dc629d17f3fd20356b4bfeae6a33bcf44d8e Mon Sep 17 00:00:00 2001 From: Jerald-Golden-B Date: Sat, 10 May 2025 12:24:29 +0530 Subject: [PATCH] Refactor material handling: update loadCapacity to 1 in multiple components, enhance storage unit actions, and implement new store handler logic for improved material management --- .../IntialLoad/loadInitialFloorItems.ts | 2 +- .../geomentries/assets/addAssetModel.ts | 2 +- .../selectionControls/copyPasteControls.tsx | 2 +- .../selectionControls/duplicationControls.tsx | 2 +- .../actionHandler/useStoreHandler.ts | 38 +++++++ .../storageUnit/useStorageUnitActions.ts | 15 ++- .../simulation/actions/useActionHandler.ts | 2 +- .../triggerHandler/useTriggerHandler.ts | 48 ++++++-- .../instances/animator/vehicleAnimator.tsx | 6 +- .../instances/instance/vehicleInstance.tsx | 107 +++++++++++++++++- app/src/store/simulation/useVehicleStore.ts | 6 +- 11 files changed, 200 insertions(+), 30 deletions(-) create mode 100644 app/src/modules/simulation/actions/storageUnit/actionHandler/useStoreHandler.ts diff --git a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts index 651f2f9..e625116 100644 --- a/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts +++ b/app/src/modules/builder/IntialLoad/loadInitialFloorItems.ts @@ -204,7 +204,7 @@ function processLoadedModel( actionName: "Action 1", actionType: "travel", unLoadDuration: 5, - loadCapacity: 10, + loadCapacity: 1, steeringAngle: 0, pickUpPoint: null, unLoadPoint: null, diff --git a/app/src/modules/builder/geomentries/assets/addAssetModel.ts b/app/src/modules/builder/geomentries/assets/addAssetModel.ts index acb4ee8..6023422 100644 --- a/app/src/modules/builder/geomentries/assets/addAssetModel.ts +++ b/app/src/modules/builder/geomentries/assets/addAssetModel.ts @@ -265,7 +265,7 @@ async function handleModelLoad( actionName: "Action 1", actionType: "travel", unLoadDuration: 5, - loadCapacity: 10, + loadCapacity: 1, steeringAngle: 0, pickUpPoint: null, unLoadPoint: null, diff --git a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx index 9a47caf..82f21ab 100644 --- a/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/copyPasteControls.tsx @@ -209,7 +209,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas actionName: "Action 1", actionType: "travel", unLoadDuration: 5, - loadCapacity: 10, + loadCapacity: 1, steeringAngle: 0, pickUpPoint: null, unLoadPoint: null, diff --git a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx index e4eb9a1..3e951a3 100644 --- a/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx +++ b/app/src/modules/scene/controls/selectionControls/duplicationControls.tsx @@ -186,7 +186,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb actionName: "Action 1", actionType: "travel", unLoadDuration: 5, - loadCapacity: 10, + loadCapacity: 1, steeringAngle: 0, pickUpPoint: null, unLoadPoint: null, diff --git a/app/src/modules/simulation/actions/storageUnit/actionHandler/useStoreHandler.ts b/app/src/modules/simulation/actions/storageUnit/actionHandler/useStoreHandler.ts new file mode 100644 index 0000000..92c1575 --- /dev/null +++ b/app/src/modules/simulation/actions/storageUnit/actionHandler/useStoreHandler.ts @@ -0,0 +1,38 @@ +import { useCallback } from "react"; +import { useMaterialStore } from "../../../../../store/simulation/useMaterialStore"; +import { useStorageUnitStore } from "../../../../../store/simulation/useStorageUnitStore"; +import { useProductStore } from "../../../../../store/simulation/useProductStore"; +import { useSelectedProduct } from "../../../../../store/simulation/useSimulationStore"; + +export function useStoreHandler() { + const { getMaterialById, removeMaterial } = useMaterialStore(); + const { addCurrentMaterial, updateCurrentLoad } = useStorageUnitStore(); + const { getModelUuidByActionUuid } = useProductStore(); + const { selectedProduct } = useSelectedProduct(); + + const storeLogStatus = (materialUuid: string, status: string) => { + // console.log(`${materialUuid}, ${status}`); + } + + const handleStore = useCallback((action: StorageAction, materialId?: string) => { + if (!action || action.actionType !== 'store' || !materialId) return; + + const material = getMaterialById(materialId); + if (!material) return; + + const modelUuid = getModelUuidByActionUuid(selectedProduct.productId, action.actionUuid); + + if (!modelUuid) return; + + removeMaterial(material.materialId); + addCurrentMaterial(modelUuid, material.materialType, material.materialId); + updateCurrentLoad(modelUuid, 1); + + storeLogStatus(material.materialId, `performed Store action`); + + }, [getMaterialById]); + + return { + handleStore, + }; +} \ No newline at end of file diff --git a/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts b/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts index bc1ab94..07b45f3 100644 --- a/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts +++ b/app/src/modules/simulation/actions/storageUnit/useStorageUnitActions.ts @@ -1,16 +1,19 @@ -import { useEffect, useCallback, useRef, useState } from 'react'; +import { useEffect, useCallback } from 'react'; +import { useStoreHandler } from './actionHandler/useStoreHandler'; export function useStorageActions() { - const handleStoreAction = useCallback((action: StorageAction) => { - if (!action || action.actionType !== 'store') return; - }, []); + const { handleStore } = useStoreHandler(); - const handleStorageAction = useCallback((action: StorageAction) => { + const handleStoreAction = useCallback((action: StorageAction, materialId: string) => { + handleStore(action, materialId); + }, [handleStore]); + + const handleStorageAction = useCallback((action: StorageAction, materialId: string) => { if (!action) return; switch (action.actionType) { case 'store': - handleStoreAction(action); + handleStoreAction(action, materialId); break; default: console.warn(`Unknown storage action type: ${action.actionType}`); diff --git a/app/src/modules/simulation/actions/useActionHandler.ts b/app/src/modules/simulation/actions/useActionHandler.ts index 30e0dad..a4c5d1a 100644 --- a/app/src/modules/simulation/actions/useActionHandler.ts +++ b/app/src/modules/simulation/actions/useActionHandler.ts @@ -36,7 +36,7 @@ export function useActionHandler() { handleMachineAction(action as MachineAction, materialId as string); break; case 'store': - handleStorageAction(action as StorageAction); + handleStorageAction(action as StorageAction, materialId as string); break; default: console.warn(`Unknown action type: ${(action as Action).actionType}`); diff --git a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts index 4f4a947..6b974d5 100644 --- a/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts +++ b/app/src/modules/simulation/triggers/triggerHandler/useTriggerHandler.ts @@ -6,6 +6,7 @@ import { useMaterialStore } from '../../../../store/simulation/useMaterialStore' import { useArmBotStore } from '../../../../store/simulation/useArmBotStore'; import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'; import { useMachineStore } from '../../../../store/simulation/useMachineStore'; +import { useStorageUnitStore } from '../../../../store/simulation/useStorageUnitStore'; export function useTriggerHandler() { const { handleAction } = useActionHandler(); @@ -14,6 +15,7 @@ export function useTriggerHandler() { const { getArmBotById } = useArmBotStore(); const { getVehicleById } = useVehicleStore(); const { getMachineById } = useMachineStore(); + const { getStorageUnitById } = useStorageUnitStore(); const { setCurrentLocation, setNextLocation, setPreviousLocation, getMaterialById, setIsPaused, setIsVisible, setEndTime } = useMaterialStore(); const handleTrigger = (trigger: TriggerSchema, action: Action, materialId?: string) => { @@ -219,10 +221,7 @@ export function useTriggerHandler() { setIsVisible(materialId, false); - if (action && armBot && - action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && - action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid - ) { + if (action && armBot) { if (armBot.isActive === false && armBot.state === 'idle') { @@ -240,7 +239,43 @@ export function useTriggerHandler() { } else if (toEvent?.type === 'storageUnit') { // Vehicle to Storage Unit + if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) { + const material = getMaterialById(materialId); + if (material) { + const action = getActionByUuid(selectedProduct.productId, trigger.triggeredAsset.triggeredAction.actionUuid); + const storageUnit = getStorageUnitById(trigger.triggeredAsset?.triggeredModel.modelUuid); + setPreviousLocation(material.materialId, { + modelUuid: material.current.modelUuid, + pointUuid: material.current.pointUuid, + actionUuid: material.current.actionUuid, + }) + + setCurrentLocation(material.materialId, { + modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid, + pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid, + actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid, + }); + + setNextLocation(material.materialId, null); + + setIsVisible(materialId, false); + + if (action && storageUnit) { + + if (storageUnit.currentLoad < storageUnit.point.action.storageCapacity) { + + // Handle current action from vehicle + handleAction(action, materialId); + + } else { + + // Event Manager Needed + + } + } + } + } } } else if (fromEvent?.type === 'machine') { if (toEvent?.type === 'transfer') { @@ -276,10 +311,7 @@ export function useTriggerHandler() { setIsVisible(materialId, false); - if (action && armBot && - action.triggers[0].triggeredAsset?.triggeredModel.modelUuid && - action.triggers[0].triggeredAsset?.triggeredPoint?.pointUuid - ) { + if (action && armBot) { if (armBot.isActive === false && armBot.state === 'idle') { diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index d2ecfc3..a3af481 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -73,6 +73,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai const distances = []; let accumulatedDistance = 0; let index = 0; + const rotationSpeed = 1; for (let i = 0; i < currentPath.length - 1; i++) { const start = new THREE.Vector3(...currentPath[i]); @@ -95,14 +96,13 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); - const rotationSpeed = speed; const currentAngle = object.rotation.y; let angleDifference = targetAngle - currentAngle; if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - const maxRotationStep = rotationSpeed * delta; + const maxRotationStep = (rotationSpeed * speed * agvDetail.speed) * delta; object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); const isAligned = Math.abs(angleDifference) < 0.01; @@ -122,7 +122,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai objectRotation.z ); const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); - object.quaternion.slerp(targetQuaternion, delta * 2); + object.quaternion.slerp(targetQuaternion, delta * (rotationSpeed * speed * agvDetail.speed)); if (object.quaternion.angleTo(targetQuaternion) < 0.01) { object.quaternion.copy(targetQuaternion); object.rotation.copy(targetEuler); diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index a97730b..88d2b4e 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -5,6 +5,7 @@ import { NavMeshQuery } from '@recast-navigation/core'; import { useNavMesh } from '../../../../../store/store'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; +import { useStorageUnitStore } from '../../../../../store/simulation/useStorageUnitStore'; import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore'; import { useProductStore } from '../../../../../store/simulation/useProductStore'; import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; @@ -14,7 +15,8 @@ import MaterialAnimator from '../animator/materialAnimator'; function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { const { navMesh } = useNavMesh(); const { isPlaying } = usePlayButtonStore(); - const { removeMaterial } = useMaterialStore(); + const { removeMaterial, addMaterial } = useMaterialStore(); + const { getStorageUnitById, addCurrentMaterial, updateCurrentLoad } = useStorageUnitStore(); const { triggerPointActions } = useTriggerHandler(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore(); const { selectedProduct } = useSelectedProduct(); @@ -154,7 +156,10 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) handleMaterialDropToArmBot(action); } } else if (model.type === 'storageUnit') { - // + const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid); + if (action) { + handleMaterialDropToStorageUnit(action); + } } } else { const droppedMaterial = agvDetail.currentLoad; @@ -168,6 +173,98 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) } } + function handleMaterialDropToStorageUnit(action: Action) { + if (action.triggers.length > 0 && action.triggers[0].triggeredAsset?.triggeredModel.modelUuid) { + const storageUnit = getStorageUnitById(action.triggers[0].triggeredAsset?.triggeredModel.modelUuid); + if (storageUnit) { + if (storageUnit.point.action.actionType === 'spawn') { + // const newMaterial: MaterialSchema = { + // materialId: THREE.MathUtils.generateUUID(), + // materialName: `${storageUnit.point.action.materialType}-${Date.now()}`, + // materialType: storageUnit.point.action.materialType || 'Default material', + // isActive: false, + // isVisible: true, + // isPaused: false, + // isRendered: true, + // startTime: performance.now(), + // current: { + // modelUuid: storageUnit.modelUuid, + // pointUuid: storageUnit.point.uuid, + // actionUuid: storageUnit.point.action.actionUuid + // }, + // }; + } else if (storageUnit.point.action.actionType === 'store') { + handleMaterialDropToStorage( + agvDetail.modelUuid, + agvDetail.currentLoad, + agvDetail.point.action.unLoadDuration, + storageUnit.modelUuid, + storageUnit.point.action.storageCapacity, + agvDetail.point.action + ); + } + } + } + } + + function handleMaterialDropToStorage( + vehicleId: string, + vehicleCurrentLoad: number, + unLoadDuration: number, + storageUnitId: string, + storageMaxCapacity: number, + action: VehicleAction + ) { + startTime = performance.now(); + const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / speed)); + + const unloadLoop = () => { + if (isPausedRef.current) { + pauseTimeRef.current ??= performance.now(); + requestAnimationFrame(unloadLoop); + return; + } + + if (pauseTimeRef.current) { + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; + } + + const elapsedTime = performance.now() - startTime; + const storageUnit = getStorageUnitById(storageUnitId); + + if (elapsedTime >= fixedInterval) { + if (storageUnit && agvDetail && + storageUnit.currentLoad < storageMaxCapacity && + vehicleCurrentLoad > 0) { + + decrementVehicleLoad(vehicleId, 1); + vehicleCurrentLoad -= 1; + + const material = removeLastMaterial(vehicleId); + if (material) { + + triggerPointActions(action, material.materialId); + + } + + if (vehicleCurrentLoad > 0 && storageUnit.currentLoad < storageMaxCapacity) { + startTime = performance.now(); + requestAnimationFrame(unloadLoop); + } + } + } else { + requestAnimationFrame(unloadLoop); + } + }; + + const storageUnit = getStorageUnitById(storageUnitId); + if (storageUnit && vehicleCurrentLoad > 0 && storageUnit?.currentLoad < storageMaxCapacity) { + unloadLoop(); + } + } + function handleMaterialDropToConveyor(action: Action) { if (agvDetail.currentLoad > 1) { // @@ -206,9 +303,9 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) if (elapsedTime >= fixedInterval) { let droppedMat = droppedMaterial - 1; decrementVehicleLoad(agvDetail.modelUuid, 1); - const materialId = removeLastMaterial(agvDetail.modelUuid); - if (materialId) { - removeMaterial(materialId); + const material = removeLastMaterial(agvDetail.modelUuid); + if (material) { + removeMaterial(material.materialId); } if (droppedMat > 0) { startTime = performance.now(); diff --git a/app/src/store/simulation/useVehicleStore.ts b/app/src/store/simulation/useVehicleStore.ts index 52d9ce0..f026edd 100644 --- a/app/src/store/simulation/useVehicleStore.ts +++ b/app/src/store/simulation/useVehicleStore.ts @@ -23,7 +23,7 @@ interface VehiclesStore { ) => void; addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void; setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void; - removeLastMaterial: (modelUuid: string) => string | undefined; + removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined; clearCurrentMaterials: (modelUuid: string) => void; incrementActiveTime: (modelUuid: string, incrementBy: number) => void; incrementIdleTime: (modelUuid: string, incrementBy: number) => void; @@ -153,14 +153,14 @@ export const useVehicleStore = create()( }, removeLastMaterial: (modelUuid) => { - let materialId: string | undefined; + let materialId: { materialId: string; materialType: string; } | undefined; set((state) => { const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); if (vehicle) { if (vehicle.currentMaterials.length > 0) { const material = vehicle.currentMaterials.pop(); if (material) { - materialId = material.materialId + materialId = { materialId: material.materialId, materialType: material.materialType }; } } }