diff --git a/app/src/modules/IIOTTemp/AgvSimulation.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/AgvSimulation.tsx similarity index 96% rename from app/src/modules/IIOTTemp/AgvSimulation.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/AgvSimulation.tsx index 015eac9..4bfb9c6 100644 --- a/app/src/modules/IIOTTemp/AgvSimulation.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/AgvSimulation.tsx @@ -1,8 +1,9 @@ import { useFrame, useThree } from '@react-three/fiber'; import React, { useEffect, useRef, useState } from 'react'; import * as THREE from 'three'; -import useModuleStore from '../../store/useModuleStore'; -import { MaterialModel } from '../simulation/materials/instances/material/materialModel'; +import useModuleStore from '../../../../store/useModuleStore'; +import { MaterialModel } from '../../../simulation/materials/instances/material/materialModel'; + type AgvSimulationProps = { data: any; diff --git a/app/src/modules/IIOTTemp/ArmAnimator.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ArmAnimator.tsx similarity index 99% rename from app/src/modules/IIOTTemp/ArmAnimator.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ArmAnimator.tsx index 11bf86c..66d355c 100644 --- a/app/src/modules/IIOTTemp/ArmAnimator.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ArmAnimator.tsx @@ -1,7 +1,8 @@ import { useFrame, useThree } from '@react-three/fiber'; import React, { useEffect, useRef, useState } from 'react' import * as THREE from "three"; -import { useAnimationPlaySpeed } from '../../store/usePlayButtonStore'; +import { useAnimationPlaySpeed } from '../../../../store/usePlayButtonStore'; + type PointWithDegree = { position: [number, number, number]; diff --git a/app/src/modules/IIOTTemp/ConveyorSimulation.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ConveyorSimulation.tsx similarity index 95% rename from app/src/modules/IIOTTemp/ConveyorSimulation.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ConveyorSimulation.tsx index 4abe165..32330e3 100644 --- a/app/src/modules/IIOTTemp/ConveyorSimulation.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/ConveyorSimulation.tsx @@ -1,9 +1,11 @@ import React, { useEffect, useRef, useState } from 'react'; import * as THREE from 'three'; -import useMqttConnectionStore from '../../store/iiot/iiotmqttConnectionStore'; + import { useFrame, useThree } from '@react-three/fiber'; -import useModuleStore from '../../store/useModuleStore'; -import { MaterialModel } from '../simulation/materials/instances/material/materialModel'; +import useMqttConnectionStore from '../../../../store/iiot/iiotmqttConnectionStore'; +import useModuleStore from '../../../../store/useModuleStore'; +import { MaterialModel } from '../../../simulation/materials/instances/material/materialModel'; + type ConveyorSimulationProps = { data: any; diff --git a/app/src/modules/IIOTTemp/MachineSimulation.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/MachineSimulation.tsx similarity index 95% rename from app/src/modules/IIOTTemp/MachineSimulation.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/MachineSimulation.tsx index b270227..b0424eb 100644 --- a/app/src/modules/IIOTTemp/MachineSimulation.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/MachineSimulation.tsx @@ -1,6 +1,7 @@ import { useFrame, useThree } from '@react-three/fiber'; import React, { useEffect, useRef, useState } from 'react'; -import useModuleStore from '../../store/useModuleStore'; +import useModuleStore from '../../../../store/useModuleStore'; + type MachineSimulationProps = { data: any; diff --git a/app/src/modules/IIOTTemp/IIotIkSolver.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/RoboticArm/IIotIkSolver.tsx similarity index 100% rename from app/src/modules/IIOTTemp/IIotIkSolver.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/RoboticArm/IIotIkSolver.tsx diff --git a/app/src/modules/IIOTTemp/RoboticArmSimulation.tsx b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/RoboticArm/RoboticArmSimulation.tsx similarity index 96% rename from app/src/modules/IIOTTemp/RoboticArmSimulation.tsx rename to app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/RoboticArm/RoboticArmSimulation.tsx index 316fbe1..43c284d 100644 --- a/app/src/modules/IIOTTemp/RoboticArmSimulation.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/IIOTSimulation/RoboticArm/RoboticArmSimulation.tsx @@ -1,12 +1,11 @@ import React, { useEffect, useRef, useState } from "react"; -import useModuleStore from "../../store/useModuleStore"; import { useThree } from "@react-three/fiber"; -import IIotIkSolver from "./IIotIkSolver"; -import armModel from "../../assets/gltf-glb/rigged/ik_arm_1.glb"; +import armModel from "../../../../../assets/gltf-glb/rigged/ik_arm_1.glb"; import * as THREE from "three"; -import ArmAnimator from "./ArmAnimator"; -import { useFloorItems } from "../../store/builder/store"; -import { MaterialModel } from "../simulation/materials/instances/material/materialModel"; +import useModuleStore from "../../../../../store/useModuleStore"; +import IIotIkSolver from "./IIotIkSolver"; +import ArmAnimator from "../ArmAnimator"; + type ArmBotSimulationProps = { data: any; diff --git a/app/src/modules/IIOTTemp/MqttListener.tsx b/app/src/modules/IIOTTemp/RTSimulation/MqttData/MqttListener.tsx similarity index 95% rename from app/src/modules/IIOTTemp/MqttListener.tsx rename to app/src/modules/IIOTTemp/RTSimulation/MqttData/MqttListener.tsx index fb2ebf1..c511958 100644 --- a/app/src/modules/IIOTTemp/MqttListener.tsx +++ b/app/src/modules/IIOTTemp/RTSimulation/MqttData/MqttListener.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; -import useMqttConnectionStore from '../../store/iiot/iiotmqttConnectionStore'; + import { IClientSubscribeOptions } from 'mqtt'; +import useMqttConnectionStore from '../../../../store/iiot/iiotmqttConnectionStore'; interface MqttListenerProps { @@ -20,27 +21,27 @@ const MqttListener: React.FC = ({ setData }) => { const topic4 = 'agv0001/0001/status' const topic5 = 'arm0001/0001/status' - client.subscribe(topic1, {} as IClientSubscribeOptions, (err) => { + client.subscribe(topic1, {} as IClientSubscribeOptions, (err:any) => { if (err) { console.error('Subscription error:', err); } }); - client.subscribe(topic2, {} as IClientSubscribeOptions, (err) => { + client.subscribe(topic2, {} as IClientSubscribeOptions, (err:any) => { if (err) { console.error('Subscription error:', err); } }); - client.subscribe(topic3, {} as IClientSubscribeOptions, (err) => { + client.subscribe(topic3, {} as IClientSubscribeOptions, (err:any) => { if (err) { console.error('Subscription error:', err); } }); - client.subscribe(topic4, {} as IClientSubscribeOptions, (err) => { + client.subscribe(topic4, {} as IClientSubscribeOptions, (err:any) => { if (err) { console.error('Subscription error:', err); } }); - client.subscribe(topic5, {} as IClientSubscribeOptions, (err) => { + client.subscribe(topic5, {} as IClientSubscribeOptions, (err:any) => { if (err) { console.error('Subscription error:', err); } diff --git a/app/src/modules/IIOTTemp/RealTimeSimulation.tsx b/app/src/modules/IIOTTemp/RealTimeSimulation.tsx index b1b0f5f..f10a2f8 100644 --- a/app/src/modules/IIOTTemp/RealTimeSimulation.tsx +++ b/app/src/modules/IIOTTemp/RealTimeSimulation.tsx @@ -1,12 +1,13 @@ //singleConveyor import { useEffect, useState } from 'react'; -import MqttListener from './MqttListener'; -import ConveyorSimulation from './ConveyorSimulation'; -import MachineSimulation from './MachineSimulation'; -import AgvSimulation from './AgvSimulation'; -import RoboticArmSimulation from './RoboticArmSimulation'; + import useModuleStore from '../../store/useModuleStore'; +import ConveyorSimulation from './RTSimulation/IIOTSimulation/ConveyorSimulation'; +import MachineSimulation from './RTSimulation/IIOTSimulation/MachineSimulation'; +import AgvSimulation from './RTSimulation/IIOTSimulation/AgvSimulation'; +import RoboticArmSimulation from './RTSimulation/IIOTSimulation/RoboticArm/RoboticArmSimulation'; +import MqttListener from './RTSimulation/MqttData/MqttListener'; type MqttData = { state?: string; diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 3d5df6a..ed64ff3 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -41,44 +41,3 @@ export default function Scene() { ); } - - - - - -// export default function Scene() { -// const map = useMemo(() => [ -// { name: "forward", keys: ["ArrowUp", "w", "W"] }, -// { name: "backward", keys: ["ArrowDown", "s", "S"] }, -// { name: "left", keys: ["ArrowLeft", "a", "A"] }, -// { name: "right", keys: ["ArrowRight", "d", "D"] }, -// ], []); -// const { activeModule, setActiveModule } = useModuleStore(); - -// return ( -// -// {activeModule !== "visualization" && -// { -// e.preventDefault(); -// }} -// > -// - -// - -// - -// - - - -// -// } -// {activeModule === "visualization" && } - -// -// ); -// } \ No newline at end of file diff --git a/app/src/modules/simulation/analysis/ROI/roiData.tsx b/app/src/modules/simulation/analysis/ROI/roiData.tsx index f1ddda5..869f84d 100644 --- a/app/src/modules/simulation/analysis/ROI/roiData.tsx +++ b/app/src/modules/simulation/analysis/ROI/roiData.tsx @@ -41,10 +41,6 @@ export default function ROIData() { if (!isNaN(electricityCost) && !isNaN(fixedCost) && !isNaN(laborCost) && !isNaN(maintenanceCost) && !isNaN(materialCost) && !isNaN(productionPeriod) && !isNaN(salvageValue) && !isNaN(sellingPrice) && !isNaN(shiftLength) && !isNaN(shiftsPerDay) && !isNaN(workingDaysPerYear) && productionCapacityData > 0) { - - - - const totalHoursPerYear = shiftLength * shiftsPerDay * workingDaysPerYear; // Total good units produced per year diff --git a/app/src/modules/simulation/roboticArm/functions/collectArcPoints.ts b/app/src/modules/simulation/roboticArm/functions/collectArcPoints.ts new file mode 100644 index 0000000..67bffb3 --- /dev/null +++ b/app/src/modules/simulation/roboticArm/functions/collectArcPoints.ts @@ -0,0 +1,29 @@ +import { findNearestIndex } from "./findNearestIndex"; + +// Helper function to collect points and check forbidden degrees +type PointWithDegree = { + position: [number, number, number]; + degree: number; +}; +export function collectArcPoints(circlePointsWithDegrees: PointWithDegree[], startIdx: number, endIdx: number, clockwise: boolean) { + const totalSegments = 64; + const arcPoints: [number, number, number][] = []; + let i = startIdx; + + while (i !== (endIdx + (clockwise ? 1 : -1) + totalSegments) % totalSegments) { + const { degree, position } = circlePointsWithDegrees[i]; + // Skip over + arcPoints.push(position); + i = (i + (clockwise ? 1 : -1) + totalSegments) % totalSegments; + } + return arcPoints; +}; + +//Range to restrict angle +export function hasForbiddenDegrees(circlePoints: [number, number, number][], circlePointsWithDegrees: PointWithDegree[], arc: [number, number, number][]) { + return arc.some(p => { + const idx = findNearestIndex(p, circlePoints); + const degree = circlePointsWithDegrees[idx]?.degree || 0; + return degree >= 271 && degree <= 300; // Forbidden range: 271° to 300° + }); +}; \ No newline at end of file diff --git a/app/src/modules/simulation/roboticArm/functions/findNearestIndex.ts b/app/src/modules/simulation/roboticArm/functions/findNearestIndex.ts new file mode 100644 index 0000000..ed7773c --- /dev/null +++ b/app/src/modules/simulation/roboticArm/functions/findNearestIndex.ts @@ -0,0 +1,23 @@ +// Function for find nearest Circlepoints Index +export function 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 +export function findNearest(circlePoints: [number, number, number][], 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]); +}; \ No newline at end of file diff --git a/app/src/modules/simulation/roboticArm/functions/generateRingPoints.ts b/app/src/modules/simulation/roboticArm/functions/generateRingPoints.ts new file mode 100644 index 0000000..758d419 --- /dev/null +++ b/app/src/modules/simulation/roboticArm/functions/generateRingPoints.ts @@ -0,0 +1,29 @@ + //Generate Circle Points +export 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; +} + + //Generate CirclePoints with Angle + export function generateRingPointsWithDegrees(radius: number, segments: number, initialRotation: [number, number, number]) { + const points: { position: [number, number, number]; degree: number }[] = []; + for (let i = 0; i < segments; i++) { + const angleRadians = (i / segments) * Math.PI * 2; + const x = Math.cos(angleRadians) * radius; + const z = Math.sin(angleRadians) * radius; + const degree = (angleRadians * 180) / Math.PI; // Convert radians to degrees + points.push({ + position: [x, 1.5, z], + degree, + }); + } + return points; + } \ No newline at end of file diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index 52213fe..8832f26 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -3,6 +3,9 @@ import { useFrame, useThree } from '@react-three/fiber'; import * as THREE from 'three'; import { Line, Text } from '@react-three/drei'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; +import { generateRingPoints, generateRingPointsWithDegrees } from '../../functions/generateRingPoints'; +import { findNearest, findNearestIndex } from '../../functions/findNearestIndex'; +import { collectArcPoints, hasForbiddenDegrees } from '../../functions/collectArcPoints'; type PointWithDegree = { position: [number, number, number]; @@ -58,90 +61,12 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone } }, [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; - } - - //Generate CirclePoints with Angle - function generateRingPointsWithDegrees(radius: number, segments: number, initialRotation: [number, number, number]) { - const points: { position: [number, number, number]; degree: number }[] = []; - for (let i = 0; i < segments; i++) { - const angleRadians = (i / segments) * Math.PI * 2; - const x = Math.cos(angleRadians) * radius; - const z = Math.sin(angleRadians) * radius; - const degree = (angleRadians * 180) / Math.PI; // Convert radians to degrees - points.push({ - position: [x, 1.5, z], - degree, - }); - } - return points; - } - // Handle circle points based on armBot position useEffect(() => { const points = generateRingPointsWithDegrees(CIRCLE_RADIUS, 64, armBot.rotation); setCirclePointsWithDegrees(points) }, [armBot.rotation]); - // 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 - 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]); - }; - - // Helper function to collect points and check forbidden degrees - const collectArcPoints = (startIdx: number, endIdx: number, clockwise: boolean) => { - const totalSegments = 64; - const arcPoints: [number, number, number][] = []; - let i = startIdx; - - while (i !== (endIdx + (clockwise ? 1 : -1) + totalSegments) % totalSegments) { - const { degree, position } = circlePointsWithDegrees[i]; - // Skip over - arcPoints.push(position); - i = (i + (clockwise ? 1 : -1) + totalSegments) % totalSegments; - } - return arcPoints; - }; - - //Range to restrict angle - const hasForbiddenDegrees = (arc: [number, number, number][]) => { - return arc.some(p => { - const idx = findNearestIndex(p, circlePoints); - const degree = circlePointsWithDegrees[idx]?.degree || 0; - return degree >= 271 && degree <= 300; // Forbidden range: 271° to 300° - }); - }; - // Handle nearest points and final path (including arc points) useEffect(() => { if (circlePoints.length > 0 && currentPath.length > 0) { @@ -152,8 +77,8 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone 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 nearestToStart = findNearest(raisedStart); - const nearestToEnd = findNearest(raisedEnd); + const nearestToStart = findNearest(circlePoints, raisedStart); + const nearestToEnd = findNearest(circlePoints, raisedEnd); const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints); const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints); @@ -163,11 +88,11 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + totalSegments) % totalSegments; // Try both directions - const arcClockwise = collectArcPoints(indexOfNearestStart, indexOfNearestEnd, true); - const arcCounterClockwise = collectArcPoints(indexOfNearestStart, indexOfNearestEnd, false); + const arcClockwise = collectArcPoints(circlePointsWithDegrees, indexOfNearestStart, indexOfNearestEnd, true); + const arcCounterClockwise = collectArcPoints(circlePointsWithDegrees, indexOfNearestStart, indexOfNearestEnd, false); - const clockwiseForbidden = hasForbiddenDegrees(arcClockwise); - const counterClockwiseForbidden = hasForbiddenDegrees(arcCounterClockwise); + const clockwiseForbidden = hasForbiddenDegrees(circlePoints, circlePointsWithDegrees, arcClockwise); + const counterClockwiseForbidden = hasForbiddenDegrees(circlePoints, circlePointsWithDegrees, arcCounterClockwise); let arcPoints: [number, number, number][] = []; diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index ce5a280..3104578 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -84,7 +84,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { } const handleDropTrigger = () => { - if (armBot.currentAction) { const action = getActionByUuid(selectedProduct.productId, armBot.currentAction.actionUuid); const model = getEventByModelUuid(selectedProduct.productId, action?.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid || ''); @@ -177,6 +176,30 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { } } + function animate(currentTime: number) { + if (previousTimeRef.current === null) { + previousTimeRef.current = currentTime; + } + const deltaTime = (currentTime - previousTimeRef.current) / 1000; + previousTimeRef.current = currentTime; + if (armBot.isActive) { + if (!isPausedRef.current) { + activeSecondsElapsed.current += deltaTime * isSpeedRef.current; + } + } else { + if (!isPausedRef.current) { + idleSecondsElapsed.current += deltaTime * isSpeedRef.current; + } + } + animationFrameIdRef.current = requestAnimationFrame(animate); + } + function createCurveBetweenTwoPoints(p1: any, p2: any) { + const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5); + const points = [p1, mid, p2]; + return new THREE.CatmullRomCurve3(points); + } + + useEffect(() => { isPausedRef.current = isPaused; }, [isPaused]); @@ -217,27 +240,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { } }, [isReset, isPlaying]) - - function animate(currentTime: number) { - if (previousTimeRef.current === null) { - previousTimeRef.current = currentTime; - } - const deltaTime = (currentTime - previousTimeRef.current) / 1000; - previousTimeRef.current = currentTime; - if (armBot.isActive) { - if (!isPausedRef.current) { - activeSecondsElapsed.current += deltaTime * isSpeedRef.current; - // console.log(' activeSecondsElapsed.current: ', activeSecondsElapsed.current); - } - } else { - if (!isPausedRef.current) { - idleSecondsElapsed.current += deltaTime * isSpeedRef.current; - // console.log('idleSecondsElapsed.current: ', idleSecondsElapsed.current); - } - } - animationFrameIdRef.current = requestAnimationFrame(animate); - } - useEffect(() => { if (!isPlaying) return @@ -346,11 +348,6 @@ function RoboticArmInstance({ armBot }: { armBot: ArmBotStatus }) { }, [currentPhase, armBot, isPlaying, isReset, ikSolver]) - function createCurveBetweenTwoPoints(p1: any, p2: any) { - const mid = new THREE.Vector3().addVectors(p1, p2).multiplyScalar(0.5); - const points = [p1, mid, p2]; - return new THREE.CatmullRomCurve3(points); - } const HandleCallback = () => {