feat(lidar): add RAVNOVES field review
This commit is contained in:
@@ -8,10 +8,14 @@ let parseLidarReplayCatalog;
|
||||
let parseLidarReplayDetail;
|
||||
let parseLidarGroundBenchmarkCatalog;
|
||||
let parseLidarGroundFrame;
|
||||
let parseLidarFieldReviewCatalog;
|
||||
let parseLidarFieldReviewWindow;
|
||||
let fetchLidarReplayCatalog;
|
||||
let fetchLidarReplayDetail;
|
||||
let fetchLidarGroundBenchmarks;
|
||||
let fetchLidarGroundFrame;
|
||||
let fetchLidarFieldReviews;
|
||||
let fetchLidarFieldReviewWindow;
|
||||
let LidarReplayContractError;
|
||||
let workspaceById;
|
||||
|
||||
@@ -26,10 +30,14 @@ before(async () => {
|
||||
parseLidarReplayDetail,
|
||||
parseLidarGroundBenchmarkCatalog,
|
||||
parseLidarGroundFrame,
|
||||
parseLidarFieldReviewCatalog,
|
||||
parseLidarFieldReviewWindow,
|
||||
fetchLidarReplayCatalog,
|
||||
fetchLidarReplayDetail,
|
||||
fetchLidarGroundBenchmarks,
|
||||
fetchLidarGroundFrame,
|
||||
fetchLidarFieldReviews,
|
||||
fetchLidarFieldReviewWindow,
|
||||
LidarReplayContractError,
|
||||
} = await server.ssrLoadModule("/src/core/lidar/replayQuality.ts"));
|
||||
({ workspaceById } = await server.ssrLoadModule("/src/productModel.ts"));
|
||||
@@ -40,6 +48,8 @@ after(async () => {
|
||||
});
|
||||
|
||||
const packId = `lidar-replay-pack-${"a".repeat(64)}`;
|
||||
const fieldReviewId = `lidar-field-review-${"d".repeat(64)}`;
|
||||
const e10PackId = `e10-lidar-pack-${"e".repeat(64)}`;
|
||||
|
||||
function summary(overrides = {}) {
|
||||
return {
|
||||
@@ -267,6 +277,145 @@ function groundFrame(overrides = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
function fieldReviewWindowSummary(overrides = {}) {
|
||||
return {
|
||||
index: 0,
|
||||
key: "intersection-facades",
|
||||
label: "Перекрёсток, дорога и фасады",
|
||||
start_seconds: 145,
|
||||
end_seconds: 151,
|
||||
midpoint_seconds: 148,
|
||||
source_lidar_samples: 56,
|
||||
source_point_count: 98538,
|
||||
display_point_count: 3,
|
||||
source_frame_start: 1097,
|
||||
source_frame_end: 1156,
|
||||
preview_source_frame_index: 1120,
|
||||
preview_session_seconds: 147.451857292,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function fieldReviewCatalog(overrides = {}) {
|
||||
const provider = (providerId, sourceCommit = undefined) => ({
|
||||
provider_id: providerId,
|
||||
source_commit: sourceCommit,
|
||||
});
|
||||
const branch = (providerValue) => ({
|
||||
provider: providerValue,
|
||||
ground_fraction: distribution(),
|
||||
latency_ms: distribution(),
|
||||
});
|
||||
return {
|
||||
schema_version: "missioncore.lidar-field-review-catalog/v1",
|
||||
configured: true,
|
||||
valid_total: 1,
|
||||
invalid_total: 0,
|
||||
access: "read-only",
|
||||
items: [{
|
||||
review_id: fieldReviewId,
|
||||
display_name: "RAVNOVES00 · центральный городской интервал",
|
||||
session_id: "20260720T065719Z_viewer_live",
|
||||
source_pack_id: e10PackId,
|
||||
status: "diagnostic-only",
|
||||
source: {
|
||||
timeline_start_seconds: 135.365857292,
|
||||
timeline_end_seconds: 195.334857292,
|
||||
available_lidar_frames: 526,
|
||||
point_count: 1182292,
|
||||
representation: "legacy-e10-vendor-map-with-pose",
|
||||
intensity_available: false,
|
||||
raw_scan_accepted: false,
|
||||
},
|
||||
selection: {
|
||||
purpose: "operator-readable-central-urban-field-review",
|
||||
default_window_index: 0,
|
||||
accumulation: "per-source-frame masks accumulated in map frame",
|
||||
sampling: {
|
||||
method: "uniform-point-index-per-window",
|
||||
maximum_points_per_window: 80000,
|
||||
},
|
||||
},
|
||||
windows: [fieldReviewWindowSummary()],
|
||||
metrics: {
|
||||
source_samples: 56,
|
||||
current: branch(
|
||||
provider("missioncore-local-percentile-ground/v1"),
|
||||
),
|
||||
candidate: branch(
|
||||
provider(
|
||||
"patchworkpp/v1.4.1",
|
||||
"3e6903a1d5537a4cc2ace897b0bbb98a92d6014c",
|
||||
),
|
||||
),
|
||||
comparison: {
|
||||
algorithm_to_algorithm_ground_iou: distribution(),
|
||||
ground_disagreement_fraction: distribution(),
|
||||
is_accuracy_metric: false,
|
||||
},
|
||||
},
|
||||
decision: {
|
||||
status: "visual-review-only",
|
||||
production_promotion: false,
|
||||
reasons: ["legacy derivative does not retain intensity"],
|
||||
},
|
||||
created_at_utc: "2026-07-25T02:00:00Z",
|
||||
ground_truth: false,
|
||||
authority: {
|
||||
commands_enabled: false,
|
||||
navigation_or_safety_accepted: false,
|
||||
},
|
||||
}],
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function fieldReviewWindow(overrides = {}) {
|
||||
return {
|
||||
schema_version: "missioncore.lidar-field-review-window/v1",
|
||||
review_id: fieldReviewId,
|
||||
display_name: "RAVNOVES00 · центральный городской интервал",
|
||||
session_id: "20260720T065719Z_viewer_live",
|
||||
source_pack_id: e10PackId,
|
||||
window_index: 0,
|
||||
window_count: 1,
|
||||
window: fieldReviewWindowSummary(),
|
||||
point_count: 3,
|
||||
coordinate_frame: "map",
|
||||
distance_unit: "m",
|
||||
intensity: {
|
||||
available: false,
|
||||
reason: "E10 derivative did not retain rgbi/intensity",
|
||||
},
|
||||
points_xyz_m: [
|
||||
[0, 0, 0],
|
||||
[1, 0, 0.1],
|
||||
[0, 1, 0.5],
|
||||
],
|
||||
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,
|
||||
},
|
||||
preview_url:
|
||||
`/api/v1/lidar/field-reviews/${fieldReviewId}/windows/0/preview`,
|
||||
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,
|
||||
@@ -359,6 +508,49 @@ test("ground frame stays point-aligned, bounded and path-free", () => {
|
||||
);
|
||||
});
|
||||
|
||||
test("field review identifies RAVNOVES00 source and stays visual-only", () => {
|
||||
const parsedCatalog = parseLidarFieldReviewCatalog(fieldReviewCatalog());
|
||||
const parsedWindow = parseLidarFieldReviewWindow(fieldReviewWindow());
|
||||
|
||||
assert.equal(parsedCatalog.items[0].sourcePackId, e10PackId);
|
||||
assert.equal(parsedCatalog.items[0].source.availableLidarFrames, 526);
|
||||
assert.equal(parsedCatalog.items[0].selection.defaultWindowIndex, 0);
|
||||
assert.equal(parsedWindow.window.label, "Перекрёсток, дорога и фасады");
|
||||
assert.equal(parsedWindow.intensity0To255, null);
|
||||
assert.equal(parsedWindow.counts.disagreement, 1);
|
||||
assert.equal("path" in parsedWindow, false);
|
||||
|
||||
const promoted = fieldReviewCatalog();
|
||||
promoted.items[0].decision.production_promotion = true;
|
||||
assert.throws(
|
||||
() => parseLidarFieldReviewCatalog(promoted),
|
||||
LidarReplayContractError,
|
||||
);
|
||||
});
|
||||
|
||||
test("field-review window refuses forged preview and point masks", () => {
|
||||
assert.throws(
|
||||
() => parseLidarFieldReviewWindow(fieldReviewWindow({
|
||||
preview_url: "https://example.invalid/frame.jpg",
|
||||
})),
|
||||
LidarReplayContractError,
|
||||
);
|
||||
assert.throws(
|
||||
() => parseLidarFieldReviewWindow(fieldReviewWindow({
|
||||
masks: {
|
||||
...fieldReviewWindow().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) => {
|
||||
@@ -368,6 +560,11 @@ test("LiDAR fetchers use read-only endpoints and workspace is registered", async
|
||||
? jsonResponse(groundFrame())
|
||||
: jsonResponse(groundCatalog());
|
||||
}
|
||||
if (String(input).includes("field-reviews")) {
|
||||
return String(input).includes("/windows/")
|
||||
? jsonResponse(fieldReviewWindow())
|
||||
: jsonResponse(fieldReviewCatalog());
|
||||
}
|
||||
return String(input).includes(packId)
|
||||
? jsonResponse(detail())
|
||||
: jsonResponse(catalog());
|
||||
@@ -380,11 +577,19 @@ test("LiDAR fetchers use read-only endpoints and workspace is registered", async
|
||||
0,
|
||||
{ fetcher },
|
||||
);
|
||||
const fieldCatalog = await fetchLidarFieldReviews({ fetcher });
|
||||
const fieldWindow = await fetchLidarFieldReviewWindow(
|
||||
fieldReviewId,
|
||||
0,
|
||||
{ fetcher },
|
||||
);
|
||||
|
||||
assert.equal(parsedCatalog.validTotal, 1);
|
||||
assert.equal(parsedDetail.pack.packId, packId);
|
||||
assert.equal(ground.validTotal, 1);
|
||||
assert.equal(frame.pointCount, 3);
|
||||
assert.equal(fieldCatalog.items[0].windows[0].sourceLidarSamples, 56);
|
||||
assert.equal(fieldWindow.previewUrl.endsWith("/preview"), true);
|
||||
assert.deepEqual(calls, [
|
||||
{ input: "/api/v1/lidar/replay-packs?limit=50", method: "GET" },
|
||||
{ input: `/api/v1/lidar/replay-packs/${packId}`, method: "GET" },
|
||||
@@ -396,6 +601,14 @@ test("LiDAR fetchers use read-only endpoints and workspace is registered", async
|
||||
input: `/api/v1/lidar/ground-benchmarks/ground-benchmark-${"c".repeat(64)}/frames/0`,
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
input: "/api/v1/lidar/field-reviews?limit=10",
|
||||
method: "GET",
|
||||
},
|
||||
{
|
||||
input: `/api/v1/lidar/field-reviews/${fieldReviewId}/windows/0`,
|
||||
method: "GET",
|
||||
},
|
||||
]);
|
||||
assert.equal(workspaceById("lidar-quality").root, "data");
|
||||
assert.equal(workspaceById("lidar-quality").kind, "lidar-quality");
|
||||
|
||||
Reference in New Issue
Block a user