feat: introduce comprehensive simulation analyzer component with detailed tracking and metric calculation capabilities.
This commit is contained in:
@@ -555,7 +555,7 @@ function Analyzer() {
|
|||||||
/**
|
/**
|
||||||
* Track asset state change
|
* Track asset state change
|
||||||
*/
|
*/
|
||||||
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string) => {
|
const trackStateChange = useCallback((assetId: string, fromState: string, toState: string, context?: { actionName?: string }) => {
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
|
|
||||||
// Increment error count if entering error state
|
// Increment error count if entering error state
|
||||||
@@ -564,6 +564,18 @@ function Analyzer() {
|
|||||||
errorCountsRef.current[assetId] = 0;
|
errorCountsRef.current[assetId] = 0;
|
||||||
}
|
}
|
||||||
errorCountsRef.current[assetId]++;
|
errorCountsRef.current[assetId]++;
|
||||||
|
|
||||||
|
// Granular error tracking based on action type
|
||||||
|
if (context?.actionName) {
|
||||||
|
const actionName = context.actionName.toLowerCase();
|
||||||
|
if (actionName.includes("pick")) {
|
||||||
|
if (!errorCountsRef.current[`${assetId}_pick`]) errorCountsRef.current[`${assetId}_pick`] = 0;
|
||||||
|
errorCountsRef.current[`${assetId}_pick`]++;
|
||||||
|
} else if (actionName.includes("place")) {
|
||||||
|
if (!errorCountsRef.current[`${assetId}_place`]) errorCountsRef.current[`${assetId}_place`] = 0;
|
||||||
|
errorCountsRef.current[`${assetId}_place`]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!assetStateChangesRef.current[assetId]) {
|
if (!assetStateChangesRef.current[assetId]) {
|
||||||
@@ -1155,9 +1167,23 @@ 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 + errorCount;
|
// Calculate success rates
|
||||||
const pickSuccessRate = pickAttempts > 0 ? (pickAndPlaceCount / pickAttempts) * 100 : 100;
|
const pickSuccessCount = completedActionsRef.current[`${armBot.modelUuid}_pick`] || pickAndPlaceCount / 2;
|
||||||
const placeAccuracy = pickSuccessRate * 0.98; // Assuming 98% of successful picks are placed correctly
|
const placeSuccessCount = completedActionsRef.current[`${armBot.modelUuid}_place`] || pickAndPlaceCount / 2;
|
||||||
|
|
||||||
|
const pickErrors = errorCountsRef.current[`${armBot.modelUuid}_pick`] || 0;
|
||||||
|
const placeErrors = errorCountsRef.current[`${armBot.modelUuid}_place`] || 0;
|
||||||
|
|
||||||
|
// If granular errors are 0 but main error count > 0, distribute them (fallback)
|
||||||
|
const remainingErrors = Math.max(0, errorCount - pickErrors - placeErrors);
|
||||||
|
const effectivePickErrors = pickErrors + (remainingErrors > 0 ? Math.ceil(remainingErrors / 2) : 0);
|
||||||
|
const effectivePlaceErrors = placeErrors + (remainingErrors > 0 ? Math.floor(remainingErrors / 2) : 0);
|
||||||
|
|
||||||
|
const pickAttempts = pickSuccessCount + effectivePickErrors;
|
||||||
|
const placeAttempts = placeSuccessCount + effectivePlaceErrors;
|
||||||
|
|
||||||
|
const pickSuccessRate = pickAttempts > 0 ? (pickSuccessCount / pickAttempts) * 100 : 100;
|
||||||
|
const placeAccuracy = placeAttempts > 0 ? (placeSuccessCount / placeAttempts) * 100 : 100;
|
||||||
|
|
||||||
// Update historical data
|
// Update historical data
|
||||||
|
|
||||||
@@ -2279,7 +2305,7 @@ function Analyzer() {
|
|||||||
const allAssets = [
|
const allAssets = [
|
||||||
...conveyors.map((c) => ({ id: c.modelUuid, state: c.state, isActive: !c.isPaused, type: "conveyor" as const })),
|
...conveyors.map((c) => ({ id: c.modelUuid, state: c.state, isActive: !c.isPaused, type: "conveyor" as const })),
|
||||||
...machines.map((m) => ({ id: m.modelUuid, state: m.state, isActive: m.isActive, type: "machine" as const })),
|
...machines.map((m) => ({ id: m.modelUuid, state: m.state, isActive: m.isActive, type: "machine" as const })),
|
||||||
...armBots.map((a) => ({ id: a.modelUuid, state: a.state, isActive: a.isActive, type: "roboticArm" as const })),
|
...armBots.map((a) => ({ id: a.modelUuid, state: a.state, isActive: a.isActive, type: "roboticArm" as const, currentAction: a.currentAction })),
|
||||||
...vehicles.map((v) => ({ id: v.modelUuid, state: v.state, isActive: v.isActive, type: "vehicle" as const })),
|
...vehicles.map((v) => ({ id: v.modelUuid, state: v.state, isActive: v.isActive, type: "vehicle" as const })),
|
||||||
...humans.map((h) => ({ id: h.modelUuid, state: h.state, isActive: h.isActive, type: "human" as const })),
|
...humans.map((h) => ({ id: h.modelUuid, state: h.state, isActive: h.isActive, type: "human" as const })),
|
||||||
...cranes.map((c) => ({ id: c.modelUuid, state: c.state, isActive: c.isActive, type: "crane" as const })),
|
...cranes.map((c) => ({ id: c.modelUuid, state: c.state, isActive: c.isActive, type: "crane" as const })),
|
||||||
@@ -2293,7 +2319,7 @@ function Analyzer() {
|
|||||||
if (previousState) {
|
if (previousState) {
|
||||||
// Check for state change
|
// Check for state change
|
||||||
if (previousState.state !== asset.state) {
|
if (previousState.state !== asset.state) {
|
||||||
trackStateChange(asset.id, previousState.state, asset.state);
|
trackStateChange(asset.id, previousState.state, asset.state, asset.type === "roboticArm" ? { actionName: (asset as any).currentAction?.actionName } : undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for material count change (potential bottleneck)
|
// Check for material count change (potential bottleneck)
|
||||||
@@ -2330,6 +2356,24 @@ function Analyzer() {
|
|||||||
completedActionsRef.current[`${armBot.modelUuid}_pickplace`] = 0;
|
completedActionsRef.current[`${armBot.modelUuid}_pickplace`] = 0;
|
||||||
}
|
}
|
||||||
completedActionsRef.current[`${armBot.modelUuid}_pickplace`]++;
|
completedActionsRef.current[`${armBot.modelUuid}_pickplace`]++;
|
||||||
|
|
||||||
|
// Granular pick/place tracking
|
||||||
|
if (previousActionUuid) {
|
||||||
|
// We need to look up what action this UUID corresponded to
|
||||||
|
// Since we don't store the action map history, we check the current config
|
||||||
|
// This assumes configuration hasn't changed, which is true for runtime
|
||||||
|
const action = armBot.point.actions.find((a) => a.actionUuid === previousActionUuid);
|
||||||
|
if (action) {
|
||||||
|
const actionName = action.actionName.toLowerCase();
|
||||||
|
if (actionName.includes("pick")) {
|
||||||
|
if (!completedActionsRef.current[`${armBot.modelUuid}_pick`]) completedActionsRef.current[`${armBot.modelUuid}_pick`] = 0;
|
||||||
|
completedActionsRef.current[`${armBot.modelUuid}_pick`]++;
|
||||||
|
} else if (actionName.includes("place")) {
|
||||||
|
if (!completedActionsRef.current[`${armBot.modelUuid}_place`]) completedActionsRef.current[`${armBot.modelUuid}_place`] = 0;
|
||||||
|
completedActionsRef.current[`${armBot.modelUuid}_place`]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
|
previousArmBotActionsRef.current[armBot.modelUuid] = currentActionUuid;
|
||||||
|
|||||||
Reference in New Issue
Block a user