feat: qualify complete RELLIS ground dataset

This commit is contained in:
DCCONSTRUCTIONS
2026-07-25 21:12:37 +03:00
parent 054feec0d2
commit f2f044080f
17 changed files with 2349 additions and 35 deletions
@@ -12,7 +12,8 @@ export type DatasetSourceAdmissionStatus =
| "verifying"
| "verified"
| "frame-ready"
| "smoke-ready";
| "smoke-ready"
| "dataset-ready";
export interface DatasetSource {
sourceId: string;
@@ -308,6 +309,7 @@ export function parseDatasetGatewayCatalog(
&& admissionStatus !== "verified"
&& admissionStatus !== "frame-ready"
&& admissionStatus !== "smoke-ready"
&& admissionStatus !== "dataset-ready"
) {
throw new DatasetGatewayContractError("source admission status неизвестен");
}
@@ -42,7 +42,10 @@ export interface GroundQualification {
checks: QualificationCheck[];
worstFrames: QualificationWorstFrame[];
decision: {
status: "shadow-candidate" | "qualification-rejected";
status:
| "shadow-candidate"
| "cross-dataset-qualified"
| "qualification-rejected";
passed: boolean;
promotedToNavigationOrSafety: false;
reason: string;
@@ -75,7 +78,7 @@ export interface GroundReviewFrameSummary {
frameId: string;
datasetSequenceId: string;
datasetFrameNumber: number;
sensorTimestampNs: string;
sensorTimestampNs: string | null;
sourcePointCount: number;
pointCount: number;
current: GroundReviewFrameMetrics;
@@ -264,7 +267,11 @@ export function decodeGroundQualification(payload: unknown): GroundQualification
);
const decision = record(source.decision, "decision");
const status = text(decision.status, "decision.status", 64);
if (status !== "shadow-candidate" && status !== "qualification-rejected") {
if (
status !== "shadow-candidate"
&& status !== "cross-dataset-qualified"
&& status !== "qualification-rejected"
) {
throw new GroundQualificationContractError("Решение квалификации неизвестно.");
}
if (decision.promoted_to_navigation_or_safety !== false) {
@@ -384,7 +391,11 @@ export function decodeGroundReview(payload: unknown): GroundReview {
throw new GroundQualificationContractError("Неизвестная схема покадрового просмотра.");
}
const frameCount = integer(source.frame_count, "frame_count", 1);
const frames = array(source.frames, "frames", 2_000).map(
const sourceId = text(source.source_id, "source_id");
if (sourceId !== "goose-3d/v2025-08-22" && sourceId !== "rellis-3d/v1.1") {
throw new GroundQualificationContractError("Источник review неизвестен.");
}
const frames = array(source.frames, "frames", 3_000).map(
(value, index): GroundReviewFrameSummary => {
const frame = record(value, `frames[${index}]`);
const sequence = integer(frame.sequence, `frames[${index}].sequence`);
@@ -392,7 +403,6 @@ export function decodeGroundReview(payload: unknown): GroundReview {
throw new GroundQualificationContractError("Кадры просмотра идут не по порядку.");
}
const frameId = id(frame.frame_id, `frames[${index}].frame_id`);
const frameIdentity = parseGooseFrameId(frameId);
const datasetSequenceId = id(
frame.dataset_sequence_id,
`frames[${index}].dataset_sequence_id`,
@@ -401,18 +411,30 @@ export function decodeGroundReview(payload: unknown): GroundReview {
frame.dataset_frame_number,
`frames[${index}].dataset_frame_number`,
);
const sensorTimestampNs = text(
frame.sensor_timestamp_ns,
`frames[${index}].sensor_timestamp_ns`,
20,
);
if (
datasetSequenceId !== frameIdentity.datasetSequenceId
|| datasetFrameNumber !== frameIdentity.datasetFrameNumber
|| sensorTimestampNs !== frameIdentity.sensorTimestampNs
let sensorTimestampNs: string | null = null;
if (sourceId === "goose-3d/v2025-08-22") {
const frameIdentity = parseGooseFrameId(frameId);
sensorTimestampNs = text(
frame.sensor_timestamp_ns,
`frames[${index}].sensor_timestamp_ns`,
20,
);
if (
datasetSequenceId !== frameIdentity.datasetSequenceId
|| datasetFrameNumber !== frameIdentity.datasetFrameNumber
|| sensorTimestampNs !== frameIdentity.sensorTimestampNs
) {
throw new GroundQualificationContractError(
`frames[${index}] противоречит идентичности GOOSE-кадра.`,
);
}
} else if (
frame.sensor_timestamp_ns !== null
|| !/^rellis-0000[0-4]-[0-9]{6}$/.test(frameId)
|| frameId !== `rellis-${datasetSequenceId}-${String(datasetFrameNumber).padStart(6, "0")}`
) {
throw new GroundQualificationContractError(
`frames[${index}] противоречит идентичности GOOSE-кадра.`,
`frames[${index}] противоречит идентичности RELLIS-кадра.`,
);
}
return {
@@ -457,7 +479,7 @@ export function decodeGroundReview(payload: unknown): GroundReview {
return {
runId: id(source.run_id, "run_id"),
identitySha256,
sourceId: text(source.source_id, "source_id"),
sourceId,
frameCount,
previewPoints: integer(source.preview_points, "preview_points", 1),
frames,