From fe57e6c8739d35b702378a2bd5d6803c2e7f9dae Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Tue, 29 Apr 2025 19:01:06 +0530 Subject: [PATCH] playSpeed,reset,exit added and armbot movemets added --- .../instances/animator/roboticArmAnimator.tsx | 147 +++-- .../armInstance/roboticArmInstance.tsx | 567 +++++++++++++++--- .../instances/ikInstance/ikInstance.tsx | 17 +- .../instances/roboticArmInstances.tsx | 2 +- .../simulation/roboticArm/roboticArm.tsx | 4 +- .../simulation/ui/arm/useDraggableGLTF.ts | 2 +- 6 files changed, 576 insertions(+), 163 deletions(-) diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index c82b73d..611ded5 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -1,68 +1,117 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react' -import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; -import { useFrame, useThree } from '@react-three/fiber'; -import * as THREE from "three" -import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; +import React, { useEffect, useRef, useState } from 'react'; +import { useFrame } from '@react-three/fiber'; +import * as THREE from 'three'; +import { + useAnimationPlaySpeed, + usePauseButtonStore, + usePlayButtonStore, + useResetButtonStore +} from '../../../../../store/usePlayButtonStore'; +import { Line } from '@react-three/drei'; -function RoboticArmAnimator({ armUuid, HandleCallback, currentPhase, ikSolver, targetBone, robot, logStatus, groupRef, processes, armBotCurveRef, path }: any) { - const { armBots } = useArmBotStore(); - const { scene } = useThree(); - const restSpeed = 0.1; - const restPosition = new THREE.Vector3(0, 1, -1.6); - const initialCurveRef = useRef(null); - const initialStartPositionRef = useRef(null); - const [initialProgress, setInitialProgress] = useState(0); - const [progress, setProgress] = useState(0); - const [needsInitialMovement, setNeedsInitialMovement] = useState(true); - const [isInitializing, setIsInitializing] = useState(true); - const { isPlaying } = usePlayButtonStore(); - const statusRef = useRef("idle"); - // Create a ref for initialProgress - const initialProgressRef = useRef(0); +function RoboticArmAnimator({ + HandleCallback, + restPosition, + ikSolver, + targetBone, + armBot, + logStatus, + path +}: any) { + const progressRef = useRef(0); + const curveRef = useRef(null); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); + const [curvePoints, setCurvePoints] = useState(null); + + // Zustand stores + const { isPlaying } = usePlayButtonStore(); + const { isPaused } = usePauseButtonStore(); + const { isReset } = useResetButtonStore(); // optional use depending on your logic + const { speed } = useAnimationPlaySpeed(); useEffect(() => { - setCurrentPath(path) }, [path]) useEffect(() => { + if (!isPlaying) { + setCurrentPath([]) + curveRef.current = null + } + }, [isPlaying]) - }, [currentPath]) + useEffect(() => { + if (currentPath && currentPath.length === 3) { + const [start, mid, end] = currentPath; + const points = [ + new THREE.Vector3(start[0], start[1], start[2]), + new THREE.Vector3(start[0], mid[1] + 0.5, start[2]), + new THREE.Vector3(mid[0], mid[1] + 0.5, mid[2]), + new THREE.Vector3(mid[0], end[1] + 0.5, mid[2]), + new THREE.Vector3(end[0], end[1], end[2]) + ]; + const generatedCurve = new THREE.CatmullRomCurve3(points, false, 'centripetal', 1).getPoints(100); + // console.log('generatedCurve: ', generatedCurve); + curveRef.current = generatedCurve; + setCurvePoints(generatedCurve); + + } + }, [currentPath]); useFrame((_, delta) => { - if (!ikSolver || !currentPath || currentPath.length === 0) return; + if (ikSolver && curveRef.current && currentPath.length >= 0) { + const bone = ikSolver.mesh.skeleton.bones.find( + (b: any) => b.name === targetBone + ); + if (!bone) return; - const bone = ikSolver.mesh.skeleton.bones.find( - (b: any) => b.name === targetBone - ); - if (!bone) return; + if (isPlaying) { + if (!isPaused) { + const curvePoints = curveRef.current; + const speedAdjustedProgress = progressRef.current + (speed * armBot.speed); + const index = Math.floor(speedAdjustedProgress); + if (index >= curvePoints.length) { + HandleCallback(); + setCurrentPath([]); + curveRef.current = null; + progressRef.current = 0; + } else { + const point = curvePoints[index]; + bone.position.copy(point); + progressRef.current = speedAdjustedProgress; + } + } + } else { + logStatus(armBot.modelUuid, 'Simulation Play Exited'); + // bone.position.copy(restPosition); + } - // Ensure currentPath is a valid array of 3D points, create a CatmullRomCurve3 from it - const curve = new THREE.CatmullRomCurve3( - currentPath.map(point => new THREE.Vector3(point[0], point[1], point[2])) - ); + ikSolver.update(); + } else if (ikSolver && !isPlaying && currentPath.length === 0) { + const bone = ikSolver.mesh.skeleton.bones.find( + (b: any) => b.name === targetBone + ); + bone.position.copy(restPosition); + ikSolver.update(); + }; - - const next = initialProgressRef.current + delta * 0.5; - if (next >= 1) { - // bone.position.copy(restPosition); - HandleCallback(); // Call the callback when the path is completed - initialProgressRef.current = 0; // Set ref to 1 when done - } else { - const point = curve.getPoint(next); // Get the interpolated point from the curve - bone.position.copy(point); // Update the bone position along the curve - initialProgressRef.current = next; // Update progress - } - - ikSolver.update(); }); - - return ( - <> - ) + <> + {/* {currentPath.length > 0 && ( + <> + + {currentPath.map((point, index) => ( + + + + + ))} + + )} */} + + ); } -export default RoboticArmAnimator; \ No newline at end of file +export default RoboticArmAnimator; diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 3fe8af1..5f00a45 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -1,42 +1,100 @@ import React, { useEffect, useRef, useState } from 'react' import IKInstance from '../ikInstance/ikInstance'; import RoboticArmAnimator from '../animator/roboticArmAnimator'; -import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore'; +import { usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_4.glb"; import { useThree } from "@react-three/fiber"; import { useFloorItems } from '../../../../../store/store'; import useModuleStore from '../../../../../store/useModuleStore'; -import { Vector3 } from "three"; import * as THREE from "three"; -interface Process { - triggerId: string; - startPoint?: Vector3; - endPoint?: Vector3; - speed: number; -} +function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { -function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { - - const { isPlaying } = usePlayButtonStore(); const [currentPhase, setCurrentPhase] = useState<(string)>("init"); - const { scene } = useThree(); - const targetBone = "Target"; - const { activeModule } = useModuleStore(); + const [path, setPath] = useState<[number, number, number][]>([]); const [ikSolver, setIkSolver] = useState(null); + const { scene } = useThree(); + const restPosition = new THREE.Vector3(0, 1.75, -1.6); + const targetBone = "Target"; + const groupRef = useRef(null); + const pauseTimeRef = useRef(null); + const isPausedRef = useRef(false); + let startTime: number; + //zustand const { addCurrentAction, setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore(); const { floorItems } = useFloorItems(); - const groupRef = useRef(null); - const [processes, setProcesses] = useState([]); - const [armBotCurvePoints, setArmBotCurvePoints] = useState({ start: [], end: [] }) - const restPosition = new THREE.Vector3(0, 1, -1.6); - let armBotCurveRef = useRef(null) - const [path, setPath] = useState<[number, number, number][]>([]); + const { activeModule } = useModuleStore(); + const { isPlaying } = usePlayButtonStore(); + const { isReset, setReset } = useResetButtonStore(); + const { isPaused } = usePauseButtonStore(); + + function firstFrame() { + startTime = performance.now(); + step(); + } + function step() { + if (isPausedRef.current) { + if (!pauseTimeRef.current) { + pauseTimeRef.current = performance.now(); + } + requestAnimationFrame(() => step()); + return; + } + if (pauseTimeRef.current) { + const pauseDuration = performance.now() - pauseTimeRef.current; + startTime += pauseDuration; + pauseTimeRef.current = null; + } + const elapsedTime = performance.now() - startTime; + if (elapsedTime < 1500) { + // Wait until 1500ms has passed + requestAnimationFrame(step); + return; + } + if(currentPhase==="picking"){ + + setArmBotActive(armBot.modelUuid, true); + setArmBotState(armBot.modelUuid, "running"); + setCurrentPhase("start-to-end"); + startTime=0 + const startPoint = armBot.point.actions[0].process.startPoint; + const endPoint = armBot.point.actions[0].process.endPoint; + if (startPoint && endPoint) { + let curve = createCurveBetweenTwoPoints( + new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]), + new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2])); + if (curve) { + logStatus(armBot.modelUuid, "picking the object"); + setPath(curve.points.map(point => [point.x, point.y, point.z])) + } + } + logStatus(armBot.modelUuid, "Moving armBot from start point to end position.") + }else if(currentPhase==="dropping"){ + + setArmBotActive(armBot.modelUuid, true); + setArmBotState(armBot.modelUuid, "running"); + setCurrentPhase("end-to-rest"); + startTime=0; + const endPoint = armBot.point.actions[0].process.endPoint; + if (endPoint) { + let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition); + if (curve) { + logStatus(armBot.modelUuid, "dropping the object"); + setPath(curve.points.map(point => [point.x, point.y, point.z])); + } + } + logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.") + } + + } + useEffect(() => { + isPausedRef.current = isPaused; + }, [isPaused]); useEffect(() => { let armItems = floorItems?.filter((val: any) => - val.modeluuid === "3abf5d46-b59e-4e6b-9c02-a4634b64b82d" + val.modeluuid === armBot.modelUuid ); // Get the first matching item let armItem = armItems?.[0]; @@ -49,13 +107,30 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { const targetBones = ikSolver?.mesh.skeleton.bones.find( (b: any) => b.name === targetBone ); - + if (isReset) { + logStatus(armBot.modelUuid, "Simulation Play Reset Successfully") + removeCurrentAction(armBot.modelUuid) + setArmBotActive(armBot.modelUuid, true) + setArmBotState(armBot.modelUuid, "running") + setCurrentPhase("init-to-rest"); + isPausedRef.current=false + pauseTimeRef.current=null + isPausedRef.current=false + startTime=0 + if (targetBones) { + let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition) + if (curve) { + setPath(curve.points.map(point => [point.x, point.y, point.z])); + } + } + setReset(false); + logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.") + } if (isPlaying) { //Moving armBot from initial point to rest position. - if (!robot?.isActive && robot?.state == "idle" && currentPhase == "init") { - - setArmBotActive(robot.modelUuid, true) - setArmBotState(robot.modelUuid, "running") + if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") { + setArmBotActive(armBot.modelUuid, true) + setArmBotState(armBot.modelUuid, "running") setCurrentPhase("init-to-rest"); if (targetBones) { let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition) @@ -63,21 +138,22 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { setPath(curve.points.map(point => [point.x, point.y, point.z])); } } - logStatus(robot.modelUuid, "Moving armBot from initial point to rest position.") + logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.") } //Waiting for trigger. - else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && !robot.currentAction) { - logStatus(robot.modelUuid, "Waiting to trigger CurrentAction") - setTimeout(() => { - addCurrentAction(robot.modelUuid, 'action-003'); + else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && !armBot.currentAction) { + logStatus(armBot.modelUuid, "Waiting to trigger CurrentAction") + const timeoutId = setTimeout(() => { + addCurrentAction(armBot.modelUuid, 'action-003'); }, 3000); + return () => clearTimeout(timeoutId); } - else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "rest" && robot.currentAction) { - if (robot.currentAction) { - setArmBotActive(robot.modelUuid, true); - setArmBotState(robot.modelUuid, "running"); + else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && armBot.currentAction) { + if (armBot.currentAction) { + setArmBotActive(armBot.modelUuid, true); + setArmBotState(armBot.modelUuid, "running"); setCurrentPhase("rest-to-start"); - const startPoint = robot.point.actions[0].process.startPoint; + const startPoint = armBot.point.actions[0].process.startPoint; if (startPoint) { let curve = createCurveBetweenTwoPoints(restPosition, new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2])); if (curve) { @@ -85,105 +161,396 @@ function RoboticArmInstance({ robot }: { robot: ArmBotStatus }) { } } } - logStatus(robot.modelUuid, "Moving armBot from rest point to start position.") + logStatus(armBot.modelUuid, "Moving armBot from rest point to start position.") } - else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "picking" && robot.currentAction) { - setArmBotActive(robot.modelUuid, true); - setArmBotState(robot.modelUuid, "running"); - setCurrentPhase("start-to-end"); - const startPoint = robot.point.actions[0].process.startPoint; - const endPoint = robot.point.actions[0].process.endPoint; - if (startPoint && endPoint) { - let curve = createCurveBetweenTwoPoints( - new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]), - new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]) - ); - if (curve) { - setTimeout(() => { - logStatus(robot.modelUuid, "picking the object"); - setPath(curve.points.map(point => [point.x, point.y, point.z])); - }, 1500) - } - } - logStatus(robot.modelUuid, "Moving armBot from start point to end position.") + else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) { + requestAnimationFrame(firstFrame); + // setArmBotActive(armBot.modelUuid, true); + // setArmBotState(armBot.modelUuid, "running"); + // setCurrentPhase("start-to-end"); + // const startPoint = armBot.point.actions[0].process.startPoint; + // const endPoint = armBot.point.actions[0].process.endPoint; + // if (startPoint && endPoint) { + // let curve = createCurveBetweenTwoPoints( + // new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]), + // new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2])); + // if (curve) { + // setTimeout(() => { + // logStatus(armBot.modelUuid, "picking the object"); + // setPath(curve.points.map(point => [point.x, point.y, point.z])); + // }, 1500) + // } + // } + // logStatus(armBot.modelUuid, "Moving armBot from start point to end position.") } - else if (robot && !robot.isActive && robot.state === "idle" && currentPhase === "dropping" && robot.currentAction) { - setArmBotActive(robot.modelUuid, true); - setArmBotState(robot.modelUuid, "running"); - setCurrentPhase("end-to-rest"); - const endPoint = robot.point.actions[0].process.endPoint; - if (endPoint) { - let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition - ); - if (curve) { - setTimeout(() => { - logStatus(robot.modelUuid, "dropping the object"); - setPath(curve.points.map(point => [point.x, point.y, point.z])); - }, 1500) - } - } - logStatus(robot.modelUuid, "Moving armBot from end point to rest position.") + else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) { + requestAnimationFrame(firstFrame); + // setArmBotActive(armBot.modelUuid, true); + // setArmBotState(armBot.modelUuid, "running"); + // setCurrentPhase("end-to-rest"); + // const endPoint = armBot.point.actions[0].process.endPoint; + // if (endPoint) { + // let curve = createCurveBetweenTwoPoints(new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]), restPosition); + // if (curve) { + // setTimeout(() => { + // logStatus(armBot.modelUuid, "dropping the object"); + // setPath(curve.points.map(point => [point.x, point.y, point.z])); + // }, 1500) + // } + // } + // logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.") } + } else { + logStatus(armBot.modelUuid, "Simulation Play Stopped") + setArmBotActive(armBot.modelUuid, false) + setArmBotState(armBot.modelUuid, "idle") + setCurrentPhase("init"); + setPath([]) + removeCurrentAction(armBot.modelUuid) + } - }, [currentPhase, robot, isPlaying, ikSolver]) + }, [currentPhase, armBot, isPlaying, ikSolver, isReset]) function createCurveBetweenTwoPoints(p1: any, p2: any) { const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5); - mid.y += 0.5; - + // mid.y += 0.5; const points = [p1, mid, p2]; return new THREE.CatmullRomCurve3(points); } const HandleCallback = () => { - if (robot.isActive && robot.state == "running" && currentPhase == "init-to-rest") { - logStatus(robot.modelUuid, "Callback triggered: rest"); - setArmBotActive(robot.modelUuid, false) - setArmBotState(robot.modelUuid, "idle") + if (armBot.isActive && armBot.state == "running" && currentPhase == "init-to-rest") { + logStatus(armBot.modelUuid, "Callback triggered: rest"); + setArmBotActive(armBot.modelUuid, false) + setArmBotState(armBot.modelUuid, "idle") setCurrentPhase("rest"); setPath([]) } - else if (robot.isActive && robot.state == "running" && currentPhase == "rest-to-start") { - logStatus(robot.modelUuid, "Callback triggered: pick."); - setArmBotActive(robot.modelUuid, false) - setArmBotState(robot.modelUuid, "idle") + 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") setCurrentPhase("picking"); setPath([]) } - else if (robot.isActive && robot.state == "running" && currentPhase == "start-to-end") { - logStatus(robot.modelUuid, "Callback triggered: drop."); - setArmBotActive(robot.modelUuid, false) - setArmBotState(robot.modelUuid, "idle") + 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") setCurrentPhase("dropping"); setPath([]) } - else if (robot.isActive && robot.state == "running" && currentPhase == "end-to-rest") { - logStatus(robot.modelUuid, "Callback triggered: rest, cycle completed."); - setArmBotActive(robot.modelUuid, false) - setArmBotState(robot.modelUuid, "idle") + else if (armBot.isActive && armBot.state == "running" && currentPhase == "end-to-rest") { + logStatus(armBot.modelUuid, "Callback triggered: rest, cycle completed."); + setArmBotActive(armBot.modelUuid, false) + setArmBotState(armBot.modelUuid, "idle") setCurrentPhase("rest"); setPath([]) - removeCurrentAction(robot.modelUuid) + removeCurrentAction(armBot.modelUuid) } } const logStatus = (id: string, status: string) => { - // console.log(id + "," + status); - console.log( status); + // console.log('status: ', status); } return ( <> - - + + ) } -export default RoboticArmInstance; \ No newline at end of file +export default RoboticArmInstance; + + + + + + + + + + + + +// import React, { useEffect, useRef, useState } from 'react'; +// import IKInstance from '../ikInstance/ikInstance'; +// import RoboticArmAnimator from '../animator/roboticArmAnimator'; +// import { usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +// import { useArmBotStore } from '../../../../../store/simulation/useArmBotStore'; +// import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_4.glb"; +// import { useThree } from "@react-three/fiber"; +// import { useFloorItems } from '../../../../../store/store'; +// import useModuleStore from '../../../../../store/useModuleStore'; +// import * as THREE from "three"; + +// function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { + +// const [currentPhase, setCurrentPhase] = useState("init"); +// const [path, setPath] = useState<[number, number, number][]>([]); +// const [ikSolver, setIkSolver] = useState(null); +// const { scene } = useThree(); +// const restPosition = new THREE.Vector3(0, 1, -1.6); +// const targetBone = "Target"; +// const groupRef = useRef(null); + +// // Zustand Stores +// const { addCurrentAction, setArmBotActive, setArmBotState, removeCurrentAction } = useArmBotStore(); +// const { floorItems } = useFloorItems(); +// const { activeModule } = useModuleStore(); +// const { isPlaying } = usePlayButtonStore(); +// const { isReset, setReset } = useResetButtonStore(); + +// // Generate path according to constraints +// const generateArmPath = ( +// startPoint: [number, number, number], +// endPoint: [number, number, number], +// restPos: THREE.Vector3 = new THREE.Vector3(0, 1, -1.6) +// ): [number, number, number][] => { +// const path: [number, number, number][] = []; + +// const startVec = new THREE.Vector3(...startPoint); +// const endVec = new THREE.Vector3(...endPoint); + +// // Helper functions +// const addLinePoints = (from: THREE.Vector3, to: THREE.Vector3, segments: number) => { +// for (let i = 0; i <= segments; i++) { +// const t = i / segments; +// const point = new THREE.Vector3().lerpVectors(from, to, t); +// path.push([point.x, point.y, point.z]); +// } +// }; + +// const addCurveFromTo = (from: THREE.Vector3, to: THREE.Vector3, segments: number = 15) => { +// const mid = new THREE.Vector3() +// .addVectors(from, to) +// .multiplyScalar(0.5) +// .setY(Math.max(from.y, to.y) + 0.5); +// const curve = new THREE.CatmullRomCurve3([from, mid, to]); +// const points = curve.getPoints(segments); +// for (const p of points) { +// path.push([p.x, p.y, p.z]); +// } +// }; + +// // Step 1: Move vertically to align Y with start point +// const step1Start = startVec.clone().setY(restPos.y); +// const step1End = startVec.clone(); +// addLinePoints(step1Start, step1End, 10); + +// // Step 2: Move horizontally XZ to reach start point +// const step2Start = step1End.clone(); +// const step2End = startVec.clone(); // ✅ Fixed here +// addLinePoints(step2Start, step2End, 10); +// addLinePoints(step1End, step2End, 10); + +// // Optional Step 3: Move to rest/midpoint if needed +// const distanceToRest = startVec.distanceTo(restPos); +// if (distanceToRest > 1) { +// addCurveFromTo(step2End, restPos, 15); +// } + +// // Step 4: Move up/down to align Y with end point +// const step4Start = endVec.clone().setY(restPos.y); +// const step4End = endVec.clone(); +// addLinePoints(step4Start, step4End, 10); + +// // Step 5: Move horizontally XZ to end point +// addLinePoints(step4End, endVec.clone(), 10); + +// // Step 6: Return to rest or mid-position after dropping +// const finalRestHeight = restPos.clone().setY(endVec.y + 0.5); +// addCurveFromTo(endVec, finalRestHeight, 15); + +// return path; +// }; + +// useEffect(() => { +// let armItems = floorItems?.filter((val: any) => +// val.modeluuid === armBot.modelUuid +// ); +// let armItem = armItems?.[0]; +// if (armItem) { +// const targetMesh = scene?.getObjectByProperty("uuid", armItem.modeluuid); +// if (targetMesh) { +// targetMesh.visible = activeModule !== "simulation"; +// } +// } + +// const targetBones = ikSolver?.mesh.skeleton.bones.find( +// (b: any) => b.name === targetBone +// ); + +// if (isReset) { +// logStatus(armBot.modelUuid, "Simulation Play Reset Successfully"); +// removeCurrentAction(armBot.modelUuid); +// setArmBotActive(armBot.modelUuid, true); +// setArmBotState(armBot.modelUuid, "running"); +// setCurrentPhase("init-to-rest"); + +// if (targetBones) { +// const startPoint = new THREE.Vector3(targetBones.position.x, targetBones.position.y, targetBones.position.z); +// const curve = new THREE.CatmullRomCurve3([ +// startPoint, +// startPoint.clone().setY(restPosition.y + 0.5), +// restPosition.clone(), +// ]); +// setPath(curve.getPoints(30).map(p => [p.x, p.y, p.z])); +// } + +// setReset(false); +// logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position."); +// } + +// if (isPlaying) { +// // Phase 1: Initial -> Rest +// if (!armBot.isActive && armBot.state === "idle" && currentPhase === "init") { +// setArmBotActive(armBot.modelUuid, true); +// setArmBotState(armBot.modelUuid, "running"); +// setCurrentPhase("init-to-rest"); + +// if (targetBones) { +// const startPoint = new THREE.Vector3(targetBones.position.x, targetBones.position.y, targetBones.position.z); +// const curve = new THREE.CatmullRomCurve3([ +// startPoint, +// startPoint.clone().setY(restPosition.y + 0.5), +// restPosition.clone(), +// ]); +// setPath(curve.getPoints(30).map(p => [p.x, p.y, p.z])); +// } + +// logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position."); +// } + +// // Phase 2: Wait for trigger +// else if (!armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && !armBot.currentAction) { +// logStatus(armBot.modelUuid, "Waiting to trigger CurrentAction"); +// const timeoutId = setTimeout(() => { +// addCurrentAction(armBot.modelUuid, 'action-003'); +// }, 3000); +// return () => clearTimeout(timeoutId); +// } + +// // Phase 3: Rest -> Start Point +// else if (!armBot.isActive && armBot.state === "idle" && currentPhase === "rest" && armBot.currentAction) { +// setArmBotActive(armBot.modelUuid, true); +// setArmBotState(armBot.modelUuid, "running"); +// setCurrentPhase("rest-to-start"); + +// const startPoint = armBot.point.actions[0].process.startPoint; +// if (startPoint) { +// const start = new THREE.Vector3(startPoint[0], startPoint[1], startPoint[2]); +// const curve = new THREE.CatmullRomCurve3([restPosition, restPosition.clone().setY(start.y), start]); +// setPath(curve.getPoints(30).map(p => [p.x, p.y, p.z])); +// } + +// logStatus(armBot.modelUuid, "Moving armBot from rest point to start position."); +// } + +// // Phase 4: Start -> End (Pick & Move Object) +// else if (!armBot.isActive && armBot.state === "idle" && currentPhase === "picking" && armBot.currentAction) { +// setArmBotActive(armBot.modelUuid, true); +// setArmBotState(armBot.modelUuid, "running"); +// setCurrentPhase("start-to-end"); + +// const startPoint = armBot.point.actions[0].process.startPoint; +// const endPoint = armBot.point.actions[0].process.endPoint; + +// if (startPoint && endPoint) { +// const path = generateArmPath(startPoint, endPoint, restPosition); +// logStatus(armBot.modelUuid, "Waiting to pick."); +// setTimeout(()=>{ +// setPath(path); +// },3000) +// } + +// logStatus(armBot.modelUuid, "Moving armBot from start point to end position."); +// } + +// // Phase 5: End -> Rest (Drop & Return) +// else if (!armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) { +// setArmBotActive(armBot.modelUuid, true); +// setArmBotState(armBot.modelUuid, "running"); +// setCurrentPhase("end-to-rest"); + +// const endPoint = armBot.point.actions[0].process.endPoint; +// if (endPoint) { +// const start = new THREE.Vector3(endPoint[0], endPoint[1], endPoint[2]); +// const curve = new THREE.CatmullRomCurve3([start, start.clone().setY(restPosition.y), restPosition]); +// logStatus(armBot.modelUuid, "Waiting to drop."); +// setTimeout(()=>{ +// setPath(curve.getPoints(30).map(p => [p.x, p.y, p.z])); +// },3000) + +// } + +// logStatus(armBot.modelUuid, "Moving armBot from end point to rest position."); +// } +// } else { +// logStatus(armBot.modelUuid, "Simulation Play Stopped"); +// setArmBotActive(armBot.modelUuid, false); +// setArmBotState(armBot.modelUuid, "idle"); +// setCurrentPhase("init"); +// setPath([]); +// removeCurrentAction(armBot.modelUuid); +// } + +// }, [currentPhase, armBot, isPlaying, ikSolver, isReset]); + +// const HandleCallback = () => { +// if (armBot.isActive && armBot.state === "running" && currentPhase === "init-to-rest") { +// logStatus(armBot.modelUuid, "Callback triggered: rest"); +// setArmBotActive(armBot.modelUuid, false); +// setArmBotState(armBot.modelUuid, "idle"); +// setCurrentPhase("rest"); +// setPath([]); +// } 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"); +// 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"); +// setCurrentPhase("dropping"); +// setPath([]); +// } else if (armBot.isActive && armBot.state === "running" && currentPhase === "end-to-rest") { +// logStatus(armBot.modelUuid, "Callback triggered: rest, cycle completed."); +// setArmBotActive(armBot.modelUuid, false); +// setArmBotState(armBot.modelUuid, "idle"); +// setCurrentPhase("rest"); +// setPath([]); +// removeCurrentAction(armBot.modelUuid); +// } +// }; + +// const logStatus = (id: string, status: string) => { +// console.log( status); +// // console.log(`status [${id}]: ${status}`); +// }; + +// return ( +// <> +// +// +// +// ); +// } + +// export default RoboticArmInstance; \ No newline at end of file diff --git a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx index 645cbb5..e49f5bf 100644 --- a/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/ikInstance/ikInstance.tsx @@ -3,20 +3,18 @@ import * as THREE from "three"; import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { clone } from "three/examples/jsm/utils/SkeletonUtils"; -import { useFrame, useLoader, useThree } from "@react-three/fiber"; +import { useLoader, useThree } from "@react-three/fiber"; import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver"; + type IKInstanceProps = { modelUrl: string; ikSolver: any; setIkSolver: any - robot: any; + armBot: any; groupRef: React.RefObject; - processes: any; - setArmBotCurvePoints: any }; -function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processes, setArmBotCurvePoints }: IKInstanceProps) { - - const { scene } = useThree(); +function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef}: IKInstanceProps) { + const {scene}=useThree() const gltf = useLoader(GLTFLoader, modelUrl, (loader) => { const draco = new DRACOLoader(); draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/"); @@ -25,6 +23,7 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processe const cloned = useMemo(() => clone(gltf?.scene), [gltf]); const targetBoneName = "Target"; const skinnedMeshName = "link_0"; + useEffect(() => { if (!gltf) return; const OOI: any = {}; @@ -67,14 +66,14 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, robot, groupRef, processe const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05) - // scene.add(helper) + scene.add(helper) }, [gltf]); return ( <> - + {armBots?.map((robot: ArmBotStatus) => ( - + ))} diff --git a/app/src/modules/simulation/roboticArm/roboticArm.tsx b/app/src/modules/simulation/roboticArm/roboticArm.tsx index 69e6da0..41d10f9 100644 --- a/app/src/modules/simulation/roboticArm/roboticArm.tsx +++ b/app/src/modules/simulation/roboticArm/roboticArm.tsx @@ -6,8 +6,6 @@ import { useFloorItems } from "../../../store/store"; function RoboticArm() { const { armBots, addArmBot, removeArmBot } = useArmBotStore(); const { floorItems } = useFloorItems(); - - const armBotStatusSample: RoboticArmEventSchema[] = [ { state: "idle", @@ -95,7 +93,7 @@ function RoboticArm() { position: [95.94347308985614, 0, 6.742905194869091], rotation: [0, 0, 0], type: "roboticArm", - speed: 1.5, + speed: 0.1, point: { uuid: "point-123", position: [0, 1.5, 0], diff --git a/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts b/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts index b7e9272..d73b4a9 100644 --- a/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts +++ b/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts @@ -80,7 +80,7 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) { // Add offset for dragging intersection.add(offsetRef.current); - console.log('intersection: ', intersection); + // Get the parent's world matrix if exists const parent = activeObjRef.current.parent;