Merge remote-tracking branch 'origin/simulation-agv-v2' into analysis

This commit is contained in:
Gomathi 2025-05-14 14:39:21 +05:30
commit 952602469d
7 changed files with 315 additions and 150 deletions
app/src
modules
market
simulation
machine/instances/machineInstance
vehicle/instances/instance
store/simulation

View File

@ -17,7 +17,6 @@ interface CardProps {
image: string;
description: string;
AssetID: string
modelUrl: string
onSelectCard: (cardData: {
assetName: string;
uploadedOn: number;
@ -38,13 +37,10 @@ const Card: React.FC<CardProps> = ({
image,
description,
AssetID,
modelUrl,
onSelectCard,
}) => {
const handleCardSelect = () => {
console.log('assetName: ', assetName);
console.log('AssetID: ', AssetID);
onSelectCard({
assetName, uploadedOn, price, rating, views, description, AssetID

View File

@ -45,7 +45,7 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
}) => {
setSelectedCard(cardData);
const res = await fetchGltfUrl(cardData.assetName, cardData.AssetID);
console.log("res: ", res);
// console.log("res: ", res);
setModelUrl(res.url);
};
return (
@ -66,7 +66,6 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
AssetID={assetDetail.AssetID}
image={assetDetail.thumbnail}
description={assetDetail.description}
modelUrl={modelUrl}
/>
</React.Fragment>
))}

View File

@ -33,7 +33,6 @@ const MarketPlace = () => {
try {
const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
setModels(filt.items);
console.log('filt.items: ', filt.items);
setFilteredModels(filt.items);
setisLoading(false);
} catch {

View File

@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react'
import { useMachineStore } from '../../../../../store/simulation/useMachineStore';
import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import MachineAnimator from '../animator/machineAnimator';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
@ -9,22 +9,94 @@ import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHa
function MachineInstance({ machineDetail }: { machineDetail: MachineStatus }) {
const [currentPhase, setCurrentPhase] = useState<string>('idle');
let isIncrememtable = useRef<boolean>(true);
const idleTimeRef = useRef<number>(0);
const activeTimeRef = useRef<number>(0);
const previousTimeRef = useRef<number | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
const isSpeedRef = useRef<number>(0);
const isPausedRef = useRef<boolean>(false);
const { isPlaying } = usePlayButtonStore();
const { machines, setMachineState, setMachineActive } = useMachineStore();
const { machines, setMachineState, setMachineActive, incrementIdleTime, incrementActiveTime, resetTime } = useMachineStore();
const { selectedProduct } = useSelectedProduct();
const { getActionByUuid } = useProductStore();
const { triggerPointActions } = useTriggerHandler();
const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore();
useEffect(() => {
isPausedRef.current = isPaused;
}, [isPaused]);
useEffect(() => {
isSpeedRef.current = speed;
}, [speed]);
const reset = () => {
setCurrentPhase("idle");
console.log("exit");
setMachineState(machineDetail.modelUuid, 'idle');
setMachineActive(machineDetail.modelUuid, false);
isIncrememtable.current = true;
isPausedRef.current = false;
resetTime(machineDetail.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
}
}
function machineStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`);
}
function animate(currentTime: number) {
if (previousTimeRef.current === null) {
previousTimeRef.current = currentTime;
}
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
previousTimeRef.current = currentTime;
if (machineDetail.isActive) {
if (!isPausedRef.current) {
activeTimeRef.current += deltaTime * isSpeedRef.current;
// console.log(' activeTimeRef.current: ', activeTimeRef.current);
}
} else {
if (!isPausedRef.current) {
idleTimeRef.current += deltaTime * isSpeedRef.current;
// console.log('idleTimeRef.curre: ', idleTimeRef.current);
}
}
animationFrameIdRef.current = requestAnimationFrame(animate);
}
useEffect(() => {
if (!isPlaying) return
if (!machineDetail.isActive) {
const roundedActiveTime = Math.round(activeTimeRef.current);
// console.log('Final Active Time:', roundedActiveTime, 'seconds');
incrementActiveTime(machineDetail.modelUuid, roundedActiveTime);
activeTimeRef.current = 0;
} else {
const roundedIdleTime = Math.round(idleTimeRef.current);
// console.log('Final Idle Time:', roundedIdleTime, 'seconds');
incrementIdleTime(machineDetail.modelUuid, roundedIdleTime);
idleTimeRef.current = 0;
}
if (animationFrameIdRef.current === null) {
animationFrameIdRef.current = requestAnimationFrame(animate);
}
return () => {
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
};
}, [machineDetail, isPlaying]);
useEffect(() => {
if (isPlaying) {

View File

@ -11,10 +11,7 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import MaterialAnimator from '../animator/materialAnimator';
type Timer = {
start: number | null;
active: boolean;
};
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore();
@ -23,20 +20,29 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { triggerPointActions } = useTriggerHandler();
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial } = useVehicleStore();
const { vehicles, setVehicleActive, setVehicleState, setVehiclePicking, clearCurrentMaterials, setVehicleLoad, decrementVehicleLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null);
const idleTimeRef = useRef<number>(0);
const activeTimeRef = useRef<number>(0);
const isPausedRef = useRef<boolean>(false);
const isSpeedRef = useRef<number>(0);
let startTime: number;
let fixedInterval: number;
const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore();
const previousTimeRef = useRef<number | null>(null);
const animationFrameIdRef = useRef<number | null>(null);
useEffect(() => {
isPausedRef.current = isPaused;
}, [isPaused]);
useEffect(() => {
isSpeedRef.current = speed;
}, [speed]);
const computePath = useCallback(
(start: any, end: any) => {
try {
@ -54,7 +60,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
);
function vehicleStatus(modelId: string, status: string) {
//
// console.log(`${modelId} , ${status}`);
}
// Function to reset everything
@ -68,6 +74,14 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
startTime = 0;
isPausedRef.current = false;
pauseTimeRef.current = 0;
resetTime(agvDetail.modelUuid)
activeTimeRef.current = 0
idleTimeRef.current = 0
previousTimeRef.current = null
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current)
animationFrameIdRef.current = null
}
}
useEffect(() => {
@ -115,12 +129,61 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point');
}
}
} else {
}
else {
reset()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [vehicles, currentPhase, path, isPlaying]);
function animate(currentTime: number) {
if (previousTimeRef.current === null) {
previousTimeRef.current = currentTime;
}
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
previousTimeRef.current = currentTime;
if (agvDetail.isActive) {
if (!isPausedRef.current) {
activeTimeRef.current += deltaTime * isSpeedRef.current;
}
} else {
if (!isPausedRef.current) {
idleTimeRef.current += deltaTime * isSpeedRef.current; // Scale idle time by speed
}
}
animationFrameIdRef.current = requestAnimationFrame(animate);
}
useEffect(() => {
if (!isPlaying) return
if (!agvDetail.isActive) {
const roundedActiveTime = Math.round(activeTimeRef.current);
// console.log('Final Active Time:', roundedActiveTime, 'seconds');
incrementActiveTime(agvDetail.modelUuid, roundedActiveTime);
activeTimeRef.current = 0;
} else {
const roundedIdleTime = Math.round(idleTimeRef.current);
// console.log('Final Idle Time:', roundedIdleTime, 'seconds');
incrementIdleTime(agvDetail.modelUuid, roundedIdleTime);
idleTimeRef.current = 0;
}
if (animationFrameIdRef.current === null) {
animationFrameIdRef.current = requestAnimationFrame(animate);
}
return () => {
if (animationFrameIdRef.current !== null) {
cancelAnimationFrame(animationFrameIdRef.current);
animationFrameIdRef.current = null;
}
};
}, [agvDetail, isPlaying]);
function handleCallBack() {
if (currentPhase === 'stationed-pickup') {
setCurrentPhase('picking');
@ -147,9 +210,6 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
}
function startUnloadingProcess() {
if (agvDetail.point.action.triggers.length > 0) {
const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid);
@ -213,7 +273,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
action: VehicleAction
) {
startTime = performance.now();
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / speed));
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current));
const unloadLoop = () => {
if (isPausedRef.current) {
@ -295,7 +355,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const elapsedTime = performance.now() - startTime;
const unLoadDuration = agvDetail.point.action.unLoadDuration;
fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed));
fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / isSpeedRef.current));
if (elapsedTime >= fixedInterval) {
let droppedMat = droppedMaterial - 1;
@ -332,4 +392,10 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
);
}
export default VehicleInstance;
export default VehicleInstance;

View File

@ -1,154 +1,176 @@
import { create } from 'zustand';
import { immer } from 'zustand/middleware/immer';
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
interface MachineStore {
machines: MachineStatus[];
machines: MachineStatus[];
addMachine: (productId: string, machine: MachineEventSchema) => void;
removeMachine: (modelUuid: string) => void;
updateMachine: (
modelUuid: string,
updates: Partial<Omit<MachineStatus, 'modelUuid' | 'productId'>>
) => void;
clearMachines: () => void;
addMachine: (productId: string, machine: MachineEventSchema) => void;
removeMachine: (modelUuid: string) => void;
updateMachine: (
modelUuid: string,
updates: Partial<Omit<MachineStatus, "modelUuid" | "productId">>
) => void;
clearMachines: () => void;
addCurrentAction: (modelUuid: string, actionUuid: string, materialType: string, materialId: string) => void;
removeCurrentAction: (modelUuid: string) => void;
addCurrentAction: (
modelUuid: string,
actionUuid: string,
materialType: string,
materialId: string
) => void;
removeCurrentAction: (modelUuid: string) => void;
setMachineActive: (modelUuid: string, isActive: boolean) => void;
setMachineState: (modelUuid: string, newState: MachineStatus['state']) => void;
setMachineActive: (modelUuid: string, isActive: boolean) => void;
setMachineState: (
modelUuid: string,
newState: MachineStatus["state"]
) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
resetTime: (modelUuid: string) => void;
getMachineById: (modelUuid: string) => MachineStatus | undefined;
getMachinesByProduct: (productId: string) => MachineStatus[];
getMachinesBystate: (state: string) => MachineStatus[];
getActiveMachines: () => MachineStatus[];
getIdleMachines: () => MachineStatus[];
getMachineById: (modelUuid: string) => MachineStatus | undefined;
getMachinesByProduct: (productId: string) => MachineStatus[];
getMachinesBystate: (state: string) => MachineStatus[];
getActiveMachines: () => MachineStatus[];
getIdleMachines: () => MachineStatus[];
}
export const useMachineStore = create<MachineStore>()(
immer((set, get) => ({
machines: [],
immer((set, get) => ({
machines: [],
addMachine: (productId, machine) => {
set((state) => {
const exists = state.machines.some(m => m.modelUuid === machine.modelUuid);
if (!exists) {
state.machines.push({
...machine,
productId,
isActive: false,
idleTime: 0,
activeTime: 0,
state: 'idle',
});
}
});
},
addMachine: (productId, machine) => {
set((state) => {
const exists = state.machines.some(
(m) => m.modelUuid === machine.modelUuid
);
if (!exists) {
state.machines.push({
...machine,
productId,
isActive: false,
idleTime: 0,
activeTime: 0,
state: "idle",
});
}
});
},
removeMachine: (modelUuid) => {
set((state) => {
state.machines = state.machines.filter(m => m.modelUuid !== modelUuid);
});
},
removeMachine: (modelUuid) => {
set((state) => {
state.machines = state.machines.filter(
(m) => m.modelUuid !== modelUuid
);
});
},
updateMachine: (modelUuid, updates) => {
set((state) => {
const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) {
Object.assign(machine, updates);
}
});
},
updateMachine: (modelUuid, updates) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
Object.assign(machine, updates);
}
});
},
clearMachines: () => {
set((state) => {
state.machines = [];
});
},
clearMachines: () => {
set((state) => {
state.machines = [];
});
},
addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => {
set((state) => {
const armBot = state.machines.find(a => a.modelUuid === modelUuid);
if (armBot) {
const action = armBot.point.action;
if (action) {
armBot.currentAction = {
actionUuid: actionUuid,
actionName: action.actionName,
materialType: materialType,
materialId: materialId
};
}
}
});
},
addCurrentAction: (modelUuid, actionUuid, materialType, materialId) => {
set((state) => {
const armBot = state.machines.find((a) => a.modelUuid === modelUuid);
if (armBot) {
const action = armBot.point.action;
if (action) {
armBot.currentAction = {
actionUuid: actionUuid,
actionName: action.actionName,
materialType: materialType,
materialId: materialId,
};
}
}
});
},
removeCurrentAction: (modelUuid) => {
set((state) => {
const armBot = state.machines.find(a => a.modelUuid === modelUuid);
if (armBot) {
armBot.currentAction = undefined;
}
});
},
removeCurrentAction: (modelUuid) => {
set((state) => {
const armBot = state.machines.find((a) => a.modelUuid === modelUuid);
if (armBot) {
armBot.currentAction = undefined;
}
});
},
setMachineActive: (modelUuid, isActive) => {
set((state) => {
const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) {
machine.isActive = isActive;
}
});
},
setMachineActive: (modelUuid, isActive) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
machine.isActive = isActive;
}
});
},
setMachineState: (modelUuid, newState) => {
set((state) => {
const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) {
machine.state = newState;
}
});
},
setMachineState: (modelUuid, newState) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
machine.state = newState;
}
});
},
incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => {
const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) {
machine.activeTime += incrementBy;
}
});
},
incrementActiveTime: (modelUuid, incrementBy) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
machine.activeTime += incrementBy;
}
});
},
incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => {
const machine = state.machines.find(m => m.modelUuid === modelUuid);
if (machine) {
machine.idleTime += incrementBy;
}
});
},
incrementIdleTime: (modelUuid, incrementBy) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
machine.idleTime += incrementBy;
}
});
},
resetTime: (modelUuid) => {
set((state) => {
const machine = state.machines.find((m) => m.modelUuid === modelUuid);
if (machine) {
machine.activeTime = 0;
machine.idleTime = 0;
}
});
},
getMachineById: (modelUuid) => {
return get().machines.find(m => m.modelUuid === modelUuid);
},
getMachineById: (modelUuid) => {
return get().machines.find((m) => m.modelUuid === modelUuid);
},
getMachinesByProduct: (productId) => {
return get().machines.filter(m => m.productId === productId);
},
getMachinesByProduct: (productId) => {
return get().machines.filter((m) => m.productId === productId);
},
getMachinesBystate: (state) => {
return get().machines.filter(m => m.state === state);
},
getMachinesBystate: (state) => {
return get().machines.filter((m) => m.state === state);
},
getActiveMachines: () => {
return get().machines.filter(m => m.isActive);
},
getActiveMachines: () => {
return get().machines.filter((m) => m.isActive);
},
getIdleMachines: () => {
return get().machines.filter(m => !m.isActive && m.state === 'idle');
},
}))
getIdleMachines: () => {
return get().machines.filter((m) => !m.isActive && m.state === "idle");
},
}))
);

View File

@ -28,6 +28,7 @@ interface VehiclesStore {
clearCurrentMaterials: (modelUuid: string) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
resetTime: (modelUuid: string) => void;
getVehicleById: (modelUuid: string) => VehicleStatus | undefined;
getVehiclesByProduct: (productId: string) => VehicleStatus[];
@ -206,6 +207,16 @@ export const useVehicleStore = create<VehiclesStore>()(
});
},
resetTime: (modelUuid) => {
set((state) => {
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
if (vehicle) {
vehicle.activeTime = 0;
vehicle.idleTime = 0;
}
});
},
getVehicleById: (modelUuid) => {
return get().vehicles.find((v) => v.modelUuid === modelUuid);
},