"updated arm logic"

This commit is contained in:
SreeNath14
2025-04-15 18:34:38 +05:30
parent ca3028985f
commit c7147773c5
7 changed files with 822 additions and 1069 deletions

View File

@@ -150,6 +150,7 @@ const ArmBotMechanics: React.FC = () => {
modeluuid: updatedPath.modeluuid,
eventData: { type: "ArmBot", points: updatedPath.points }
}
console.log('data: ', data);
socket.emit('v2:model-asset:updateEventData', data);
}

View File

@@ -3,7 +3,10 @@ import * as THREE from "three";
import { useFrame, useThree } from "@react-three/fiber";
import { NavMeshQuery } from "@recast-navigation/core";
import { Line } from "@react-three/drei";
import { useAnimationPlaySpeed, usePlayButtonStore } from "../../../store/usePlayButtonStore";
import {
useAnimationPlaySpeed,
usePlayButtonStore,
} from "../../../store/usePlayButtonStore";
import { usePlayAgv } from "../../../store/store";
interface PathNavigatorProps {
@@ -11,7 +14,7 @@ interface PathNavigatorProps {
pathPoints: any;
id: string;
speed: number;
globalSpeed: number,
globalSpeed: number;
bufferTime: number;
hitCount: number;
processes: any[];
@@ -40,11 +43,21 @@ export default function PathNavigator({
}: PathNavigatorProps) {
const [currentPhase, setCurrentPhase] = useState<Phase>("initial");
const [path, setPath] = useState<[number, number, number][]>([]);
const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>([]);
const [pickupDropPath, setPickupDropPath] = useState<[number, number, number][]>([]);
const [dropPickupPath, setDropPickupPath] = useState<[number, number, number][]>([]);
const [initialPosition, setInitialPosition] = useState<THREE.Vector3 | null>(null);
const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(null);
const [toPickupPath, setToPickupPath] = useState<[number, number, number][]>(
[]
);
const [pickupDropPath, setPickupDropPath] = useState<
[number, number, number][]
>([]);
const [dropPickupPath, setDropPickupPath] = useState<
[number, number, number][]
>([]);
const [initialPosition, setInitialPosition] = useState<THREE.Vector3 | null>(
null
);
const [initialRotation, setInitialRotation] = useState<THREE.Euler | null>(
null
);
const [boxVisible, setBoxVisible] = useState(false);
const distancesRef = useRef<number[]>([]);
@@ -61,11 +74,14 @@ export default function PathNavigator({
const boxRef = useRef<THREE.Mesh | null>(null);
const baseMaterials = useMemo(() => ({
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
Default: new THREE.MeshStandardMaterial({ color: 0xcccccc })
}), []);
const baseMaterials = useMemo(
() => ({
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
Default: new THREE.MeshStandardMaterial({ color: 0xcccccc }),
}),
[]
);
useEffect(() => {
const object = scene.getObjectByProperty("uuid", id);
@@ -135,7 +151,11 @@ export default function PathNavigator({
const pickupToDropPath = computePath(pickup, drop);
const dropToPickupPath = computePath(drop, pickup);
if (toPickupPath.length && pickupToDropPath.length && dropToPickupPath.length) {
if (
toPickupPath.length &&
pickupToDropPath.length &&
dropToPickupPath.length
) {
setPickupDropPath(pickupToDropPath);
setDropPickupPath(dropToPickupPath);
setToPickupPath(toPickupPath);
@@ -163,7 +183,10 @@ export default function PathNavigator({
}, [path]);
function logAgvStatus(id: string, status: string) {
// console.log(`AGV ${id}: ${status}`);
// console.log(
// `AGV ${id}: ${status}`
// );
}
function findProcessByTargetModelUUID(processes: any, targetModelUUID: any) {
@@ -223,7 +246,9 @@ export default function PathNavigator({
}, [processes, MaterialRef, boxVisible, scene, id, baseMaterials]);
useFrame((_, delta) => {
const currentAgv = (agvRef.current || []).find((agv: AGVData) => agv.vehicleId === id);
const currentAgv = (agvRef.current || []).find(
(agv: AGVData) => agv.vehicleId === id
);
if (!scene || !id || !isPlaying) return;
@@ -243,6 +268,7 @@ export default function PathNavigator({
const isAgvReady = () => {
if (!agvRef.current || agvRef.current.length === 0) return false;
if (!currentAgv) return false;
return currentAgv.isActive && hitCount >= currentAgv.maxHitCount;
};
@@ -266,12 +292,19 @@ export default function PathNavigator({
}
if (isPlaying && currentPhase === "initial" && !hasReachedPickup.current) {
const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
const reached = moveAlongPath(
object,
path,
distancesRef.current,
speed,
delta,
progressRef
);
if (reached) {
hasReachedPickup.current = true;
if (currentAgv) {
currentAgv.status = 'picking';
currentAgv.status = "picking";
}
logAgvStatus(id, "Reached pickup point, Waiting for material");
}
@@ -287,20 +320,28 @@ export default function PathNavigator({
progressRef.current = 0;
logAgvStatus(id, "Started from pickup point, heading to drop point");
if (currentAgv) {
currentAgv.status = 'toDrop';
currentAgv.status = "toDrop";
}
}, 0)
}, 0);
return;
}
if (isPlaying && currentPhase === "toDrop") {
const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
const reached = moveAlongPath(
object,
path,
distancesRef.current,
speed,
delta,
progressRef
);
if (reached && !isWaiting.current) {
isWaiting.current = true;
logAgvStatus(id, "Reached drop point");
if (currentAgv) {
currentAgv.status = 'droping';
currentAgv.status = "droping";
currentAgv.hitCount = currentAgv.hitCount--;
}
timeoutRef.current = setTimeout(() => {
setPath([...dropPickupPath]);
@@ -309,16 +350,26 @@ export default function PathNavigator({
isWaiting.current = false;
setBoxVisible(false);
if (currentAgv) {
currentAgv.status = 'toPickup';
currentAgv.status = "toPickup";
}
logAgvStatus(id, "Started from droping point, heading to pickup point");
logAgvStatus(
id,
"Started from droping point, heading to pickup point"
);
}, bufferTime * 1000);
}
return;
}
if (isPlaying && currentPhase === "toPickup") {
const reached = moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
const reached = moveAlongPath(
object,
path,
distancesRef.current,
speed,
delta,
progressRef
);
if (reached) {
if (currentAgv) {
@@ -326,14 +377,21 @@ export default function PathNavigator({
}
setCurrentPhase("initial");
if (currentAgv) {
currentAgv.status = 'picking';
currentAgv.status = "picking";
}
logAgvStatus(id, "Reached pickup point again, cycle complete");
}
return;
}
moveAlongPath(object, path, distancesRef.current, speed, delta, progressRef);
moveAlongPath(
object,
path,
distancesRef.current,
speed,
delta,
progressRef
);
});
function moveAlongPath(
@@ -379,7 +437,11 @@ export default function PathNavigator({
const targetRotationY = Math.atan2(targetDirection.x, targetDirection.z);
const rotationSpeed = Math.min(5 * delta, 1);
object.rotation.y = THREE.MathUtils.lerp(object.rotation.y, targetRotationY, rotationSpeed);
object.rotation.y = THREE.MathUtils.lerp(
object.rotation.y,
targetRotationY,
rotationSpeed
);
}
return false;

View File

@@ -8,8 +8,7 @@ import crate from "../../../assets/gltf-glb/crate_box.glb";
import { useProcessAnimation } from "./useProcessAnimations";
import ProcessObject from "./processObject";
import { ProcessData } from "./types";
import { useSimulationStates } from "../../../store/store";
import { retrieveGLTF } from "../../../utils/indexDB/idbUtils";
interface ProcessContainerProps {
processes: ProcessData[];
@@ -44,19 +43,23 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
checkAndCountTriggers,
} = useProcessAnimation(processes, setProcesses, agvRef);
const baseMaterials = useMemo(() => ({
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
Default: new THREE.MeshStandardMaterial(),
}), []);
const baseMaterials = useMemo(
() => ({
Box: new THREE.MeshStandardMaterial({ color: 0x8b4513 }),
Crate: new THREE.MeshStandardMaterial({ color: 0x00ff00 }),
Default: new THREE.MeshStandardMaterial(),
}),
[]
);
useEffect(() => {
// Update material references for all spawned objects
Object.entries(animationStates).forEach(([processId, processState]) => {
Object.keys(processState.spawnedObjects).forEach((objectId) => {
const entry = { processId, objectId, };
const entry = { processId, objectId };
const materialType = processState.spawnedObjects[objectId]?.currentMaterialType;
const materialType =
processState.spawnedObjects[objectId]?.currentMaterialType;
if (!materialType) {
return;
@@ -65,13 +68,17 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
const matRefArray = MaterialRef.current;
// Find existing material group
const existing = matRefArray.find((entryGroup: { material: string; objects: any[] }) =>
entryGroup.material === materialType
const existing = matRefArray.find(
(entryGroup: { material: string; objects: any[] }) =>
entryGroup.material === materialType
);
if (existing) {
// Check if this processId + objectId already exists
const alreadyExists = existing.objects.some((o: any) => o.processId === entry.processId && o.objectId === entry.objectId);
const alreadyExists = existing.objects.some(
(o: any) =>
o.processId === entry.processId && o.objectId === entry.objectId
);
if (!alreadyExists) {
existing.objects.push(entry);
@@ -91,7 +98,8 @@ const ProcessAnimator: React.FC<ProcessContainerProps> = ({
useFrame(() => {
// Spawn logic frame
const currentTime = clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
const currentTime =
clockRef.current.getElapsedTime() - elapsedBeforePauseRef.current;
setAnimationStates((prev) => {
const newStates = { ...prev };
@@ -119,7 +127,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
}
@@ -324,10 +335,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) {
@@ -358,7 +372,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) {
@@ -377,7 +392,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;

View File

@@ -1,450 +1,3 @@
// import React, {
// useEffect,
// useMemo,
// useState,
// useCallback,
// useRef,
// } from "react";
// import { useSimulationStates } from "../../../store/store";
// import * as THREE from "three";
// import { useThree } from "@react-three/fiber";
// import {
// ConveyorEventsSchema,
// VehicleEventsSchema,
// } from "../../../types/world/worldTypes";
// // Type definitions
// export interface PointAction {
// uuid: string;
// name: string;
// type: string;
// material: string;
// delay: number | string;
// spawnInterval: string | number;
// isUsed: boolean;
// }
// export interface PointTrigger {
// uuid: string;
// bufferTime: number;
// name: string;
// type: string;
// isUsed: boolean;
// }
// export interface PathPoint {
// uuid: string;
// position: [number, number, number];
// actions: PointAction[];
// triggers: PointTrigger[];
// connections: {
// targets: Array<{ modelUUID: string }>;
// };
// }
// export interface SimulationPath {
// type: string;
// modeluuid: string;
// points: PathPoint[];
// pathPosition: [number, number, number];
// speed?: number;
// }
// export interface Process {
// id: string;
// paths: SimulationPath[];
// animationPath: THREE.Vector3[];
// pointActions: PointAction[][];
// pointTriggers: PointTrigger[][];
// speed: number;
// isActive: boolean;
// }
// interface ProcessCreatorProps {
// onProcessesCreated: (processes: Process[]) => void;
// }
// // Convert event schemas to SimulationPath
// function convertToSimulationPath(
// path: ConveyorEventsSchema | VehicleEventsSchema
// ): SimulationPath {
// const { modeluuid } = path;
// // Normalized action handler
// const normalizeAction = (action: any): PointAction => {
// return { ...action }; // Return exact copy with no modifications
// };
// // Normalized trigger handler
// const normalizeTrigger = (trigger: any): PointTrigger => {
// return { ...trigger }; // Return exact copy with no modifications
// };
// if (path.type === "Conveyor") {
// return {
// type: path.type,
// modeluuid,
// points: path.points.map((point) => ({
// uuid: point.uuid,
// position: point.position,
// actions: Array.isArray(point.actions)
// ? point.actions.map(normalizeAction)
// : point.actions
// ? [normalizeAction(point.actions)]
// : [],
// triggers: Array.isArray(point.triggers)
// ? point.triggers.map(normalizeTrigger)
// : point.triggers
// ? [normalizeTrigger(point.triggers)]
// : [],
// connections: {
// targets: point.connections.targets.map((target) => ({
// modelUUID: target.modelUUID,
// })),
// },
// })),
// pathPosition: path.position,
// speed:
// typeof path.speed === "string"
// ? parseFloat(path.speed) || 1
// : path.speed || 1,
// };
// } else {
// // For vehicle paths, handle the case where triggers might not exist
// return {
// type: path.type,
// modeluuid,
// points: [
// {
// uuid: path.points.uuid,
// position: path.points.position,
// actions: Array.isArray(path.points.actions)
// ? path.points.actions.map(normalizeAction)
// : path.points.actions
// ? [normalizeAction(path.points.actions)]
// : [],
// // For vehicle paths, since triggers might not exist in the schema,
// // we always define default to an empty array
// triggers: [],
// connections: {
// targets: path.points.connections.targets.map((target) => ({
// modelUUID: target.modelUUID,
// })),
// },
// },
// ],
// pathPosition: path.position,
// speed: path.points.speed || 1,
// };
// }
// }
// // Helper function to create an empty process
// const createEmptyProcess = (): Process => ({
// id: `process-${Math.random().toString(36).substring(2, 11)}`,
// paths: [],
// animationPath: [],
// pointActions: [],
// pointTriggers: [], // Added point triggers array
// speed: 1,
// isActive: false,
// });
// // Enhanced connection checking function
// function shouldReverseNextPath(
// currentPath: SimulationPath,
// nextPath: SimulationPath
// ): boolean {
// if (nextPath.points.length !== 3) return false;
// const currentLastPoint = currentPath.points[currentPath.points.length - 1];
// const nextFirstPoint = nextPath.points[0];
// const nextLastPoint = nextPath.points[nextPath.points.length - 1];
// // Check if current last connects to next last (requires reversal)
// const connectsToLast = currentLastPoint.connections.targets.some(
// (target) =>
// target.modelUUID === nextPath.modeluuid &&
// nextLastPoint.connections.targets.some(
// (t) => t.modelUUID === currentPath.modeluuid
// )
// );
// // Check if current last connects to next first (no reversal needed)
// const connectsToFirst = currentLastPoint.connections.targets.some(
// (target) =>
// target.modelUUID === nextPath.modeluuid &&
// nextFirstPoint.connections.targets.some(
// (t) => t.modelUUID === currentPath.modeluuid
// )
// );
// // Only reverse if connected to last point and not to first point
// return connectsToLast && !connectsToFirst;
// }
// // Check if a point has a spawn action
// function hasSpawnAction(point: PathPoint): boolean {
// return point.actions.some((action) => action.type.toLowerCase() === "spawn");
// }
// // Ensure spawn point is always at the beginning of the path
// function ensureSpawnPointIsFirst(path: SimulationPath): SimulationPath {
// if (path.points.length !== 3) return path;
// // If the third point has spawn action and first doesn't, reverse the array
// if (hasSpawnAction(path.points[2]) && !hasSpawnAction(path.points[0])) {
// return {
// ...path,
// points: [...path.points].reverse(),
// };
// }
// return path;
// }
// // Updated path adjustment function
// function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
// if (paths.length < 1) return paths;
// const adjustedPaths = [...paths];
// // First ensure all paths have spawn points at the beginning
// for (let i = 0; i < adjustedPaths.length; i++) {
// adjustedPaths[i] = ensureSpawnPointIsFirst(adjustedPaths[i]);
// }
// // Then handle connections between paths
// for (let i = 0; i < adjustedPaths.length - 1; i++) {
// const currentPath = adjustedPaths[i];
// const nextPath = adjustedPaths[i + 1];
// if (shouldReverseNextPath(currentPath, nextPath)) {
// const reversedPoints = [
// nextPath.points[2],
// nextPath.points[1],
// nextPath.points[0],
// ];
// adjustedPaths[i + 1] = {
// ...nextPath,
// points: reversedPoints,
// };
// }
// }
// return adjustedPaths;
// }
// // Main hook for process creation
// export function useProcessCreation() {
// const { scene } = useThree();
// const [processes, setProcesses] = useState<Process[]>([]);
// const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
// if (path.type !== "Conveyor") return false;
// return path.points.some((point) =>
// point.actions.some((action) => action.type.toLowerCase() === "spawn")
// );
// }, []);
// const createProcess = useCallback(
// (paths: SimulationPath[]): Process => {
// if (!paths || paths.length === 0) {
// return createEmptyProcess();
// }
// const animationPath: THREE.Vector3[] = [];
// const pointActions: PointAction[][] = [];
// const pointTriggers: PointTrigger[][] = []; // Added point triggers collection
// const processSpeed = paths[0]?.speed || 1;
// for (const path of paths) {
// for (const point of path.points) {
// if (path.type === "Conveyor") {
// const obj = scene.getObjectByProperty("uuid", point.uuid);
// if (!obj) {
// console.warn(`Object with UUID ${point.uuid} not found in scene`);
// continue;
// }
// const position = obj.getWorldPosition(new THREE.Vector3());
// animationPath.push(position.clone());
// pointActions.push(point.actions);
// pointTriggers.push(point.triggers); // Collect triggers for each point
// }
// }
// }
// return {
// id: `process-${Math.random().toString(36).substring(2, 11)}`,
// paths,
// animationPath,
// pointActions,
// pointTriggers,
// speed: processSpeed,
// isActive: false,
// };
// },
// [scene]
// );
// const getAllConnectedPaths = useCallback(
// (
// initialPath: SimulationPath,
// allPaths: SimulationPath[],
// visited: Set<string> = new Set()
// ): SimulationPath[] => {
// const connectedPaths: SimulationPath[] = [];
// const queue: SimulationPath[] = [initialPath];
// visited.add(initialPath.modeluuid);
// const pathMap = new Map<string, SimulationPath>();
// allPaths.forEach((path) => pathMap.set(path.modeluuid, path));
// while (queue.length > 0) {
// const currentPath = queue.shift()!;
// connectedPaths.push(currentPath);
// // Process outgoing connections
// for (const point of currentPath.points) {
// for (const target of point.connections.targets) {
// if (!visited.has(target.modelUUID)) {
// const targetPath = pathMap.get(target.modelUUID);
// if (targetPath) {
// visited.add(target.modelUUID);
// queue.push(targetPath);
// }
// }
// }
// }
// // Process incoming connections
// for (const [uuid, path] of pathMap) {
// if (!visited.has(uuid)) {
// const hasConnectionToCurrent = path.points.some((point) =>
// point.connections.targets.some(
// (t) => t.modelUUID === currentPath.modeluuid
// )
// );
// if (hasConnectionToCurrent) {
// visited.add(uuid);
// queue.push(path);
// }
// }
// }
// }
// return connectedPaths;
// },
// []
// );
// const createProcessesFromPaths = useCallback(
// (paths: SimulationPath[]): Process[] => {
// if (!paths || paths.length === 0) return [];
// const visited = new Set<string>();
// const processes: Process[] = [];
// const pathMap = new Map<string, SimulationPath>();
// paths.forEach((path) => pathMap.set(path.modeluuid, path));
// for (const path of paths) {
// if (!visited.has(path.modeluuid) && hasSpawnAction(path)) {
// const connectedPaths = getAllConnectedPaths(path, paths, visited);
// const adjustedPaths = adjustPathPointsOrder(connectedPaths);
// const process = createProcess(adjustedPaths);
// processes.push(process);
// }
// }
// return processes;
// },
// [createProcess, getAllConnectedPaths, hasSpawnAction]
// );
// return {
// processes,
// createProcessesFromPaths,
// setProcesses,
// };
// }
// const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
// ({ onProcessesCreated }) => {
// const { simulationStates } = useSimulationStates();
// const { createProcessesFromPaths } = useProcessCreation();
// const prevPathsRef = useRef<SimulationPath[]>([]);
// const prevProcessesRef = useRef<Process[]>([]);
// const convertedPaths = useMemo((): SimulationPath[] => {
// if (!simulationStates) return [];
// return simulationStates.map((path) =>
// convertToSimulationPath(
// path as ConveyorEventsSchema | VehicleEventsSchema
// )
// );
// }, [simulationStates]);
// // Enhanced dependency tracking that includes action and trigger types
// const pathsDependency = useMemo(() => {
// if (!convertedPaths) return null;
// return convertedPaths.map((path) => ({
// id: path.modeluuid,
// // Track all action types for each point
// actionSignature: path.points
// .map((point, index) =>
// point.actions.map((action) => `${index}-${action.type}`).join("|")
// )
// .join(","),
// // Track all trigger types for each point
// triggerSignature: path.points
// .map((point, index) =>
// point.triggers
// .map((trigger) => `${index}-${trigger.type}`)
// .join("|")
// )
// .join(","),
// connections: path.points
// .flatMap((p: PathPoint) =>
// p.connections.targets.map((t: { modelUUID: string }) => t.modelUUID)
// )
// .join(","),
// isActive: false,
// }));
// }, [convertedPaths]);
// // Force process recreation when paths change
// useEffect(() => {
// if (!convertedPaths || convertedPaths.length === 0) {
// if (prevProcessesRef.current.length > 0) {
// onProcessesCreated([]);
// prevProcessesRef.current = [];
// }
// return;
// }
// // Always regenerate processes if the pathsDependency has changed
// // This ensures action and trigger type changes will be detected
// const newProcesses = createProcessesFromPaths(convertedPaths);
// prevPathsRef.current = convertedPaths;
// // Always update processes when action or trigger types change
// onProcessesCreated(newProcesses);
// prevProcessesRef.current = newProcesses;
// }, [
// pathsDependency, // This now includes action and trigger types
// onProcessesCreated,
// convertedPaths,
// createProcessesFromPaths,
// ]);
// return null;
// }
// );
// export default ProcessCreator;
import React, {
useEffect,
useMemo,
@@ -456,6 +9,7 @@ import { useSimulationStates } from "../../../store/store";
import * as THREE from "three";
import { useThree } from "@react-three/fiber";
import {
ArmBotEventsSchema,
ConveyorEventsSchema,
VehicleEventsSchema,
} from "../../../types/simulation";
@@ -480,13 +34,14 @@ export interface PointTrigger {
isUsed: boolean;
}
// Update the connections type in your interfaces
export interface PathPoint {
uuid: string;
position: [number, number, number];
actions: PointAction[];
triggers: PointTrigger[];
connections: {
targets: Array<{ modelUUID: string }>;
targets: Array<{ modelUUID: string; pointUUID?: string }>;
};
}
@@ -498,6 +53,14 @@ export interface SimulationPath {
speed?: number;
isActive: boolean;
}
export interface ArmBot {
type: string;
modeluuid: string;
points: PathPoint[];
pathPosition: [number, number, number];
speed?: number;
isActive: boolean;
}
export interface Process {
id: string;
@@ -515,7 +78,7 @@ interface ProcessCreatorProps {
// Convert event schemas to SimulationPath
function convertToSimulationPath(
path: ConveyorEventsSchema | VehicleEventsSchema
path: ConveyorEventsSchema | VehicleEventsSchema | ArmBotEventsSchema
): SimulationPath {
const { modeluuid } = path;
@@ -539,13 +102,13 @@ function convertToSimulationPath(
actions: Array.isArray(point.actions)
? point.actions.map(normalizeAction)
: point.actions
? [normalizeAction(point.actions)]
: [],
? [normalizeAction(point.actions)]
: [],
triggers: Array.isArray(point.triggers)
? point.triggers.map(normalizeTrigger)
: point.triggers
? [normalizeTrigger(point.triggers)]
: [],
? [normalizeTrigger(point.triggers)]
: [],
connections: {
targets: point.connections.targets.map((target) => ({
modelUUID: target.modelUUID,
@@ -559,6 +122,36 @@ function convertToSimulationPath(
: path.speed || 1,
isActive: false, // Added missing property
};
} else if (path.type === "ArmBot") {
return {
type: path.type,
modeluuid,
points: [
{
uuid: path.points.uuid,
position: path.points.position,
actions: Array.isArray(path.points.actions)
? path.points.actions.map(normalizeAction)
: path.points.actions
? [normalizeAction(path.points.actions)]
: [],
triggers: Array.isArray(path.points.triggers)
? path.points.triggers.map(normalizeTrigger)
: path.points.triggers
? [normalizeTrigger(path.points.triggers)]
: [],
connections: {
targets: path.points.connections.targets.map((target) => ({
modelUUID: target.modelUUID,
pointUUID: target.pointUUID, // Include if available
})),
},
},
],
pathPosition: path.position,
speed: path.points.actions?.speed || 1,
isActive: false,
};
} else {
// For vehicle paths, handle the case where triggers might not exist
return {
@@ -571,8 +164,8 @@ function convertToSimulationPath(
actions: Array.isArray(path.points.actions)
? path.points.actions.map(normalizeAction)
: path.points.actions
? [normalizeAction(path.points.actions)]
: [],
? [normalizeAction(path.points.actions)]
: [],
triggers: [],
connections: {
targets: path.points.connections.targets.map((target) => ({
@@ -831,7 +424,10 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
if (!simulationStates) return [];
return simulationStates.map((path) =>
convertToSimulationPath(
path as ConveyorEventsSchema | VehicleEventsSchema
path as
| ConveyorEventsSchema
| VehicleEventsSchema
| ArmBotEventsSchema
)
);
}, [simulationStates]);

View File

@@ -21,15 +21,15 @@ export interface PointAction {
}
export interface ProcessPoint {
uuid: string;
uuid: string;
position: number[];
rotation: number[];
actions: PointAction[];
rotation: number[];
actions: PointAction[];
connections: {
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
source: { modelUUID: string; pointUUID: string };
targets: { modelUUID: string; pointUUID: string }[];
};
triggers?: Trigger[];
triggers?: Trigger[];
}
export interface ProcessPath {
modeluuid: string;
@@ -38,8 +38,8 @@ export interface ProcessPath {
pathPosition: number[];
pathRotation: number[];
speed: number;
type: "Conveyor" | "Vehicle";
isActive: boolean
type: "Conveyor" | "Vehicle" | "ArmBot";
isActive: boolean;
}
export interface ProcessData {

File diff suppressed because it is too large Load Diff

View File

@@ -11,8 +11,10 @@ function Simulation() {
const { activeModule } = useModuleStore();
const pathsGroupRef = useRef() as React.MutableRefObject<THREE.Group>;
const [processes, setProcesses] = useState<any[]>([]);
const agvRef = useRef([]);
const MaterialRef = useRef([]);
const { simulationStates } = useSimulationStates();
return (
<>