Merge remote-tracking branch 'origin/dev-simulation/human' into main-demo

This commit is contained in:
2025-07-10 11:08:30 +05:30
10 changed files with 270 additions and 149 deletions

View File

@@ -16,7 +16,7 @@ import { getUserData } from '../../../../../functions/getUserData';
import { useSceneContext } from '../../../../scene/sceneContext'; import { useSceneContext } from '../../../../scene/sceneContext';
import { useVersionContext } from '../../../version/versionContext'; import { useVersionContext } from '../../../version/versionContext';
import { SkeletonUtils } from 'three-stdlib'; import { SkeletonUtils } from 'three-stdlib';
import { useAnimationPlaySpeed } from '../../../../../store/usePlayButtonStore'; import { useAnimationPlaySpeed, usePauseButtonStore } from '../../../../../store/usePlayButtonStore';
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi'; import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs'; import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
@@ -29,6 +29,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { speed } = useAnimationPlaySpeed(); const { speed } = useAnimationPlaySpeed();
const { isPaused } = usePauseButtonStore();
const { assetStore, eventStore, productStore } = useSceneContext(); const { assetStore, eventStore, productStore } = useSceneContext();
const { removeAsset, setAnimations, resetAnimation, setAnimationComplete } = assetStore(); const { removeAsset, setAnimations, resetAnimation, setAnimationComplete } = assetStore();
const { setTop } = useTopData(); const { setTop } = useTopData();
@@ -81,7 +82,8 @@ function Model({ asset }: { readonly asset: Asset }) {
if (!ikData && asset.eventData && asset.eventData.type === 'ArmBot') { if (!ikData && asset.eventData && asset.eventData.type === 'ArmBot') {
getAssetIksApi(asset.assetId).then((data) => { getAssetIksApi(asset.assetId).then((data) => {
if (data.iks) { if (data.iks) {
setIkData(data.iks); const iks: IK[] = data.iks;
setIkData(iks);
} }
}) })
} }
@@ -385,7 +387,7 @@ function Model({ asset }: { readonly asset: Asset }) {
const currentAction = actions.current[current]; const currentAction = actions.current[current];
const previousAction = previousAnimation ? actions.current[previousAnimation] : null; const previousAction = previousAnimation ? actions.current[previousAnimation] : null;
if (isPlaying && currentAction) { if (isPlaying && currentAction && activeModule === 'simulation' && !isPaused) {
blendFactor.current = 0; blendFactor.current = 0;
currentAction.reset(); currentAction.reset();
@@ -408,7 +410,7 @@ function Model({ asset }: { readonly asset: Asset }) {
mixerRef.current.removeEventListener('finished', handleAnimationComplete); mixerRef.current.removeEventListener('finished', handleAnimationComplete);
} }
}; };
}, [asset.animationState?.current, asset.animationState?.isPlaying]); }, [asset.animationState?.current, asset.animationState?.isPlaying, isPaused, activeModule]);
useEffect(() => { useEffect(() => {
const canvasElement = gl.domElement; const canvasElement = gl.domElement;
@@ -463,7 +465,7 @@ function Model({ asset }: { readonly asset: Asset }) {
position={asset.position} position={asset.position}
rotation={asset.rotation} rotation={asset.rotation}
visible={asset.isVisible} visible={asset.isVisible}
userData={asset} userData={{ ...asset, iks: ikData }}
onDoubleClick={(e) => { onDoubleClick={(e) => {
e.stopPropagation(); e.stopPropagation();
if (!toggleView) { if (!toggleView) {

View File

@@ -3,76 +3,97 @@ import { useFrame } from '@react-three/fiber';
import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../store/usePlayButtonStore'; import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../store/usePlayButtonStore';
import { useSceneContext } from '../../../scene/sceneContext'; import { useSceneContext } from '../../../scene/sceneContext';
type HumanCallback = {
humanId: string;
callback: () => void;
};
export function useHumanEventManager() { export function useHumanEventManager() {
const { humanStore } = useSceneContext(); const { humanStore } = useSceneContext();
const { getHumanById } = humanStore(); const { getHumanById } = humanStore();
const callbacksRef = useRef<HumanCallback[]>([]);
const callbacksRef = useRef<Map<string, (() => void)[]>>(new Map());
const isMonitoringRef = useRef(false); const isMonitoringRef = useRef(false);
const isCooldownRef = useRef<Map<string, boolean>>(new Map());
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isReset } = useResetButtonStore(); const { isReset } = useResetButtonStore();
useEffect(() => { useEffect(() => {
if (isReset) { if (isReset) {
callbacksRef.current = []; callbacksRef.current.clear();
isCooldownRef.current.clear();
} }
}, [isReset]) }, [isReset]);
// Add a new human to monitor
const addHumanToMonitor = (humanId: string, callback: () => void) => { const addHumanToMonitor = (humanId: string, callback: () => void) => {
// Avoid duplicates if (!callbacksRef.current.has(humanId)) {
if (!callbacksRef.current.some((entry) => entry.humanId === humanId)) { callbacksRef.current.set(humanId, []);
callbacksRef.current.push({ humanId, callback });
} }
callbacksRef.current.get(humanId)!.push(callback);
// Start monitoring if not already running
if (!isMonitoringRef.current) { if (!isMonitoringRef.current) {
isMonitoringRef.current = true; isMonitoringRef.current = true;
} }
}; };
// Remove a human from monitoring
const removeHumanFromMonitor = (humanId: string) => { const removeHumanFromMonitor = (humanId: string) => {
callbacksRef.current = callbacksRef.current.filter( callbacksRef.current.delete(humanId);
(entry) => entry.humanId !== humanId isCooldownRef.current.delete(humanId);
);
// Stop monitoring if no more humans to track if (callbacksRef.current.size === 0) {
if (callbacksRef.current.length === 0) {
isMonitoringRef.current = false; isMonitoringRef.current = false;
} }
}; };
// Check human states every frame
useFrame(() => { useFrame(() => {
if (!isMonitoringRef.current || callbacksRef.current.length === 0 || !isPlaying || isPaused) return;
callbacksRef.current.forEach(({ humanId, callback }) => { if (!isMonitoringRef.current || !isPlaying || isPaused) return;
callbacksRef.current.forEach((queue, humanId) => {
if (queue.length === 0 || isCooldownRef.current.get(humanId)) return;
const human = getHumanById(humanId); const human = getHumanById(humanId);
if (human?.point.action.actionType === 'worker') { const actionType = human?.point.action.actionType;
if (human && human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) {
callback(); let conditionMet = false;
removeHumanFromMonitor(humanId); // Remove after triggering
if (actionType === 'worker') {
conditionMet = Boolean(
human &&
human.isActive === false &&
human.state === 'idle' &&
human.isScheduled === false &&
human.currentLoad < human.point.action.loadCapacity
);
} else if (actionType === 'assembly') {
conditionMet = Boolean(
human &&
human.isActive === false &&
human.state === 'idle' &&
human.isScheduled === false
);
} }
} else if (human?.point.action.actionType === 'assembly') {
if (human && human.isActive === false && human.state === 'idle') { if (conditionMet) {
const callback = queue.shift();
if (callback) {
callback(); callback();
removeHumanFromMonitor(humanId); // Remove after triggering
if (queue.length === 0) {
removeHumanFromMonitor(humanId);
} else {
isCooldownRef.current.set(humanId, true);
setTimeout(() => {
isCooldownRef.current.set(humanId, false);
}, 1000);
}
} }
} }
}); });
}); });
// Cleanup on unmount
useEffect(() => { useEffect(() => {
return () => { return () => {
callbacksRef.current = []; callbacksRef.current.clear();
isMonitoringRef.current = false; isMonitoringRef.current = false;
isCooldownRef.current.clear();
}; };
}, []); }, []);

View File

@@ -27,7 +27,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore(); const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
const { selectedProductStore } = useProductContext(); const { selectedProductStore } = useProductContext();
const { selectedProduct } = selectedProductStore(); const { selectedProduct } = selectedProductStore();
const { setHumanActive, setHumanState, setHumanPicking, clearCurrentMaterials, setHumanLoad, decrementHumanLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore(); const { setHumanActive, setHumanState, clearCurrentMaterials, setHumanLoad, setHumanScheduled, decrementHumanLoad, removeLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore();
const [currentPhase, setCurrentPhase] = useState<string>('init'); const [currentPhase, setCurrentPhase] = useState<string>('init');
const [path, setPath] = useState<[number, number, number][]>([]); const [path, setPath] = useState<[number, number, number][]>([]);
@@ -86,8 +86,8 @@ function HumanInstance({ human }: { human: HumanStatus }) {
function reset() { function reset() {
setCurrentPhase('init'); setCurrentPhase('init');
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setHumanPicking(human.modelUuid, false);
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setHumanScheduled(human.modelUuid, false);
setHumanLoad(human.modelUuid, 0); setHumanLoad(human.modelUuid, 0);
resetAnimation(human.modelUuid); resetAnimation(human.modelUuid);
setPath([]); setPath([]);
@@ -125,7 +125,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
if (!human.isActive && human.state === 'idle' && currentPhase === 'init') { if (!human.isActive && human.state === 'idle' && currentPhase === 'init') {
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setCurrentPhase('waiting'); setCurrentPhase('waiting');
setHumanPicking(human.modelUuid, false);
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true); setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Human is waiting for material in assembly'); humanStatus(human.modelUuid, 'Human is waiting for material in assembly');
@@ -134,7 +133,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setCurrentAnimation(human.modelUuid, 'working_standing', true, true, false); setCurrentAnimation(human.modelUuid, 'working_standing', true, true, false);
setHumanState(human.modelUuid, 'running'); setHumanState(human.modelUuid, 'running');
setCurrentPhase('assembling'); setCurrentPhase('assembling');
setHumanPicking(human.modelUuid, true);
setHumanActive(human.modelUuid, true); setHumanActive(human.modelUuid, true);
processStartTimeRef.current = performance.now(); processStartTimeRef.current = performance.now();
@@ -152,8 +150,8 @@ function HumanInstance({ human }: { human: HumanStatus }) {
if (human.point.action.assemblyPoint && currentPhase === 'assembling') { if (human.point.action.assemblyPoint && currentPhase === 'assembling') {
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setCurrentPhase('waiting'); setCurrentPhase('waiting');
setHumanPicking(human.modelUuid, false);
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setHumanScheduled(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true); setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Human is waiting for material in assembly'); humanStatus(human.modelUuid, 'Human is waiting for material in assembly');
@@ -230,7 +228,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setPath(toPickupPath); setPath(toPickupPath);
setCurrentPhase('init-pickup'); setCurrentPhase('init-pickup');
setHumanState(human.modelUuid, 'running'); setHumanState(human.modelUuid, 'running');
setHumanPicking(human.modelUuid, false);
setHumanActive(human.modelUuid, true); setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true); setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
humanStatus(human.modelUuid, 'Started from init, heading to pickup'); humanStatus(human.modelUuid, 'Started from init, heading to pickup');
@@ -253,8 +250,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setPath(toDrop); setPath(toDrop);
setCurrentPhase('pickup-drop'); setCurrentPhase('pickup-drop');
setHumanState(human.modelUuid, 'running'); setHumanState(human.modelUuid, 'running');
setHumanPicking(human.modelUuid, false);
setHumanPicking(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true); setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
humanStatus(human.modelUuid, 'Started from pickup point, heading to drop point'); humanStatus(human.modelUuid, 'Started from pickup point, heading to drop point');
} }
@@ -278,7 +273,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
setPath(dropToPickup); setPath(dropToPickup);
setCurrentPhase('drop-pickup'); setCurrentPhase('drop-pickup');
setHumanState(human.modelUuid, 'running'); setHumanState(human.modelUuid, 'running');
setHumanPicking(human.modelUuid, false);
setHumanActive(human.modelUuid, true); setHumanActive(human.modelUuid, true);
setCurrentAnimation(human.modelUuid, 'walking', true, true, true); setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
humanStatus(human.modelUuid, 'Started from dropping point, heading to pickup point'); humanStatus(human.modelUuid, 'Started from dropping point, heading to pickup point');
@@ -295,7 +289,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
if (currentPhase === 'init-pickup') { if (currentPhase === 'init-pickup') {
setCurrentPhase('picking'); setCurrentPhase('picking');
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setHumanPicking(human.modelUuid, true);
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true); setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
humanStatus(human.modelUuid, 'Reached pickup point, waiting for material'); humanStatus(human.modelUuid, 'Reached pickup point, waiting for material');
@@ -303,7 +296,6 @@ function HumanInstance({ human }: { human: HumanStatus }) {
} else if (currentPhase === 'pickup-drop') { } else if (currentPhase === 'pickup-drop') {
setCurrentPhase('dropping'); setCurrentPhase('dropping');
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setHumanPicking(human.modelUuid, false);
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setCurrentAnimation(human.modelUuid, 'drop', true, false, false); setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
humanStatus(human.modelUuid, 'Reached drop point'); humanStatus(human.modelUuid, 'Reached drop point');
@@ -311,8 +303,8 @@ function HumanInstance({ human }: { human: HumanStatus }) {
} else if (currentPhase === 'drop-pickup') { } else if (currentPhase === 'drop-pickup') {
setCurrentPhase('picking'); setCurrentPhase('picking');
setHumanState(human.modelUuid, 'idle'); setHumanState(human.modelUuid, 'idle');
setHumanPicking(human.modelUuid, true);
setHumanActive(human.modelUuid, false); setHumanActive(human.modelUuid, false);
setHumanScheduled(human.modelUuid, false);
setPath([]); setPath([]);
clearCurrentMaterials(human.modelUuid); clearCurrentMaterials(human.modelUuid);
setCurrentAnimation(human.modelUuid, 'idle', true, true, true); setCurrentAnimation(human.modelUuid, 'idle', true, true, true);

View File

@@ -22,7 +22,7 @@ function IKInstance({ setIkSolver, armBot }: IKInstanceProps) {
const trySetup = () => { const trySetup = () => {
const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid); const targetMesh = scene?.getObjectByProperty("uuid", armBot.modelUuid);
if (!targetMesh) { if (!targetMesh || !targetMesh.userData.iks || targetMesh.userData.iks.length < 1) {
retryId = setTimeout(trySetup, 100); retryId = setTimeout(trySetup, 100);
return; return;
} }
@@ -33,34 +33,23 @@ function IKInstance({ setIkSolver, armBot }: IKInstanceProps) {
if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n; if (n.name === skinnedMeshName) OOI.Skinned_Mesh = n;
}); });
if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return; if (!OOI.Target_Bone || !OOI.Skinned_Mesh) return;
const iks = [
{ const rawIks: IK[] = targetMesh.userData.iks;
target: 7, const iks = rawIks.map((ik) => ({
effector: 6, target: ik.target,
links: [ effector: ik.effector,
{ links: ik.links.map((link) => ({
index: 5, index: link.index,
enabled: true, enabled: link.enabled,
rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), rotationMin: link.rotationMin ? new THREE.Vector3(...link.rotationMin) : undefined,
rotationMax: new THREE.Vector3(Math.PI / 2, 0, 0), rotationMax: link.rotationMax ? new THREE.Vector3(...link.rotationMax) : undefined,
}, limitation: link.limitation ? new THREE.Vector3(...link.limitation) : undefined,
{ })),
index: 4, minDistance: ik.minDistance,
enabled: true, maxDistance: ik.maxDistance,
rotationMin: new THREE.Vector3(-Math.PI / 2, 0, 0), maxheight: ik.maxheight,
rotationMax: new THREE.Vector3(0, 0, 0), minheight: ik.minheight,
}, }));
{
index: 3,
enabled: true,
rotationMin: new THREE.Vector3(0, 0, 0),
rotationMax: new THREE.Vector3(2, 0, 0),
},
{ index: 1, enabled: true, limitation: new THREE.Vector3(0, 1, 0) },
{ index: 0, enabled: false, limitation: new THREE.Vector3(0, 0, 0) },
],
},
];
const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks); const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
setIkSolver(solver); setIkSolver(solver);

View File

@@ -171,11 +171,22 @@ const ArmBotUI = () => {
} }
} }
const { handlePointerDown } = useDraggableGLTF(updatePointToState); const targetMesh = scene?.getObjectByProperty("uuid", selectedArmBotData?.modelUuid || '');
const { handlePointerDown } = useDraggableGLTF(
updatePointToState,
{
minDistance: targetMesh?.userData?.iks[0]?.minDistance || 1.2,
maxDistance: targetMesh?.userData?.iks[0]?.maxDistance || 2,
maxheight: targetMesh?.userData?.iks[0]?.maxheight || 0.6,
minheight: targetMesh?.userData?.iks[0]?.minheight || 1.9,
}
);
if (!selectedArmBotData || !Array.isArray(selectedArmBotData.point?.actions)) { if (!selectedArmBotData || !Array.isArray(selectedArmBotData.point?.actions)) {
return null; // avoid rendering if no data yet return null;
} }
return ( return (
<> <>
{selectedArmBotData.point.actions.map((action: any) => { {selectedArmBotData.point.actions.map((action: any) => {

View File

@@ -1,15 +1,26 @@
import { useRef, useState } from "react"; import { useRef, useState } from "react";
import * as THREE from "three"; import * as THREE from "three";
import { ThreeEvent, useThree } from "@react-three/fiber"; import { ThreeEvent, useThree } from "@react-three/fiber";
import { import { useSelectedEventData } from "../../../../store/simulation/useSimulationStore";
useSelectedEventData,
} from "../../../../store/simulation/useSimulationStore";
import { useProductContext } from "../../products/productContext"; import { useProductContext } from "../../products/productContext";
import { useSceneContext } from "../../../scene/sceneContext"; import { useSceneContext } from "../../../scene/sceneContext";
type OnUpdateCallback = (object: THREE.Object3D) => void; type OnUpdateCallback = (object: THREE.Object3D) => void;
export default function useDraggableGLTF(onUpdate: OnUpdateCallback) { export default function useDraggableGLTF(
onUpdate: OnUpdateCallback,
constraints: {
minDistance?: number;
maxDistance?: number;
maxheight?: number;
minheight?: number;
} = {
minDistance: 1.2,
maxDistance: 2,
minheight: 0.6,
maxheight: 1.9
}
) {
const { productStore } = useSceneContext(); const { productStore } = useSceneContext();
const { getEventByModelUuid } = productStore(); const { getEventByModelUuid } = productStore();
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
@@ -120,8 +131,10 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
// CONSTRAIN MOVEMENT HERE: // CONSTRAIN MOVEMENT HERE:
const centerX = selectedArmBot.position[0]; const centerX = selectedArmBot.position[0];
const centerZ = selectedArmBot.position[2]; const centerZ = selectedArmBot.position[2];
const minDistance = 1.2; const minDistance = constraints.minDistance ?? 1.2;
const maxDistance = 2; const maxDistance = constraints.maxDistance ?? 2;
const minHeight = constraints.minheight ?? 0.6;
const maxHeight = constraints.maxheight ?? 1.9;
const delta = new THREE.Vector3(targetPosition.x - centerX, 0, targetPosition.z - centerZ); const delta = new THREE.Vector3(targetPosition.x - centerX, 0, targetPosition.z - centerZ);
@@ -169,9 +182,8 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) {
targetPosition.x = centerX + finalLocal.x; targetPosition.x = centerX + finalLocal.x;
targetPosition.z = centerZ + finalLocal.z; targetPosition.z = centerZ + finalLocal.z;
// Clamp Y axis using variables
// Clamp Y axis if needed targetPosition.y = Math.min(Math.max(targetPosition.y, minHeight), maxHeight);
targetPosition.y = Math.min(Math.max(targetPosition.y, 0.6), 1.9);
// Convert to local if parent exists // Convert to local if parent exists
if (parent) { if (parent) {

View File

@@ -22,7 +22,7 @@ export function useTriggerHandler() {
const { addMachineToMonitor } = useMachineEventManager(); const { addMachineToMonitor } = useMachineEventManager();
const { addHumanToMonitor } = useHumanEventManager(); const { addHumanToMonitor } = useHumanEventManager();
const { getVehicleById } = vehicleStore(); const { getVehicleById } = vehicleStore();
const { getHumanById } = humanStore(); const { getHumanById, setHumanScheduled } = humanStore();
const { getMachineById } = machineStore(); const { getMachineById } = machineStore();
const { getStorageUnitById } = storageUnitStore(); const { getStorageUnitById } = storageUnitStore();
const { getMaterialById, setCurrentLocation, setNextLocation, setPreviousLocation, setIsPaused, setIsVisible, setEndTime } = materialStore(); const { getMaterialById, setCurrentLocation, setNextLocation, setPreviousLocation, setIsPaused, setIsVisible, setEndTime } = materialStore();
@@ -334,12 +334,14 @@ export function useTriggerHandler() {
setIsVisible(materialId, false); setIsVisible(materialId, false);
} }
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addVehicleToMonitor(vehicle.modelUuid, addVehicleToMonitor(vehicle.modelUuid,
() => { () => {
@@ -362,12 +364,14 @@ export function useTriggerHandler() {
setIsVisible(materialId, false); setIsVisible(materialId, false);
} }
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addVehicleToMonitor(vehicle.modelUuid, addVehicleToMonitor(vehicle.modelUuid,
() => { () => {
@@ -386,24 +390,11 @@ export function useTriggerHandler() {
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid); const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
if (human) { if (human) {
if (human.isActive === false && human.state === 'idle') { if (human.isActive === false && human.state === 'idle') {
if (human && human.modelUuid === "cc62adae-7000-447b-b845-6d4910de503a") {
console.log(human);
}
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid); const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (conveyor) { if (conveyor) {
if (!conveyor.isPaused) {
// Handle current action from vehicle
if (action.actionType === 'worker') {
setIsVisible(materialId, false);
}
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addConveyorToMonitor(conveyor.modelUuid, addConveyorToMonitor(conveyor.modelUuid,
() => { () => {
@@ -414,24 +405,14 @@ export function useTriggerHandler() {
} }
) )
} }
}
} else { } else {
setIsPaused(materialId, true); setIsPaused(materialId, true);
addHumanToMonitor(human.modelUuid, () => { addHumanToMonitor(human.modelUuid, () => {
const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); const conveyor = getConveyorById(action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || '');
if (conveyor) { if (conveyor) {
if (!conveyor.isPaused) {
// Handle current action from vehicle
if (action.actionType === 'worker') {
setIsVisible(materialId, false);
}
setIsPaused(materialId, true);
handleAction(action, materialId);
} else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addConveyorToMonitor(conveyor.modelUuid, addConveyorToMonitor(conveyor.modelUuid,
() => { () => {
@@ -442,7 +423,6 @@ export function useTriggerHandler() {
} }
) )
} }
}
}) })
} }
} }
@@ -457,11 +437,13 @@ export function useTriggerHandler() {
if (action.actionType === 'worker') { if (action.actionType === 'worker') {
setIsVisible(materialId, false); setIsVisible(materialId, false);
} }
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addMachineToMonitor(machine.modelUuid, addMachineToMonitor(machine.modelUuid,
() => { () => {
@@ -483,11 +465,13 @@ export function useTriggerHandler() {
if (action.actionType === 'worker') { if (action.actionType === 'worker') {
setIsVisible(materialId, false); setIsVisible(materialId, false);
} }
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addMachineToMonitor(machine.modelUuid, addMachineToMonitor(machine.modelUuid,
() => { () => {
@@ -536,12 +520,14 @@ export function useTriggerHandler() {
if (action.actionType === 'worker') { if (action.actionType === 'worker') {
setIsVisible(materialId, false); setIsVisible(materialId, false);
} }
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addHumanToMonitor(human.modelUuid, addHumanToMonitor(human.modelUuid,
() => { () => {
if (action.actionType === 'worker') { if (action.actionType === 'worker') {
@@ -711,7 +697,6 @@ export function useTriggerHandler() {
setNextLocation(material.materialId, null); setNextLocation(material.materialId, null);
if (action && human) { if (action && human) {
if (human.isActive === false && human.state === 'idle') { if (human.isActive === false && human.state === 'idle') {
@@ -719,10 +704,13 @@ export function useTriggerHandler() {
// Handle current action from arm bot // Handle current action from arm bot
setIsVisible(materialId, false); setIsVisible(materialId, false);
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
setHumanScheduled(human.modelUuid, true);
addHumanToMonitor(human.modelUuid, addHumanToMonitor(human.modelUuid,
() => { () => {
setIsVisible(materialId, false); setIsVisible(materialId, false);
@@ -879,8 +867,10 @@ export function useTriggerHandler() {
const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || ''); const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || '');
if (previousModel) { if (previousModel) {
if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) { if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} else { } else {
setHumanScheduled(human.modelUuid, true);
addConveyorToMonitor(conveyor.modelUuid, addConveyorToMonitor(conveyor.modelUuid,
() => { () => {
handleAction(action, materialId) handleAction(action, materialId)
@@ -888,6 +878,7 @@ export function useTriggerHandler() {
) )
} }
} else { } else {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} }
// handleAction(action, materialId) // handleAction(action, materialId)
@@ -898,12 +889,14 @@ export function useTriggerHandler() {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle // Handle current action from vehicle
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addVehicleToMonitor(vehicle.modelUuid, addVehicleToMonitor(vehicle.modelUuid,
() => { () => {
@@ -913,6 +906,7 @@ export function useTriggerHandler() {
} }
} }
} else { } else {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} }
@@ -928,8 +922,11 @@ export function useTriggerHandler() {
const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || ''); const previousModel = getEventByModelUuid(selectedProduct.productUuid, material.previous?.modelUuid || '');
if (previousModel) { if (previousModel) {
if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) { if (previousModel.type === 'transfer' && previousModel.modelUuid === model.modelUuid) {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} else { } else {
setHumanScheduled(human.modelUuid, true);
addConveyorToMonitor(conveyor.modelUuid, addConveyorToMonitor(conveyor.modelUuid,
() => { () => {
handleAction(action, materialId) handleAction(action, materialId)
@@ -937,6 +934,7 @@ export function useTriggerHandler() {
) )
} }
} else { } else {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} }
} }
@@ -946,12 +944,14 @@ export function useTriggerHandler() {
if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) { if (vehicle.isActive === false && vehicle.state === 'idle' && vehicle.isPicking && vehicle.currentLoad < vehicle.point.action.loadCapacity) {
// Handle current action from vehicle // Handle current action from vehicle
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
// Handle current action using Event Manager // Handle current action using Event Manager
setIsPaused(materialId, true); setIsPaused(materialId, true);
setHumanScheduled(human.modelUuid, true);
addVehicleToMonitor(vehicle.modelUuid, addVehicleToMonitor(vehicle.modelUuid,
() => { () => {
@@ -961,6 +961,7 @@ export function useTriggerHandler() {
} }
} }
} else { } else {
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId) handleAction(action, materialId)
} }
} }
@@ -1259,7 +1260,7 @@ export function useTriggerHandler() {
if (human) { if (human) {
if (human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) { if (human.isActive === false && human.state === 'idle' && !human.isScheduled && human.currentLoad < human.point.action.loadCapacity) {
setIsVisible(materialId, false); setIsVisible(materialId, false);
@@ -1276,6 +1277,7 @@ export function useTriggerHandler() {
}); });
// Handle current action from human // Handle current action from human
setHumanScheduled(human.modelUuid, true);
handleAction(action, materialId); handleAction(action, materialId);
} else { } else {
@@ -1460,14 +1462,60 @@ export function useTriggerHandler() {
actionUuid: material.current.actionUuid, actionUuid: material.current.actionUuid,
}); });
setIsPaused(material.materialId, true);
setIsVisible(material.materialId, true);
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
if (action && action.triggers.length > 0 &&
action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid &&
action.triggers[0]?.triggeredAsset?.triggeredAction?.actionUuid &&
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid) {
const model = getEventByModelUuid(selectedProduct.productUuid, action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid);
if (model?.type === 'roboticArm') {
addArmBotToMonitor(model.modelUuid, () => {
setNextLocation(material.materialId, { setNextLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid, modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid, pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid || '',
}) })
setIsPaused(material.materialId, false); setIsPaused(material.materialId, false);
setIsVisible(material.materialId, true); })
} else if (model?.type === 'vehicle') {
addVehicleToMonitor(model.modelUuid, () => {
setNextLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid || '',
})
setIsPaused(material.materialId, false);
})
} else if (model?.type === 'transfer') {
setNextLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid || '',
})
setIsPaused(material.materialId, false);
} else if (model?.type === 'human') {
addHumanToMonitor(model.modelUuid, () => {
setNextLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid || '',
})
setIsPaused(material.materialId, false);
})
} else {
setNextLocation(material.materialId, {
modelUuid: trigger.triggeredAsset?.triggeredModel.modelUuid || '',
pointUuid: trigger.triggeredAsset?.triggeredPoint?.pointUuid || '',
})
setIsPaused(material.materialId, false);
}
}
} }
} }
@@ -1510,8 +1558,31 @@ export function useTriggerHandler() {
} else { } else {
// Event Manager Needed setIsPaused(materialId, true);
addVehicleToMonitor(vehicle.modelUuid,
() => {
setIsPaused(materialId, false);
setIsVisible(materialId, false);
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);
// Handle current action from vehicle
handleAction(action, materialId);
}
)
} }
} }
} }

View File

@@ -5,6 +5,7 @@ import { generateSoloNavMesh } from "@recast-navigation/generators";
import { init as initRecastNavigation } from "@recast-navigation/core"; import { init as initRecastNavigation } from "@recast-navigation/core";
import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three"; import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three";
import { useSceneContext } from "../../../scene/sceneContext"; import { useSceneContext } from "../../../scene/sceneContext";
import { useToggleView } from "../../../../store/builder/store";
interface NavMeshDetailsProps { interface NavMeshDetailsProps {
setNavMesh: (navMesh: any) => void; setNavMesh: (navMesh: any) => void;
@@ -19,8 +20,10 @@ export default function NavMeshDetails({
const { aisles } = aisleStore(); const { aisles } = aisleStore();
const { scene } = useThree(); const { scene } = useThree();
const { walls } = wallStore(); const { walls } = wallStore();
const { toggleView } = useToggleView();
useEffect(() => { useEffect(() => {
if (toggleView) return;
const initializeNavigation = async () => { const initializeNavigation = async () => {
try { try {
await initRecastNavigation(); await initRecastNavigation();
@@ -64,7 +67,7 @@ export default function NavMeshDetails({
}; };
initializeNavigation(); initializeNavigation();
}, [scene, groupRef, aisles, walls]); }, [scene, groupRef, aisles, walls, toggleView]);
return null; return null;
} }

View File

@@ -13,7 +13,7 @@ interface HumansStore {
clearHumans: () => void; clearHumans: () => void;
setHumanActive: (modelUuid: string, isActive: boolean) => void; setHumanActive: (modelUuid: string, isActive: boolean) => void;
setHumanPicking: (modelUuid: string, isPicking: boolean) => void; setHumanScheduled: (modelUuid: string, isPicking: boolean) => void;
setHumanLoad: (modelUuid: string, load: number) => void; setHumanLoad: (modelUuid: string, load: number) => void;
setHumanState: ( setHumanState: (
modelUuid: string, modelUuid: string,
@@ -51,7 +51,7 @@ export const createHumanStore = () => {
...event, ...event,
productUuid, productUuid,
isActive: false, isActive: false,
isPicking: false, isScheduled: false,
idleTime: 0, idleTime: 0,
activeTime: 0, activeTime: 0,
currentLoad: 0, currentLoad: 0,
@@ -92,11 +92,11 @@ export const createHumanStore = () => {
}); });
}, },
setHumanPicking: (modelUuid, isPicking) => { setHumanScheduled: (modelUuid, isScheduled) => {
set((state) => { set((state) => {
const human = state.humans.find(h => h.modelUuid === modelUuid); const human = state.humans.find(h => h.modelUuid === modelUuid);
if (human) { if (human) {
human.isPicking = isPicking; human.isScheduled = isScheduled;
} }
}); });
}, },

View File

@@ -224,7 +224,7 @@ interface StorageUnitStatus extends StorageEventSchema {
interface HumanStatus extends HumanEventSchema { interface HumanStatus extends HumanEventSchema {
productUuid: string; productUuid: string;
isActive: boolean; isActive: boolean;
isPicking: boolean; isScheduled: boolean;
idleTime: number; idleTime: number;
activeTime: number; activeTime: number;
currentLoad: number; currentLoad: number;
@@ -287,3 +287,23 @@ interface MaterialHistoryEntry {
} }
type MaterialHistorySchema = MaterialHistoryEntry[]; type MaterialHistorySchema = MaterialHistoryEntry[];
//IK
type Link = {
index: number;
enabled: boolean;
rotationMin?: [number, number, number];
rotationMax?: [number, number, number];
limitation?: [number, number, number];
};
type IK = {
target: number;
effector: number;
links: Link[];
minDistance?: number;
maxDistance?: number;
maxheight?: number;
minheight?: number;
} ;