armbot circular path updated and ui dynamic updation
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
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';
|
||||
@@ -21,14 +21,8 @@ function RoboticArmAnimator({
|
||||
const progressRef = useRef(0);
|
||||
const curveRef = useRef<THREE.Vector3[] | null>(null);
|
||||
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
|
||||
const [curvePoints, setCurvePoints] = useState<THREE.Vector3[] | null>(null);
|
||||
const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]);
|
||||
const [nearestStartPoint, setNearestStartPoint] = useState<[number, number, number] | null>(null);
|
||||
const [nearestEndPoint, setNearestEndPoint] = useState<[number, number, number] | null>(null);
|
||||
const [customCurvePoints, setCustomCurvePoints] = useState<THREE.Vector3[] | null>(null);
|
||||
const stepSegmentsRef = useRef<THREE.Vector3[][]>([]);
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const elapsedTimeRef = useRef(0);
|
||||
|
||||
// Zustand stores
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
@@ -41,7 +35,6 @@ function RoboticArmAnimator({
|
||||
setCurrentPath(path);
|
||||
}, [path]);
|
||||
|
||||
|
||||
// Reset logic when `isPlaying` changes
|
||||
useEffect(() => {
|
||||
if (!isPlaying) {
|
||||
@@ -50,221 +43,172 @@ function RoboticArmAnimator({
|
||||
}
|
||||
}, [isPlaying]);
|
||||
|
||||
// Handle path generation (including CatmullRomCurve3)
|
||||
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);
|
||||
curveRef.current = generatedCurve;
|
||||
setCurvePoints(generatedCurve);
|
||||
}
|
||||
}, [currentPath]);
|
||||
|
||||
// Handle circle points based on armBot position
|
||||
useEffect(() => {
|
||||
const radius = 1.6; // Circle radius
|
||||
const segments = 64;
|
||||
const points: [number, number, number][] = [];
|
||||
|
||||
for (let i = 0; i <= segments; i++) {
|
||||
const theta = (i / segments) * Math.PI * 2;
|
||||
const x = radius * Math.cos(theta) + armBot.position[0];
|
||||
const z = radius * Math.sin(theta) + armBot.position[2];
|
||||
const y = armBot.position[1];
|
||||
points.push([x, y, z]);
|
||||
}
|
||||
|
||||
const points = generateRingPoints(1.6, 64)
|
||||
setCirclePoints(points);
|
||||
}, [armBot.position]);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 startPoint = [currentPath[0][0], currentPath[0][1] + 0.5, currentPath[0][2]] as [number, number, number];
|
||||
const endPoint = [currentPath[currentPath.length - 1][0], currentPath[currentPath.length - 1][1] + 0.5, currentPath[currentPath.length - 1][2]] as [number, number, number];
|
||||
|
||||
const findNearest = (target: [number, number, number]) => {
|
||||
let nearestPoint = circlePoints[0];
|
||||
let minDistance = Infinity;
|
||||
|
||||
for (const point of circlePoints) {
|
||||
const dx = target[0] - point[0];
|
||||
const dy = target[1] - point[1];
|
||||
const dz = target[2] - point[2];
|
||||
const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
nearestPoint = point;
|
||||
}
|
||||
}
|
||||
return nearestPoint;
|
||||
};
|
||||
|
||||
const nearestToStart = findNearest(startPoint);
|
||||
const nearestToEnd = findNearest(endPoint);
|
||||
|
||||
setNearestStartPoint(nearestToStart);
|
||||
setNearestEndPoint(nearestToEnd);
|
||||
|
||||
const radius = 1.6;
|
||||
const segments = 64;
|
||||
const center = armBot.position;
|
||||
|
||||
const startAngle = Math.atan2(nearestToStart[2] - center[2], nearestToStart[0] - center[0]);
|
||||
const endAngle = Math.atan2(nearestToEnd[2] - center[2], nearestToEnd[0] - center[0]);
|
||||
let deltaAngle = endAngle - startAngle;
|
||||
|
||||
if (deltaAngle > Math.PI) {
|
||||
deltaAngle -= 2 * Math.PI;
|
||||
} else if (deltaAngle < -Math.PI) {
|
||||
deltaAngle += 2 * Math.PI;
|
||||
}
|
||||
|
||||
const arcPoints: [number, number, number][] = [];
|
||||
|
||||
for (let i = 0; i <= segments; i++) {
|
||||
const t = i / segments;
|
||||
const angle = startAngle + deltaAngle * t;
|
||||
const x = center[0] + radius * Math.cos(angle);
|
||||
const z = center[2] + radius * Math.sin(angle);
|
||||
const y = startPoint[1];
|
||||
arcPoints.push([x, y, z]);
|
||||
}
|
||||
const start = currentPath[0];
|
||||
const end = currentPath[currentPath.length - 1];
|
||||
|
||||
let step1 = [
|
||||
[start[0], start[1], start[2]],
|
||||
[start[0], start[1] + 0.5, start[2]]
|
||||
];
|
||||
let step2 = [
|
||||
[start[0], start[1] + 0.5, start[2]],
|
||||
[nearestToStart[0], start[1] + 0.5, nearestToStart[2]]
|
||||
];
|
||||
let step3 = [
|
||||
[nearestToStart[0], start[1] + 0.5, nearestToStart[2]],
|
||||
[end[0], arcPoints[arcPoints.length - 1][1], end[2]]
|
||||
]
|
||||
let step4 = [
|
||||
[end[0], arcPoints[arcPoints.length - 1][1], end[2]],
|
||||
[end[0], end[1] + 0.5, end[2]]
|
||||
]
|
||||
let step5 = [
|
||||
[end[0], end[1] + 0.5, end[2]],
|
||||
[end[0], end[1], end[2]],
|
||||
]
|
||||
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 points = [
|
||||
new THREE.Vector3(start[0], start[1], start[2]),
|
||||
new THREE.Vector3(start[0], start[1] + 0.5, start[2]),
|
||||
const findNearest = (target: [number, number, number]) => {
|
||||
return circlePoints.reduce((nearest, point) => {
|
||||
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]);
|
||||
};
|
||||
|
||||
new THREE.Vector3(start[0], start[1] + 0.5, start[2]),
|
||||
new THREE.Vector3(nearestToStart[0], start[1] + 0.5, nearestToStart[2]),
|
||||
const nearestToStart = findNearest(raisedStart);
|
||||
|
||||
new THREE.Vector3(nearestToStart[0], start[1] + 0.5, nearestToStart[2]),
|
||||
new THREE.Vector3(end[0], arcPoints[arcPoints.length - 1][1], end[2]),
|
||||
const nearestToEnd = findNearest(raisedEnd);
|
||||
|
||||
new THREE.Vector3(end[0], arcPoints[arcPoints.length - 1][1], end[2]),
|
||||
new THREE.Vector3(end[0], end[1] + 0.5, end[2]),
|
||||
const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints);
|
||||
|
||||
new THREE.Vector3(end[0], end[1] + 0.5, end[2]),
|
||||
new THREE.Vector3(end[0], end[1], end[2])
|
||||
];
|
||||
const steps = [
|
||||
[points[0], points[1]], // step1
|
||||
[points[2], points[3]], // step2
|
||||
[points[4], points[5]], // step3
|
||||
[points[6], points[7]], // step4
|
||||
[points[8], points[9]] // step5
|
||||
];
|
||||
stepSegmentsRef.current = steps;
|
||||
setCurrentStep(0);
|
||||
elapsedTimeRef.current = 0;
|
||||
const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints);
|
||||
|
||||
const finalPath = [
|
||||
new THREE.Vector3(start[0], start[1], start[2]),
|
||||
new THREE.Vector3(start[0], start[1] + 0.5, start[2]),
|
||||
new THREE.Vector3(nearestToStart[0], start[1] + 0.5, nearestToStart[2]),
|
||||
...arcPoints.map(([x, y, z]) => new THREE.Vector3(x, y, z)),
|
||||
new THREE.Vector3(end[0], arcPoints[arcPoints.length - 1][1], end[2]),
|
||||
new THREE.Vector3(end[0], end[1], end[2])
|
||||
// Find clockwise and counter-clockwise distances
|
||||
const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64;
|
||||
|
||||
const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64;
|
||||
|
||||
const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance;
|
||||
|
||||
// Collect arc points between start and end
|
||||
let arcPoints: [number, number, number][] = [];
|
||||
|
||||
if (clockwiseIsShorter) {
|
||||
if (indexOfNearestStart <= indexOfNearestEnd) {
|
||||
arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1);
|
||||
} else {
|
||||
// Wrap around
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue your custom path logic
|
||||
const pathVectors = [
|
||||
new THREE.Vector3(start[0], start[1], start[2]), // start
|
||||
new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up
|
||||
new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start
|
||||
...arcPoints.map(point => new THREE.Vector3(point[0], raisedStart[1], point[2])),
|
||||
new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end
|
||||
new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end
|
||||
new THREE.Vector3(end[0], end[1], end[2]) // end
|
||||
];
|
||||
|
||||
const customCurve = new THREE.CatmullRomCurve3(finalPath, false, 'centripetal', 1);
|
||||
const customCurveGeneratedPoints = customCurve.getPoints(100);
|
||||
|
||||
setCustomCurvePoints(customCurveGeneratedPoints);
|
||||
const customCurve = new THREE.CatmullRomCurve3(pathVectors, false, 'centripetal', 1);
|
||||
const generatedPoints = customCurve.getPoints(100);
|
||||
setCustomCurvePoints(generatedPoints);
|
||||
}
|
||||
}, [circlePoints, currentPath]);
|
||||
|
||||
// Frame update for animation
|
||||
useFrame((_, delta) => {
|
||||
if (ikSolver && curveRef.current && currentPath.length >= 0) {
|
||||
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
||||
if (!bone) return;
|
||||
if (!ikSolver) return;
|
||||
|
||||
if (isPlaying) {
|
||||
if (!isPaused) {
|
||||
const curvePoints = curveRef.current;
|
||||
const speedAdjustedProgress = progressRef.current + (speed * armBot.speed);
|
||||
const index = Math.floor(speedAdjustedProgress);
|
||||
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
||||
if (!bone) return;
|
||||
|
||||
if (curvePoints) {
|
||||
|
||||
if (index >= curvePoints.length) {
|
||||
HandleCallback();
|
||||
setCurrentPath([]);
|
||||
curveRef.current = null;
|
||||
progressRef.current = 0;
|
||||
} else {
|
||||
const point = curvePoints[index];
|
||||
bone.position.copy(point);
|
||||
progressRef.current = speedAdjustedProgress;
|
||||
}
|
||||
}
|
||||
if (isPlaying) {
|
||||
if (!isPaused && customCurvePoints && currentPath.length > 0) {
|
||||
const curvePoints = customCurvePoints;
|
||||
const speedAdjustedProgress = progressRef.current + (speed * armBot.speed);
|
||||
const index = Math.floor(speedAdjustedProgress);
|
||||
|
||||
if (index >= curvePoints.length) {
|
||||
// Reached the end of the curve
|
||||
HandleCallback();
|
||||
setCurrentPath([]);
|
||||
curveRef.current = null;
|
||||
progressRef.current = 0;
|
||||
} else {
|
||||
logStatus(armBot.modelUuid, 'Simulation Play Exited');
|
||||
const point = curvePoints[index];
|
||||
bone.position.copy(point);
|
||||
progressRef.current = speedAdjustedProgress;
|
||||
}
|
||||
|
||||
ikSolver.update();
|
||||
} else if (isPaused) {
|
||||
logStatus(armBot.modelUuid, 'Simulation Paused');
|
||||
}
|
||||
} else if (ikSolver && !isPlaying && currentPath.length === 0) {
|
||||
const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone);
|
||||
|
||||
ikSolver.update();
|
||||
} else if (!isPlaying && currentPath.length === 0) {
|
||||
// Not playing anymore, reset to rest
|
||||
bone.position.copy(restPosition);
|
||||
ikSolver.update();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<>
|
||||
{customCurvePoints && currentPath && (
|
||||
<mesh rotation={armBot.rotation}>
|
||||
<Line points={customCurvePoints.map(p => [p.x, p.y, p.z])} color="green" lineWidth={5} dashed={false} />
|
||||
{/* <Line points={currentPath} color="green" lineWidth={5} dashed={false} /> */}
|
||||
{currentPath.length >= 1 && (
|
||||
<>
|
||||
{/* First point */}
|
||||
{/* <mesh position={nearestStartPoint || currentPath[0]} rotation={armBot.rotation}>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
</mesh> */}
|
||||
|
||||
{/* Last point */}
|
||||
{/* <mesh position={nearestEndPoint || currentPath[currentPath.length - 1]} rotation={armBot.rotation}>
|
||||
<sphereGeometry args={[0.1, 16, 16]} />
|
||||
<meshStandardMaterial color="red" />
|
||||
</mesh> */}
|
||||
</>
|
||||
)}
|
||||
{customCurvePoints && currentPath && isPlaying && (
|
||||
<mesh rotation={armBot.rotation} position={armBot.position}>
|
||||
<Line
|
||||
points={customCurvePoints.map((p) => [p.x, p.y, p.z] as [number, number, number])}
|
||||
color="green"
|
||||
lineWidth={5}
|
||||
dashed={false}
|
||||
/>
|
||||
</mesh>
|
||||
)}
|
||||
<mesh position={[armBot.position[0], armBot.position[1] + 1.5, armBot.position[2]]} rotation={[-Math.PI / 2, 0, 0]}>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useThree } from "@react-three/fiber";
|
||||
import { useFloorItems } from '../../../../../store/store';
|
||||
import useModuleStore from '../../../../../store/useModuleStore';
|
||||
import * as THREE from "three";
|
||||
import { useSelectedAction } from '../../../../../store/simulation/useSimulationStore';
|
||||
|
||||
function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
|
||||
@@ -28,6 +29,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { isReset, setReset } = useResetButtonStore();
|
||||
const { isPaused } = usePauseButtonStore();
|
||||
const { selectedAction } = useSelectedAction();
|
||||
|
||||
function firstFrame() {
|
||||
startTime = performance.now();
|
||||
@@ -78,6 +80,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
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");
|
||||
@@ -93,21 +96,17 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
}, [isPaused]);
|
||||
|
||||
useEffect(() => {
|
||||
let armItems = floorItems?.filter((val: any) =>
|
||||
val.modelUuid === "3abf5d46-b59e-4e6b-9c02-a4634b64b82d"
|
||||
);
|
||||
// Get the first matching item
|
||||
let armItem = armItems?.[0];
|
||||
if (armItem) {
|
||||
const targetMesh = scene?.getObjectByProperty("uuid", armItem.modelUuid);
|
||||
const targetMesh = scene?.getObjectByProperty("uuid", armBot.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)
|
||||
@@ -127,8 +126,10 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
logStatus(armBot.modelUuid, "Moving armBot from initial point to rest position.")
|
||||
}
|
||||
if (isPlaying) {
|
||||
|
||||
//Moving armBot from initial point to rest position.
|
||||
if (!armBot?.isActive && armBot?.state == "idle" && currentPhase == "init") {
|
||||
|
||||
setArmBotActive(armBot.modelUuid, true)
|
||||
setArmBotState(armBot.modelUuid, "running")
|
||||
setCurrentPhase("init-to-rest");
|
||||
@@ -144,12 +145,15 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
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');
|
||||
let actionId=armBot.point.actions[0].actionUuid
|
||||
// addCurrentAction(armBot.modelUuid,actionId);
|
||||
addCurrentAction(armBot.modelUuid, selectedAction?.actionId);
|
||||
}, 3000);
|
||||
return () => clearTimeout(timeoutId);
|
||||
}
|
||||
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");
|
||||
@@ -253,7 +257,7 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
}
|
||||
}
|
||||
const logStatus = (id: string, status: string) => {
|
||||
// console.log('status: ', status);
|
||||
//
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -261,296 +265,8 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) {
|
||||
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} />
|
||||
<RoboticArmAnimator HandleCallback={HandleCallback} restPosition={restPosition} ikSolver={ikSolver} targetBone={targetBone} armBot={armBot}
|
||||
logStatus={logStatus} path={path}currentPhase={currentPhase} />
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
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<string>("init");
|
||||
// const [path, setPath] = useState<[number, number, number][]>([]);
|
||||
// const [ikSolver, setIkSolver] = useState<any>(null);
|
||||
// const { scene } = useThree();
|
||||
// const restPosition = new THREE.Vector3(0, 1, -1.6);
|
||||
// const targetBone = "Target";
|
||||
// const groupRef = useRef<any>(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 (
|
||||
// <>
|
||||
// <IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} />
|
||||
// <RoboticArmAnimator
|
||||
// HandleCallback={HandleCallback}
|
||||
// restPosition={restPosition}
|
||||
// ikSolver={ikSolver}
|
||||
// targetBone={targetBone}
|
||||
// armBot={armBot}
|
||||
// logStatus={logStatus}
|
||||
// path={path}
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default RoboticArmInstance;
|
||||
@@ -71,8 +71,7 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKIns
|
||||
|
||||
setSelectedArm(OOI.Target_Bone);
|
||||
|
||||
// scene.add(helper)
|
||||
|
||||
scene.add(helper)
|
||||
|
||||
}, [gltf]);
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import React from 'react'
|
||||
import RoboticArmInstance from './armInstance/roboticArmInstance';
|
||||
import { useArmBotStore } from '../../../../store/simulation/useArmBotStore';
|
||||
|
||||
@@ -10,7 +9,6 @@ function RoboticArmInstances() {
|
||||
{armBots?.map((robot: ArmBotStatus) => (
|
||||
<RoboticArmInstance key={robot.modelUuid} armBot={robot} />
|
||||
))}
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user