Merge remote-tracking branch 'origin/simulation-agv-v2' into v2

This commit is contained in:
2025-05-13 18:43:01 +05:30
12 changed files with 520 additions and 308 deletions

View File

@@ -4,62 +4,102 @@ import { computeArea } from '../functions/computeArea';
import { Html } from '@react-three/drei'; import { Html } from '@react-three/drei';
import * as CONSTANTS from "../../../types/world/worldConstants"; import * as CONSTANTS from "../../../types/world/worldConstants";
import * as turf from '@turf/turf'; import * as turf from '@turf/turf';
import * as THREE from "three"
const CalculateAreaGroup = () => { const CalculateAreaGroup = () => {
const { roomsState } = useRoomsState(); const { roomsState } = useRoomsState();
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
const savedTheme: string | null = localStorage.getItem('theme');
return ( return (
<group name="roomArea" visible={toggleView}> <group name="roomArea" visible={toggleView}>
{roomsState.length > 0 && <group name="roomFills" visible={toggleView}>
roomsState.flat().map((room: any, index: number) => { {roomsState.length > 0 &&
if (!toggleView) return null; roomsState.flat().map((room: any, index: number) => {
const coordinates = room.coordinates; const coordinates = room.coordinates;
if (!coordinates || coordinates.length < 3) return null;
if (!coordinates || coordinates.length < 3) return null; const yPos = (room.layer || 0) * CONSTANTS.zoneConfig.height;
const coords2D = coordinates.map((p: any) => new THREE.Vector2(p.position.x, p.position.z));
// console.log('coords2D: ', coords2D);
let coords2D = coordinates.map((p: any) => [p.position.x, p.position.z]); if (!coords2D[0].equals(coords2D[coords2D.length - 1])) {
coords2D.push(coords2D[0]);
}
const first = coords2D[0]; const shape = new THREE.Shape(coords2D);
const last = coords2D[coords2D.length - 1]; const extrudeSettings = {
if (first[0] !== last[0] || first[1] !== last[1]) { depth: 0.01,
coords2D.push(first); bevelEnabled: false,
} };
const polygon = turf.polygon([coords2D]); const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
const center2D = turf.center(polygon).geometry.coordinates; geometry.rotateX(Math.PI / 2);
const sumY = coordinates.reduce((sum: number, p: any) => sum + p.position.y, 0); const material = new THREE.MeshBasicMaterial({
const avgY = sumY / coordinates.length; color: savedTheme === "dark" ? "#d2baff" : '#6f42c1',
side: THREE.DoubleSide,
transparent: true,
opacity: 0.4,
depthWrite: false,
});
const area = computeArea(room, "rooms"); return (
const formattedArea = `${area.toFixed(2)}`; <group key={`roomFill-${index}`}>
<mesh geometry={geometry} material={material} position={[0, yPos, 0]} />
</group>
);
})}
</group>
{roomsState.length > 0 &&
roomsState.flat().map((room: any, index: number) => {
if (!toggleView) return null;
const coordinates = room.coordinates;
const htmlPosition: [number, number, number] = [ if (!coordinates || coordinates.length < 3) return null;
center2D[0],
avgY + CONSTANTS.zoneConfig.height,
center2D[1],
];
return ( let coords2D = coordinates.map((p: any) => [p.position.x, p.position.z]);
<Html
key={`${index}-${room.layer || index}`} const first = coords2D[0];
position={htmlPosition} const last = coords2D[coords2D.length - 1];
wrapperClass="distance-text-wrapper" if (first[0] !== last[0] || first[1] !== last[1]) {
className="distance-text" coords2D.push(first);
zIndexRange={[1, 0]} }
prepend
center const polygon = turf.polygon([coords2D]);
sprite const center2D = turf.center(polygon).geometry.coordinates;
>
<div className={`distance area line-${room.layer || index}`}> const sumY = coordinates.reduce((sum: number, p: any) => sum + p.position.y, 0);
Room ({formattedArea}) const avgY = sumY / coordinates.length;
</div>
</Html> const area = computeArea(room, "rooms");
); const formattedArea = `${area.toFixed(2)}`;
})}
</group> const htmlPosition: [number, number, number] = [
); center2D[0],
avgY + CONSTANTS.zoneConfig.height,
center2D[1],
];
return (
<Html
key={`${index}-${room.layer || index}`}
position={htmlPosition}
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
prepend
center
sprite
>
<div className={`distance area line-${room.layer || index}`}>
Room ({formattedArea})
</div>
</Html>
);
})}
</group>
);
} }
export default CalculateAreaGroup; export default CalculateAreaGroup;

View File

@@ -376,7 +376,6 @@ const ZoneGroup: React.FC = () => {
setZonePoints(updatedZonePoints); setZonePoints(updatedZonePoints);
addZoneToBackend(newZone); addZoneToBackend(newZone);
setStartPoint(null); setStartPoint(null);
setEndPoint(null); setEndPoint(null);
} }

View File

@@ -41,8 +41,17 @@ function Ui() {
const AssetPreview: React.FC<AssetPreviewProps> = ({ const AssetPreview: React.FC<AssetPreviewProps> = ({
selectedCard, selectedCard,
setSelectedCard, setSelectedCard,
modelUrl, modelUrl
}) => { }) => {
// Ensure rating is a valid number between 0 and 5
const rating = Math.max(
0,
Math.min(5, isNaN(selectedCard.rating) ? 0 : selectedCard.rating)
);
// Ensure that the rating is a valid positive integer for array length
const starsArray = Array.from({ length: rating }, (_, index) => index);
return ( return (
<div className="assetPreview-wrapper"> <div className="assetPreview-wrapper">
<div className="assetPreview"> <div className="assetPreview">
@@ -65,7 +74,7 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
> >
<Suspense fallback={<Ui />}> <Suspense fallback={<Ui />}>
{selectedCard.assetName && modelUrl && ( {selectedCard.assetName && modelUrl && (
<GltfLoader fromServer={modelUrl} /> <GltfLoader fromServer={modelUrl} assetId={selectedCard?.AssetID} />
)} )}
<OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} /> <OrbitControls minPolarAngle={0} maxPolarAngle={Math.PI / 2} />
<ContactShadows <ContactShadows

View File

@@ -16,7 +16,8 @@ interface CardProps {
views: number; views: number;
image: string; image: string;
description: string; description: string;
AssetID: string; AssetID: string
modelUrl: string
onSelectCard: (cardData: { onSelectCard: (cardData: {
assetName: string; assetName: string;
uploadedOn: number; uploadedOn: number;
@@ -36,18 +37,17 @@ const Card: React.FC<CardProps> = ({
views, views,
image, image,
description, description,
onSelectCard,
AssetID, AssetID,
modelUrl,
onSelectCard,
}) => { }) => {
const handleCardSelect = () => { const handleCardSelect = () => {
console.log('assetName: ', assetName);
console.log('AssetID: ', AssetID);
onSelectCard({ onSelectCard({
assetName, assetName, uploadedOn, price, rating, views, description, AssetID
uploadedOn,
price,
rating,
views,
description,
AssetID,
}); });
}; };

View File

@@ -66,6 +66,7 @@ const CardsContainer: React.FC<ModelsProps> = ({ models }) => {
AssetID={assetDetail.AssetID} AssetID={assetDetail.AssetID}
image={assetDetail.thumbnail} image={assetDetail.thumbnail}
description={assetDetail.description} description={assetDetail.description}
modelUrl={modelUrl}
/> />
</React.Fragment> </React.Fragment>
))} ))}

View File

@@ -10,6 +10,7 @@ interface GltfLoaderProps {
setAnimations?: (animations?: string[]) => void; setAnimations?: (animations?: string[]) => void;
selectedAnimation?: string; selectedAnimation?: string;
setSelectedAnimation?: (animation: string) => void; setSelectedAnimation?: (animation: string) => void;
assetId: string
} }
@@ -18,6 +19,7 @@ const GltfLoader: React.FC<GltfLoaderProps> = ({
fromServer, fromServer,
setAnimations, setAnimations,
selectedAnimation, selectedAnimation,
assetId
}) => { }) => {
const { scene, animations } = useGLTF(fromServer ?? "") as { const { scene, animations } = useGLTF(fromServer ?? "") as {
scene: Object3D; scene: Object3D;

View File

@@ -33,6 +33,7 @@ const MarketPlace = () => {
try { try {
const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6"); const filt = await getAssetImages("67d934ad0f42a1fdadb19aa6");
setModels(filt.items); setModels(filt.items);
console.log('filt.items: ', filt.items);
setFilteredModels(filt.items); setFilteredModels(filt.items);
setisLoading(false); setisLoading(false);
} catch { } catch {

View File

@@ -1,270 +1,339 @@
import React, { useRef } from "react"; import React, { useRef, useState } from "react";
import { import {
Vector3, Vector3,
Raycaster, Raycaster,
BufferGeometry, BufferGeometry,
LineBasicMaterial, LineBasicMaterial,
Line, Line,
Mesh, Mesh,
Group, Group,
} from "three"; } from "three";
import { useThree, useFrame } from "@react-three/fiber"; import { useThree, useFrame } from "@react-three/fiber";
import { Html } from "@react-three/drei"; import { Html } from "@react-three/drei";
interface DistanceFindingControlsProps { interface DistanceFindingControlsProps {
boundingBoxRef: React.RefObject<Mesh>; boundingBoxRef: React.RefObject<Mesh>;
object: number; object: number;
} }
const DistanceFindingControls = ({ const DistanceFindingControls = ({
boundingBoxRef, boundingBoxRef,
object, object,
}: DistanceFindingControlsProps) => { }: DistanceFindingControlsProps) => {
const { camera, scene } = useThree(); const { camera, scene } = useThree();
const [labelValues, setLabelValues] = useState<{
textPosX: any;
textNegX: any;
textPosZ: any;
textNegZ: any;
}>({
textPosX: "",
textNegX: "",
textPosZ: "",
textNegZ: "",
});
// Refs for measurement lines // Refs for measurement lines
const line1 = useRef<Line>(null); const line1 = useRef<Line>(null);
const line2 = useRef<Line>(null); const line2 = useRef<Line>(null);
const line3 = useRef<Line>(null); const line3 = useRef<Line>(null);
const line4 = useRef<Line>(null); const line4 = useRef<Line>(null);
const line5 = useRef<Line>(null); const line5 = useRef<Line>(null);
// Refs for measurement text labels // Refs for measurement text labels
const textPosX = useRef<Group>(null); const textPosX = useRef<Group>(null);
const textNegX = useRef<Group>(null); const textNegX = useRef<Group>(null);
const textPosZ = useRef<Group>(null); const textPosZ = useRef<Group>(null);
const textNegZ = useRef<Group>(null); const textNegZ = useRef<Group>(null);
const textPosY = useRef<Group>(null); const textPosY = useRef<Group>(null);
// Store line geometries to avoid recreation // Store line geometries to avoid recreation
const lineGeometries = useRef({ const lineGeometries = useRef({
posX: new BufferGeometry(), posX: new BufferGeometry(),
negX: new BufferGeometry(), negX: new BufferGeometry(),
posZ: new BufferGeometry(), posZ: new BufferGeometry(),
negZ: new BufferGeometry(), negZ: new BufferGeometry(),
posY: new BufferGeometry(), posY: new BufferGeometry(),
}); });
useFrame(() => { useFrame(() => {
if (!boundingBoxRef?.current) return; if (!boundingBoxRef?.current) return;
boundingBoxRef.current.geometry.computeBoundingBox(); boundingBoxRef.current.geometry.computeBoundingBox();
const bbox = boundingBoxRef.current.geometry.boundingBox; const bbox = boundingBoxRef.current.geometry.boundingBox;
if (!bbox) return; if (!bbox) return;
const size = { const size = {
x: bbox.max.x - bbox.min.x, x: bbox.max.x - bbox.min.x,
y: bbox.max.y - bbox.min.y, y: bbox.max.y - bbox.min.y,
z: bbox.max.z - bbox.min.z, z: bbox.max.z - bbox.min.z,
};
const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
if (!vec) return;
updateLine({
line: line1.current,
geometry: lineGeometries.current.posX,
direction: new Vector3(1, 0, 0), // Positive X
angle: "pos",
mesh: textPosX,
vec,
size,
});
updateLine({
line: line2.current,
geometry: lineGeometries.current.negX,
direction: new Vector3(-1, 0, 0), // Negative X
angle: "neg",
mesh: textNegX,
vec,
size,
});
updateLine({
line: line3.current,
geometry: lineGeometries.current.posZ,
direction: new Vector3(0, 0, 1), // Positive Z
angle: "pos",
mesh: textPosZ,
vec,
size,
});
updateLine({
line: line4.current,
geometry: lineGeometries.current.negZ,
direction: new Vector3(0, 0, -1), // Negative Z
angle: "neg",
mesh: textNegZ,
vec,
size,
});
updateLine({
line: line5.current,
geometry: lineGeometries.current.posY,
direction: new Vector3(0, -1, 0), // Down (Y)
angle: "posY",
mesh: textPosY,
vec,
size,
});
});
const updateLine = ({
line,
geometry,
direction,
angle,
mesh,
vec,
size,
}: {
line: Line | null;
geometry: BufferGeometry;
direction: Vector3;
angle: string;
mesh: React.RefObject<Group>;
vec: Vector3;
size: { x: number; y: number; z: number };
}) => {
if (!line) return;
const points = [];
if (angle === "pos") {
points[0] = new Vector3(vec.x, vec.y, vec.z).add(
new Vector3((direction.x * size.x) / 2, 0, (direction.z * size.z) / 2)
);
} else if (angle === "neg") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3((-direction.x * size.x) / 2, 0, (-direction.z * size.z) / 2)
);
} else if (angle === "posY") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3(0, size.y / 2, 0)
);
}
const ray = new Raycaster();
if (camera) ray.camera = camera;
ray.set(new Vector3(vec.x, vec.y, vec.z), direction);
ray.params.Line.threshold = 0.1;
// Find intersection points
const wallsGroup = scene.children.find((val) =>
val?.name.includes("Walls")
);
const intersects = wallsGroup
? ray.intersectObjects([wallsGroup], true)
: [];
// Find intersection point
if (intersects[0]) {
for (const intersect of intersects) {
if (intersect.object.name.includes("Wall")) {
points[1] =
angle !== "posY" ? intersect.point : new Vector3(vec.x, 0, vec.z); // Floor
break;
}
}
}
// Update line geometry
if (points[1]) {
geometry.dispose();
geometry.setFromPoints([points[0], points[1]]);
line.geometry = geometry;
// Update measurement text
if (mesh?.current) {
geometry.computeBoundingSphere();
const center = geometry.boundingSphere?.center;
if (center) {
mesh.current.position.copy(center);
}
const label = document.getElementById(mesh.current.name);
if (label) {
label.innerText = `${points[0].distanceTo(points[1]).toFixed(2)}m`;
}
}
} else {
// No intersection found - clear the line
geometry.dispose();
geometry.setFromPoints([new Vector3(), new Vector3()]);
line.geometry = geometry;
const label = document.getElementById(mesh?.current?.name ?? "");
if (label) label.innerText = "";
}
}; };
const Material = new LineBasicMaterial({ color: "#d2baff" }); const vec = boundingBoxRef.current?.getWorldPosition(new Vector3()).clone();
return ( if (!vec) return;
<> updateLine({
{/* Measurement text labels */} line: line1.current,
{boundingBoxRef.current && object > 0 && ( geometry: lineGeometries.current.posX,
<> direction: new Vector3(1, 0, 0), // Positive X
<group name="textPosX" ref={textPosX}> angle: "pos",
<Html mesh: textPosX,
wrapperClass="distance-text-wrapper" vec,
className="distance-text" size,
zIndexRange={[1, 0]} });
style={{ pointerEvents: "none" }} updateLine({
> line: line2.current,
<div className="distance-label" id="textPosX"></div> geometry: lineGeometries.current.negX,
</Html> direction: new Vector3(-1, 0, 0), // Negative X
</group> angle: "neg",
<group name="textNegX" ref={textNegX}> mesh: textNegX,
<Html vec,
wrapperClass="distance-text-wrapper" size,
className="distance-text" });
zIndexRange={[1, 0]} updateLine({
style={{ pointerEvents: "none" }} line: line3.current,
> geometry: lineGeometries.current.posZ,
<div className="distance-label" id="textNegX"></div> direction: new Vector3(0, 0, 1), // Positive Z
</Html> angle: "pos",
</group> mesh: textPosZ,
<group name="textPosZ" ref={textPosZ}> vec,
<Html size,
wrapperClass="distance-text-wrapper" });
className="distance-text" updateLine({
zIndexRange={[2, 0]} line: line4.current,
style={{ pointerEvents: "none" }} geometry: lineGeometries.current.negZ,
> direction: new Vector3(0, 0, -1), // Negative Z
<div className="distance-label" id="textPosZ"></div> angle: "neg",
</Html> mesh: textNegZ,
</group> vec,
<group name="textNegZ" ref={textNegZ}> size,
<Html });
wrapperClass="distance-text-wrapper" updateLine({
className="distance-text" line: line5.current,
zIndexRange={[1, 0]} geometry: lineGeometries.current.posY,
style={{ pointerEvents: "none" }} direction: new Vector3(0, -1, 0), // Down (Y)
> angle: "posY",
<div className="distance-label" id="textNegZ"></div> mesh: textPosY,
</Html> vec,
</group> size,
});
});
{/* Measurement lines */} const updateLine = ({
<primitive line,
object={new Line(new BufferGeometry(), Material)} geometry,
ref={line1} direction,
/> angle,
<primitive mesh,
object={new Line(new BufferGeometry(), Material)} vec,
ref={line2} size,
/> }: {
<primitive line: Line | null;
object={new Line(new BufferGeometry(), Material)} geometry: BufferGeometry;
ref={line3} direction: Vector3;
/> angle: string;
<primitive mesh: React.RefObject<Group>;
object={new Line(new BufferGeometry(), Material)} vec: Vector3;
ref={line4} size: { x: number; y: number; z: number };
/> }) => {
</> if (!line) return;
)}
</> const points = [];
if (angle === "pos") {
points[0] = new Vector3(vec.x, vec.y, vec.z).add(
new Vector3((direction.x * size.x) / 2, 0, (direction.z * size.z) / 2)
);
} else if (angle === "neg") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3((-direction.x * size.x) / 2, 0, (-direction.z * size.z) / 2)
);
} else if (angle === "posY") {
points[0] = new Vector3(vec.x, vec.y, vec.z).sub(
new Vector3(0, size.y / 2, 0)
);
}
const ray = new Raycaster();
if (camera) ray.camera = camera;
ray.set(new Vector3(vec.x, vec.y, vec.z), direction);
ray.params.Line.threshold = 0.1;
// Find intersection points
const wallsGroup = scene.children.find((val) =>
val?.name.includes("Walls")
); );
const intersects = wallsGroup
? ray.intersectObjects([wallsGroup], true)
: [];
// Find intersection point
if (intersects[0]) {
for (const intersect of intersects) {
if (intersect.object.name.includes("Wall")) {
points[1] =
angle !== "posY" ? intersect.point : new Vector3(vec.x, 0, vec.z); // Floor
break;
}
}
}
if (points[1]) {
geometry.dispose();
geometry.setFromPoints([points[0], points[1]]);
line.geometry = geometry;
// Calculate the distance only once
const distance = points[0].distanceTo(points[1]).toFixed(2);
// Update measurement text
if (mesh?.current) {
geometry.computeBoundingSphere();
const center = geometry.boundingSphere?.center;
if (center) {
mesh.current.position.copy(center);
}
const label = document.getElementById(mesh.current.name);
if (label) {
label.innerText = `${distance}m`;
// Update specific label state based on the label ID
switch (label.id) {
case "textPosX":
setLabelValues((prevState) => ({ ...prevState, textPosX: distance }));
break;
case "textNegX":
setLabelValues((prevState) => ({ ...prevState, textNegX: distance }));
break;
case "textPosZ":
setLabelValues((prevState) => ({ ...prevState, textPosZ: distance }));
break;
case "textNegZ":
setLabelValues((prevState) => ({ ...prevState, textNegZ: distance }));
break;
default:
break;
}
}
}
} else {
// No intersection found - clear the line
geometry.dispose();
geometry.setFromPoints([new Vector3(), new Vector3()]);
line.geometry = geometry;
const label = document.getElementById(mesh?.current?.name ?? "");
if (label) {
label.innerText = "";
// Clear the corresponding label value in the state
switch (label.id) {
case "textPosX":
setLabelValues((prevState) => ({ ...prevState, textPosX: "" }));
break;
case "textNegX":
setLabelValues((prevState) => ({ ...prevState, textNegX: "" }));
break;
case "textPosZ":
setLabelValues((prevState) => ({ ...prevState, textPosZ: "" }));
break;
case "textNegZ":
setLabelValues((prevState) => ({ ...prevState, textNegZ: "" }));
break;
default:
break;
}
}
}
};
const Material = new LineBasicMaterial({ color: "#d2baff" });
return (
<>
{/* Measurement text labels */}
{boundingBoxRef.current && object > 0 && (
<>
<group name="textPosX" ref={textPosX}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textPosX === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textPosX">{labelValues.textPosX}</div>
</Html>
</group>
<group name="textNegX" ref={textNegX}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textNegX === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textNegX">{labelValues.textNegX}</div>
</Html>
</group>
<group name="textPosZ" ref={textPosZ}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[2, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textPosZ === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textPosZ">{labelValues.textPosZ}</div>
</Html>
</group>
<group name="textNegZ" ref={textNegZ}>
<Html
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
style={{
pointerEvents: "none",
visibility: labelValues.textNegZ === "" ? "hidden" : "visible",
}}
>
<div className="distance-label" id="textNegZ">{labelValues.textNegZ}</div>
</Html>
</group>
{/* Measurement lines */}
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line1}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line2}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line3}
/>
<primitive
object={new Line(new BufferGeometry(), Material)}
ref={line4}
/>
</>
)
}
</>
);
}; };
export default DistanceFindingControls; export default DistanceFindingControls;

View File

@@ -64,7 +64,91 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
} }
}, [isReset, isPlaying]) }, [isReset, isPlaying])
useFrame((_, delta) => { // useFrame((_, delta) => {
// const object = scene.getObjectByProperty('uuid', agvUuid);
// if (!object || currentPath.length < 2) return;
// if (isPaused) return;
// let totalDistance = 0;
// const distances = [];
// let accumulatedDistance = 0;
// let index = 0;
// const rotationSpeed = 1;
// for (let i = 0; i < currentPath.length - 1; i++) {
// const start = new THREE.Vector3(...currentPath[i]);
// const end = new THREE.Vector3(...currentPath[i + 1]);
// const segmentDistance = start.distanceTo(end);
// distances.push(segmentDistance);
// totalDistance += segmentDistance;
// }
// while (index < distances.length && progressRef.current > accumulatedDistance + distances[index]) {
// accumulatedDistance += distances[index];
// index++;
// }
// if (index < distances.length) {
// const start = new THREE.Vector3(...currentPath[index]);
// const end = new THREE.Vector3(...currentPath[index + 1]);
// const segmentDistance = distances[index];
// const currentDirection = new THREE.Vector3().subVectors(end, start).normalize();
// const targetAngle = Math.atan2(currentDirection.x, currentDirection.z);
// const currentAngle = object.rotation.y;
// let angleDifference = targetAngle - currentAngle;
// if (angleDifference > Math.PI) angleDifference -= 2 * Math.PI;
// if (angleDifference < -Math.PI) angleDifference += 2 * Math.PI;
// const maxRotationStep = (rotationSpeed * speed * agvDetail.speed) * delta;
// object.rotation.y += Math.sign(angleDifference) * Math.min(Math.abs(angleDifference), maxRotationStep);
// const isAligned = Math.abs(angleDifference) < 0.01;
// if (isAligned) {
// progressRef.current += delta * (speed * agvDetail.speed);
// const t = (progressRef.current - accumulatedDistance) / segmentDistance;
// const position = start.clone().lerp(end, t);
// object.position.copy(position);
// }
// }
// if (progressRef.current >= totalDistance) {
// if (restRotation && objectRotation) {
// const targetEuler = new THREE.Euler(
// objectRotation.x,
// objectRotation.y - (agvDetail.point.action.steeringAngle),
// objectRotation.z
// );
// const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler);
// object.quaternion.slerp(targetQuaternion, delta * (rotationSpeed * speed * agvDetail.speed));
// if (object.quaternion.angleTo(targetQuaternion) < 0.01) {
// object.quaternion.copy(targetQuaternion);
// object.rotation.copy(targetEuler);
// setRestingRotation(false);
// }
// return;
// }
// }
// if (progressRef.current >= totalDistance) {
// setRestingRotation(true);
// progressRef.current = 0;
// movingForward.current = !movingForward.current;
// setCurrentPath([]);
// handleCallBack();
// if (currentPhase === 'pickup-drop') {
// requestAnimationFrame(startUnloadingProcess);
// }
// }
// });
const lastTimeRef = useRef(performance.now());
useFrame(() => {
const now = performance.now();
const delta = (now - lastTimeRef.current) / 1000;
lastTimeRef.current = now;
const object = scene.getObjectByProperty('uuid', agvUuid); const object = scene.getObjectByProperty('uuid', agvUuid);
if (!object || currentPath.length < 2) return; if (!object || currentPath.length < 2) return;
if (isPaused) return; if (isPaused) return;
@@ -95,7 +179,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
const currentDirection = new THREE.Vector3().subVectors(end, start).normalize(); const currentDirection = new THREE.Vector3().subVectors(end, start).normalize();
const targetAngle = Math.atan2(currentDirection.x, currentDirection.z); const targetAngle = Math.atan2(currentDirection.x, currentDirection.z);
const currentAngle = object.rotation.y; const currentAngle = object.rotation.y;
let angleDifference = targetAngle - currentAngle; let angleDifference = targetAngle - currentAngle;
@@ -118,7 +201,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
if (restRotation && objectRotation) { if (restRotation && objectRotation) {
const targetEuler = new THREE.Euler( const targetEuler = new THREE.Euler(
objectRotation.x, objectRotation.x,
objectRotation.y - (agvDetail.point.action.steeringAngle), objectRotation.y - agvDetail.point.action.steeringAngle,
objectRotation.z objectRotation.z
); );
const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler); const targetQuaternion = new THREE.Quaternion().setFromEuler(targetEuler);
@@ -131,6 +214,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
return; return;
} }
} }
if (progressRef.current >= totalDistance) { if (progressRef.current >= totalDistance) {
setRestingRotation(true); setRestingRotation(true);
progressRef.current = 0; progressRef.current = 0;

View File

@@ -11,7 +11,10 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore
import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore'; import { useSelectedProduct } from '../../../../../store/simulation/useSimulationStore';
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler'; import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
import MaterialAnimator from '../animator/materialAnimator'; import MaterialAnimator from '../animator/materialAnimator';
type Timer = {
start: number | null;
active: boolean;
};
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) { function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
const { navMesh } = useNavMesh(); const { navMesh } = useNavMesh();
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
@@ -51,7 +54,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
); );
function vehicleStatus(modelId: string, status: string) { function vehicleStatus(modelId: string, status: string) {
// console.log(`${modelId} , ${status}`); //
} }
// Function to reset everything // Function to reset everything
@@ -144,6 +147,9 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
} }
} }
function startUnloadingProcess() { function startUnloadingProcess() {
if (agvDetail.point.action.triggers.length > 0) { if (agvDetail.point.action.triggers.length > 0) {
const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid); const trigger = getTriggerByUuid(selectedProduct.productId, agvDetail.point.action.triggers[0].triggerUuid);

View File

@@ -1,5 +1,6 @@
let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; let BackEnd_url = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
export const getAssetDetails = async (filename: string) => { export const getAssetDetails = async (filename: string) => {
console.log('filename: ', filename);
try { try {
const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, { const response = await fetch(`${BackEnd_url}/api/v1/assetDetails`, {
method: "POST", method: "POST",