feat: implement a comprehensive simulation analyzer module for tracking and calculating performance metrics.
This commit is contained in:
@@ -184,6 +184,9 @@ function Analyzer() {
|
|||||||
>
|
>
|
||||||
>({});
|
>({});
|
||||||
|
|
||||||
|
// Track previous actions for ArmBots to detect cycle completion
|
||||||
|
const previousArmBotActionsRef = useRef<Record<string, string | undefined>>({});
|
||||||
|
|
||||||
// Material lifecycle tracking
|
// Material lifecycle tracking
|
||||||
const materialLifecycleRef = useRef<
|
const materialLifecycleRef = useRef<
|
||||||
Record<
|
Record<
|
||||||
@@ -215,6 +218,7 @@ function Analyzer() {
|
|||||||
performanceSnapshotsRef.current = {};
|
performanceSnapshotsRef.current = {};
|
||||||
bottleneckEventsRef.current = {};
|
bottleneckEventsRef.current = {};
|
||||||
previousAssetStatesRef.current = {};
|
previousAssetStatesRef.current = {};
|
||||||
|
previousArmBotActionsRef.current = {};
|
||||||
materialLifecycleRef.current = {};
|
materialLifecycleRef.current = {};
|
||||||
setAnalysis(null);
|
setAnalysis(null);
|
||||||
setAnalyzing(false);
|
setAnalyzing(false);
|
||||||
@@ -554,6 +558,14 @@ function Analyzer() {
|
|||||||
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => {
|
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => {
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
|
|
||||||
|
// Increment error count if entering error state
|
||||||
|
if (toState === "error") {
|
||||||
|
if (!errorCountsRef.current[assetId]) {
|
||||||
|
errorCountsRef.current[assetId] = 0;
|
||||||
|
}
|
||||||
|
errorCountsRef.current[assetId]++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!assetStateChangesRef.current[assetId]) {
|
if (!assetStateChangesRef.current[assetId]) {
|
||||||
assetStateChangesRef.current[assetId] = [];
|
assetStateChangesRef.current[assetId] = [];
|
||||||
}
|
}
|
||||||
@@ -1126,7 +1138,7 @@ function Analyzer() {
|
|||||||
const materialFlow = calculateMaterialFlowMetricsForAsset(armBot.modelUuid);
|
const materialFlow = calculateMaterialFlowMetricsForAsset(armBot.modelUuid);
|
||||||
const cyclesCompleted = completedActionsRef.current[armBot.modelUuid] || 0;
|
const cyclesCompleted = completedActionsRef.current[armBot.modelUuid] || 0;
|
||||||
const pickAndPlaceCount = completedActionsRef.current[`${armBot.modelUuid}_pickplace`] || cyclesCompleted;
|
const pickAndPlaceCount = completedActionsRef.current[`${armBot.modelUuid}_pickplace`] || cyclesCompleted;
|
||||||
const defects = errorCountsRef.current[`${armBot.modelUuid}_defects`] || 0;
|
const defects = errorCount; // Use main error count directly
|
||||||
|
|
||||||
const qualityMetrics = calculateQualityMetrics(armBot.modelUuid, pickAndPlaceCount, defects);
|
const qualityMetrics = calculateQualityMetrics(armBot.modelUuid, pickAndPlaceCount, defects);
|
||||||
|
|
||||||
@@ -1143,7 +1155,7 @@ function Analyzer() {
|
|||||||
const energyMetrics = calculateEnergyMetrics("roboticArm", armBot.activeTime || 0);
|
const energyMetrics = calculateEnergyMetrics("roboticArm", armBot.activeTime || 0);
|
||||||
|
|
||||||
// Calculate success rates
|
// Calculate success rates
|
||||||
const pickAttempts = pickAndPlaceCount + (errorCountsRef.current[armBot.modelUuid] || 0);
|
const pickAttempts = pickAndPlaceCount + errorCount;
|
||||||
const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100;
|
const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100;
|
||||||
const placeAccuracy = pickSuccessRate * 0.98; // Assuming 98% of successful picks are placed correctly
|
const placeAccuracy = pickSuccessRate * 0.98; // Assuming 98% of successful picks are placed correctly
|
||||||
|
|
||||||
@@ -2297,6 +2309,33 @@ function Analyzer() {
|
|||||||
});
|
});
|
||||||
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]);
|
}, [conveyors, machines, armBots, vehicles, humans, cranes, storageUnits, isPlaying, getMaterialsByModel, trackStateChange, trackBottleneckEvent, updatePreviousAssetState]);
|
||||||
|
|
||||||
|
// Monitor ArmBot action changes to track cycles
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return;
|
||||||
|
|
||||||
|
armBots.forEach((armBot) => {
|
||||||
|
const previousActionUuid = previousArmBotActionsRef.current[armBot.modelUuid];
|
||||||
|
const currentActionUuid = armBot.currentAction?.actionUuid;
|
||||||
|
|
||||||
|
// Check if action completed (transition from an action to no action or different action)
|
||||||
|
if (previousActionUuid && previousActionUuid !== currentActionUuid) {
|
||||||
|
// Action completed
|
||||||
|
if (!completedActionsRef.current[armBot.modelUuid]) {
|
||||||
|
completedActionsRef.current[armBot.modelUuid] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[armBot.modelUuid]++;
|
||||||
|
|
||||||
|
// Also update pick and place count which is used in analysis
|
||||||
|
if (!completedActionsRef.current[`${armBot.modelUuid}_pickplace`]) {
|
||||||
|
completedActionsRef.current[`${armBot.modelUuid}_pickplace`] = 0;
|
||||||
|
}
|
||||||
|
completedActionsRef.current[`${armBot.modelUuid}_pickplace`]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
|
||||||
|
});
|
||||||
|
}, [armBots, isPlaying]);
|
||||||
|
|
||||||
// Periodic WIP and throughput snapshots
|
// Periodic WIP and throughput snapshots
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isPlaying) return;
|
if (!isPlaying) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user