feat(lidar): add point-aligned ground review

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 09:44:38 +03:00
parent 75a3e669d9
commit 2dfb34ef21
15 changed files with 1548 additions and 140 deletions
@@ -7,9 +7,11 @@ let server;
let parseLidarReplayCatalog;
let parseLidarReplayDetail;
let parseLidarGroundBenchmarkCatalog;
let parseLidarGroundFrame;
let fetchLidarReplayCatalog;
let fetchLidarReplayDetail;
let fetchLidarGroundBenchmarks;
let fetchLidarGroundFrame;
let LidarReplayContractError;
let workspaceById;
@@ -23,9 +25,11 @@ before(async () => {
parseLidarReplayCatalog,
parseLidarReplayDetail,
parseLidarGroundBenchmarkCatalog,
parseLidarGroundFrame,
fetchLidarReplayCatalog,
fetchLidarReplayDetail,
fetchLidarGroundBenchmarks,
fetchLidarGroundFrame,
LidarReplayContractError,
} = await server.ssrLoadModule("/src/core/lidar/replayQuality.ts"));
({ workspaceById } = await server.ssrLoadModule("/src/productModel.ts"));
@@ -176,6 +180,11 @@ function groundCatalog(overrides = {}) {
representation: "vendor-map-increment",
physical_sensor_height_known: false,
sensor_scan_geometry_known: false,
normalization: {
sensor_height_m: 1.27,
map_vertical_origin_offset_m: 1.27,
height_evidence: "operator-estimated",
},
reason: "Patchwork++ expects sensor-centric scans.",
},
labels: {
@@ -218,6 +227,46 @@ function groundCatalog(overrides = {}) {
};
}
function groundFrame(overrides = {}) {
return {
schema_version: "missioncore.lidar-ground-frame/v1",
benchmark_id: `ground-benchmark-${"c".repeat(64)}`,
replay_pack_id: packId,
session_id: "20260719T220917Z_viewer_live",
frame_index: 0,
frame_count: 2,
capture_sequence: 42,
point_count: 3,
coordinate_frame: "map",
distance_unit: "m",
points_xyz_m: [
[0, 0, 0],
[1, 0, 0.1],
[0, 1, 0.5],
],
intensity_0_255: [10, 120, 255],
masks: {
current_ground: [1, 1, 0],
current_assigned: [1, 1, 1],
candidate_ground: [1, 0, 0],
candidate_assigned: [1, 1, 1],
disagreement: [0, 1, 0],
},
counts: {
current_ground: 2,
candidate_ground: 1,
disagreement: 1,
},
access: "read-only",
ground_truth: false,
authority: {
commands_enabled: false,
navigation_or_safety_accepted: false,
},
...overrides,
};
}
function jsonResponse(payload, status = 200) {
return new Response(JSON.stringify(payload), {
status,
@@ -252,6 +301,10 @@ test("ground benchmark stays diagnostic until input and labels are accepted", ()
assert.equal(parsed.items[0].inputDomain.accepted, false);
assert.equal(parsed.items[0].labels.metricsAvailable, false);
assert.equal(parsed.items[0].candidate.groundFraction.p50, 0.005);
assert.equal(
parsed.items[0].inputDomain.normalization.heightEvidence,
"operator-estimated",
);
assert.equal(parsed.items[0].decision.productionPromotion, false);
const promoted = groundCatalog();
@@ -262,12 +315,58 @@ test("ground benchmark stays diagnostic until input and labels are accepted", ()
);
});
test("ground frame stays point-aligned, bounded and path-free", () => {
const parsed = parseLidarGroundFrame(groundFrame());
assert.equal(parsed.pointCount, 3);
assert.deepEqual(parsed.pointsXyzM[1], [1, 0, 0.1]);
assert.deepEqual(parsed.masks.disagreement, [0, 1, 0]);
assert.equal(parsed.counts.currentGround, 2);
assert.equal("path" in parsed, false);
assert.throws(
() => parseLidarGroundFrame(groundFrame({
masks: {
...groundFrame().masks,
disagreement: [0, 1],
},
})),
LidarReplayContractError,
);
assert.throws(
() => parseLidarGroundFrame(groundFrame({
counts: {
current_ground: 1,
candidate_ground: 1,
disagreement: 1,
},
})),
LidarReplayContractError,
);
assert.throws(
() => parseLidarGroundFrame(groundFrame({
masks: {
...groundFrame().masks,
disagreement: [0, 0, 0],
},
counts: {
current_ground: 2,
candidate_ground: 1,
disagreement: 0,
},
})),
LidarReplayContractError,
);
});
test("LiDAR fetchers use read-only endpoints and workspace is registered", async () => {
const calls = [];
const fetcher = async (input, init) => {
calls.push({ input: String(input), method: init?.method });
if (String(input).includes("ground-benchmarks")) {
return jsonResponse(groundCatalog());
return String(input).includes("/frames/")
? jsonResponse(groundFrame())
: jsonResponse(groundCatalog());
}
return String(input).includes(packId)
? jsonResponse(detail())
@@ -276,10 +375,16 @@ test("LiDAR fetchers use read-only endpoints and workspace is registered", async
const parsedCatalog = await fetchLidarReplayCatalog({ fetcher });
const parsedDetail = await fetchLidarReplayDetail(packId, { fetcher });
const ground = await fetchLidarGroundBenchmarks(packId, { fetcher });
const frame = await fetchLidarGroundFrame(
`ground-benchmark-${"c".repeat(64)}`,
0,
{ fetcher },
);
assert.equal(parsedCatalog.validTotal, 1);
assert.equal(parsedDetail.pack.packId, packId);
assert.equal(ground.validTotal, 1);
assert.equal(frame.pointCount, 3);
assert.deepEqual(calls, [
{ input: "/api/v1/lidar/replay-packs?limit=50", method: "GET" },
{ input: `/api/v1/lidar/replay-packs/${packId}`, method: "GET" },
@@ -287,6 +392,10 @@ test("LiDAR fetchers use read-only endpoints and workspace is registered", async
input: `/api/v1/lidar/ground-benchmarks?pack_id=${packId}&limit=20`,
method: "GET",
},
{
input: `/api/v1/lidar/ground-benchmarks/ground-benchmark-${"c".repeat(64)}/frames/0`,
method: "GET",
},
]);
assert.equal(workspaceById("lidar-quality").root, "data");
assert.equal(workspaceById("lidar-quality").kind, "lidar-quality");