Enhance vehicle handling: add picking state management, update action handling in VehicleInstance, and refine useVehicleStore for improved vehicle interactions.
This commit is contained in:
@@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
1
app/src/types/simulationTypes.d.ts
vendored
1
app/src/types/simulationTypes.d.ts
vendored
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user