armbot animator movements and path updated

This commit is contained in:
Gomathi 2025-05-06 11:30:32 +05:30
parent bda6cbe8be
commit bb7315edeb
3 changed files with 107 additions and 41 deletions

View File

@ -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({
/>
</mesh>
)}
<mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[CIRCLE_RADIUS, CIRCLE_RADIUS + 0.02, 64]} />
<meshBasicMaterial color="green" side={THREE.DoubleSide} />
</mesh>
<group position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]}>
{/* Green ring */}
<mesh rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[CIRCLE_RADIUS, CIRCLE_RADIUS + 0.02, 64]} />
<meshBasicMaterial color="green" side={THREE.DoubleSide} />
</mesh>
{/* 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 (
<mesh key={index} position={[x, y, z]}>
<sphereGeometry args={[0.05, 16, 16]} />
<meshStandardMaterial color="red" />
</mesh>
);
})}
{/* 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 (
<Text
key={`text-${index}`}
position={[x, y, z]}
fontSize={0.2}
color="yellow"
anchorX="center"
anchorY="middle"
>
{degree}°
</Text>
);
})}
</group>
</>
);
}

View File

@ -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])

View File

@ -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