Enhance vehicle handling: add picking state management, update action handling in VehicleInstance, and refine useVehicleStore for improved vehicle interactions.

This commit is contained in:
2025-05-10 17:19:43 +05:30
parent e16a0a6d8b
commit c0a7eebecb
5 changed files with 131 additions and 70 deletions

View File

@@ -12,10 +12,10 @@ import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore } from "..
export function useRetrieveHandler() { export function useRetrieveHandler() {
const { addMaterial } = useMaterialStore(); const { addMaterial } = useMaterialStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid } = useProductStore(); const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid } = useProductStore();
const { getStorageUnitById, getLastMaterial } = useStorageUnitStore(); const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = useStorageUnitStore();
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = useVehicleStore();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const { getArmBotById, addCurrentAction } = useArmBotStore(); const { getArmBotById, addCurrentAction } = useArmBotStore();
const { getVehicleById } = useVehicleStore();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isReset } = useResetButtonStore(); const { isReset } = useResetButtonStore();
@@ -48,7 +48,7 @@ export function useRetrieveHandler() {
isPaused: false, isPaused: false,
isRendered: true, isRendered: true,
startTime: currentTime, startTime: currentTime,
previous:{ previous: {
modelUuid: modelUuid, modelUuid: modelUuid,
pointUuid: pointUuid, pointUuid: pointUuid,
actionUuid: action.actionUuid actionUuid: action.actionUuid
@@ -125,49 +125,94 @@ export function useRetrieveHandler() {
if (triggeredModel.type === 'roboticArm') { if (triggeredModel.type === 'roboticArm') {
const armBot = getArmBotById(triggeredModel.modelUuid); const armBot = getArmBotById(triggeredModel.modelUuid);
isIdle = armBot && !armBot.isActive && armBot.state === 'idle' && !armBot.currentAction || false; isIdle = armBot && !armBot.isActive && armBot.state === 'idle' && !armBot.currentAction || false;
} else if (triggeredModel.type === 'vehicle') {
const vehicle = getVehicleById(triggeredModel.modelUuid);
isIdle = vehicle && !vehicle.isActive && vehicle.state === 'idle' || false;
}
if (isIdle) { if (isIdle) {
setActiveRetrievals(prev => { setActiveRetrievals(prev => {
const newRetrievals = new Map(prev); const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, { newRetrievals.set(actionUuid, {
...retrieval, ...retrieval,
isProcessing: true, isProcessing: true,
lastCheckTime: currentTime lastCheckTime: currentTime
});
return newRetrievals;
}); });
return newRetrievals;
});
const lastMaterial = getLastMaterial(storageUnit.modelUuid); const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) { if (lastMaterial) {
const material = createNewMaterial( const material = createNewMaterial(
lastMaterial.materialId, lastMaterial.materialId,
lastMaterial.materialType, lastMaterial.materialType,
storageUnit.point.action storageUnit.point.action
);
if (material && triggeredModel.type === 'roboticArm') {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0].triggeredAsset.triggeredAction?.actionUuid || '',
material.materialType,
material.materialId
); );
if (material) {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0].triggeredAsset.triggeredAction?.actionUuid || '',
material.materialType,
material.materialId
);
}
} }
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: false,
lastCheckTime: currentTime
});
return newRetrievals;
});
} }
setActiveRetrievals(prev => { } else if (triggeredModel.type === 'vehicle') {
const newRetrievals = new Map(prev); const vehicle = getVehicleById(triggeredModel.modelUuid);
newRetrievals.set(actionUuid, { isIdle = vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking || false;
...retrieval,
isProcessing: false, if (!vehicle) return;
lastCheckTime: currentTime const loadDuration = vehicle.point.action.unLoadDuration;
if (isIdle) {
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: true,
lastCheckTime: currentTime
});
return newRetrievals;
}); });
return newRetrievals;
}); const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
if (vehicle?.currentLoad < vehicle.point.action.loadCapacity) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageUnit.point.action
);
if (material) {
removeLastMaterial(storageUnit.modelUuid);
updateCurrentLoad(storageUnit.modelUuid, -1)
incrementVehicleLoad(vehicle.modelUuid, 1);
addCurrentMaterial(vehicle.modelUuid, material.materialType, material.materialId);
}
}
}
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: false,
lastCheckTime: currentTime
});
return newRetrievals;
});
}
} }
}); });

View File

@@ -18,36 +18,33 @@ export function useActionHandler() {
const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions(); const { handleMachineAction, cleanup: cleanupMachine } = useMachineActions();
const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions(); const { handleStorageAction, cleanup: cleanupStorage } = useStorageActions();
const handleAction = useCallback( const handleAction = useCallback((action: Action, materialId?: string) => {
(action: Action, materialId?: string) => { if (!action) return;
if (!action) return; try {
try { switch (action.actionType) {
switch (action.actionType) { case 'default': case 'spawn': case 'swap': case 'delay': case 'despawn':
case 'default': case 'spawn': case 'swap': case 'delay': case 'despawn': handleConveyorAction(action as ConveyorAction, materialId as string);
handleConveyorAction(action as ConveyorAction, materialId as string); break;
break; case 'travel':
case 'travel': handleVehicleAction(action as VehicleAction, materialId as string);
handleVehicleAction(action as VehicleAction, materialId as string); break;
break; case 'pickAndPlace':
case 'pickAndPlace': handleRoboticArmAction(action as RoboticArmAction, materialId as string);
handleRoboticArmAction(action as RoboticArmAction, materialId as string); break;
break; case 'process':
case 'process': handleMachineAction(action as MachineAction, materialId as string);
handleMachineAction(action as MachineAction, materialId as string); break;
break; case 'store': case 'retrieve':
case 'store': case 'retrieve': handleStorageAction(action as StorageAction, materialId as string);
handleStorageAction(action as StorageAction, materialId as string); break;
break; default:
default: console.warn(`Unknown action type: ${(action as Action).actionType}`);
console.warn(`Unknown action type: ${(action as Action).actionType}`);
}
} catch (error) {
echo.error("Failed to handle action");
console.error("Error handling action:", error);
} }
}, } catch (error) {
[handleConveyorAction, handleVehicleAction, handleRoboticArmAction, handleMachineAction, handleStorageAction,] echo.error("Failed to handle action");
); console.error("Error handling action:", error);
}
}, [handleConveyorAction, handleVehicleAction, handleRoboticArmAction, handleMachineAction, handleStorageAction,]);
const cleanup = useCallback(() => { const cleanup = useCallback(() => {
cleanupConveyor(); cleanupConveyor();

View File

@@ -15,12 +15,12 @@ import MaterialAnimator from '../animator/materialAnimator';
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh(); const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { removeMaterial, addMaterial } = useMaterialStore(); const { removeMaterial } = useMaterialStore();
const { getStorageUnitById, addCurrentMaterial, updateCurrentLoad } = useStorageUnitStore(); const { getStorageUnitById } = useStorageUnitStore();
const { triggerPointActions } = useTriggerHandler(); const { triggerPointActions } = useTriggerHandler();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct(); const { selectedProduct } = useSelectedProduct();
const { vehicles, setVehicleActive, setVehicleState, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore(); const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed'); const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]); const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null); const pauseTimeRef = useRef<number | null>(null);
@@ -58,6 +58,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
function reset() { function reset() {
setCurrentPhase('stationed'); setCurrentPhase('stationed');
setVehicleActive(agvDetail.modelUuid, false); setVehicleActive(agvDetail.modelUuid, false);
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleState(agvDetail.modelUuid, 'idle'); setVehicleState(agvDetail.modelUuid, 'idle');
setVehicleLoad(agvDetail.modelUuid, 0); setVehicleLoad(agvDetail.modelUuid, 0);
setPath([]); setPath([]);
@@ -78,6 +79,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
setPath(toPickupPath); setPath(toPickupPath);
setCurrentPhase('stationed-pickup'); setCurrentPhase('stationed-pickup');
setVehicleState(agvDetail.modelUuid, 'running'); setVehicleState(agvDetail.modelUuid, 'running');
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true); setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup'); vehicleStatus(agvDetail.modelUuid, 'Started from station, heading to pickup');
return; return;
@@ -91,6 +93,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
setPath(toDrop); setPath(toDrop);
setCurrentPhase('pickup-drop'); setCurrentPhase('pickup-drop');
setVehicleState(agvDetail.modelUuid, 'running'); setVehicleState(agvDetail.modelUuid, 'running');
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true); setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point'); vehicleStatus(agvDetail.modelUuid, 'Started from pickup point, heading to drop point');
} }
@@ -104,6 +107,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
setPath(dropToPickup); setPath(dropToPickup);
setCurrentPhase('drop-pickup'); setCurrentPhase('drop-pickup');
setVehicleState(agvDetail.modelUuid, 'running'); setVehicleState(agvDetail.modelUuid, 'running');
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, true); setVehicleActive(agvDetail.modelUuid, true);
vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point');
} }
@@ -118,18 +122,21 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
if (currentPhase === 'stationed-pickup') { if (currentPhase === 'stationed-pickup') {
setCurrentPhase('picking'); setCurrentPhase('picking');
setVehicleState(agvDetail.modelUuid, 'idle'); setVehicleState(agvDetail.modelUuid, 'idle');
setVehiclePicking(agvDetail.modelUuid, true);
setVehicleActive(agvDetail.modelUuid, false); setVehicleActive(agvDetail.modelUuid, false);
vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material'); vehicleStatus(agvDetail.modelUuid, 'Reached pickup point, waiting for material');
setPath([]); setPath([]);
} else if (currentPhase === 'pickup-drop') { } else if (currentPhase === 'pickup-drop') {
setCurrentPhase('dropping'); setCurrentPhase('dropping');
setVehicleState(agvDetail.modelUuid, 'idle'); setVehicleState(agvDetail.modelUuid, 'idle');
setVehiclePicking(agvDetail.modelUuid, false);
setVehicleActive(agvDetail.modelUuid, false); setVehicleActive(agvDetail.modelUuid, false);
vehicleStatus(agvDetail.modelUuid, 'Reached drop point'); vehicleStatus(agvDetail.modelUuid, 'Reached drop point');
setPath([]); setPath([]);
} else if (currentPhase === 'drop-pickup') { } else if (currentPhase === 'drop-pickup') {
setCurrentPhase('picking'); setCurrentPhase('picking');
setVehicleState(agvDetail.modelUuid, 'idle'); setVehicleState(agvDetail.modelUuid, 'idle');
setVehiclePicking(agvDetail.modelUuid, true);
setVehicleActive(agvDetail.modelUuid, false); setVehicleActive(agvDetail.modelUuid, false);
setPath([]); setPath([]);
clearCurrentMaterials(agvDetail.modelUuid) clearCurrentMaterials(agvDetail.modelUuid)

View File

@@ -13,6 +13,7 @@ interface VehiclesStore {
clearvehicles: () => void; clearvehicles: () => void;
setVehicleActive: (modelUuid: string, isActive: boolean) => void; setVehicleActive: (modelUuid: string, isActive: boolean) => void;
setVehiclePicking: (modelUuid: string, isPicking: boolean) => void;
updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void; updateSteeringAngle: (modelUuid: string, steeringAngle: number) => void;
incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void; incrementVehicleLoad: (modelUuid: string, incrementBy: number) => void;
decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void; decrementVehicleLoad: (modelUuid: string, decrementBy: number) => void;
@@ -46,6 +47,7 @@ export const useVehicleStore = create<VehiclesStore>()(
...event, ...event,
productId, productId,
isActive: false, isActive: false,
isPicking: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
currentLoad: 0, currentLoad: 0,
@@ -89,6 +91,15 @@ export const useVehicleStore = create<VehiclesStore>()(
}); });
}, },
setVehiclePicking: (modelUuid, isPicking) => {
set((state) => {
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
if (vehicle) {
vehicle.isPicking = isPicking;
}
});
},
updateSteeringAngle: (modelUuid, steeringAngle) => { updateSteeringAngle: (modelUuid, steeringAngle) => {
set((state) => { set((state) => {
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid); const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);

View File

@@ -180,6 +180,7 @@ interface ArmBotStatus extends RoboticArmEventSchema {
interface VehicleStatus extends VehicleEventSchema { interface VehicleStatus extends VehicleEventSchema {
productId: string; productId: string;
isActive: boolean; isActive: boolean;
isPicking: boolean;
idleTime: number; idleTime: number;
activeTime: number; activeTime: number;
currentLoad: number; currentLoad: number;