Merge remote-tracking branch 'origin/v2' into v2-ui

This commit is contained in:
Vishnu 2025-05-16 12:43:29 +05:30
commit bb826b7bdb
8 changed files with 640 additions and 418 deletions

View File

@ -30,13 +30,10 @@ const GlobalProperties: React.FC = () => {
const { elevation, setElevation } = useElevation();
const { azimuth, setAzimuth } = useAzimuth();
const { renderDistance, setRenderDistance } = useRenderDistance();
const { setPlaneValue, setGridValue, planeValue, gridValue } =
useTileDistance();
useEffect(() => {}, [gridValue, planeValue]);
const { setPlaneValue, setGridValue, planeValue, gridValue } = useTileDistance();
const { socket } = useSocketStore();
const { limitDistance, setLimitDistance } = useLimitDistance();
const [distance, setDistance] = useState<number>(40);
useEffect(() => {}, [limitDistance]);
const [limitGridDistance, setLimitGridDistance] = useState(false);
const [gridDistance, setGridDistance] = useState<number>(3);
@ -57,6 +54,7 @@ const GlobalProperties: React.FC = () => {
setRenderDistance(30);
setLimitDistance(true);
};
const limitRenderDistance = async () => {
const email = localStorage.getItem("email");
const organization = email?.split("@")[1]?.split(".")[0] || "defaultOrg";
@ -205,6 +203,7 @@ const GlobalProperties: React.FC = () => {
setShadows(!shadows);
};
const toggleResetCamera = () => {
if (!toggleView) {
setResetCamera(true); // Trigger reset camera action

View File

@ -27,6 +27,7 @@ import addAssetModel from "../geomentries/assets/addAssetModel";
import { getFloorAssets } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi";
import useModuleStore from "../../../store/useModuleStore";
import { useEventsStore } from "../../../store/simulation/useEventsStore";
import { findEnvironment } from "../../../services/factoryBuilder/environment/findEnvironment";
const assetManagerWorker = new Worker(
new URL(
@ -77,6 +78,11 @@ const FloorItemsGroup = ({
const email = localStorage.getItem("email");
const organization = email!.split("@")[1].split(".")[0];
findEnvironment(
organization,
localStorage.getItem("userId")!
).then((evnironMentData) => {
let totalAssets = 0;
let loadedAssets = 0;
@ -111,7 +117,7 @@ const FloorItemsGroup = ({
itemsGroup,
setFloorItems,
addEvent,
renderDistance
evnironMentData.renderDistance
);
updateLoadingProgress(100);
}
@ -135,13 +141,14 @@ const FloorItemsGroup = ({
itemsGroup,
setFloorItems,
addEvent,
renderDistance
evnironMentData.renderDistance
);
updateLoadingProgress(100);
}
});
}
};
})
}, []);
useEffect(() => {

View File

@ -6,20 +6,22 @@ import { useSelectedProduct } from "../../../../../store/simulation/useSimulatio
import { useStorageUnitStore } from "../../../../../store/simulation/useStorageUnitStore";
import { useArmBotStore } from "../../../../../store/simulation/useArmBotStore";
import { useVehicleStore } from "../../../../../store/simulation/useVehicleStore";
import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore } from "../../../../../store/usePlayButtonStore";
import { usePlayButtonStore, usePauseButtonStore, useResetButtonStore, useAnimationPlaySpeed } from "../../../../../store/usePlayButtonStore";
export function useRetrieveHandler() {
const { addMaterial } = useMaterialStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid } = useProductStore();
const { getModelUuidByActionUuid, getPointUuidByActionUuid, getEventByModelUuid, getActionByUuid } = useProductStore();
const { getStorageUnitById, getLastMaterial, updateCurrentLoad, removeLastMaterial } = useStorageUnitStore();
const { getVehicleById, incrementVehicleLoad, addCurrentMaterial } = useVehicleStore();
const { selectedProduct } = useSelectedProduct();
const { getArmBotById, addCurrentAction } = useArmBotStore();
const { isPlaying } = usePlayButtonStore();
const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore();
const { isReset } = useResetButtonStore();
const [activeRetrievals, setActiveRetrievals] = useState<Map<string, { action: StorageAction, isProcessing: boolean, lastCheckTime: number }>>(new Map());
const retrievalTimeRef = useRef<Map<string, number>>(new Map());
const [initialDelayComplete, setInitialDelayComplete] = useState(false);
const delayTimerRef = useRef<NodeJS.Timeout | null>(null);
@ -125,7 +127,26 @@ export function useRetrieveHandler() {
const armBot = getArmBotById(triggeredModel.modelUuid);
isIdle = (armBot && !armBot.isActive && armBot.state === 'idle' && !armBot.currentAction) || false;
if (isIdle) {
if (!armBot) return;
if (!retrievalTimeRef.current.has(actionUuid) && isIdle) {
retrievalTimeRef.current.set(actionUuid, currentTime);
return;
}
const idleStartTime = retrievalTimeRef.current.get(actionUuid);
const minIdleTimeBeforeFirstRetrieval = 5000 / speed;
const minDelayBetweenRetrievals = 5000 / speed;
const canProceedFirstRetrieval = idleStartTime !== undefined &&
(currentTime - idleStartTime) >= minIdleTimeBeforeFirstRetrieval;
const lastRetrievalTime = retrievalTimeRef.current.get(`${actionUuid}_last`) ?? null;
const canProceedSubsequent = lastRetrievalTime === null ||
(currentTime - lastRetrievalTime) >= minDelayBetweenRetrievals;
const canProceed = lastRetrievalTime === null ? canProceedFirstRetrieval : canProceedSubsequent;
if (isIdle && canProceed) {
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
@ -138,13 +159,23 @@ export function useRetrieveHandler() {
const lastMaterial = getLastMaterial(storageUnit.modelUuid);
if (lastMaterial) {
if (retrieval.action.triggers[0].triggeredAsset.triggeredAction?.actionUuid) {
const action = getActionByUuid(selectedProduct.productId, retrieval.action.triggers[0].triggeredAsset.triggeredAction.actionUuid);
if (action && action.triggers.length > 0 && action.triggers[0].triggeredAsset?.triggeredModel.modelUuid) {
const model = getEventByModelUuid(selectedProduct.productId, action.triggers[0].triggeredAsset.triggeredModel.modelUuid);
if (model) {
if (model.type === 'vehicle') {
const vehicle = getVehicleById(model.modelUuid);
if (vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageUnit.point.action
);
if (material) {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0].triggeredAsset.triggeredAction?.actionUuid ?? '',
@ -154,26 +185,71 @@ export function useRetrieveHandler() {
retrieveLogStatus(material.materialName, `is being picked by ${armBot?.modelName}`);
}
}
} else {
const material = createNewMaterial(
lastMaterial.materialId,
lastMaterial.materialType,
storageUnit.point.action
);
if (material) {
addCurrentAction(
triggeredModel.modelUuid,
retrieval.action.triggers[0].triggeredAsset.triggeredAction?.actionUuid ?? '',
material.materialType,
material.materialId
);
retrieveLogStatus(material.materialName, `is being picked by ${armBot?.modelName}`);
}
}
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: false,
lastCheckTime: currentTime
lastCheckTime: currentTime,
});
return newRetrievals;
});
retrievalTimeRef.current.set(actionUuid, currentTime);
}
}
}
}
} else if (!isIdle) {
retrievalTimeRef.current.delete(actionUuid);
}
} else if (triggeredModel.type === 'vehicle') {
const vehicle = getVehicleById(triggeredModel.modelUuid);
isIdle = (vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking) || false;
isIdle = (vehicle && !vehicle.isActive && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) || false;
if (!vehicle) return;
// const loadDuration = vehicle.point.action.unLoadDuration;
if (isIdle) {
const loadDuration = vehicle.point.action.unLoadDuration;
let minDelayBetweenRetrievals = (loadDuration * 1000) / speed;
const minIdleTimeBeforeFirstRetrieval = 3000 / speed;
if (!retrievalTimeRef.current.has(actionUuid) && isIdle) {
retrievalTimeRef.current.set(actionUuid, currentTime);
return;
}
const idleStartTime = retrievalTimeRef.current.get(actionUuid);
const lastRetrievalTime = retrievalTimeRef.current.get(`${actionUuid}_last`) ?? null;
const canProceedFirstRetrieval = idleStartTime !== undefined &&
(currentTime - idleStartTime) >= minIdleTimeBeforeFirstRetrieval;
const canProceedSubsequent = lastRetrievalTime === null ||
(currentTime - lastRetrievalTime) >= minDelayBetweenRetrievals;
const canProceed = lastRetrievalTime === null ? canProceedFirstRetrieval : canProceedSubsequent;
if (isIdle && canProceed) {
setActiveRetrievals(prev => {
const newRetrievals = new Map(prev);
newRetrievals.set(actionUuid, {
@ -208,12 +284,17 @@ export function useRetrieveHandler() {
newRetrievals.set(actionUuid, {
...retrieval,
isProcessing: false,
lastCheckTime: currentTime
lastCheckTime: currentTime,
});
return newRetrievals;
});
}
retrievalTimeRef.current.set(actionUuid, currentTime);
retrievalTimeRef.current.set(`${actionUuid}_last`, currentTime);
} else if (!isIdle) {
retrievalTimeRef.current.delete(actionUuid);
retrievalTimeRef.current.delete(`${actionUuid}_last`);
}
}
});
@ -234,7 +315,7 @@ export function useRetrieveHandler() {
newRetrievals.set(action.actionUuid, {
action,
isProcessing: false,
lastCheckTime: performance.now()
lastCheckTime: performance.now(),
});
return newRetrievals;
});

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react'
import { useEffect } from 'react'
import MaterialInstances from './instances/materialInstances'
import { usePlayButtonStore, useResetButtonStore } from '../../../store/usePlayButtonStore';
import { useMaterialStore } from '../../../store/simulation/useMaterialStore';

View File

@ -228,11 +228,11 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
logStatus(armBot.modelUuid, "Moving armBot from rest point to start position.")
}
// Moving to Pick to Drop position
else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) {
else if (armBot && !armBot.isActive && armBot.state === "running" && currentPhase === "picking" && armBot.currentAction) {
requestAnimationFrame(firstFrame);
}
//Moving to drop point to restPosition
else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) {
else if (armBot && !armBot.isActive && armBot.state === "running" && currentPhase === "dropping" && armBot.currentAction) {
requestAnimationFrame(firstFrame);
}
} else {
@ -270,14 +270,14 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
else if (armBot.isActive && armBot.state == "running" && currentPhase == "rest-to-start") {
logStatus(armBot.modelUuid, "Callback triggered: pick.");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
setArmBotState(armBot.modelUuid, "running")
setCurrentPhase("picking");
setPath([])
}
else if (armBot.isActive && armBot.state == "running" && currentPhase == "start-to-end") {
logStatus(armBot.modelUuid, "Callback triggered: drop.");
setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle")
setArmBotState(armBot.modelUuid, "running")
setCurrentPhase("dropping");
setPath([])
}

View File

@ -414,6 +414,10 @@ export function useTriggerHandler() {
handleAction(action, material.materialId);
}
} else if (action) {
setNextLocation(material.materialId, null)
handleAction(action, material.materialId);
}
}

View File

@ -5,6 +5,8 @@ import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/builder/store';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore';
import { useConveyorStore } from '../../../../../store/simulation/useConveyorStore';
import { useStorageUnitStore } from '../../../../../store/simulation/useStorageUnitStore';
import { useMaterialStore } from '../../../../../store/simulation/useMaterialStore';
import { useProductStore } from '../../../../../store/simulation/useProductStore';
@ -20,10 +22,12 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
const { isPlaying } = usePlayButtonStore();
const { removeMaterial, setEndTime } = useMaterialStore();
const { getStorageUnitById } = useStorageUnitStore();
const { getArmBotById } = useArmBotStore();
const { getConveyorById } = useConveyorStore();
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, getLastMaterial } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]);
const pauseTimeRef = useRef<number | null>(null);
@ -147,9 +151,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);
@ -159,19 +160,19 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
if (model.type === 'transfer') {
const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToConveyor(action);
handleMaterialDropToConveyor(model);
}
} else if (model.type === 'machine') {
//
} else if (model.type === 'roboticArm') {
const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToArmBot(action);
handleMaterialDropToArmBot(model);
}
} else if (model.type === 'storageUnit') {
const action = getActionByUuid(selectedProduct.productId, agvDetail.point.action.actionUuid);
if (action) {
handleMaterialDropToStorageUnit(action);
handleMaterialDropToStorageUnit(model);
}
}
} else {
@ -186,25 +187,22 @@ 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 === 'store') {
handleMaterialDropToStorage(
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
if (model) {
if (model.point.action.actionType === 'store') {
loopMaterialDropToStorage(
agvDetail.modelUuid,
agvDetail.currentLoad,
agvDetail.point.action.unLoadDuration,
storageUnit.modelUuid,
storageUnit.point.action.storageCapacity,
model.modelUuid,
model.point.action.storageCapacity,
agvDetail.point.action
);
}
}
}
}
function handleMaterialDropToStorage(
function loopMaterialDropToStorage(
vehicleId: string,
vehicleCurrentLoad: number,
unLoadDuration: number,
@ -262,22 +260,138 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
}
}
function handleMaterialDropToConveyor(action: Action) {
if (agvDetail.currentLoad > 1) {
//
} else if (agvDetail.currentLoad === 1 && agvDetail.currentMaterials.length === 1) {
triggerPointActions(action, agvDetail.currentMaterials[0].materialId);
decrementVehicleLoad(agvDetail.modelUuid, 1);
removeLastMaterial(agvDetail.modelUuid);
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
const conveyor = getConveyorById(model.modelUuid);
if (conveyor) {
loopMaterialDropToConveyor(
agvDetail.modelUuid,
agvDetail.currentLoad,
conveyor.modelUuid,
agvDetail.point.action.unLoadDuration,
agvDetail.point.action
);
}
}
function handleMaterialDropToArmBot(action: Action) {
if (agvDetail.currentLoad > 1) {
//
} else if (agvDetail.currentLoad === 1 && agvDetail.currentMaterials.length === 1) {
triggerPointActions(action, agvDetail.currentMaterials[0].materialId);
function loopMaterialDropToConveyor(
vehicleId: string,
vehicleCurrentLoad: number,
conveyorId: string,
unLoadDuration: number,
action: VehicleAction
) {
startTime = performance.now();
const fixedInterval = unLoadDuration * (1000 / speed);
const dropLoop = () => {
if (isPausedRef.current) {
pauseTimeRef.current ??= performance.now();
requestAnimationFrame(dropLoop);
return;
}
if (pauseTimeRef.current) {
const pauseDuration = performance.now() - pauseTimeRef.current;
startTime += pauseDuration;
pauseTimeRef.current = null;
}
const elapsedTime = performance.now() - startTime;
const conveyor = getConveyorById(conveyorId);
if (elapsedTime >= fixedInterval) {
if (conveyor && !conveyor.isPaused && vehicleCurrentLoad > 0) {
decrementVehicleLoad(vehicleId, 1);
vehicleCurrentLoad -= 1;
const material = removeLastMaterial(vehicleId);
if (material) {
triggerPointActions(action, material.materialId);
}
if (vehicleCurrentLoad > 0) {
startTime = performance.now();
requestAnimationFrame(dropLoop);
}
} else if (!conveyor?.isActive) {
requestAnimationFrame(dropLoop);
}
} else {
requestAnimationFrame(dropLoop);
}
};
dropLoop();
}
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
const armBot = getArmBotById(model.modelUuid);
if (armBot && armBot.state === 'idle' && !armBot.isActive) {
loopMaterialDropToArmBot(
agvDetail.modelUuid,
agvDetail.currentLoad,
agvDetail.point.action.unLoadDuration,
model.modelUuid,
agvDetail.point.action
);
}
}
function loopMaterialDropToArmBot(
vehicleId: string,
vehicleCurrentLoad: number,
unLoadDuration: number,
armBotId: string,
action: VehicleAction
) {
startTime = performance.now();
const armBot = getArmBotById(armBotId);
if (!armBot || armBot.state !== 'idle' || armBot.isActive || vehicleCurrentLoad <= 0) {
return;
}
const checkIdleDuration = () => {
if (isPausedRef.current) {
pauseTimeRef.current ??= performance.now();
requestAnimationFrame(checkIdleDuration);
return;
}
if (pauseTimeRef.current) {
const pauseDuration = performance.now() - pauseTimeRef.current;
startTime += pauseDuration;
pauseTimeRef.current = null;
}
const elapsedTime = performance.now() - startTime;
if (elapsedTime >= unLoadDuration * (1000 / speed)) {
const material = getLastMaterial(vehicleId);
if (material) {
vehicleCurrentLoad -= 1;
triggerPointActions(action, material.materialId);
if (vehicleCurrentLoad > 0) {
setTimeout(() => {
const waitForNextTransfer = () => {
const currentArmBot = getArmBotById(armBotId);
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
startTime = performance.now();
loopMaterialDropToArmBot(vehicleId, vehicleCurrentLoad, unLoadDuration, armBotId, action);
} else {
requestAnimationFrame(waitForNextTransfer);
}
};
waitForNextTransfer();
}, 0)
}
}
} else {
requestAnimationFrame(checkIdleDuration);
}
};
checkIdleDuration();
}
function handleMaterialDropByDefault(droppedMaterial: number) {

View File

@ -25,6 +25,7 @@ interface VehiclesStore {
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string; }[]) => void;
removeLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
getLastMaterial: (modelUuid: string) => { materialId: string; materialType: string; } | undefined;
clearCurrentMaterials: (modelUuid: string) => void;
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
@ -179,6 +180,22 @@ export const useVehicleStore = create<VehiclesStore>()(
return removedMaterial;
},
getLastMaterial: (modelUuid) => {
let removedMaterial: { materialId: string; materialType: string; } | undefined;
set((state) => {
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);
if (vehicle) {
if (vehicle.currentMaterials.length > 0) {
removedMaterial = {
materialId: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialId,
materialType: vehicle.currentMaterials[vehicle.currentMaterials.length - 1].materialType
};
}
}
});
return removedMaterial;
},
clearCurrentMaterials: (modelUuid) => {
set((state) => {
const vehicle = state.vehicles.find((v) => v.modelUuid === modelUuid);