human to conveyor, conveyor to human multiple actions completed
This commit is contained in:
@@ -180,7 +180,6 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
||||
setCurrentPath(updated);
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedPath === "auto" &&
|
||||
|
||||
@@ -11,16 +11,20 @@ import InteractivePoints from '../animator/interactivePoint';
|
||||
import MaterialAnimator from '../animator/materialAnimator';
|
||||
import VehicleAnimator from '../animator/vehicleAnimator';
|
||||
|
||||
import { useHumanEventManager } from '../../../human/eventManager/useHumanEventManager';
|
||||
|
||||
function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>) {
|
||||
const { navMesh } = useNavMesh();
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore } = useSceneContext();
|
||||
const { removeMaterial, setEndTime } = materialStore();
|
||||
const { materialStore, armBotStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, productStore, assetStore } = useSceneContext();
|
||||
const { removeMaterial, setEndTime, setIsVisible } = materialStore();
|
||||
const { getStorageUnitById } = storageUnitStore();
|
||||
const { getHumanById } = humanStore();
|
||||
const { getHumanById, addCurrentAction } = humanStore();
|
||||
const { getArmBotById } = armBotStore();
|
||||
const { getConveyorById } = conveyorStore();
|
||||
const { triggerPointActions } = useTriggerHandler();
|
||||
const { setCurrentAnimation, getAssetById } = assetStore();
|
||||
const { addHumanToMonitor } = useHumanEventManager();
|
||||
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
@@ -96,7 +100,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isPlaying || selectedPath === "auto") {
|
||||
if (isPlaying && selectedPath === "auto") {
|
||||
if (!agvDetail.point.action.unLoadPoint || !agvDetail.point.action.pickUpPoint) return;
|
||||
|
||||
if (!agvDetail.isActive && agvDetail.state === 'idle' && currentPhase === 'stationed') {
|
||||
@@ -223,6 +227,7 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
if (agvDetail.point.action.triggers.length > 0) {
|
||||
const trigger = getTriggerByUuid(selectedProduct.productUuid, agvDetail.point.action.triggers[0]?.triggerUuid);
|
||||
const model = getEventByModelUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredModel?.modelUuid || '');
|
||||
const triggeredAction = getActionByUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredAction?.actionUuid || '');
|
||||
|
||||
if (trigger && model) {
|
||||
if (model.type === 'transfer') {
|
||||
@@ -244,8 +249,8 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
} else if (model.type === 'human') {
|
||||
const action = getActionByUuid(selectedProduct.productUuid, agvDetail.point.action.actionUuid);
|
||||
if (action) {
|
||||
handleMaterialDropToHuman(model);
|
||||
if (action && (triggeredAction?.actionType === 'assembly' || triggeredAction?.actionType === 'worker')) {
|
||||
handleMaterialDropToHuman(model, triggeredAction);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -260,75 +265,56 @@ function VehicleInstance({ agvDetail }: Readonly<{ agvDetail: VehicleStatus }>)
|
||||
}
|
||||
}
|
||||
|
||||
function handleMaterialDropToHuman(model: HumanEventSchema) {
|
||||
function handleMaterialDropToHuman(model: HumanEventSchema, action: HumanAction) {
|
||||
|
||||
if (model) {
|
||||
if (model.point.action.actionType === 'worker') {
|
||||
loopMaterialDropToHuman(
|
||||
agvDetail.modelUuid,
|
||||
agvDetail.currentLoad,
|
||||
agvDetail.point.action.unLoadDuration,
|
||||
model.modelUuid,
|
||||
model.point.action.loadCapacity,
|
||||
agvDetail.point.action
|
||||
);
|
||||
if (action.actionType === 'worker') {
|
||||
addHumanToMonitor(model.modelUuid, () => {
|
||||
loopMaterialDropToHuman(
|
||||
agvDetail,
|
||||
model.modelUuid,
|
||||
agvDetail.point.action,
|
||||
action.actionUuid
|
||||
);
|
||||
}, action.actionUuid || '')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loopMaterialDropToHuman(
|
||||
vehicleId: string,
|
||||
vehicleCurrentLoad: number,
|
||||
unLoadDuration: number,
|
||||
vehicle: VehicleStatus,
|
||||
humanId: string,
|
||||
storageMaxCapacity: number,
|
||||
action: VehicleAction
|
||||
vehicleAction: VehicleAction,
|
||||
humanActionId: string
|
||||
) {
|
||||
startTime = performance.now();
|
||||
const fixedInterval = ((unLoadDuration / vehicleCurrentLoad) * (1000 / isSpeedRef.current));
|
||||
let currentVehicleLoad = vehicle.currentLoad;
|
||||
|
||||
const unloadLoop = () => {
|
||||
if (isPausedRef.current) {
|
||||
pauseTimeRef.current ??= performance.now();
|
||||
requestAnimationFrame(unloadLoop);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pauseTimeRef.current) {
|
||||
const pauseDuration = performance.now() - pauseTimeRef.current;
|
||||
startTime += pauseDuration;
|
||||
pauseTimeRef.current = null;
|
||||
}
|
||||
|
||||
const elapsedTime = performance.now() - startTime;
|
||||
const human = getHumanById(humanId);
|
||||
const humanAsset = getAssetById(humanId);
|
||||
const humanAction = human?.point.actions.find((action) => action.actionUuid === humanActionId);
|
||||
|
||||
if (elapsedTime >= fixedInterval) {
|
||||
if (human && agvDetail &&
|
||||
human.currentLoad < storageMaxCapacity &&
|
||||
vehicleCurrentLoad > 0) {
|
||||
if (!human || human.currentAction?.actionUuid !== humanAction?.actionUuid) return;
|
||||
|
||||
decrementVehicleLoad(vehicleId, 1);
|
||||
vehicleCurrentLoad -= 1;
|
||||
|
||||
const material = removeLastMaterial(vehicleId);
|
||||
if (material) {
|
||||
|
||||
triggerPointActions(action, material.materialId);
|
||||
|
||||
}
|
||||
|
||||
if (vehicleCurrentLoad > 0 && human.currentLoad < storageMaxCapacity) {
|
||||
startTime = performance.now();
|
||||
requestAnimationFrame(unloadLoop);
|
||||
}
|
||||
if (humanAsset && human.currentMaterials.length > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
|
||||
decrementVehicleLoad(vehicle.modelUuid, 1);
|
||||
currentVehicleLoad -= 1;
|
||||
const material = removeLastMaterial(vehicle.modelUuid);
|
||||
if (material) {
|
||||
setIsVisible(material.materialId, false);
|
||||
}
|
||||
} else {
|
||||
requestAnimationFrame(unloadLoop);
|
||||
} else if (!human.isActive && human.currentLoad < (humanAction?.loadCapacity || 0) && humanAsset?.animationState?.current === 'waiting') {
|
||||
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
|
||||
}
|
||||
setTimeout(() => {
|
||||
requestAnimationFrame(unloadLoop);
|
||||
}, 150)
|
||||
};
|
||||
|
||||
const human = getHumanById(humanId);
|
||||
if (human && vehicleCurrentLoad > 0 && human?.currentLoad < storageMaxCapacity) {
|
||||
const humanAction = human?.point.actions.find((action) => action.actionUuid === humanActionId);
|
||||
if (human && human.currentAction?.actionUuid !== humanActionId && human.currentLoad < (humanAction?.loadCapacity || 0)) {
|
||||
addCurrentAction(humanId, humanActionId);
|
||||
unloadLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,32 @@
|
||||
import { useRef } from "react";
|
||||
import { useNavMesh } from "../../../../store/builder/store";
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
import * as CONSTANTS from "../../../../types/world/worldConstants";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import { useLoadingProgress, useNavMesh, useTileDistance } from "../../../../store/builder/store";
|
||||
import useModuleStore from "../../../../store/useModuleStore";
|
||||
import PolygonGenerator from "./polygonGenerator";
|
||||
import NavMeshDetails from "./navMeshDetails";
|
||||
|
||||
function NavMesh() {
|
||||
let groupRef = useRef() as Types.RefGroup;
|
||||
const { setNavMesh } = useNavMesh();
|
||||
const { loadingProgress } = useLoadingProgress();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { planeValue, gridValue } = useTileDistance();
|
||||
|
||||
return (
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} />
|
||||
<NavMeshDetails setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||
{activeModule === 'simulation' && loadingProgress === 0 &&
|
||||
<>
|
||||
<PolygonGenerator groupRef={groupRef} />
|
||||
<NavMeshDetails setNavMesh={setNavMesh} groupRef={groupRef} />
|
||||
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
|
||||
<planeGeometry args={[300, 300]} />
|
||||
<meshBasicMaterial color={CONSTANTS.planeConfig.color} />
|
||||
</mesh>
|
||||
</group>
|
||||
<group ref={groupRef} visible={false} name="Meshes">
|
||||
<mesh rotation-x={CONSTANTS.planeConfig.rotation} position={CONSTANTS.planeConfig.position3D} receiveShadow>
|
||||
<planeGeometry args={[planeValue.width, planeValue.height]} />
|
||||
</mesh>
|
||||
</group>
|
||||
</>
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useThree } from "@react-three/fiber";
|
||||
import { generateSoloNavMesh } from "@recast-navigation/generators";
|
||||
import { init as initRecastNavigation } from "@recast-navigation/core";
|
||||
import { DebugDrawer, getPositionsAndIndices } from "@recast-navigation/three";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useToggleView } from "../../../../store/builder/store";
|
||||
|
||||
interface NavMeshDetailsProps {
|
||||
@@ -12,45 +11,48 @@ interface NavMeshDetailsProps {
|
||||
groupRef: React.MutableRefObject<THREE.Group | null>;
|
||||
}
|
||||
|
||||
const NAVMESH_CONFIG = {
|
||||
|
||||
// cellSize: 0.2,
|
||||
// cellHeight: 0.7,
|
||||
// walkableRadius: 0.5,
|
||||
|
||||
cellSize: 0.3,
|
||||
cellHeight: 0.7,
|
||||
walkableRadius: 0.7,
|
||||
};
|
||||
|
||||
export default function NavMeshDetails({
|
||||
setNavMesh,
|
||||
groupRef,
|
||||
}: NavMeshDetailsProps) {
|
||||
const { aisleStore, wallStore } = useSceneContext();
|
||||
const { aisles } = aisleStore();
|
||||
const { scene } = useThree();
|
||||
const { walls } = wallStore();
|
||||
const { toggleView } = useToggleView();
|
||||
|
||||
const meshes = useMemo(() => {
|
||||
return groupRef.current?.children.filter((child): child is THREE.Mesh =>
|
||||
child instanceof THREE.Mesh
|
||||
) || [];
|
||||
}, [groupRef.current?.children]);
|
||||
|
||||
useEffect(() => {
|
||||
if (toggleView) return;
|
||||
if (toggleView || meshes.length === 0) return;
|
||||
|
||||
const initializeNavigation = async () => {
|
||||
try {
|
||||
await initRecastNavigation();
|
||||
|
||||
if (!groupRef.current || groupRef.current.children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const meshes = groupRef?.current?.children as THREE.Mesh[];
|
||||
const [positions, indices] = getPositionsAndIndices(meshes);
|
||||
|
||||
// const cellSize = 0.2;
|
||||
// const cellHeight = 0.7;
|
||||
// const walkableRadius = 0.5;
|
||||
const { cellSize, cellHeight, walkableRadius } = NAVMESH_CONFIG;
|
||||
|
||||
const cellSize = 0.3;
|
||||
const cellHeight = 0.7;
|
||||
const walkableRadius = 0.7;
|
||||
const { success, navMesh } = generateSoloNavMesh(positions, indices, {
|
||||
cs: cellSize,
|
||||
ch: cellHeight,
|
||||
walkableRadius: Math.round(walkableRadius / cellHeight),
|
||||
});
|
||||
|
||||
if (!success || !navMesh) {
|
||||
return;
|
||||
}
|
||||
if (!success || !navMesh) return;
|
||||
|
||||
setNavMesh(navMesh);
|
||||
|
||||
@@ -62,12 +64,12 @@ export default function NavMeshDetails({
|
||||
debugDrawer.drawNavMesh(navMesh);
|
||||
// scene.add(debugDrawer);
|
||||
} catch (error) {
|
||||
echo.error("Failed to initialize navigation")
|
||||
console.error("Failed to initialize navigation:", error);
|
||||
}
|
||||
};
|
||||
|
||||
initializeNavigation();
|
||||
}, [scene, groupRef, aisles, walls, toggleView]);
|
||||
}, [meshes, setNavMesh, toggleView, scene]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -76,42 +76,18 @@ export default function PolygonGenerator({
|
||||
turf.lineString(line.map((p: any) => p?.position))
|
||||
);
|
||||
|
||||
const validLineFeatures = lineFeatures.map(ls => {
|
||||
const coords = ls.geometry.coordinates.map(coord => coord.join(','));
|
||||
|
||||
if (coords.length < 2) return null;
|
||||
|
||||
const start = coords[0];
|
||||
const end = coords[coords.length - 1];
|
||||
const middle = coords.slice(1, -1);
|
||||
|
||||
const seen = new Set<string>([start, end]);
|
||||
const filteredMiddle: string[] = [];
|
||||
|
||||
for (const point of middle) {
|
||||
if (!seen.has(point)) {
|
||||
seen.add(point);
|
||||
filteredMiddle.push(point);
|
||||
}
|
||||
let validLineFeatures = lineFeatures.filter((line) => {
|
||||
const coords = line.geometry.coordinates;
|
||||
return coords.length >= 2;
|
||||
}).filter((line) => {
|
||||
if (line.geometry.coordinates[0].toString() !== line.geometry.coordinates[1].toString()) {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
const newCoords = [start, ...filteredMiddle, end];
|
||||
if (validLineFeatures.length < 3) { validLineFeatures = [] }
|
||||
|
||||
if (newCoords.length >= 4) {
|
||||
const resultCoords = newCoords.map(str => str.split(',').map(Number));
|
||||
return {
|
||||
...ls,
|
||||
geometry: {
|
||||
...ls.geometry,
|
||||
coordinates: resultCoords,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}).filter(Boolean);
|
||||
|
||||
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures as any) as any);
|
||||
const polygons = turf.polygonize(turf.featureCollection(validLineFeatures));
|
||||
|
||||
renderWallGeometry(wallPoints);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user