Merged With AGV-UI

This commit is contained in:
Poovizhi99 2025-04-29 12:56:20 +05:30
parent 4dd0840980
commit fdf10589a7
5 changed files with 287 additions and 183 deletions

View File

@ -5,37 +5,40 @@ import { useGLTF } from "@react-three/drei";
import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore"; import { useSelectedEventSphere } from "../../../../store/simulation/useSimulationStore";
import * as THREE from "three"; import * as THREE from "three";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import { useVehicleStore } from "../../../../store/simulation/useVehicleStore";
type VehicleUIProps = { type VehicleUIProps = {
vehicleStatusSample: VehicleEventSchema[]; vehicleStatusSample: VehicleEventSchema[];
setVehicleStatusSample: React.Dispatch< setVehicleStatusSample: React.Dispatch<
React.SetStateAction<VehicleEventSchema[]> React.SetStateAction<VehicleEventSchema[]>
>; >;
vehicle: any
}; };
const VehicleUI: React.FC<VehicleUIProps> = ({ const VehicleUI: React.FC<VehicleUIProps> = ({
vehicleStatusSample, vehicleStatusSample,
setVehicleStatusSample, setVehicleStatusSample,
vehicle
}) => { }) => {
const { scene: startScene } = useGLTF(startPoint) as any; const { scene: startScene } = useGLTF(startPoint) as any;
const { scene: endScene } = useGLTF(startEnd) as any; const { scene: endScene } = useGLTF(startEnd) as any;
const { camera, gl, controls } = useThree(); const { camera, gl, controls } = useThree();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { updateVehicle } = useVehicleStore();
const startMarker = useRef<THREE.Group>(null); const startMarker = useRef<THREE.Group>(null);
const endMarker = useRef<THREE.Group>(null); const endMarker = useRef<THREE.Group>(null);
const hasInitialized = useRef(false); const hasInitialized = useRef<boolean>(false);
const raycaster = useRef(new THREE.Raycaster());
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane
const mouse = useRef(new THREE.Vector2());
const prevMousePos = useRef({ x: 0, y: 0 });
const [draggedMarker, setDraggedMarker] = useState<"start" | "end" | null>( const [draggedMarker, setDraggedMarker] = useState<"start" | "end" | null>(
null null
); );
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null); const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const [isRotating, setIsRotating] = useState(false); const [isRotating, setIsRotating] = useState<boolean>(false);
const raycaster = useRef(new THREE.Raycaster());
const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Y = 0 plane
const mouse = useRef(new THREE.Vector2());
const prevMousePos = useRef({ x: 0, y: 0 });
// Initialize start/end markers // Initialize start/end markers
useEffect(() => { useEffect(() => {
@ -91,9 +94,8 @@ const VehicleUI: React.FC<VehicleUIProps> = ({
pickUpPoint.y, pickUpPoint.y,
pickUpPoint.z pickUpPoint.z
); );
const worldPos = selectedEventSphere.localToWorld(localPos); localPos.y = 0; // Force y to 0
worldPos.y = 0; // Force y to 0 startMarker.current.position.copy(localPos);
startMarker.current.position.copy(worldPos);
} else { } else {
const defaultLocal = new THREE.Vector3(0, 0, 1.5); const defaultLocal = new THREE.Vector3(0, 0, 1.5);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
@ -108,9 +110,10 @@ const VehicleUI: React.FC<VehicleUIProps> = ({
unLoadPoint.y, unLoadPoint.y,
unLoadPoint.z unLoadPoint.z
); );
const worldPos = selectedEventSphere.localToWorld(localPos);
worldPos.y = 0; // Force y to 0
endMarker.current.position.copy(worldPos); localPos.y = 0; // Force y to 0
endMarker.current.position.copy(localPos);
} else { } else {
const defaultLocal = new THREE.Vector3(0, 0, -1.5); const defaultLocal = new THREE.Vector3(0, 0, -1.5);
const defaultWorld = selectedEventSphere.localToWorld(defaultLocal); const defaultWorld = selectedEventSphere.localToWorld(defaultLocal);
@ -190,6 +193,7 @@ const VehicleUI: React.FC<VehicleUIProps> = ({
z: intersectPoint.z + dragOffset.z, z: intersectPoint.z + dragOffset.z,
}; };
if (draggedMarker === "start" && startMarker.current) { if (draggedMarker === "start" && startMarker.current) {
startMarker.current.position.set(newPos.x, newPos.y, newPos.z); startMarker.current.position.set(newPos.x, newPos.y, newPos.z);
} else if (draggedMarker === "end" && endMarker.current) { } else if (draggedMarker === "end" && endMarker.current) {
@ -215,35 +219,50 @@ const VehicleUI: React.FC<VehicleUIProps> = ({
draggedMarker === "start" ? startMarker.current : endMarker.current; draggedMarker === "start" ? startMarker.current : endMarker.current;
if (!marker) return; if (!marker) return;
const worldPos = marker.position.clone(); const worldPos = marker.position;
const localPos = selectedEventSphere.worldToLocal(worldPos);
// Direct update (no snapping, ground level forced at y = 0) const updatedLocalPos = { x: worldPos.x, y: 0, z: worldPos.z };
const updatedLocalPos = { x: localPos.x, y: 0, z: localPos.z }; console.log('updatedLocalPos: ', updatedLocalPos);
setVehicleStatusSample((prev) =>
prev.map((vehicle) => { console.log('draggedMarker: ', draggedMarker);
if ( // setVehicleStatusSample((prev) =>
vehicle.modelUuid === selectedEventSphere.userData.modelUuid && // prev.map((vehicle) => {
selectedEventSphere // if (
) { // vehicle.modelUuid === selectedEventSphere.userData.modelUuid &&
const updatedVehicle = { // selectedEventSphere
...vehicle, // ) {
// const updatedVehicle = {
// ...vehicle,
// point: {
// ...vehicle.point,
// action: {
// ...vehicle.point?.action,
// ...(draggedMarker === "start"
// ? { pickUpPoint: updatedLocalPos }
// : { unLoadPoint: updatedLocalPos }),
// },
// },
// };
// return updatedVehicle;
// }
// return vehicle;
// })
// );
updateVehicle(selectedEventSphere.userData.modelUuid, {
point: { point: {
...vehicle.point, ...vehicle?.point,
action: { action: {
...vehicle.point?.action, ...vehicle?.point?.action,
...(draggedMarker === "start" ...(draggedMarker === "start"
? { pickUpPoint: updatedLocalPos } ? { pickUpPoint: updatedLocalPos }
: { unLoadPoint: updatedLocalPos }), : { unLoadPoint: updatedLocalPos }),
}, },
}, },
}; });
return updatedVehicle;
}
return vehicle;
})
);
setDraggedMarker(null); setDraggedMarker(null);
setDragOffset(null); setDragOffset(null);

View File

@ -1,11 +1,9 @@
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from '@react-three/fiber';
import { useActiveTool, useFloorItems } from '../../../../../store/store';
import * as THREE from 'three'; import * as THREE from 'three';
import { Line } from '@react-three/drei'; import { Line } from '@react-three/drei';
import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { useAnimationPlaySpeed, usePauseButtonStore, usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore';
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
import useModuleStore from '../../../../../store/useModuleStore';
interface VehicleAnimatorProps { interface VehicleAnimatorProps {
path: [number, number, number][]; path: [number, number, number][];
@ -17,23 +15,24 @@ interface VehicleAnimatorProps {
} }
function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) { function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetail, reset }: VehicleAnimatorProps) {
// console.log('path: ', path);
const { decrementVehicleLoad } = useVehicleStore(); const { decrementVehicleLoad } = useVehicleStore();
const { isPaused } = usePauseButtonStore(); const { isPaused } = usePauseButtonStore();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
const { speed } = useAnimationPlaySpeed(); const { speed } = useAnimationPlaySpeed();
const { isReset, setReset } = useResetButtonStore(); const { isReset, setReset } = useResetButtonStore();
const [restRotation, setRestingRotation] = useState<boolean>(true);
const [progress, setProgress] = useState<number>(0);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
const { scene } = useThree();
const progressRef = useRef<number>(0); const progressRef = useRef<number>(0);
const movingForward = useRef<boolean>(true); const movingForward = useRef<boolean>(true);
const completedRef = useRef<boolean>(false); const completedRef = useRef<boolean>(false);
const isPausedRef = useRef<boolean>(false);
const pauseTimeRef = useRef<number | null>(null);
const [restRotation, setRestingRotation] = useState<boolean>(true);
const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]);
const [progress, setProgress] = useState<number>(0);
const { scene } = useThree();
let startTime: number; let startTime: number;
let fixedInterval: number; let fixedInterval: number;
let coveredDistance = progressRef.current; let coveredDistance = progressRef.current;
const isPausedRef = useRef(false);
const pauseTimeRef = useRef<number | null>(null);
useEffect(() => { useEffect(() => {
@ -73,6 +72,9 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
} }
}, [isReset, isPlaying]) }, [isReset, isPlaying])
useEffect(() => {
isPausedRef.current = isPaused;
}, [isPaused]);
useFrame((_, delta) => { useFrame((_, delta) => {
const object = scene.getObjectByProperty('uuid', agvUuid); const object = scene.getObjectByProperty('uuid', agvUuid);
@ -152,10 +154,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
} }
}); });
useEffect(() => {
isPausedRef.current = isPaused;
}, [isPaused]);
function firstFrame() { function firstFrame() {
const droppedMaterial = agvDetail.currentLoad; const droppedMaterial = agvDetail.currentLoad;
startTime = performance.now(); startTime = performance.now();
@ -182,11 +180,8 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed)); fixedInterval = ((unLoadDuration / agvDetail.currentLoad) * (1000 / speed));
if (elapsedTime >= fixedInterval) { if (elapsedTime >= fixedInterval) {
console.log('elapsedTime: ', elapsedTime);
let droppedMat = droppedMaterial - 1; let droppedMat = droppedMaterial - 1;
decrementVehicleLoad(agvDetail.modelUuid, 1); decrementVehicleLoad(agvDetail.modelUuid, 1);
if (droppedMat > 0) { if (droppedMat > 0) {
startTime = performance.now(); startTime = performance.now();
requestAnimationFrame(() => step(droppedMat)); requestAnimationFrame(() => step(droppedMat));

View File

@ -3,7 +3,7 @@ import VehicleAnimator from '../animator/vehicleAnimator';
import * as THREE from 'three'; import * as THREE from 'three';
import { NavMeshQuery } from '@recast-navigation/core'; import { NavMeshQuery } from '@recast-navigation/core';
import { useNavMesh } from '../../../../../store/store'; import { useNavMesh } from '../../../../../store/store';
import { usePlayButtonStore, useResetButtonStore } from '../../../../../store/usePlayButtonStore'; import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore'; import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
function VehicleInstance({ agvDetail }: any) { function VehicleInstance({ agvDetail }: any) {
@ -12,7 +12,7 @@ function VehicleInstance({ agvDetail }: any) {
const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore(); const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore();
const [currentPhase, setCurrentPhase] = useState<string>('stationed'); const [currentPhase, setCurrentPhase] = useState<string>('stationed');
const [path, setPath] = useState<[number, number, number][]>([]); const [path, setPath] = useState<[number, number, number][]>([]);
let isIncrememtable = useRef(true); let isIncrememtable = useRef<boolean>(true);
const computePath = useCallback( const computePath = useCallback(
(start: any, end: any) => { (start: any, end: any) => {
@ -20,7 +20,7 @@ function VehicleInstance({ agvDetail }: any) {
const navMeshQuery = new NavMeshQuery(navMesh); const navMeshQuery = new NavMeshQuery(navMesh);
const { path: segmentPath } = navMeshQuery.computePath(start, end); const { path: segmentPath } = navMeshQuery.computePath(start, end);
return ( return (
segmentPath?.map(({ x, y, z }) => [x, y + 0.1, z] as [number, number, number]) || [] segmentPath?.map(({ x, y, z }) => [x, 0, z] as [number, number, number]) || []
); );
} catch { } catch {
return []; return [];
@ -41,7 +41,6 @@ function VehicleInstance({ agvDetail }: any) {
setPath([]); setPath([]);
} }
const increment = () => { const increment = () => {
if (isIncrememtable.current) { if (isIncrememtable.current) {
console.log('called'); console.log('called');

View File

@ -1,14 +1,32 @@
import React from 'react' import React from 'react'
import VehicleInstance from './instance/vehicleInstance' import VehicleInstance from './instance/vehicleInstance'
import { useVehicleStore } from '../../../../store/simulation/useVehicleStore' import { useVehicleStore } from '../../../../store/simulation/useVehicleStore'
import VehicleUI from '../../ui/vehicle/vehicleUI';
type VehicleUIProps = {
vehicleStatusSample: VehicleEventSchema[];
setVehicleStatusSample: React.Dispatch<
React.SetStateAction<VehicleEventSchema[]>
>;
};
const VehicleInstances: React.FC<VehicleUIProps> = ({
vehicleStatusSample,
setVehicleStatusSample,
}) => {
function VehicleInstances() {
const { vehicles } = useVehicleStore(); const { vehicles } = useVehicleStore();
return ( return (
<> <>
{vehicles.map((val: any, i: any) => {vehicles.map((val: any, i: any) =>
<>
<VehicleInstance agvDetail={val} key={i} /> <VehicleInstance agvDetail={val} key={i} />
<VehicleUI
setVehicleStatusSample={setVehicleStatusSample}
vehicleStatusSample={vehicleStatusSample}
vehicle={val}
/>
</>
)} )}
</> </>

View File

@ -5,17 +5,59 @@ import { useFloorItems } from "../../../store/store";
import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
import VehicleUI from "../ui/vehicle/vehicleUI"; import VehicleUI from "../ui/vehicle/vehicleUI";
function Vehicles() { function Vehicles() {
const { vehicles, addVehicle } = useVehicleStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { floorItems } = useFloorItems(); const { vehicles, addVehicle } = useVehicleStore();
const { floorItems } = useFloorItems()
const [vehicleStatusSample, setVehicleStatusSample] = useState< const [vehicleStatusSample, setVehicleStatusSample] = useState<
VehicleEventSchema[] VehicleEventSchema[]
>([ >([
{ {
modelUuid: "68f8dc55-7802-47fe-aa1c-eade54b4320a", modelUuid: "9356f710-4727-4b50-bdb2-9c1e747ecc74",
modelName: "AGV",
position: [97.9252965204558, 0, 37.96138815638661],
rotation: [0, 0, 0],
state: "idle",
type: "vehicle",
speed: 2.5,
point: {
uuid: "point-789",
position: [0, 1, 0],
rotation: [0, 0, 0],
action: {
actionUuid: "action-456",
actionName: "Deliver to Zone A",
actionType: "travel",
unLoadDuration: 10,
loadCapacity: 2,
pickUpPoint: { x: 98.71483985219794, y: 0, z: 28.66321267938962 },
unLoadPoint: { x: 105.71483985219794, y: 0, z: 28.66321267938962 },
triggers: [
{
triggerUuid: "trig-001",
triggerName: "Start Travel",
triggerType: "onComplete",
delay: 0,
triggeredAsset: {
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
}
},
{
triggerUuid: "trig-002",
triggerName: "Complete Travel",
triggerType: "onComplete",
delay: 2,
triggeredAsset: null
}
]
}
}
},
{
modelUuid: "b06960bb-3d2e-41f7-a646-335f389c68b4",
modelName: "AGV", modelName: "AGV",
position: [89.61609306554463, 0, 33.634136622267356], position: [89.61609306554463, 0, 33.634136622267356],
rotation: [0, 0, 0], rotation: [0, 0, 0],
@ -42,31 +84,25 @@ function Vehicles() {
delay: 0, delay: 0,
triggeredAsset: { triggeredAsset: {
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
triggeredPoint: { triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
pointName: "Pickup Arm Point", triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
pointUuid: "arm-point-01", }
},
triggeredAction: {
actionName: "Grab Widget",
actionUuid: "grab-001",
},
},
}, },
{ {
triggerUuid: "trig-002", triggerUuid: "trig-002",
triggerName: "Complete Travel", triggerName: "Complete Travel",
triggerType: "onComplete", triggerType: "onComplete",
delay: 2, delay: 2,
triggeredAsset: null, triggeredAsset: null
}, }
], ]
}, }
}, }
}, },
{ {
modelUuid: "3a8f6da6-da57-4ef5-91e3-b8daf89e5753", modelUuid: "cd7d0584-0684-42b4-b051-9e882c1914aa",
modelName: "forklift", modelName: "AGV",
position: [98.85729337188162, 0, 38.36616546567653], position: [105.90938758014703, 0, 31.584209911095215],
rotation: [0, 0, 0], rotation: [0, 0, 0],
state: "idle", state: "idle",
type: "vehicle", type: "vehicle",
@ -79,8 +115,8 @@ function Vehicles() {
actionUuid: "action-456", actionUuid: "action-456",
actionName: "Deliver to Zone A", actionName: "Deliver to Zone A",
actionType: "travel", actionType: "travel",
unLoadDuration: 15, unLoadDuration: 10,
loadCapacity: 5, loadCapacity: 2,
pickUpPoint: null, pickUpPoint: null,
unLoadPoint: null, unLoadPoint: null,
triggers: [ triggers: [
@ -91,45 +127,82 @@ function Vehicles() {
delay: 0, delay: 0,
triggeredAsset: { triggeredAsset: {
triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" }, triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
triggeredPoint: { triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
pointName: "Pickup Arm Point", triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
pointUuid: "arm-point-01", }
},
triggeredAction: {
actionName: "Grab Widget",
actionUuid: "grab-001",
},
},
}, },
{ {
triggerUuid: "trig-002", triggerUuid: "trig-002",
triggerName: "Complete Travel", triggerName: "Complete Travel",
triggerType: "onComplete", triggerType: "onComplete",
delay: 2, delay: 2,
triggeredAsset: null, triggeredAsset: null
}, }
], ]
}, }
}, }
}, },
// {
// modelUuid: "e729a4f1-11d2-4778-8d6a-468f1b4f6b79",
// modelName: "forklift",
// position: [98.85729337188162, 0, 38.36616546567653],
// rotation: [0, 0, 0],
// state: "idle",
// type: "vehicle",
// speed: 2.5,
// point: {
// uuid: "point-789",
// position: [0, 1, 0],
// rotation: [0, 0, 0],
// action: {
// actionUuid: "action-456",
// actionName: "Deliver to Zone A",
// actionType: "travel",
// unLoadDuration: 15,
// loadCapacity: 5,
// pickUpPoint: null,
// unLoadPoint: null,
// triggers: [
// {
// triggerUuid: "trig-001",
// triggerName: "Start Travel",
// triggerType: "onStart",
// delay: 0,
// triggeredAsset: {
// triggeredModel: { modelName: "ArmBot-X", modelUuid: "arm-001" },
// triggeredPoint: { pointName: "Pickup Arm Point", pointUuid: "arm-point-01" },
// triggeredAction: { actionName: "Grab Widget", actionUuid: "grab-001" }
// }
// },
// {
// triggerUuid: "trig-002",
// triggerName: "Complete Travel",
// triggerType: "onComplete",
// delay: 2,
// triggeredAsset: null
// }
// ]
// }
// }
// }
]); ]);
// useEffect(()) useEffect(() => {
console.log("vehicleStatusSample", vehicleStatusSample); console.log("vehicles", vehicles);
}, [vehicles])
useEffect(() => { useEffect(() => {
addVehicle("123", vehicleStatusSample[0]); addVehicle("123", vehicleStatusSample[0]);
// addVehicle('123', vehicleStatusSample[1]); addVehicle('123', vehicleStatusSample[1]);
// addVehicle('123', vehicleStatusSample[2]); addVehicle('123', vehicleStatusSample[2]);
}, []); }, []);
useEffect(() => {}, [vehicles]);
return ( return (
<> <>
<VehicleInstances /> <VehicleInstances setVehicleStatusSample={setVehicleStatusSample}
<VehicleUI vehicleStatusSample={vehicleStatusSample} />
{/* <VehicleUI
setVehicleStatusSample={setVehicleStatusSample} setVehicleStatusSample={setVehicleStatusSample}
vehicleStatusSample={vehicleStatusSample} vehicleStatusSample={vehicles}
/> /> */}
</> </>
); );
} }