feat(lab): separate current increment from rolling map

This commit is contained in:
DCCONSTRUCTIONS
2026-08-05 21:12:54 +03:00
parent 7aa3ce55c0
commit 31313c3c96
7 changed files with 165 additions and 37 deletions
@@ -52,14 +52,14 @@ export function M4ReplayThreatResultView({
]}
brief={{
question: "Может ли единый слой обнаруживать потенциальное препятствие по двум независимым источникам, не теряя LiDAR-only объекты и не объявляя camera-only наблюдение безопасным?",
approach: "Все 4489 кадров RAVNOVES00 повторно пропущены через неизменяемые detector, metric geometry и temporal ledgers. Виртуальный base_footprint привязан к gravity-оси SLAM map и направлению сглаженной траектории, проверенному camera extrinsic. Geometry-only объекты получают метрическую оценку; camera-only и stale/held остаются unknown.",
principalResult: `${metrics.evidence.currentMetric.toLocaleString("ru-RU")} current metric и ${metrics.evidence.cameraOnly.toLocaleString("ru-RU")} camera-only наблюдений учтены; ${metrics.reasonCounts["geometry-only-evidence"]?.toLocaleString("ru-RU") ?? "0"} geometry-only оценок не потеряны. Критические fixtures: ${metrics.fixtures.passed}/${metrics.fixtures.total}, ложных safe: ${metrics.fixtures.criticalFalseNotThreat}.`,
approach: "Все 4489 кадров RAVNOVES00 повторно пропущены через неизменяемые detector, metric geometry и temporal ledgers. Текущий lio_pcl increment хранится отдельно от bounded rolling map: отсутствие повторной публикации точки не считается свободным пространством. Виртуальный base_footprint привязан к gravity-оси SLAM map и направлению сглаженной траектории, проверенному camera extrinsic.",
principalResult: `${metrics.evidence.currentMetric.toLocaleString("ru-RU")} current metric, ${metrics.evidence.rollingMapRetained.toLocaleString("ru-RU")} rolling-map и ${metrics.evidence.cameraOnly.toLocaleString("ru-RU")} camera-only публикаций учтены. Кадр 1880 удерживает обе видимые бетонные полусферы; критические fixtures: ${metrics.fixtures.passed}/${metrics.fixtures.total}, ложных safe: ${metrics.fixtures.criticalFalseNotThreat}.`,
limitation: "Корпус и коридор пока виртуальные, replay не является live-проходом или физическим collision test. На машине виртуальная привязка должна замениться измеренным rigid T_body_from_sensor; independent object truth остаётся следующим gate.",
}}
method={{
completeness: "complete",
executionClass: "hybrid",
pipelineId: "dual-evidence-replay-threat/v2",
pipelineId: "dual-evidence-replay-threat/v3",
components: [
{
kind: "source",
@@ -78,8 +78,8 @@ export function M4ReplayThreatResultView({
{
kind: "source",
name: result.sourceResultIds.temporal,
version: "frozen temporal object map",
role: "current / held / expired и bounded motion history",
version: "frozen temporal + rolling obstacle map",
role: "current increment / rolling retained / bounded motion history",
identitySha256: result.sourceResultIds.temporal.split("-").at(-1) ?? null,
},
{
@@ -117,7 +117,7 @@ export function M4ReplayThreatResultView({
{
label: "Metric evidence",
value: metrics.evidence.currentMetric.toLocaleString("ru-RU"),
hint: `${metrics.reasonCounts["geometry-only-evidence"]?.toLocaleString("ru-RU") ?? "0"} geometry-only`,
hint: `${metrics.evidence.rollingMapRetained.toLocaleString("ru-RU")} rolling-map publications`,
},
{
label: "Threat / clear",
@@ -131,7 +131,7 @@ export function M4ReplayThreatResultView({
},
]}
conclusion={{
proved: `На неизменяемом RAVNOVES00 каждый metric, stale/held и camera-only объект получил ровно одну консервативную оценку. ${metrics.bodyFrame.qualified}/${metrics.bodyFrame.available} доступных body frames квалифицированы без переноса handheld roll/pitch на SLAM-мир; camera/route alignment p95 ${formatNumber(metrics.bodyFrame.cameraForwardAlignmentDeg.p95, 1)}°. Видео и точное 3D-доказательство доступны в одном viewer.`,
proved: `На неизменяемом RAVNOVES00 каждый current, rolling-map, stale/held и camera-only объект получил ровно одну консервативную оценку. CURRENT INCREMENT и ROLLING MAP независимо включаются в viewer; кадр 1880 закреплён как регрессия двух бетонных полусфер. ${metrics.bodyFrame.qualified}/${metrics.bodyFrame.available} body frames квалифицированы без переноса handheld roll/pitch на SLAM-мир.`,
notProved: "Не доказаны live realtime, измеренный T_body_from_sensor и геометрия физического корпуса, независимая object-level правильность, навигационная или safety-пригодность и выдача команд.",
decision: "Сохранить dual-evidence provider как канонический replay seam и переходить к независимому object-centric gate; физическую геометрию и live/actuation authority не смешивать с дальнейшей CV-разработкой.",
}}
@@ -179,6 +179,12 @@ export function M4ReplayThreatVisual({ resultId }: { resultId: string }) {
const threatObstacles = frame?.metricObstacles.filter(
(item) => item.assessment.decision === "threat",
) ?? [];
const currentIncrementObstacles = frame?.metricObstacles.filter(
(item) => item.state === "current",
) ?? [];
const rollingMapObstacles = frame?.metricObstacles.filter(
(item) => item.state === "retained",
) ?? [];
const nearest = frame?.metricObstacles
.map((item) => item.assessment.closestApproachM)
.filter((value): value is number => value !== null)
@@ -293,9 +299,14 @@ export function M4ReplayThreatVisual({ resultId }: { resultId: string }) {
<small>{(frame.sourceTimeNs / 1_000_000_000).toFixed(3)} с · {selectedItem?.frameId}</small>
</div>
<div>
<span>Dual evidence</span>
<strong>{frame.metricObstacles.length} metric · {frame.cameraProposals.length} camera</strong>
<small>{frame.pointCloudSampleCount}/{frame.pointCloudSourceCount} LiDAR points shown</small>
<span>Representation layers</span>
<strong>
{currentIncrementObstacles.length} current · {rollingMapObstacles.length} rolling
</strong>
<small>
CURRENT INCREMENT {frame.pointCloudSampleCount}/{frame.pointCloudSourceCount} points
· ROLLING MAP {frame.rollingMapComponentCount} components
</small>
</div>
<div>
<span>Virtual corridor</span>
@@ -356,7 +367,7 @@ export function M4ReplayThreatVisual({ resultId }: { resultId: string }) {
rig={frame.rig}
corridor={frame.corridor}
mode={mode}
label={`M4.6 metric point cloud, frame ${frame.sequence}`}
label={`M4.6 current increment and rolling map, frame ${frame.sequence}`}
/>
);
}