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
|
||||
const materialLifecycleRef = useRef<
|
||||
Record<
|
||||
@@ -215,6 +218,7 @@ function Analyzer() {
|
||||
performanceSnapshotsRef.current = {};
|
||||
bottleneckEventsRef.current = {};
|
||||
previousAssetStatesRef.current = {};
|
||||
previousArmBotActionsRef.current = {};
|
||||
materialLifecycleRef.current = {};
|
||||
setAnalysis(null);
|
||||
setAnalyzing(false);
|
||||
@@ -554,6 +558,14 @@ function Analyzer() {
|
||||
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => {
|
||||
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]) {
|
||||
assetStateChangesRef.current[assetId] = [];
|
||||
}
|
||||
@@ -1126,7 +1138,7 @@ function Analyzer() {
|
||||
const materialFlow = calculateMaterialFlowMetricsForAsset(armBot.modelUuid);
|
||||
const cyclesCompleted = completedActionsRef.current[armBot.modelUuid] || 0;
|
||||
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);
|
||||
|
||||
@@ -1143,7 +1155,7 @@ function Analyzer() {
|
||||
const energyMetrics = calculateEnergyMetrics("roboticArm", armBot.activeTime || 0);
|
||||
|
||||
// Calculate success rates
|
||||
const pickAttempts = pickAndPlaceCount + (errorCountsRef.current[armBot.modelUuid] || 0);
|
||||
const pickAttempts = pickAndPlaceCount + errorCount;
|
||||
const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100;
|
||||
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]);
|
||||
|
||||
// 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
|
||||
useEffect(() => {
|
||||
if (!isPlaying) return;
|
||||
|
||||
Reference in New Issue
Block a user