317 lines
9.4 KiB
JavaScript
317 lines
9.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { after, before, test } from "node:test";
|
|
|
|
import { createServer } from "vite";
|
|
|
|
let server;
|
|
let parseDatasetGatewayCatalog;
|
|
let parseDatasetNativeScanPreview;
|
|
let parseDatasetGroundComparison;
|
|
let fetchDatasetGatewayCatalog;
|
|
let fetchDatasetNativeScanPreview;
|
|
let fetchDatasetGroundComparison;
|
|
let DatasetGatewayContractError;
|
|
|
|
before(async () => {
|
|
server = await createServer({
|
|
appType: "custom",
|
|
logLevel: "silent",
|
|
server: { middlewareMode: true },
|
|
});
|
|
({
|
|
parseDatasetGatewayCatalog,
|
|
parseDatasetNativeScanPreview,
|
|
parseDatasetGroundComparison,
|
|
fetchDatasetGatewayCatalog,
|
|
fetchDatasetNativeScanPreview,
|
|
fetchDatasetGroundComparison,
|
|
DatasetGatewayContractError,
|
|
} = await server.ssrLoadModule("/src/core/lidar/datasetGateway.ts"));
|
|
});
|
|
|
|
after(async () => {
|
|
await server?.close();
|
|
});
|
|
|
|
function catalog(overrides = {}) {
|
|
return {
|
|
schema_version: "missioncore.dataset-gateway-catalog/v2",
|
|
access: "read-only",
|
|
storage: {
|
|
configured: false,
|
|
required_windows_root: "D:\\NDC_MISSIONCORE\\datasets",
|
|
required_wsl_root: "/mnt/d/NDC_MISSIONCORE/datasets",
|
|
admitted: false,
|
|
status: "blocked-storage-policy",
|
|
attestation: "none",
|
|
manifest_valid: false,
|
|
path_exposed: false,
|
|
},
|
|
sources: [{
|
|
source_id: "goose-3d/v2025-08-22",
|
|
display_name: "GOOSE 3D",
|
|
role: "primary-offroad-semantic-baseline",
|
|
license: "CC-BY-SA-4.0",
|
|
format: "semantickitti-xyzi-label",
|
|
frame_semantics: "one-lidar-revolution",
|
|
platforms: ["MuCAR-3", "ALICE", "Spot"],
|
|
annotations: ["semantic-point", "instance-point"],
|
|
superclasses: ["natural-ground", "obstacle"],
|
|
download: {
|
|
automatic: false,
|
|
reason: "operator-admitted-large-artifact-only",
|
|
validation_archive_gb: 3.3,
|
|
},
|
|
admission: {
|
|
status: "blocked-storage-policy",
|
|
archive: null,
|
|
frame: null,
|
|
},
|
|
}],
|
|
representations: [
|
|
{
|
|
id: "native-scan",
|
|
title: "Одиночный исходный скан",
|
|
purpose: "dataset-ground-truth-and-sensor-domain",
|
|
accumulation: false,
|
|
},
|
|
{
|
|
id: "normalized-scan",
|
|
title: "Нормализованный sensor-frame скан",
|
|
purpose: "deskew-filter-inference-and-algorithm-comparison",
|
|
accumulation: false,
|
|
},
|
|
{
|
|
id: "rolling-local-map",
|
|
title: "Накопленная локальная карта",
|
|
purpose: "stable-operator-view-and-local-planning",
|
|
accumulation: true,
|
|
},
|
|
],
|
|
pipeline: [{
|
|
stage: "deskew",
|
|
requires: ["per-point-time", "imu-or-odometry"],
|
|
produces: "normalized-scan",
|
|
}],
|
|
known_inputs: [{
|
|
source_id: "current-recorded-lidar/vendor-map",
|
|
representation: "vendor-mapped-increment",
|
|
native_scan: false,
|
|
per_point_time: false,
|
|
ring_or_line: false,
|
|
admitted_for_patchworkpp: false,
|
|
reason: "post-lio-map-product-cannot-be-reconstructed-as-a-native-scan",
|
|
}],
|
|
next_action: "configure-dataset-root-on-worker-d",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test("parses three distinct LiDAR representations and current-input boundary", () => {
|
|
const parsed = parseDatasetGatewayCatalog(catalog());
|
|
assert.deepEqual(
|
|
parsed.representations.map((item) => item.id),
|
|
["native-scan", "normalized-scan", "rolling-local-map"],
|
|
);
|
|
assert.equal(parsed.representations[2].accumulation, true);
|
|
assert.equal(parsed.currentInput.admittedForPatchworkpp, false);
|
|
assert.equal(parsed.source.frameSemantics, "one-lidar-revolution");
|
|
});
|
|
|
|
test("rejects path exposure and upgraded K1 semantics", () => {
|
|
const exposed = catalog();
|
|
exposed.storage.path_exposed = true;
|
|
assert.throws(
|
|
() => parseDatasetGatewayCatalog(exposed),
|
|
DatasetGatewayContractError,
|
|
);
|
|
|
|
const upgraded = catalog();
|
|
upgraded.known_inputs[0].per_point_time = true;
|
|
assert.throws(
|
|
() => parseDatasetGatewayCatalog(upgraded),
|
|
DatasetGatewayContractError,
|
|
);
|
|
});
|
|
|
|
test("fetches the read-only gateway endpoint", async () => {
|
|
const calls = [];
|
|
const parsed = await fetchDatasetGatewayCatalog({
|
|
fetcher: async (url, init) => {
|
|
calls.push({ url, init });
|
|
return new Response(JSON.stringify(catalog()), {
|
|
status: 200,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
},
|
|
});
|
|
assert.equal(calls[0].url, "/api/v1/lidar/dataset-gateway");
|
|
assert.equal(calls[0].init.method, "GET");
|
|
assert.equal(parsed.source.displayName, "GOOSE 3D");
|
|
});
|
|
|
|
test("decodes one bounded point-aligned native-scan preview", async () => {
|
|
const payload = {
|
|
schema_version: "missioncore.dataset-native-scan-preview/v1",
|
|
source_id: "goose-3d/v2025-08-22",
|
|
frame_id: "frame-1",
|
|
representation: "native-scan",
|
|
sampling: "deterministic-even-index",
|
|
source_point_count: 2,
|
|
point_count: 2,
|
|
points_xyz_m: [[1, 2, 3], [4, 5, 6]],
|
|
remission_0_to_255: [0, 255],
|
|
semantic_label_ids: [23, 38],
|
|
semantic_rgb_0_to_255: [255, 47, 128, 1, 51, 73],
|
|
ground_truth_ground: [1, 0],
|
|
classes: [
|
|
{
|
|
label_id: 23,
|
|
class_name: "asphalt",
|
|
hex: "#ff2f80",
|
|
challenge_category_id: 2,
|
|
challenge_category_name: "artificial_ground",
|
|
},
|
|
],
|
|
safety: {
|
|
visualization_only: true,
|
|
navigation_or_safety_accepted: false,
|
|
},
|
|
};
|
|
const parsed = parseDatasetNativeScanPreview(payload);
|
|
assert.equal(parsed.pointCount, 2);
|
|
assert.deepEqual(parsed.groundTruthGround, [1, 0]);
|
|
|
|
const fetched = await fetchDatasetNativeScanPreview({
|
|
fetcher: async () => new Response(JSON.stringify(payload), { status: 200 }),
|
|
});
|
|
assert.equal(fetched.frameId, "frame-1");
|
|
|
|
payload.semantic_rgb_0_to_255.pop();
|
|
assert.throws(
|
|
() => parseDatasetNativeScanPreview(payload),
|
|
DatasetGatewayContractError,
|
|
);
|
|
});
|
|
|
|
test("decodes a point-aligned current-vs-Patchwork++ comparison", async () => {
|
|
const payload = {
|
|
schema_version: "missioncore.dataset-ground-comparison-preview/v2",
|
|
source_id: "goose-3d/v2025-08-22",
|
|
frame_id: "frame-1",
|
|
sampling: "deterministic-even-index",
|
|
point_count: 2,
|
|
current_ground: [1, 1],
|
|
patchwork_ground: [1, 0],
|
|
patchwork_assigned: [1, 1],
|
|
ground_truth_ground: [1, 0],
|
|
evaluated: [1, 1],
|
|
current_disagreement: [0, 1],
|
|
patchwork_disagreement: [0, 0],
|
|
metrics: {
|
|
current: {
|
|
true_positive: 1,
|
|
false_positive: 1,
|
|
false_negative: 0,
|
|
true_negative: 0,
|
|
precision: 0.5,
|
|
recall: 1,
|
|
f1: 2 / 3,
|
|
ground_iou: 0.5,
|
|
accuracy: 0.5,
|
|
artificial_ground_recall: 1,
|
|
natural_ground_recall: 0,
|
|
obstacle_non_ground_recall: 1,
|
|
},
|
|
patchworkpp: {
|
|
true_positive: 1,
|
|
false_positive: 0,
|
|
false_negative: 0,
|
|
true_negative: 1,
|
|
precision: 1,
|
|
recall: 1,
|
|
f1: 1,
|
|
ground_iou: 1,
|
|
accuracy: 1,
|
|
artificial_ground_recall: 1,
|
|
natural_ground_recall: 1,
|
|
obstacle_non_ground_recall: 1,
|
|
},
|
|
},
|
|
latency_ms: {
|
|
current: 12.5,
|
|
patchworkpp: 0.4,
|
|
},
|
|
patchwork_assigned_fraction: 1,
|
|
providers: {
|
|
current: {
|
|
provider_id: "missioncore-local-percentile-ground/v1",
|
|
implementation_sha256: "a".repeat(64),
|
|
ground_truth: false,
|
|
},
|
|
patchworkpp: {
|
|
provider_id: "patchworkpp/v1.4.1",
|
|
source_url: "https://github.com/url-kaist/patchwork-plusplus",
|
|
source_tag: "v1.4.1",
|
|
source_commit: "3e6903a1d5537a4cc2ace897b0bbb98a92d6014c",
|
|
binding_version: "0.0.1",
|
|
binary_sha256: "b".repeat(64),
|
|
platform: "linux",
|
|
machine: "x86_64",
|
|
ground_truth: false,
|
|
},
|
|
},
|
|
input_profile: {
|
|
schema_version: "missioncore.goose-patchwork-profile/v1",
|
|
source_id: "goose-3d/v2025-08-22",
|
|
representation: "native-scan",
|
|
sensor_frame: {
|
|
frame_id: "sensor/lidar/vls128_roof",
|
|
handedness: "right",
|
|
x: "forward",
|
|
y: "left",
|
|
z: "up",
|
|
one_revolution: true,
|
|
},
|
|
height: {
|
|
base_link_above_ground_m: 0.64,
|
|
lidar_above_base_link_m: 1.6,
|
|
sensor_above_ground_m: 2.24,
|
|
evidence: "published-dimensioned-schematic",
|
|
},
|
|
scope: {
|
|
patchworkpp_eligible: true,
|
|
normalized_scan_produced: false,
|
|
complete_vehicle_transform_known: false,
|
|
deskew_claimed: false,
|
|
},
|
|
},
|
|
safety: {
|
|
qualification_only: true,
|
|
navigation_or_safety_accepted: false,
|
|
},
|
|
};
|
|
const parsed = parseDatasetGroundComparison(payload);
|
|
assert.equal(parsed.metrics.current.groundIou, 0.5);
|
|
assert.equal(parsed.metrics.patchworkpp.groundIou, 1);
|
|
assert.deepEqual(parsed.patchworkDisagreement, [0, 0]);
|
|
assert.equal(parsed.inputProfile.sensorHeightM, 2.24);
|
|
|
|
const fetched = await fetchDatasetGroundComparison({
|
|
fetcher: async () => new Response(JSON.stringify(payload), { status: 200 }),
|
|
});
|
|
assert.equal(fetched.latencyMs.patchworkpp, 0.4);
|
|
|
|
payload.patchwork_disagreement.pop();
|
|
assert.throws(
|
|
() => parseDatasetGroundComparison(payload),
|
|
DatasetGatewayContractError,
|
|
);
|
|
payload.patchwork_disagreement.push(0);
|
|
payload.input_profile.height.sensor_above_ground_m = 2.25;
|
|
assert.throws(
|
|
() => parseDatasetGroundComparison(payload),
|
|
DatasetGatewayContractError,
|
|
);
|
|
});
|