feat(lidar): qualify Patchwork++ on GOOSE
This commit is contained in:
@@ -90,25 +90,43 @@ export interface DatasetNativeScanPreview {
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface DatasetGroundMetrics {
|
||||
precision: number;
|
||||
recall: number;
|
||||
f1: number;
|
||||
groundIou: number;
|
||||
accuracy: number;
|
||||
artificialGroundRecall: number;
|
||||
naturalGroundRecall: number;
|
||||
obstacleNonGroundRecall: number;
|
||||
}
|
||||
|
||||
export interface DatasetGroundComparison {
|
||||
sourceId: "goose-3d/v2025-08-22";
|
||||
frameId: string;
|
||||
pointCount: number;
|
||||
currentGround: number[];
|
||||
patchworkGround: number[];
|
||||
patchworkAssigned: number[];
|
||||
groundTruthGround: number[];
|
||||
evaluated: number[];
|
||||
disagreement: number[];
|
||||
currentDisagreement: number[];
|
||||
patchworkDisagreement: number[];
|
||||
metrics: {
|
||||
precision: number;
|
||||
recall: number;
|
||||
f1: number;
|
||||
groundIou: number;
|
||||
accuracy: number;
|
||||
artificialGroundRecall: number;
|
||||
naturalGroundRecall: number;
|
||||
obstacleNonGroundRecall: number;
|
||||
current: DatasetGroundMetrics;
|
||||
patchworkpp: DatasetGroundMetrics;
|
||||
};
|
||||
latencyMs: {
|
||||
current: number;
|
||||
patchworkpp: number;
|
||||
};
|
||||
patchworkAssignedFraction: number;
|
||||
inputProfile: {
|
||||
frameId: "sensor/lidar/vls128_roof";
|
||||
sensorHeightM: number;
|
||||
heightEvidence: "published-dimensioned-schematic";
|
||||
normalizedScanProduced: false;
|
||||
};
|
||||
latencyMs: number;
|
||||
}
|
||||
|
||||
export class DatasetGatewayContractError extends Error {}
|
||||
@@ -500,7 +518,7 @@ export function parseDatasetGroundComparison(
|
||||
): DatasetGroundComparison {
|
||||
const source = record(value, "Ground comparison");
|
||||
if (
|
||||
source.schema_version !== "missioncore.dataset-ground-comparison-preview/v1"
|
||||
source.schema_version !== "missioncore.dataset-ground-comparison-preview/v2"
|
||||
|| source.source_id !== "goose-3d/v2025-08-22"
|
||||
|| source.sampling !== "deterministic-even-index"
|
||||
) {
|
||||
@@ -508,41 +526,135 @@ export function parseDatasetGroundComparison(
|
||||
}
|
||||
const pointCount = number(source.point_count, "point_count");
|
||||
const currentGround = integers(source.current_ground, "current_ground", 1);
|
||||
const patchworkGround = integers(source.patchwork_ground, "patchwork_ground", 1);
|
||||
const patchworkAssigned = integers(
|
||||
source.patchwork_assigned,
|
||||
"patchwork_assigned",
|
||||
1,
|
||||
);
|
||||
const groundTruthGround = integers(
|
||||
source.ground_truth_ground,
|
||||
"ground_truth_ground",
|
||||
1,
|
||||
);
|
||||
const evaluated = integers(source.evaluated, "evaluated", 1);
|
||||
const disagreement = integers(source.disagreement, "disagreement", 1);
|
||||
const currentDisagreement = integers(
|
||||
source.current_disagreement,
|
||||
"current_disagreement",
|
||||
1,
|
||||
);
|
||||
const patchworkDisagreement = integers(
|
||||
source.patchwork_disagreement,
|
||||
"patchwork_disagreement",
|
||||
1,
|
||||
);
|
||||
if (
|
||||
pointCount < 1
|
||||
|| pointCount > 50_000
|
||||
|| currentGround.length !== pointCount
|
||||
|| patchworkGround.length !== pointCount
|
||||
|| patchworkAssigned.length !== pointCount
|
||||
|| groundTruthGround.length !== pointCount
|
||||
|| evaluated.length !== pointCount
|
||||
|| disagreement.length !== pointCount
|
||||
|| currentDisagreement.length !== pointCount
|
||||
|| patchworkDisagreement.length !== pointCount
|
||||
) {
|
||||
throw new DatasetGatewayContractError("Ground comparison arrays не выровнены");
|
||||
}
|
||||
const metrics = record(source.metrics, "metrics");
|
||||
const fraction = (key: string): number => {
|
||||
const value = number(metrics[key], `metrics.${key}`);
|
||||
if (value > 1) {
|
||||
throw new DatasetGatewayContractError(`metrics.${key}: ожидалась доля`);
|
||||
}
|
||||
return value;
|
||||
const parseMetrics = (
|
||||
value: unknown,
|
||||
label: string,
|
||||
): DatasetGroundMetrics => {
|
||||
const providerMetrics = record(value, label);
|
||||
const fraction = (key: string): number => {
|
||||
const result = number(providerMetrics[key], `${label}.${key}`);
|
||||
if (result > 1) {
|
||||
throw new DatasetGatewayContractError(`${label}.${key}: ожидалась доля`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
return {
|
||||
precision: fraction("precision"),
|
||||
recall: fraction("recall"),
|
||||
f1: fraction("f1"),
|
||||
groundIou: fraction("ground_iou"),
|
||||
accuracy: fraction("accuracy"),
|
||||
artificialGroundRecall: fraction("artificial_ground_recall"),
|
||||
naturalGroundRecall: fraction("natural_ground_recall"),
|
||||
obstacleNonGroundRecall: fraction("obstacle_non_ground_recall"),
|
||||
};
|
||||
};
|
||||
const provider = record(source.provider, "provider");
|
||||
const currentMetrics = parseMetrics(metrics.current, "metrics.current");
|
||||
const patchworkMetrics = parseMetrics(
|
||||
metrics.patchworkpp,
|
||||
"metrics.patchworkpp",
|
||||
);
|
||||
const providers = record(source.providers, "providers");
|
||||
const currentProvider = record(providers.current, "providers.current");
|
||||
const patchworkProvider = record(providers.patchworkpp, "providers.patchworkpp");
|
||||
if (
|
||||
provider.provider_id !== "missioncore-local-percentile-ground/v1"
|
||||
|| provider.ground_truth !== false
|
||||
currentProvider.provider_id !== "missioncore-local-percentile-ground/v1"
|
||||
|| currentProvider.ground_truth !== false
|
||||
|| !/^[a-f0-9]{64}$/.test(
|
||||
string(provider.implementation_sha256, "provider.implementation_sha256"),
|
||||
string(
|
||||
currentProvider.implementation_sha256,
|
||||
"providers.current.implementation_sha256",
|
||||
),
|
||||
)
|
||||
|| patchworkProvider.provider_id !== "patchworkpp/v1.4.1"
|
||||
|| patchworkProvider.source_tag !== "v1.4.1"
|
||||
|| patchworkProvider.source_commit
|
||||
!== "3e6903a1d5537a4cc2ace897b0bbb98a92d6014c"
|
||||
|| patchworkProvider.ground_truth !== false
|
||||
|| !/^[a-f0-9]{64}$/.test(
|
||||
string(
|
||||
patchworkProvider.binary_sha256,
|
||||
"providers.patchworkpp.binary_sha256",
|
||||
),
|
||||
)
|
||||
) {
|
||||
throw new DatasetGatewayContractError("Ground comparison provider несовместим");
|
||||
}
|
||||
const latency = record(source.latency_ms, "latency_ms");
|
||||
const inputProfile = record(source.input_profile, "input_profile");
|
||||
const sensorFrame = record(inputProfile.sensor_frame, "input_profile.sensor_frame");
|
||||
const height = record(inputProfile.height, "input_profile.height");
|
||||
const scope = record(inputProfile.scope, "input_profile.scope");
|
||||
const sensorHeightM = number(
|
||||
height.sensor_above_ground_m,
|
||||
"height.sensor_above_ground_m",
|
||||
);
|
||||
if (
|
||||
inputProfile.schema_version !== "missioncore.goose-patchwork-profile/v1"
|
||||
|| inputProfile.source_id !== "goose-3d/v2025-08-22"
|
||||
|| inputProfile.representation !== "native-scan"
|
||||
|| sensorFrame.frame_id !== "sensor/lidar/vls128_roof"
|
||||
|| sensorFrame.handedness !== "right"
|
||||
|| sensorFrame.x !== "forward"
|
||||
|| sensorFrame.y !== "left"
|
||||
|| sensorFrame.z !== "up"
|
||||
|| sensorFrame.one_revolution !== true
|
||||
|| height.base_link_above_ground_m !== 0.64
|
||||
|| height.lidar_above_base_link_m !== 1.6
|
||||
|| sensorHeightM !== 2.24
|
||||
|| height.evidence !== "published-dimensioned-schematic"
|
||||
|| scope.patchworkpp_eligible !== true
|
||||
|| scope.normalized_scan_produced !== false
|
||||
|| scope.complete_vehicle_transform_known !== false
|
||||
|| scope.deskew_claimed !== false
|
||||
) {
|
||||
throw new DatasetGatewayContractError("GOOSE Patchwork++ profile несовместим");
|
||||
}
|
||||
const patchworkAssignedFraction = number(
|
||||
source.patchwork_assigned_fraction,
|
||||
"patchwork_assigned_fraction",
|
||||
);
|
||||
if (patchworkAssignedFraction > 1) {
|
||||
throw new DatasetGatewayContractError(
|
||||
"patchwork_assigned_fraction: ожидалась доля",
|
||||
);
|
||||
}
|
||||
const safety = record(source.safety, "safety");
|
||||
if (
|
||||
safety.qualification_only !== true
|
||||
@@ -555,20 +667,27 @@ export function parseDatasetGroundComparison(
|
||||
frameId: string(source.frame_id, "frame_id", true),
|
||||
pointCount,
|
||||
currentGround,
|
||||
patchworkGround,
|
||||
patchworkAssigned,
|
||||
groundTruthGround,
|
||||
evaluated,
|
||||
disagreement,
|
||||
currentDisagreement,
|
||||
patchworkDisagreement,
|
||||
metrics: {
|
||||
precision: fraction("precision"),
|
||||
recall: fraction("recall"),
|
||||
f1: fraction("f1"),
|
||||
groundIou: fraction("ground_iou"),
|
||||
accuracy: fraction("accuracy"),
|
||||
artificialGroundRecall: fraction("artificial_ground_recall"),
|
||||
naturalGroundRecall: fraction("natural_ground_recall"),
|
||||
obstacleNonGroundRecall: fraction("obstacle_non_ground_recall"),
|
||||
current: currentMetrics,
|
||||
patchworkpp: patchworkMetrics,
|
||||
},
|
||||
latencyMs: {
|
||||
current: number(latency.current, "latency_ms.current"),
|
||||
patchworkpp: number(latency.patchworkpp, "latency_ms.patchworkpp"),
|
||||
},
|
||||
patchworkAssignedFraction,
|
||||
inputProfile: {
|
||||
frameId: "sensor/lidar/vls128_roof",
|
||||
sensorHeightM,
|
||||
heightEvidence: "published-dimensioned-schematic",
|
||||
normalizedScanProduced: false,
|
||||
},
|
||||
latencyMs: number(source.latency_ms, "latency_ms"),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user