feat(lidar): add dataset gateway boundary

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 11:21:22 +03:00
parent 3333e9ac0f
commit f57d64bf52
14 changed files with 1314 additions and 17 deletions
@@ -0,0 +1,133 @@
import { useEffect, useState } from "react";
import { GlassSurface, StatusBadge } from "@nodedc/ui-react";
import {
fetchDatasetGatewayCatalog,
type DatasetGatewayCatalog,
} from "../core/lidar/datasetGateway";
const representationLabels: Record<string, string> = {
"native-scan": "Один оборот / скан",
"normalized-scan": "Deskew + bounded cleanup",
"rolling-local-map": "Pose + TTL + voxel map",
};
export function DatasetGatewayPanel() {
const [catalog, setCatalog] = useState<DatasetGatewayCatalog | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
void fetchDatasetGatewayCatalog({ signal: controller.signal })
.then((value) => {
if (!controller.signal.aborted) setCatalog(value);
})
.catch((loadError: unknown) => {
if (controller.signal.aborted) return;
setError(
loadError instanceof Error
? loadError.message
: "Dataset Gateway недоступен",
);
});
return () => controller.abort();
}, []);
return (
<GlassSurface className="dataset-gateway" padding="lg">
<header className="panel-heading dataset-gateway__heading">
<div>
<span className="section-eyebrow">DATASET GATEWAY · S0</span>
<h2>Три разных LiDAR-продукта</h2>
<p>
Кольцевой одиночный скан, очищенный sensor-frame и накопленная карта
больше не считаются одним облаком.
</p>
</div>
<StatusBadge
tone={error ? "danger" : catalog?.storage.admitted ? "success" : "warning"}
>
{error
? "Gateway недоступен"
: catalog?.storage.admitted
? "D: допущен"
: "Ожидает D:"}
</StatusBadge>
</header>
{catalog ? (
<>
<div className="dataset-gateway__representations">
{catalog.representations.map((representation, index) => (
<div key={representation.id}>
<span>0{index + 1}</span>
<strong>
{representationLabels[representation.id] ?? representation.title}
</strong>
<small>{representation.title}</small>
<em>
{representation.accumulation
? "накопление включено явно"
: "без накопления"}
</em>
</div>
))}
</div>
<div className="dataset-gateway__grid">
<section>
<span className="section-eyebrow">ПЕРВЫЙ BASELINE</span>
<h3>{catalog.source.displayName}</h3>
<p>
Один оборот VLS-128 в SemanticKITTI XYZI + point-wise semantic и
instance labels. Это то самое разреженное кольцевое облако,
которое корректно сравнивать с алгоритмами.
</p>
<div className="dataset-gateway__facts">
<span>{catalog.source.platforms.join(" · ")}</span>
<span>{catalog.source.superclasses.length} superclasses</span>
<span>val {catalog.source.validationArchiveGb} ГБ</span>
<span>{catalog.source.license}</span>
</div>
</section>
<section data-warning="true">
<span className="section-eyebrow">ТЕКУЩИЙ DEVICE INPUT</span>
<h3>Mapped feed raw scan</h3>
<p>
Внешний MQTT содержит vendor-mapped increment после LIO. В нём
нет per-point time и line/ring, поэтому из него нельзя честно
восстановить один исходный скан или выполнить deskew.
</p>
<div className="dataset-gateway__facts">
<span>Patchwork++: diagnostic only</span>
<span>rolling map: возможно</span>
<span>raw reconstruction: невозможно</span>
</div>
</section>
</div>
<footer className="dataset-gateway__footer">
<div>
<span>Storage gate</span>
<strong>{catalog.storage.requiredWindowsRoot}</strong>
<small>{catalog.storage.requiredWslRoot}</small>
</div>
<div>
<span>Следующий исполнимый шаг</span>
<strong>
{catalog.storage.admitted
? "Скачать GOOSE validation и импортировать первый кадр"
: "Подключить Dataset Root на D: worker"}
</strong>
<small>Автозагрузка 3.3 ГБ намеренно запрещена</small>
</div>
</footer>
</>
) : (
<p className="dataset-gateway__pending">
{error ?? "Читаем входные контракты Dataset Gateway…"}
</p>
)}
</GlassSurface>
);
}
@@ -26,6 +26,7 @@ import {
LidarGroundPointCloud,
type LidarGroundViewMode,
} from "./LidarGroundPointCloud";
import { DatasetGatewayPanel } from "./DatasetGatewayPanel";
function formatNumber(value: number | null, digits = 1): string {
if (value === null) return "—";
@@ -220,6 +221,8 @@ export function LidarQualityWorkspace({
<span className="workspace-lead__note">Только проверенные replay-артефакты</span>
</section>
<DatasetGatewayPanel />
{loading && !detail ? (
<GlassSurface className="lidar-quality-message" padding="lg">
<StatusBadge tone="accent">Проверка evidence</StatusBadge>