feat(lab): visualize M4.8R3 system occupancy

This commit is contained in:
DCCONSTRUCTIONS
2026-08-26 13:40:24 +03:00
parent b82a97fe8b
commit 936ee479ed
13 changed files with 641 additions and 7 deletions
@@ -26,6 +26,7 @@ export interface LaboratoryMetricObstacleVisual {
state: "current" | "retained" | "held" | "expired";
centroidBodyXyzM: LaboratoryMetricPoint3;
cellCentersBodyXyzM: readonly LaboratoryMetricPoint3[];
occupancySource?: "baseline" | "mixed" | "additive-low-step";
}
export interface LaboratoryMetricRigVisual {
@@ -41,7 +42,7 @@ export interface LaboratoryMetricCorridorVisual {
}
export interface LaboratoryMetricLegendEntry {
id: LaboratoryMetricDecision | "context" | "local-surface" | "rolling";
id: LaboratoryMetricDecision | "context" | "local-surface" | "rolling" | "low-step";
label: string;
}
@@ -52,6 +53,7 @@ export function laboratoryMetricLegendEntries({
showCurrentIncrement,
showLocalSurface,
showRollingMap,
showLowStep = true,
}: {
pointCloudCount: number;
localSurfaceCount: number;
@@ -59,19 +61,29 @@ export function laboratoryMetricLegendEntries({
showCurrentIncrement: boolean;
showLocalSurface: boolean;
showRollingMap: boolean;
showLowStep?: boolean;
}): readonly LaboratoryMetricLegendEntry[] {
const visibleObstacles = obstacles.filter((obstacle) => (
obstacle.state === "current"
(showLowStep || obstacle.occupancySource === undefined || obstacle.occupancySource === "baseline")
&& (obstacle.state === "current"
? showCurrentIncrement
: obstacle.state === "retained"
? showRollingMap
: false
: false)
));
const decisions = new Set(visibleObstacles.map(({ decision }) => decision));
const entries: LaboratoryMetricLegendEntry[] = [];
if (decisions.has("threat")) entries.push({ id: "threat", label: "Угроза" });
if (decisions.has("not-threat")) entries.push({ id: "not-threat", label: "Вне коридора" });
if (decisions.has("unknown")) entries.push({ id: "unknown", label: "Неизвестно" });
if (
showLowStep
&& visibleObstacles.some((obstacle) => (
obstacle.occupancySource !== undefined && obstacle.occupancySource !== "baseline"
))
) {
entries.push({ id: "low-step", label: "LOW-STEP · добавлено системой" });
}
if (showCurrentIncrement && pointCloudCount > 0) {
entries.push({ id: "context", label: "Текущий кадр" });
}
@@ -153,6 +165,16 @@ function decisionColor(
return tokenColor(host, "--nodedc-warning-rgb", [255, 197, 92]);
}
function obstacleColor(
host: HTMLElement,
obstacle: LaboratoryMetricObstacleVisual,
): THREE.Color {
if (obstacle.occupancySource !== "baseline") {
return tokenColor(host, "--nodedc-accent-rgb", [232, 56, 126]);
}
return decisionColor(host, obstacle.decision);
}
export interface LaboratoryMetricEvidenceSceneHandle {
resetView: () => void;
}
@@ -171,6 +193,7 @@ LaboratoryMetricEvidenceSceneHandle,
showCurrentIncrement: boolean;
showLocalSurface: boolean;
showRollingMap: boolean;
showLowStep?: boolean;
pointSemanticClassIds?: readonly (number | null)[];
semanticClasses?: readonly RecordedEvidenceSemanticClass[];
semanticPalette?: readonly RecordedEvidenceSemanticPaletteEntry[];
@@ -187,6 +210,7 @@ LaboratoryMetricEvidenceSceneHandle,
showCurrentIncrement,
showLocalSurface,
showRollingMap,
showLowStep = true,
pointSemanticClassIds,
semanticClasses,
semanticPalette,
@@ -352,6 +376,12 @@ LaboratoryMetricEvidenceSceneHandle,
for (const obstacle of obstacles) {
if (
(
!showLowStep
&& obstacle.occupancySource !== undefined
&& obstacle.occupancySource !== "baseline"
)
||
(obstacle.state === "current" && !showCurrentIncrement)
|| (obstacle.state === "retained" && !showRollingMap)
|| obstacle.state === "held"
@@ -359,7 +389,7 @@ LaboratoryMetricEvidenceSceneHandle,
) {
continue;
}
const color = decisionColor(host, obstacle.decision);
const color = obstacleColor(host, obstacle);
if (obstacle.state === "retained") {
const geometry = new THREE.BoxGeometry(
occupiedVoxelSizeM * 0.82,
@@ -424,6 +454,7 @@ LaboratoryMetricEvidenceSceneHandle,
showCurrentIncrement,
showLocalSurface,
showRollingMap,
showLowStep,
]);
useEffect(() => {
@@ -538,6 +569,7 @@ LaboratoryMetricEvidenceSceneHandle,
showCurrentIncrement,
showLocalSurface,
showRollingMap,
showLowStep,
});
return (