Merge remote-tracking branch 'origin/simulation-agv-v2' into v2
This commit is contained in:
@@ -38,14 +38,6 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
const { isReset, setReset } = useResetButtonStore();
|
const { isReset, setReset } = useResetButtonStore();
|
||||||
const { subModule } = useSubModuleStore();
|
const { subModule } = useSubModuleStore();
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isReset) {
|
|
||||||
setTimeout(()=>{
|
|
||||||
setReset(false);
|
|
||||||
},0)
|
|
||||||
}
|
|
||||||
}, [isReset])
|
|
||||||
|
|
||||||
// Button functions
|
// Button functions
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setReset(true);
|
setReset(true);
|
||||||
@@ -282,7 +274,8 @@ const SimulationPlayer: React.FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
{index < intervals.length - 1 && (
|
{index < intervals.length - 1 && (
|
||||||
<div
|
<div
|
||||||
className={`line ${progress >= ((index + 1) / totalSegments) * 100
|
className={`line ${
|
||||||
|
progress >= ((index + 1) / totalSegments) * 100
|
||||||
? "filled"
|
? "filled"
|
||||||
: ""
|
: ""
|
||||||
}`}
|
}`}
|
||||||
|
|||||||
@@ -34,16 +34,12 @@ const MachineAnimator = ({ currentPhase, handleCallBack, processingTime, machine
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isPlayingRef.current = isPlaying;
|
isPlayingRef.current = isPlaying;
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
useEffect(() => {
|
|
||||||
isResetRef.current = isReset;
|
|
||||||
}, [isReset]);
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (isReset || !isPlaying) {
|
if (isReset || !isPlaying) {
|
||||||
reset();
|
reset();
|
||||||
setReset(false);
|
|
||||||
startTimeRef.current = 0;
|
startTimeRef.current = 0;
|
||||||
isPausedRef.current = false;
|
isPausedRef.current = false;
|
||||||
pauseTimeRef.current = 0;
|
pauseTimeRef.current = 0;
|
||||||
@@ -53,20 +49,19 @@ const MachineAnimator = ({ currentPhase, handleCallBack, processingTime, machine
|
|||||||
}
|
}
|
||||||
}, [isReset, isPlaying])
|
}, [isReset, isPlaying])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentPhase === 'processing' && !animationStarted.current && machineUuid) {
|
if (currentPhase === 'processing' && !animationStarted.current && machineUuid) {
|
||||||
animationStarted.current = true;
|
animationStarted.current = true;
|
||||||
startTimeRef.current = performance.now();
|
startTimeRef.current = performance.now();
|
||||||
animationFrameId.current = requestAnimationFrame(step);
|
animationFrameId.current = requestAnimationFrame(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [currentPhase]);
|
}, [currentPhase]);
|
||||||
|
|
||||||
function step(time: number) {
|
function step(time: number) {
|
||||||
if (!isPausedRef.current || !isResetRef.current) {
|
|
||||||
if (animationFrameId.current) {
|
|
||||||
cancelAnimationFrame(animationFrameId.current);
|
|
||||||
animationFrameId.current = null;
|
|
||||||
}
|
|
||||||
if (isPausedRef.current) {
|
if (isPausedRef.current) {
|
||||||
if (!pauseTimeRef.current) {
|
if (!pauseTimeRef.current) {
|
||||||
pauseTimeRef.current = performance.now();
|
pauseTimeRef.current = performance.now();
|
||||||
@@ -82,18 +77,23 @@ const MachineAnimator = ({ currentPhase, handleCallBack, processingTime, machine
|
|||||||
}
|
}
|
||||||
|
|
||||||
const elapsed = time - startTimeRef.current;
|
const elapsed = time - startTimeRef.current;
|
||||||
const processedTime = processingTime * 1000;
|
const processedTime = (processingTime * 1000) / speed;
|
||||||
|
|
||||||
if (elapsed < processedTime) {
|
if (elapsed < processedTime) {
|
||||||
machineStatus(machineUuid, "Machine is currently processing the task");
|
machineStatus(machineUuid, "Machine is currently processing the task");
|
||||||
animationFrameId.current = requestAnimationFrame(step);
|
animationFrameId.current = requestAnimationFrame(step);
|
||||||
} else {
|
} else {
|
||||||
removeCurrentAction(machineUuid);
|
|
||||||
animationStarted.current = false;
|
animationStarted.current = false;
|
||||||
|
if (animationFrameId.current !== null) {
|
||||||
|
removeCurrentAction(machineUuid);
|
||||||
|
cancelAnimationFrame(animationFrameId.current);
|
||||||
|
animationFrameId.current = null;
|
||||||
handleCallBack();
|
handleCallBack();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ function MachineInstance({ machineDetail }: any) {
|
|||||||
const { machines, addCurrentAction, setMachineState, setMachineActive } = useMachineStore();
|
const { machines, addCurrentAction, setMachineState, setMachineActive } = useMachineStore();
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
|
setCurrentPhase("idle");
|
||||||
setMachineState(machineDetail.modelUuid, 'idle');
|
setMachineState(machineDetail.modelUuid, 'idle');
|
||||||
setMachineActive(machineDetail.modelUuid, false);
|
setMachineActive(machineDetail.modelUuid, false);
|
||||||
isIncrememtable.current = true;
|
isIncrememtable.current = true;
|
||||||
setCurrentPhase("idle");
|
|
||||||
}
|
}
|
||||||
const increment = () => {
|
const increment = () => {
|
||||||
if (isIncrememtable.current) {
|
if (isIncrememtable.current) {
|
||||||
@@ -31,7 +31,7 @@ function MachineInstance({ machineDetail }: any) {
|
|||||||
if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && !machineDetail.currentAction) {
|
if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && !machineDetail.currentAction) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
increment();
|
increment();
|
||||||
}, 2000);
|
}, 5000);
|
||||||
machineStatus(machineDetail.modelUuid, 'Machine is idle and waiting for next instruction.')
|
machineStatus(machineDetail.modelUuid, 'Machine is idle and waiting for next instruction.')
|
||||||
} else if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && machineDetail.currentAction) {
|
} else if (!machineDetail.isActive && machineDetail.state === "idle" && currentPhase == "idle" && machineDetail.currentAction) {
|
||||||
setCurrentPhase("processing");
|
setCurrentPhase("processing");
|
||||||
@@ -39,8 +39,6 @@ function MachineInstance({ machineDetail }: any) {
|
|||||||
setMachineActive(machineDetail.modelUuid, true);
|
setMachineActive(machineDetail.modelUuid, true);
|
||||||
machineStatus(machineDetail.modelUuid, "Machine started processing")
|
machineStatus(machineDetail.modelUuid, "Machine started processing")
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
}, [currentPhase, isPlaying, machines])
|
}, [currentPhase, isPlaying, machines])
|
||||||
|
|
||||||
@@ -60,6 +58,7 @@ function MachineInstance({ machineDetail }: any) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MachineAnimator processingTime={machineDetail.point.action.processTime} handleCallBack={handleCallBack} currentPhase={currentPhase} machineUuid={machineDetail.modelUuid} machineStatus={machineStatus} reset={reset} />
|
<MachineAnimator processingTime={machineDetail.point.action.processTime} handleCallBack={handleCallBack} currentPhase={currentPhase} machineUuid={machineDetail.modelUuid} machineStatus={machineStatus} reset={reset} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { useThree, useFrame } from '@react-three/fiber';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
||||||
|
import { Html } from '@react-three/drei';
|
||||||
|
|
||||||
|
type MaterialAnimatorProps = {
|
||||||
|
agvDetail: VehicleStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => {
|
||||||
|
const meshRef = useRef<any>(null!);
|
||||||
|
const [hasLoad, setHasLoad] = useState(false);
|
||||||
|
const { scene } = useThree();
|
||||||
|
const offset = new THREE.Vector3(0, 0.85, 0);
|
||||||
|
const [htmlPosition, setHtmlPosition] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
|
const [htmlRotation, setHtmlRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHasLoad(agvDetail.currentLoad > 0);
|
||||||
|
}, [agvDetail.currentLoad]);
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (!hasLoad || !meshRef.current) return;
|
||||||
|
|
||||||
|
const agvModel = scene.getObjectByProperty("uuid", agvDetail.modelUuid) as THREE.Object3D;
|
||||||
|
if (agvModel) {
|
||||||
|
const worldPosition = offset.clone().applyMatrix4(agvModel.matrixWorld);
|
||||||
|
meshRef.current.position.copy(worldPosition);
|
||||||
|
setHtmlPosition([worldPosition.x, worldPosition.y, worldPosition.z]);
|
||||||
|
meshRef.current.rotation.copy(agvModel.rotation);
|
||||||
|
setHtmlRotation([agvModel.rotation.x, agvModel.rotation.y, agvModel.rotation.z]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{hasLoad && (
|
||||||
|
<>
|
||||||
|
<MaterialModel
|
||||||
|
matRef={meshRef}
|
||||||
|
materialType={agvDetail.materialType || 'Default material'}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Html
|
||||||
|
position={htmlPosition}
|
||||||
|
rotation={htmlRotation}
|
||||||
|
style={{ backgroundColor: "pink", padding: "4px", borderRadius: "4px" }}
|
||||||
|
>
|
||||||
|
{agvDetail.currentLoad}
|
||||||
|
</Html>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default MaterialAnimator;
|
||||||
@@ -199,7 +199,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{currentPath.length > 0 && (
|
{currentPath.length > 0 && (
|
||||||
<>
|
<group visible={false}>
|
||||||
<Line points={currentPath} color="blue" lineWidth={3} />
|
<Line points={currentPath} color="blue" lineWidth={3} />
|
||||||
{currentPath.map((point, index) => (
|
{currentPath.map((point, index) => (
|
||||||
<mesh key={index} position={point}>
|
<mesh key={index} position={point}>
|
||||||
@@ -207,7 +207,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai
|
|||||||
<meshStandardMaterial color="red" />
|
<meshStandardMaterial color="red" />
|
||||||
</mesh>
|
</mesh>
|
||||||
))}
|
))}
|
||||||
</>
|
</group>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ import { NavMeshQuery } from '@recast-navigation/core';
|
|||||||
import { useNavMesh } from '../../../../../store/store';
|
import { useNavMesh } from '../../../../../store/store';
|
||||||
import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
|
import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
|
||||||
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
|
import { useVehicleStore } from '../../../../../store/simulation/useVehicleStore';
|
||||||
|
import MaterialAnimator from '../animator/materialAnimator';
|
||||||
|
|
||||||
function VehicleInstance({ agvDetail }: any) {
|
function VehicleInstance({ agvDetail }: any) {
|
||||||
const { navMesh } = useNavMesh();
|
const { navMesh } = useNavMesh();
|
||||||
|
const vehicleRef: any = useRef();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad } = useVehicleStore();
|
const { vehicles, setVehicleActive, setVehicleState, incrementVehicleLoad, setMaterialType } = 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<boolean>(true);
|
let isIncrememtable = useRef<boolean>(true);
|
||||||
@@ -44,8 +46,8 @@ function VehicleInstance({ agvDetail }: any) {
|
|||||||
|
|
||||||
const increment = () => {
|
const increment = () => {
|
||||||
if (isIncrememtable.current) {
|
if (isIncrememtable.current) {
|
||||||
|
|
||||||
incrementVehicleLoad(agvDetail.modelUuid, 10);
|
incrementVehicleLoad(agvDetail.modelUuid, 10);
|
||||||
|
setMaterialType(agvDetail.modelUuid, 'Material 1')
|
||||||
isIncrememtable.current = false;
|
isIncrememtable.current = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,7 +73,7 @@ function VehicleInstance({ agvDetail }: any) {
|
|||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
|
|
||||||
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity) {
|
if (agvDetail.currentLoad === agvDetail.point.action.loadCapacity && agvDetail.materialType) {
|
||||||
const toDrop = computePath(
|
const toDrop = computePath(
|
||||||
agvDetail.point.action.pickUpPoint.position,
|
agvDetail.point.action.pickUpPoint.position,
|
||||||
agvDetail.point.action.unLoadPoint.position
|
agvDetail.point.action.unLoadPoint.position
|
||||||
@@ -118,6 +120,7 @@ function VehicleInstance({ agvDetail }: any) {
|
|||||||
setVehicleState(agvDetail.modelUuid, 'idle');
|
setVehicleState(agvDetail.modelUuid, 'idle');
|
||||||
setVehicleActive(agvDetail.modelUuid, false);
|
setVehicleActive(agvDetail.modelUuid, false);
|
||||||
setPath([]);
|
setPath([]);
|
||||||
|
setMaterialType(agvDetail.modelUuid, null)
|
||||||
vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete');
|
vehicleStatus(agvDetail.modelUuid, 'Reached pickup point again, cycle complete');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,6 +135,7 @@ function VehicleInstance({ agvDetail }: any) {
|
|||||||
agvDetail={agvDetail}
|
agvDetail={agvDetail}
|
||||||
reset={reset}
|
reset={reset}
|
||||||
/>
|
/>
|
||||||
|
<MaterialAnimator agvDetail={agvDetail} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user