From bb7315edeb122945737b23a7003cf6a6b2a7bbd0 Mon Sep 17 00:00:00 2001 From: Gomathi9520 Date: Tue, 6 May 2025 11:30:32 +0530 Subject: [PATCH] armbot animator movements and path updated --- .../instances/animator/roboticArmAnimator.tsx | 128 +++++++++++++----- .../armInstance/roboticArmInstance.tsx | 11 ++ .../simulation/ui/arm/useDraggableGLTF.ts | 9 +- 3 files changed, 107 insertions(+), 41 deletions(-) diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index d96182b..a1e88cc 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useFrame } from '@react-three/fiber'; import * as THREE from 'three'; -import { Line } from '@react-three/drei'; +import { Line, Text } from '@react-three/drei'; import { useAnimationPlaySpeed, usePauseButtonStore, @@ -94,9 +94,9 @@ function RoboticArmAnimator({ } useEffect(() => { const points = generateRingPointsWithDegrees(CIRCLE_RADIUS, 64); - + }, [armBot.position]); - + // Function for find nearest Circlepoints Index const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => { for (let i = 0; i < points.length; i++) { @@ -124,7 +124,6 @@ function RoboticArmAnimator({ // Handle nearest points and final path (including arc points) useEffect(() => { if (circlePoints.length > 0 && currentPath.length > 0) { - const start = currentPath[0]; const end = currentPath[currentPath.length - 1]; @@ -137,31 +136,50 @@ function RoboticArmAnimator({ const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints); const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints); - const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64; - const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64; - const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance; + const totalSegments = 64; + const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + totalSegments) % totalSegments; + const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + totalSegments) % totalSegments; + + // Prepare degrees + const degreesList = generateRingPointsWithDegrees(CIRCLE_RADIUS, totalSegments); + + // Helper function to collect points and check forbidden degrees + const collectArcPoints = (startIdx: number, endIdx: number, clockwise: boolean) => { + const arcPoints: [number, number, number][] = []; + let i = startIdx; + + while (i !== (endIdx + (clockwise ? 1 : -1) + totalSegments) % totalSegments) { + const { degree, position } = degreesList[i]; + + // Skip over + arcPoints.push(position); + i = (i + (clockwise ? 1 : -1) + totalSegments) % totalSegments; + } + return arcPoints; + }; + + const hasForbiddenDegrees = (arc: [number, number, number][]) => { + return arc.some(p => { + const idx = findNearestIndex(p, circlePoints); + const degree = degreesList[idx]?.degree || 0; + return degree >= 271 && degree <= 300; // Forbidden range: 271° to 300° + }); + }; + + + // Try both directions + const arcClockwise = collectArcPoints(indexOfNearestStart, indexOfNearestEnd, true); + const arcCounterClockwise = collectArcPoints(indexOfNearestStart, indexOfNearestEnd, false); + + const clockwiseForbidden = hasForbiddenDegrees(arcClockwise); + const counterClockwiseForbidden = hasForbiddenDegrees(arcCounterClockwise); let arcPoints: [number, number, number][] = []; - if (clockwiseIsShorter) { - if (indexOfNearestStart <= indexOfNearestEnd) { - arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1); - } else { - arcPoints = [ - ...circlePoints.slice(indexOfNearestStart, 64), - ...circlePoints.slice(0, indexOfNearestEnd + 1) - ]; - } + if (!clockwiseForbidden && (clockwiseDistance <= counterClockwiseDistance || counterClockwiseForbidden)) { + arcPoints = arcClockwise; } else { - if (indexOfNearestStart >= indexOfNearestEnd) { - for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { - arcPoints.push(circlePoints[i]); - } - } else { - for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { - arcPoints.push(circlePoints[i]); - } - } + arcPoints = arcCounterClockwise; } const pathVectors = [ @@ -174,9 +192,7 @@ function RoboticArmAnimator({ new THREE.Vector3(end[0], end[1], end[2]) ]; - const pathSegments: [THREE.Vector3, THREE.Vector3][] = []; - for (let i = 0; i < pathVectors.length - 1; i++) { pathSegments.push([pathVectors[i], pathVectors[i + 1]]); } @@ -186,16 +202,12 @@ function RoboticArmAnimator({ const totalDistance = segmentDistances.reduce((sum, d) => sum + d, 0); totalDistanceRef.current = totalDistance; - const movementSpeed = speed * armBot.speed; - const totalMoveTime = totalDistance / movementSpeed; - - const segmentTimes = segmentDistances.map(distance => (distance / totalDistance) * totalMoveTime); - setCustomCurvePoints(pathVectors); - } }, [circlePoints, currentPath]); + + // Frame update for animation useFrame((state, delta) => { if (!ikSolver) return; @@ -266,10 +278,52 @@ function RoboticArmAnimator({ /> )} - - - - + + {/* Green ring */} + + + + + + {/* Markers at 90°, 180°, 270°, 360° */} + {[90, 180, 270, 360].map((degree, index) => { + const rad = (degree * Math.PI) / 180; + const x = CIRCLE_RADIUS * Math.cos(rad); + const z = CIRCLE_RADIUS * Math.sin(rad); + const y = 0; // same plane as the ring (Y axis) + + return ( + + + + + ); + })} + + {/* Optional: Text Labels */} + + {[90, 180, 270, 360].map((degree, index) => { + const rad = (degree * Math.PI) / 180; + const x = CIRCLE_RADIUS * Math.cos(rad); + const z = CIRCLE_RADIUS * Math.sin(rad); + const y = 0.15; // lift the text slightly above the ring + + return ( + + {degree}° + + ); + })} + + + ); } diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index 21bbc7e..246d3f8 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -164,6 +164,17 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { else if (armBot && !armBot.isActive && armBot.state === "idle" && currentPhase === "dropping" && armBot.currentAction) { requestAnimationFrame(firstFrame); } + }else{ + logStatus(armBot.modelUuid, "Simulation Play Exited") + setArmBotActive(armBot.modelUuid, false) + setArmBotState(armBot.modelUuid, "idle") + setCurrentPhase("init"); + setPath([]) + isPausedRef.current = false + pauseTimeRef.current = null + isPausedRef.current = false + startTime = 0 + removeCurrentAction(armBot.modelUuid) } }, [currentPhase, armBot, isPlaying, ikSolver]) diff --git a/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts b/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts index b819852..fdb271c 100644 --- a/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts +++ b/app/src/modules/simulation/ui/arm/useDraggableGLTF.ts @@ -139,15 +139,16 @@ export default function useDraggableGLTF(onUpdate: OnUpdateCallback) { } // Allow only angles between 90° and 270° - if (angleDeg < 95 || angleDeg > 270) { + if (angleDeg < 0 || angleDeg > 270) { // Clamp to nearest boundary (90° or 270°) - const distanceTo90 = Math.abs(angleDeg - 95); + const distanceTo90 = Math.abs(angleDeg - 0); const distanceTo270 = Math.abs(angleDeg - 270); if (distanceTo90 < distanceTo270) { - angleDeg = 95; + angleDeg = 0; } else { - angleDeg = 270; + return + // angleDeg = 270; } // Update angle in radians