diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index 528fbc2..fb59d3a 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -21,6 +21,7 @@ const SimulationPlayer: React.FC = () => { // Button functions const handleReset = () => { setReset(true); + // setReset(!isReset); setSpeed(1); }; const handlePlayStop = () => { diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 86eee6a..399962e 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -66,7 +66,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { } //Waiting for trigger. else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && !robot.currentAction) { - console.log("trigger"); + setTimeout(() => { addCurrentAction(robot.modelUuid, 'action-003'); }, 3000); @@ -133,28 +133,28 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { const HandleCallback = () => { if (robot.isActive && robot.state == "running" && currentPhase == "init-to-rest") { - console.log("Callback triggered: rest"); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("rest"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "rest-to-start") { - console.log("Callback triggered: pick."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("picking"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "start-to-end") { - console.log("Callback triggered: drop."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("dropping"); setPath([]) } else if (robot.isActive && robot.state == "running" && currentPhase == "end-to-rest") { - console.log("Callback triggered: rest, cycle completed."); + setArmBotActive(robot.modelUuid, false) setArmBotState(robot.modelUuid, "idle") setCurrentPhase("rest"); @@ -163,7 +163,7 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { } } const logStatus = (id: string, status: string) => { - console.log(id +","+ status); + } return ( diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index dbc5064..1d21468 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -1,10 +1,11 @@ import { useEffect, useRef, useState } from 'react' import { useFrame, useThree } from '@react-three/fiber'; -import { useFloorItems } from '../../../../../store/store'; +import { useActiveTool, useFloorItems } from '../../../../../store/store'; import * as THREE from 'three'; import { Line } from '@react-three/drei'; -import { useAnimationPlaySpeed, usePauseButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; +import useModuleStore from '../../../../../store/useModuleStore'; interface VehicleAnimatorProps { path: [number, number, number][]; @@ -18,8 +19,10 @@ interface VehicleAnimatorProps { function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { const { decrementVehicleLoad, vehicles } = useVehicleStore(); const { isPaused } = usePauseButtonStore(); + const { isPlaying, setIsPlaying } = usePlayButtonStore(); + const { activeModule } = useModuleStore(); const { speed } = useAnimationPlaySpeed(); - const { isReset } = useResetButtonStore(); + const { isReset, setReset } = useResetButtonStore(); const [restRotation, setRestingRotation] = useState(true); const [progress, setProgress] = useState(0); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); @@ -30,6 +33,12 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai let startTime: number; let pausedTime: number; let fixedInterval: number; + let coveredDistance = progressRef.current; + let accumulatedDistance = 0; + let index = 0; + const isPausedRef = useRef(false); + const pauseTimeRef = useRef(null); + useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { @@ -45,118 +54,52 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai setProgress(0); completedRef.current = false; }, [currentPath]); - // useEffect(() => { - // console.log('isReset: ', isReset); - // if (isReset) { - // reset(); - // setCurrentPath([]); - // setProgress(0); - // completedRef.current = false; - // decrementVehicleLoad(agvDetail.modelUuid, 0) - // } - // }, [isReset]) - - // useFrame((_, delta) => { - // const object = scene.getObjectByProperty('uuid', agvUuid); - // if (!object || currentPath.length < 2) return; - // if (isPaused) return; - - // let totalDistance = 0; - // const distances = []; - - // for (let i = 0; i < currentPath.length - 1; i++) { - // const start = new THREE.Vector3(...currentPath[i]); - // const end = new THREE.Vector3(...currentPath[i + 1]); - // const segmentDistance = start.distanceTo(end); - // distances.push(segmentDistance); - // totalDistance += segmentDistance; - // } - - // let coveredDistance = progressRef.current; - // let accumulatedDistance = 0; - // let index = 0; - - // while ( - // index < distances.length && - // coveredDistance > accumulatedDistance + distances[index] - // ) { - // accumulatedDistance += distances[index]; - // index++; - // } - - // if (index < distances.length) { - // const start = new THREE.Vector3(...currentPath[index]); - // const end = new THREE.Vector3(...currentPath[index + 1]); - // const segmentDistance = distances[index]; - - // const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); - // const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); - // const rotationSpeed = 2.0; - // const currentAngle = object.rotation.y; - - // let angleDifference = targetAngle - currentAngle; - // if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; - // if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - - // const maxRotationStep = rotationSpeed * delta; - // object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - - // const isAligned = Math.abs(angleDifference) < 0.01; - - // if (isAligned) { - // progressRef.current += delta * (speed * agvDetail.speed); - // coveredDistance = progressRef.current; - - // const t = (coveredDistance - accumulatedDistance) / segmentDistance; - // const position = start.clone().lerp(end, t); - // object.position.copy(position); - // } - // } - - // if (progressRef.current >= totalDistance) { - // if (restRotation) { - // const targetQuaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, 0, 0)); - // object.quaternion.slerp(targetQuaternion, delta * 2); - // const angleDiff = object.quaternion.angleTo(targetQuaternion); - // if (angleDiff < 0.01) { - // let objectRotation = agvDetail.point.rotation - // object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); - // setRestingRotation(false); - // } - // return; - // } - // } - - // if (progressRef.current >= totalDistance) { - // setRestingRotation(true); - // progressRef.current = 0; - // movingForward.current = !movingForward.current; - // setCurrentPath([]); - // handleCallBack(); - // if (currentPhase === 'pickup-drop') { - // requestAnimationFrame(firstFrame); - // } - // } - // }); useEffect(() => { - console.log('isReset: ', isReset); if (isReset) { reset(); setCurrentPath([]); setProgress(0); - progressRef.current = 0; completedRef.current = false; movingForward.current = true; - setRestingRotation(false); + progressRef.current = 0; + startTime = 0; + coveredDistance = 0; + setReset(false); + setRestingRotation(true); decrementVehicleLoad(agvDetail.modelUuid, 0); - console.log('agvDetail: ', vehicles); + const object = scene.getObjectByProperty('uuid', agvUuid); + if (object) { + object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]); + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + } } - }, [isReset]); + }, [isReset]) + + useEffect(() => { + console.log('isPlaying: ', isPlaying); + if (!isPlaying) { + reset(); + setCurrentPath([]); + setProgress(0); + completedRef.current = false; + movingForward.current = true; + progressRef.current = 0; + startTime = 0; + coveredDistance = 0; + setReset(false); + setRestingRotation(true); + decrementVehicleLoad(agvDetail.modelUuid, 0); + const object = scene.getObjectByProperty('uuid', agvUuid); + if (object) { + object.position.set(agvDetail.position[0], agvDetail.position[1], agvDetail.position[2]) + let objectRotation = agvDetail.point.rotation + object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); + } + } + }, [isPlaying]) useFrame((_, delta) => { - // If reset is active, don't run anything in frame - if (isReset) return; - const object = scene.getObjectByProperty('uuid', agvUuid); if (!object || currentPath.length < 2) return; if (isPaused) return; @@ -172,11 +115,11 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai totalDistance += segmentDistance; } - let coveredDistance = progressRef.current; - let accumulatedDistance = 0; - let index = 0; - while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) { + while ( + index < distances.length && + coveredDistance > accumulatedDistance + distances[index] + ) { accumulatedDistance += distances[index]; index++; } @@ -188,17 +131,16 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); + + const rotationSpeed = speed; const currentAngle = object.rotation.y; let angleDifference = targetAngle - currentAngle; if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI; if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI; - const rotationSpeed = 2.0; const maxRotationStep = rotationSpeed * delta; - const rotationStep = Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); - object.rotation.y += rotationStep; - + object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep); const isAligned = Math.abs(angleDifference) < 0.01; if (isAligned) { @@ -217,46 +159,104 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai object.quaternion.slerp(targetQuaternion, delta * 2); const angleDiff = object.quaternion.angleTo(targetQuaternion); if (angleDiff < 0.01) { - const objectRotation = agvDetail.point.rotation; + let objectRotation = agvDetail.point.rotation object.rotation.set(objectRotation[0], objectRotation[1], objectRotation[2]); setRestingRotation(false); } - } else { - setRestingRotation(true); - progressRef.current = 0; - movingForward.current = !movingForward.current; - setCurrentPath([]); - handleCallBack(); - if (currentPhase === 'pickup-drop') { - requestAnimationFrame(firstFrame); - } + return; + } + } + + if (progressRef.current >= totalDistance) { + setRestingRotation(true); + progressRef.current = 0; + movingForward.current = !movingForward.current; + setCurrentPath([]); + handleCallBack(); + if (currentPhase === 'pickup-drop') { + requestAnimationFrame(firstFrame); } } }); + let pauseTime: number = 0; + + + useEffect(() => { + // Update the pause state in the ref + isPausedRef.current = isPaused; + }, [isPaused]); function firstFrame() { const unLoadDuration = agvDetail.point.action.unLoadDuration; const droppedMaterial = agvDetail.currentLoad; - fixedInterval = (unLoadDuration / droppedMaterial) * 1000; + fixedInterval = ((unLoadDuration / droppedMaterial) * 1000) / speed; + // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; startTime = performance.now(); step(droppedMaterial); } function step(droppedMaterial: number) { - const elapsedTime = (performance.now() - startTime) * speed; + if (isPausedRef.current) { + // Handle pause logic + if (!pauseTimeRef.current) { + pauseTimeRef.current = performance.now(); // Set pause time only once + } + requestAnimationFrame(() => step(droppedMaterial)); // Continue calling step during pause + return; + } + + if (pauseTimeRef.current) { + // Adjust start time after resuming from pause + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; // Clear pause time + } + + const elapsedTime = performance.now() - startTime; // Calculate elapsed time + if (elapsedTime >= fixedInterval) { - console.log('fixedInterval: ', fixedInterval); - console.log('elapsedTime: ', elapsedTime); + + let droppedMat = droppedMaterial - 1; - decrementVehicleLoad(agvDetail.modelUuid, 1); - if (droppedMat === 0) return; - startTime = performance.now(); - requestAnimationFrame(() => step(droppedMat)); + decrementVehicleLoad(agvDetail.modelUuid, 1); // Decrement vehicle load + + if (droppedMat > 0) { + // Reset start time for the next step + startTime = performance.now(); + requestAnimationFrame(() => step(droppedMat)); // Continue with the next step + } else { + + return; // Exit when all materials are dropped + } } else { - requestAnimationFrame(() => step(droppedMaterial)); + requestAnimationFrame(() => step(droppedMaterial)); // Continue animation } } + + // function firstFrame() { + // const unLoadDuration = agvDetail.point.action.unLoadDuration; + // const droppedMaterial = agvDetail.currentLoad; + // fixedInterval = (unLoadDuration / droppedMaterial) * 1000; + // startTime = performance.now(); + // step(droppedMaterial); + // } + + // function step(droppedMaterial: number) { + // const elapsedTime = (performance.now() - startTime) * speed; + // if (elapsedTime >= fixedInterval) { + // + // + // let droppedMat = droppedMaterial - 1; + // decrementVehicleLoad(agvDetail.modelUuid, 1); + // if (droppedMat === 0) return; + // startTime = performance.now(); + // requestAnimationFrame(() => step(droppedMat)); + // } else { + // requestAnimationFrame(() => step(droppedMaterial)); + // } + // } + return ( <> {currentPath.length > 0 && ( diff --git a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx index 44a8ad8..a78101e 100644 --- a/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx +++ b/app/src/modules/simulation/vehicle/instances/instance/vehicleInstance.tsx @@ -29,17 +29,27 @@ function VehicleInstance({ agvDetail }: any) { [navMesh] ); - function vehicleStatus(modelid: string, status: string) { - // console.log(`AGV ${modelid}: ${status}`); + function vehicleStatus(modelId: string, status: string) { + // console.log(`AGV ${modelId}: ${status}`); } + // Function to reset everything function reset() { - console.log("runs"); + setCurrentPhase('stationed'); setVehicleActive(agvDetail.modelUuid, false); setVehicleState(agvDetail.modelUuid, 'idle'); setPath([]); - setCurrentPhase('stationed') } + // useEffect(() => { + // console.log('isReset: ', isReset); + // if (isReset) { + // reset(); + // } + // }, [isReset]); + + + + useEffect(() => { if (isPlaying) { if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') { @@ -90,6 +100,8 @@ function VehicleInstance({ agvDetail }: any) { setCurrentPhase('drop-pickup'); vehicleStatus(agvDetail.modelUuid, 'Started from dropping point, heading to pickup point'); } + } else { + reset() } }, [vehicles, currentPhase, path, isPlaying, isReset]); diff --git a/app/src/modules/simulation/vehicle/vehicles.tsx b/app/src/modules/simulation/vehicle/vehicles.tsx index f0b4d17..1b05888 100644 --- a/app/src/modules/simulation/vehicle/vehicles.tsx +++ b/app/src/modules/simulation/vehicle/vehicles.tsx @@ -2,11 +2,12 @@ import React, { useEffect } from 'react' import VehicleInstances from './instances/vehicleInstances'; import { useVehicleStore } from '../../../store/simulation/useVehicleStore'; import { useFloorItems } from '../../../store/store'; - +import { useSelectedEventSphere } from '../../../store/simulation/useSimulationStore'; +import * as THREE from "three" function Vehicles() { const { vehicles, addVehicle } = useVehicleStore(); - + const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere } = useSelectedEventSphere(); const { floorItems } = useFloorItems(); const vehicleStatusSample: VehicleEventSchema[] = [ @@ -95,7 +96,9 @@ function Vehicles() { ] } } - }, { + }, + + { modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79", modelName: "forklift", position: [98.85729337188162, 0, 38.36616546567653],