feat: Enhance ArmBotState with connections and isActive properties

- Updated ArmBotState interface across multiple files to include connections (source and targets) and isActive properties.
- Implemented logic in ProcessAnimator to check if processes are connected to active ArmBots, preventing future spawns if connected.
- Adjusted animation state handling to account for active ArmBots, stopping animations and resetting states as necessary.
- Refactored related functions for better clarity and maintainability.
This commit is contained in:
Jerald-Golden-B 2025-04-16 11:39:03 +05:30
parent 5c24d7ca71
commit e0082cb55a
9 changed files with 755 additions and 638 deletions

View File

@ -12,7 +12,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface StaticMachineState {
@ -45,7 +50,8 @@ const ArmBot = ({ armBots, setArmBots, setStaticMachines }: ArmBotProps) => {
status: "idle",
material: "default",
triggerId: '',
actions: bot.points.actions
actions: bot.points.actions,
connections: bot.points.connections
}));
setArmBots(initialStates);
}, [simulationStates]);

View File

@ -18,16 +18,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
actions: {
uuid: string;
name: string;
speed: number;
processes: {
triggerId: string;
startPoint: string;
endPoint: string;
}[];
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface StaticMachineState {
@ -87,6 +83,7 @@ export const ArmbotInstances: React.FC<ArmbotInstancesProps> = ({ index, armBot,
rotation={armBot.rotation}
processes={processes}
armBot={armBot}
setArmBots={setArmBots}
setStaticMachines={setStaticMachines}
updateArmBotStatus={updateArmBotStatus}
/>

View File

@ -20,16 +20,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
actions: {
uuid: string;
name: string;
speed: number;
processes: {
triggerId: string;
startPoint: string;
endPoint: string;
}[];
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
type IKAnimationControllerProps = {
@ -46,6 +42,7 @@ type IKAnimationControllerProps = {
logStatus: (status: string) => void;
groupRef: React.RefObject<THREE.Group>;
armBot: ArmBotState;
setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
setStaticMachines: React.Dispatch<React.SetStateAction<StaticMachineState[]>>;
updateArmBotStatus: (status: string) => void;
}
@ -59,6 +56,7 @@ const IKAnimationController = ({
logStatus,
groupRef,
armBot,
setArmBots,
setStaticMachines,
updateArmBotStatus
}: IKAnimationControllerProps) => {
@ -120,30 +118,61 @@ const IKAnimationController = ({
if (prev.selectedTrigger !== selectedTrigger) {
logStatus(`[Arm ${uuid}] Processing new trigger: ${selectedTrigger}`);
const currentProcess = process.find(p => p.triggerId === prev.selectedTrigger);
if (currentProcess) {
const triggerId = currentProcess.triggerId;
const endPoint = armBot.actions.processes.find((process) => process.triggerId === triggerId)?.endPoint;
// Search simulationStates for a StaticMachine that has a point matching this endPointId
const matchedStaticMachine = simulationStates.find(
(state) =>
state.type === "StaticMachine" &&
state.points?.uuid === endPoint// check for static machine with matching point uuid
) as any;
// Search simulationStates for a StaticMachine or Conveyor that has a point matching this endPointId
const matchedMachine = simulationStates.find((state) => {
if (state.type === "Conveyor") {
// For Conveyor, points is an array
return (state).points.some(
(point) => point.uuid === endPoint
);
} else if (state.type === "StaticMachine") {
// For StaticMachine, points is an object
return state.points.uuid === endPoint;
}
return false;
});
if (matchedStaticMachine) {
setStaticMachines((machines) => {
return machines.map((machine) => {
if (machine.uuid === matchedStaticMachine.modeluuid) {
return { ...machine, status: "running" };
} else {
return machine;
}
if (matchedMachine) {
// Log if the end point is a conveyor
if (matchedMachine.type === "Conveyor") {
logStatus(`[Arm ${uuid}] Reached end point which is a conveyor (${matchedMachine.modelName})`);
} else {
logStatus(`[Arm ${uuid}] Reached end point which is a static machine (${matchedMachine.modelName})`);
}
if (matchedMachine.type === "StaticMachine") {
setStaticMachines((machines) => {
return machines.map((machine) => {
if (machine.uuid === matchedMachine.modeluuid) {
return { ...machine, status: "running" };
} else {
return machine;
}
});
});
});
}
if (matchedMachine.type === "Conveyor") {
setArmBots((prev) =>
prev.map((arm) => {
if (arm.uuid === uuid) {
return {
...arm,
isActive: false
};
}
else {
return arm;
}
})
);
}
}
}
}

View File

@ -23,16 +23,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
actions: {
uuid: string;
name: string;
speed: number;
processes: {
triggerId: string;
startPoint: string;
endPoint: string;
}[];
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
const IkInstances = ({
@ -43,6 +39,7 @@ const IkInstances = ({
position,
rotation,
armBot,
setArmBots,
setStaticMachines,
updateArmBotStatus
}: {
@ -53,6 +50,7 @@ const IkInstances = ({
position: [number, number, number];
rotation: [number, number, number];
armBot: ArmBotState;
setArmBots: React.Dispatch<React.SetStateAction<ArmBotState[]>>;
setStaticMachines: React.Dispatch<React.SetStateAction<StaticMachineState[]>>;
updateArmBotStatus: (status: string) => void;
}) => {
@ -141,6 +139,7 @@ const IkInstances = ({
logStatus={logStatus}
groupRef={groupRef}
armBot={armBot}
setArmBots={setArmBots}
setStaticMachines={setStaticMachines}
updateArmBotStatus={updateArmBotStatus}
/>

View File

@ -1,4 +1,4 @@
import React, { useRef, useEffect, useMemo } from "react";
import React, { useRef, useEffect, useMemo, useCallback } from "react";
import { useLoader, useFrame } from "@react-three/fiber";
import { GLTFLoader } from "three-stdlib";
import * as THREE from "three";
@ -18,9 +18,13 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface ProcessContainerProps {
processes: ProcessData[];
setProcesses: React.Dispatch<React.SetStateAction<any[]>>;
@ -103,9 +107,33 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
// In processAnimator.tsx - only the relevant spawn logic part that needs fixes
// Add this function to ProcessAnimator component
const isConnectedToActiveArmBot = useCallback(
(processId: any) => {
// Check if any active armbot is connected to this process
return armBots.some((armbot) => {
if (!armbot.isActive) return false;
// Check if this armbot is connected to the process
return armbot.connections?.targets?.some((connection: any) => {
// Find the process that owns this modelUUID
const connectedProcess = processes.find((p) =>
p.paths?.some((path) => path.modeluuid === connection.modelUUID)
);
return connectedProcess?.id === processId;
});
});
},
[armBots, processes]
);
// In processAnimator.tsx - only the relevant spawn logic part that needs fixes
useFrame(() => {
// Spawn logic frame
const currentTime = clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
const currentTime =
clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
setAnimationStates((prev) => {
const newStates = { ...prev };
@ -119,6 +147,14 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
return;
}
if (isConnectedToActiveArmBot(process.id)) {
newStates[process.id] = {
...processState,
nextSpawnTime: Infinity, // Prevent future spawns
};
return;
}
const spawnPoint = findSpawnPoint(process);
if (!spawnPoint || !spawnPoint.actions) return;
@ -133,7 +169,10 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
: parseFloat(spawnAction.spawnInterval as string) || 0;
// Check if this is a zero interval spawn and we already spawned an object
if (spawnInterval === 0 && processState.hasSpawnedZeroIntervalObject === true) {
if (
spawnInterval === 0 &&
processState.hasSpawnedZeroIntervalObject === true
) {
return; // Don't spawn more objects for zero interval
}
@ -183,6 +222,29 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
const processState = newStates[process.id];
if (!processState) return;
if (isConnectedToActiveArmBot(process.id)) {
newStates[process.id] = {
...processState,
spawnedObjects: Object.entries(processState.spawnedObjects).reduce(
(acc, [id, obj]) => ({
...acc,
[id]: {
...obj,
state: {
...obj.state,
isAnimating: false, // Stop animation
isDelaying: false, // Clear delays
delayComplete: false, // Reset delays
progress: 0, // Reset progress
},
},
}),
{}
),
};
return;
}
if (processState.isProcessDelaying) {
const effectiveDelayTime =
processState.processDelayDuration / speedRef.current;
@ -338,10 +400,13 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
if (isLastPoint) {
const isAgvPicking = agvRef.current.some(
(agv: any) => agv.processId === process.id && agv.status === "picking"
(agv: any) =>
agv.processId === process.id && agv.status === "picking"
);
const shouldHide = !currentPointData?.actions || !hasNonInheritActions(currentPointData.actions);
const shouldHide =
!currentPointData?.actions ||
!hasNonInheritActions(currentPointData.actions);
if (shouldHide) {
if (isAgvPicking) {
@ -372,7 +437,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
if (tempStackedObjectsRef.current[objectId]) {
const isAgvPicking = agvRef.current.some(
(agv: any) => agv.processId === process.id && agv.status === "picking"
(agv: any) =>
agv.processId === process.id && agv.status === "picking"
);
if (isAgvPicking) {
@ -391,7 +457,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
if (!isLastPoint) {
const nextPoint = path[nextPointIdx];
const distance = path[stateRef.currentIndex].distanceTo(nextPoint);
const distance =
path[stateRef.currentIndex].distanceTo(nextPoint);
const effectiveSpeed = stateRef.speed * speedRef.current;
const movement = effectiveSpeed * delta;
@ -442,7 +509,6 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
return newStates;
});
});
if (!processedProcesses || processedProcesses.length === 0) {
return null;
}

View File

@ -9,7 +9,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface ProcessContainerProps {

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,12 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface StaticMachineState {

View File

@ -10,9 +10,13 @@ interface ArmBotState {
status: string;
material: string;
triggerId: string;
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
actions: { uuid: string; name: string; speed: number; processes: { triggerId: string; startPoint: string; endPoint: string }[]; };
isActive?: boolean;
}
interface StaticMachineState {
uuid: string;
status: string;