reset function updated

This commit is contained in:
Gomathi 2025-05-05 11:25:06 +05:30
parent f888c2798c
commit be8f937759
4 changed files with 264 additions and 238 deletions

View File

@ -38,9 +38,17 @@ const SimulationPlayer: React.FC = () => {
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const { subModule } = useSubModuleStore(); const { subModule } = useSubModuleStore();
useEffect(() => {
if (isReset) {
setTimeout(()=>{
setReset(false);
},0)
}
}, [isReset])
// Button functions // Button functions
const handleReset = () => { const handleReset = () => {
setReset(!isReset); setReset(true);
setSpeed(1); setSpeed(1);
}; };
const handlePlayStop = () => { const handlePlayStop = () => {
@ -271,11 +279,10 @@ const SimulationPlayer: React.FC = () => {
</div> </div>
{index < intervals.length - 1 && ( {index < intervals.length - 1 && (
<div <div
className={`line ${ className={`line ${progress >= ((index + 1) / totalSegments) * 100
progress >= ((index + 1) / totalSegments) * 100
? "filled" ? "filled"
: "" : ""
}`} }`}
></div> ></div>
)} )}
</React.Fragment> </React.Fragment>
@ -314,9 +321,8 @@ const SimulationPlayer: React.FC = () => {
<div className="custom-slider-wrapper"> <div className="custom-slider-wrapper">
<div className="custom-slider"> <div className="custom-slider">
<button <button
className={`slider-handle ${ className={`slider-handle ${isDragging ? "dragging" : ""
isDragging ? "dragging" : "" }`}
}`}
style={{ left: `${calculateHandlePosition()}%` }} style={{ left: `${calculateHandlePosition()}%` }}
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
> >

View File

@ -3,240 +3,260 @@ import { useFrame } from '@react-three/fiber';
import * as THREE from 'three'; import * as THREE from 'three';
import { Line } from '@react-three/drei'; import { Line } from '@react-three/drei';
import { import {
useAnimationPlaySpeed, useAnimationPlaySpeed,
usePauseButtonStore, usePauseButtonStore,
usePlayButtonStore, usePlayButtonStore,
useResetButtonStore useResetButtonStore
} from '../../../../../store/usePlayButtonStore'; } from '../../../../../store/usePlayButtonStore';
function RoboticArmAnimator({ function RoboticArmAnimator({
HandleCallback, HandleCallback,
restPosition, restPosition,
ikSolver, ikSolver,
targetBone, targetBone,
armBot, armBot,
logStatus, logStatus,
path path
}: any) { }: any) {
const progressRef = useRef(0); const progressRef = useRef(0);
const curveRef = useRef<THREE.Vector3[] | null>(null); const curveRef = useRef<THREE.Vector3[] | null>(null);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]); const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null); const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null);
let curveHeight = 1.75 let curveHeight = 1.75
const totalDistanceRef = useRef(0); const totalDistanceRef = useRef(0);
const startTimeRef = useRef<number | null>(null); const startTimeRef = useRef<number | null>(null);
const segmentDistancesRef = useRef<number[]>([]); const segmentDistancesRef = useRef<number[]>([]);
// Zustand stores // Zustand stores
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const { speed } = useAnimationPlaySpeed(); const { speed } = useAnimationPlaySpeed();
// Update path state whenever `path` prop changes // Update path state whenever `path` prop changes
useEffect(() => { useEffect(() => {
setCurrentPath(path); setCurrentPath(path);
}, [path]); }, [path]);
// Handle circle points based on armBot position // Handle circle points based on armBot position
useEffect(() => { useEffect(() => {
const points = generateRingPoints(1.6, 64) const points = generateRingPoints(1.6, 64)
setCirclePoints(points); setCirclePoints(points);
}, [armBot.position]); }, [armBot.position]);
useEffect(() => { //Handle Reset Animation
if (isReset || !isPlaying) { useEffect(() => {
progressRef.current = 0; if (isReset ) {
curveRef.current = null; progressRef.current = 0;
setCurrentPath([]); curveRef.current = null;
setCustomCurvePoints(null); setCurrentPath([]);
totalDistanceRef.current = 0; setCustomCurvePoints(null);
startTimeRef.current = null; totalDistanceRef.current = 0;
segmentDistancesRef.current = []; startTimeRef.current = null;
setReset(false); segmentDistancesRef.current = [];
if (!ikSolver) return
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (!bone) return;
bone.position.copy(restPosition)
ikSolver.update();
}
}, [isReset, isPlaying])
//Generate Circle Points
function generateRingPoints(radius: any, segments: any) {
const points: [number, number, number][] = [];
for (let i = 0; i < segments; i++) {
// Calculate angle for current segment
const angle = (i / segments) * Math.PI * 2;
// Calculate x and z coordinates (y remains the same for a flat ring)
const x = Math.cos(angle) * radius;
const z = Math.sin(angle) * radius;
points.push([x, 1.5, z]);
}
return points;
} }
}, [isReset, isPlaying]) // 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++) {
const [x, y, z] = points[i];
if (
Math.abs(x - nearestPoint[0]) < epsilon &&
Math.abs(y - nearestPoint[1]) < epsilon &&
Math.abs(z - nearestPoint[2]) < epsilon
) {
return i; // Found the matching index
}
}
return -1; // Not found
};
//function to find nearest Circlepoints
function generateRingPoints(radius: any, segments: any) { const findNearest = (target: [number, number, number]) => {
const points: [number, number, number][] = [];
for (let i = 0; i < segments; i++) {
// Calculate angle for current segment
const angle = (i / segments) * Math.PI * 2;
// Calculate x and z coordinates (y remains the same for a flat ring)
const x = Math.cos(angle) * radius;
const z = Math.sin(angle) * radius;
points.push([x, 1.5, z]);
}
return points;
}
const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => {
for (let i = 0; i < points.length; i++) {
const [x, y, z] = points[i];
if (
Math.abs(x - nearestPoint[0]) < epsilon &&
Math.abs(y - nearestPoint[1]) < epsilon &&
Math.abs(z - nearestPoint[2]) < epsilon
) {
return i; // Found the matching index
}
}
return -1; // Not found
};
// 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];
const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
const findNearest = (target: [number, number, number]) => {
return circlePoints.reduce((nearest, point) => { return circlePoints.reduce((nearest, point) => {
const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]); const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]); const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
return distance < nearestDistance ? point : nearest; return distance < nearestDistance ? point : nearest;
}, circlePoints[0]); }, circlePoints[0]);
}; };
// Handle nearest points and final path (including arc points)
useEffect(() => {
if (circlePoints.length > 0 && currentPath.length > 0) {
const nearestToStart = findNearest(raisedStart); const start = currentPath[0];
const nearestToEnd = findNearest(raisedEnd); const end = currentPath[currentPath.length - 1];
const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints); const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number];
const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints); const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number];
const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64; // const findNearest = (target: [number, number, number]) => {
const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64; // return circlePoints.reduce((nearest, point) => {
const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance; // const distance = Math.hypot(target[0] - point[0], target[1] - point[1], target[2] - point[2]);
// const nearestDistance = Math.hypot(target[0] - nearest[0], target[1] - nearest[1], target[2] - nearest[2]);
// return distance < nearestDistance ? point : nearest;
// }, circlePoints[0]);
// };
let arcPoints: [number, number, number][] = []; const nearestToStart = findNearest(raisedStart);
const nearestToEnd = findNearest(raisedEnd);
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;
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)
];
}
} 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]);
}
}
}
const pathVectors = [
new THREE.Vector3(start[0], start[1], start[2]),
new THREE.Vector3(start[0], curveHeight, start[2]),
new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]),
...arcPoints.map(point => new THREE.Vector3(point[0], curveHeight, point[2])),
new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]),
new THREE.Vector3(end[0], curveHeight, end[2]),
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]]);
}
const segmentDistances = pathSegments.map(([p1, p2]) => p1.distanceTo(p2));
segmentDistancesRef.current = segmentDistances;
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);
if (clockwiseIsShorter) {
if (indexOfNearestStart <= indexOfNearestEnd) {
arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
} else {
arcPoints = [
...circlePoints.slice(indexOfNearestStart, 64),
...circlePoints.slice(0, indexOfNearestEnd + 1)
];
} }
} else { }, [circlePoints, currentPath]);
if (indexOfNearestStart >= indexOfNearestEnd) {
for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { // Frame update for animation
arcPoints.push(circlePoints[i]); useFrame((state, delta) => {
} if (!ikSolver) return;
} else {
for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
arcPoints.push(circlePoints[i]); if (!bone) return;
}
if (isPlaying) {
if (isReset) {
bone.position.copy(restPosition);
setCustomCurvePoints([]);
ikSolver.update();
}
if (!isPaused && customCurvePoints && customCurvePoints.length > 0) {
const distances = segmentDistancesRef.current;
const totalDistance = totalDistanceRef.current;
progressRef.current += delta * (speed * armBot.speed);
const coveredDistance = progressRef.current;
let index = 0;
let accumulatedDistance = 0;
while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) {
accumulatedDistance += distances[index];
index++;
}
if (index < distances.length) {
const startPoint = customCurvePoints[index];
const endPoint = customCurvePoints[index + 1];
const segmentDistance = distances[index];
const t = (coveredDistance - accumulatedDistance) / segmentDistance;
if (startPoint && endPoint) {
const position = startPoint.clone().lerp(endPoint, t);
bone.position.copy(position);
}
}
if (progressRef.current >= totalDistance) {
HandleCallback();
setCurrentPath([]);
setCustomCurvePoints([]);
curveRef.current = null;
progressRef.current = 0;
startTimeRef.current = null;
}
ikSolver.update();
}
} else if (!isPlaying && currentPath.length === 0) {
bone.position.copy(restPosition);
} }
}
const pathVectors = [
new THREE.Vector3(start[0], start[1], start[2]),
new THREE.Vector3(start[0], curveHeight, start[2]),
new THREE.Vector3(nearestToStart[0], curveHeight, nearestToStart[2]),
...arcPoints.map(point => new THREE.Vector3(point[0], curveHeight, point[2])),
new THREE.Vector3(nearestToEnd[0], curveHeight, nearestToEnd[2]),
new THREE.Vector3(end[0], curveHeight, end[2]),
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]]);
}
const segmentDistances = pathSegments.map(([p1, p2]) => p1.distanceTo(p2));
segmentDistancesRef.current = segmentDistances;
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;
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
if (!bone) return;
if (isPlaying) {
if (!isPaused && customCurvePoints && customCurvePoints.length > 0) {
const distances = segmentDistancesRef.current; // distances between each pair of points
const totalDistance = totalDistanceRef.current;
progressRef.current += delta * (speed * armBot.speed);
const coveredDistance = progressRef.current;
let index = 0;
let accumulatedDistance = 0;
// Find which segment we are currently in
while (index < distances.length && coveredDistance > accumulatedDistance + distances[index]) {
accumulatedDistance += distances[index];
index++;
}
if (index < distances.length) {
const startPoint = customCurvePoints[index];
const endPoint = customCurvePoints[index + 1];
const segmentDistance = distances[index];
const t = (coveredDistance - accumulatedDistance) / segmentDistance;
if (startPoint && endPoint) {
const position = startPoint.clone().lerp(endPoint, t);
bone.position.copy(position);
}
}
if (progressRef.current >= totalDistance) {
HandleCallback();
setCurrentPath([]);
setCustomCurvePoints([]);
curveRef.current = null;
progressRef.current = 0;
startTimeRef.current = null;
}
ikSolver.update(); ikSolver.update();
} });
} else if ((!isPlaying && currentPath.length === 0) || isReset) {
bone.position.copy(restPosition);
ikSolver.update();
}
});
return ( return (
<> <>
{customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && ( {customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && (
<mesh rotation={armBot.rotation} position={armBot.position}> <mesh rotation={armBot.rotation} position={armBot.position}>
<Line <Line
points={customCurvePoints.map((p) => [p.x, p.y, p.z] as [number, number, number])} points={customCurvePoints.map((p) => [p.x, p.y, p.z] as [number, number, number])}
color="green" color="green"
lineWidth={5} lineWidth={5}
dashed={false} dashed={false}
/> />
</mesh> </mesh>
)} )}
<mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}> <mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[1.59, 1.61, 64]} /> <ringGeometry args={[1.59, 1.61, 64]} />
<meshBasicMaterial color="green" side={THREE.DoubleSide} /> <meshBasicMaterial color="green" side={THREE.DoubleSide} />
</mesh> </mesh>
</> </>
); );
} }
export default RoboticArmAnimator; export default RoboticArmAnimator;

View File

@ -97,24 +97,24 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
useEffect(() => { useEffect(() => {
if (isReset || !isPlaying) { if (isReset || !isPlaying) {
logStatus(armBot.modelUuid, "Simulation Play Reset Successfully") logStatus(armBot.modelUuid, "Simulation Play Reset Successfully")
removeCurrentAction(armBot.modelUuid)
setArmBotActive(armBot.modelUuid, false) setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle") setArmBotState(armBot.modelUuid, "idle")
setCurrentPhase("init"); setCurrentPhase("init");
setPath([])
removeCurrentAction(armBot.modelUuid)
isPausedRef.current = false isPausedRef.current = false
pauseTimeRef.current = null pauseTimeRef.current = null
startTime = 0 startTime = 0
const targetBones = ikSolver?.mesh.skeleton.bones.find( const targetBones = ikSolver?.mesh.skeleton.bones.find((b: any) => b.name === targetBone
(b: any) => b.name === targetBone
); );
if (targetBones) { if (targetBones && isPlaying) {
let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition) let curve = createCurveBetweenTwoPoints(targetBones.position, restPosition)
if (curve) { if (curve) {
setPath(curve.points.map(point => [point.x, point.y, point.z])); setPath(curve.points.map(point => [point.x, point.y, point.z]));
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
} }
} }
setReset(false); // setReset(false);
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
} }
}, [isReset, isPlaying]) }, [isReset, isPlaying])
@ -127,7 +127,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
(b: any) => b.name === targetBone (b: any) => b.name === targetBone
); );
if (isPlaying) { if (isPlaying) {
//Moving armBot from initial point to rest position. //Moving armBot from initial point to rest position.
if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") { if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
@ -204,16 +203,16 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
// logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.") // logStatus(armBot.modelUuid, "Moving armBot from end point to rest position.")
} }
} else { } else {
logStatus(armBot.modelUuid, "Simulation Play Exited") // logStatus(armBot.modelUuid, "Simulation Play Exited")
setArmBotActive(armBot.modelUuid, false) // setArmBotActive(armBot.modelUuid, false)
setArmBotState(armBot.modelUuid, "idle") // setArmBotState(armBot.modelUuid, "idle")
setCurrentPhase("init"); // setCurrentPhase("init");
setPath([]) // setPath([])
isPausedRef.current = false // isPausedRef.current = false
pauseTimeRef.current = null // pauseTimeRef.current = null
isPausedRef.current = false // isPausedRef.current = false
startTime = 0 // startTime = 0
removeCurrentAction(armBot.modelUuid) // removeCurrentAction(armBot.modelUuid)
} }
}, [currentPhase, armBot, isPlaying, ikSolver]) }, [currentPhase, armBot, isPlaying, ikSolver])
@ -260,6 +259,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
} }
const logStatus = (id: string, status: string) => { const logStatus = (id: string, status: string) => {
// //
} }

View File

@ -7,7 +7,7 @@ function Simulator() {
const executionOrder = determineExecutionOrder(products); const executionOrder = determineExecutionOrder(products);
executionOrder.forEach(point => { executionOrder.forEach(point => {
useActionHandler(point); // useActionHandler(point);
}); });
function determineExecutionSequences(products: productsSchema): PointsScheme[][] { function determineExecutionSequences(products: productsSchema): PointsScheme[][] {