feat(ui): add M4.8S replay with LiDAR overlay

This commit is contained in:
DCCONSTRUCTIONS
2026-08-25 16:44:52 +03:00
parent 3679e43fe3
commit 15be698097
17 changed files with 1448 additions and 31 deletions
@@ -42,10 +42,12 @@ import {
fetchM48LifecycleResult,
} from "./m48ObjectCentricQuality";
import { fetchM48SmallStaticRegression } from "./m48SmallStaticRegression";
import { fetchM48SFixedClassDetectorResult } from "./m48sFixedClassDetector";
export type AdvancedLaboratoryWorkId =
| "m48-object-centric-quality"
| "m48-small-static-passage-regression"
| "m48s-fixed-class-detector"
| "m47-reference-graph-shadow"
| "m4-replay-threat"
| "l3-pointpillars-visual-audit"
@@ -90,6 +92,7 @@ export interface AdvancedLaboratoryIndexItem {
const WORK_IDS: readonly AdvancedLaboratoryWorkId[] = [
"m48-object-centric-quality",
"m48-small-static-passage-regression",
"m48s-fixed-class-detector",
"m47-reference-graph-shadow",
"m4-replay-threat",
"l3-pointpillars-visual-audit",
@@ -129,6 +132,7 @@ const WORK_IDS: readonly AdvancedLaboratoryWorkId[] = [
const RESULT_PREFIX: Readonly<Record<AdvancedLaboratoryWorkId, string>> = {
"m48-object-centric-quality": "m48-object-quality-(?:pack|result)",
"m48-small-static-passage-regression": "m48-small-static-passage-regression",
"m48s-fixed-class-detector": "m48s-fixed-class-detector-lab",
"m47-reference-graph-shadow": "m47-reference-graph-lab",
"m4-replay-threat": "m4-threat-replay",
"l3-pointpillars-visual-audit": "l3-pointpillars-visual-audit",
@@ -176,6 +180,7 @@ export function emptyAdvancedLaboratoryResults(): AdvancedLaboratoryResults {
m47Graph: null,
m48: null,
m48SmallStatic: null,
m48s: null,
m4Threat: null,
l3: null,
l31: null,
@@ -302,6 +307,7 @@ export function advancedLaboratoryResultAvailable(
): boolean {
return workId === "m48-object-centric-quality" ? results.m48 !== null
: workId === "m48-small-static-passage-regression" ? results.m48SmallStatic !== null
: workId === "m48s-fixed-class-detector" ? results.m48s !== null
: workId === "m47-reference-graph-shadow" ? results.m47Graph !== null
: workId === "m4-replay-threat" ? results.m4Threat !== null
: workId === "l3-pointpillars-visual-audit" ? results.l3 !== null
@@ -357,6 +363,9 @@ export async function fetchAdvancedLaboratoryResult(
} else if (workId === "m48-small-static-passage-regression") {
if (!resultId) throw new AdvancedLaboratoryContractError("M4.8R1 regression identity не выбрана.");
results.m48SmallStatic = await fetchM48SmallStaticRegression(resultId, { fetcher, signal });
} else if (workId === "m48s-fixed-class-detector") {
if (!resultId) throw new AdvancedLaboratoryContractError("M4.8S LAB identity не выбрана.");
results.m48s = await fetchM48SFixedClassDetectorResult(resultId, { fetcher, signal });
} else if (workId === "m47-reference-graph-shadow") {
if (!resultId) {
throw new AdvancedLaboratoryContractError("M4.7 LAB identity не выбрана.");
@@ -36,11 +36,13 @@ import type { M4ThreatReplayResult } from "./m4ReplayThreat";
import type { M47ReferenceGraphLabResult } from "./m47ReferenceGraph";
import type { M48AdvancedResult } from "./m48ObjectCentricQuality";
import type { M48SmallStaticRegressionResult } from "./m48SmallStaticRegression";
import type { M48SFixedClassDetectorResult } from "./m48sFixedClassDetector";
export interface AdvancedLaboratoryResults {
m47Graph: M47ReferenceGraphLabResult | null;
m48: M48AdvancedResult | null;
m48SmallStatic: M48SmallStaticRegressionResult | null;
m48s: M48SFixedClassDetectorResult | null;
m4Threat: M4ThreatReplayResult | null;
l3: L3PointPillarsVisualAuditResult | null;
l31: L31PointPillarsRavnovesResult | null;
@@ -967,7 +967,7 @@ export async function fetchAdvancedLaboratoryResults({
const e39 = settledCatalogValue(settled[7]);
const e40 = settledCatalogValue(settled[8]);
return {
m47Graph: null, m48: null, m48SmallStatic: null, m4Threat: null,
m47Graph: null, m48: null, m48SmallStatic: null, m48s: null, m4Threat: null,
l3: null, l31: null,
l32: null,
l33: null,
@@ -0,0 +1,569 @@
import type { LaboratoryFetch } from "./advancedResults";
const RESULT_ID = /^m48s-fixed-class-detector-lab-[a-f0-9]{64}$/;
const FRAME_ID = /^[0-9]{6}$/;
const MODES = ["source", "yolox", "dfine", "rf-detr"] as const;
const DETECTOR_MODES = ["yolox", "dfine", "rf-detr"] as const;
const RESULT_STATUSES = [
"detector-load-passed-reference-graph-shadow-only",
"complete-reference-graph-shadow-passed-production-not-authorized",
] as const;
export type M48SDetectorMode = typeof MODES[number];
export type M48SDetectorModel = typeof DETECTOR_MODES[number];
export interface M48SAuthority {
actuationAllowed: false;
candidateAccepted: false;
commandsEnabled: false;
groundTruth: false;
navigationOrSafetyAccepted: false;
}
export interface M48SMethodComponent {
kind: "source" | "tool" | "model" | "algorithm" | "runtime";
name: string;
version: string;
role: string;
identitySha256: string;
}
export interface M48SMethod {
completeness: "complete";
executionClass: "ai-inference";
pipelineId: string;
components: readonly M48SMethodComponent[];
}
export interface M48SDetectorCandidate {
id: M48SDetectorModel;
label: string;
providerId: string;
capacityFps: number;
p95Ms: number;
frame253DogDetected: boolean;
frame253DogScore: number | null;
selected: boolean;
}
export interface M48SFrameDescriptor {
frameId: string;
sourceSequence: number;
counts: Readonly<Record<M48SDetectorModel, number>>;
}
export interface M48SIntegratedWorldState {
durationSeconds: number;
sourceFramesAdmitted: number;
deliveredWorldStates: number;
supersededFrames: number;
effectiveWorldStateFps: number;
worldStateCompletionAgeP95Ms: number;
worldStateCompletionAgeP99Ms: number;
worldStateCompletionAgeMaximumMs: number;
localObstacleMapOutputAgeP95Ms: number;
queueHighWatermarks: Readonly<Record<"detector" | "geometry" | "temporal" | "rolling" | "threat", number>>;
queueCapacity: number;
gpuUtilizationMeanPercent: number;
gpuUtilizationMaximumPercent: number;
gpuMemoryMaximumMib: number;
gpuPowerMaximumW: number;
gpuTemperatureMaximumC: number;
uniqueComponentCount: number;
multiFrameComponentCount: number;
maximumComponentPublications: number;
duplicateComponentIdsWithinFrame: number;
advisoryFamilyCounts: Readonly<Record<"animal" | "generic-obstacle" | "light-road-user" | "person" | "vehicle", number>>;
semanticHintCounts: Readonly<Record<string, number>>;
motionCounts: Readonly<Record<"moving" | "stationary" | "unknown", number>>;
additionalInferencePasses: number;
failures: number;
}
export interface M48SFixedClassDetectorResult {
resultId: string;
createdAtUtc: string;
status: typeof RESULT_STATUSES[number];
boundedQuestionAccepted: true;
groundTruth: false;
source: {
sourceSessionId: "RAVNOVES00";
cameraSourceId: "sensor.camera.right";
cameraRaster: readonly [800, 600];
evidenceFrameCount: number;
};
configuration: {
comparisonThreshold: 0.5;
displayModes: readonly M48SDetectorMode[];
singleInferencePerFrame: true;
geometryOwnsStaticOccupancy: true;
unknownStationaryResponse: "route-around";
unknownMovingResponse: "conservative-risk";
};
method: M48SMethod;
metrics: {
candidates: readonly M48SDetectorCandidate[];
detectorLoad: {
durationSeconds: number;
sourceFramesConsumed: number;
sourceFrameReplacements: number;
effectiveConsumedFps: number;
endToEndP95Ms: number;
completionAgeP95Ms: number;
gpuUtilizationMeanPercent: number;
gpuUtilizationMaximumPercent: number;
gpuMemoryMaximumMib: number;
queueMaximumDepth: number;
queueCapacity: number;
failures: number;
};
integratedWorldState: M48SIntegratedWorldState | null;
};
decision: {
selectedCandidate: "rf-detr";
readyForReferenceGraphShadow: true;
integratedWorldStateGateEvaluated: boolean;
integratedWorldStateGatePassed: boolean;
detectorReplacementAuthorized: false;
productionAccepted: false;
};
limitations: readonly string[];
authority: M48SAuthority;
frames: readonly M48SFrameDescriptor[];
}
export interface M48SDetection {
label: string;
score: number;
bboxXyxy: readonly [number, number, number, number];
}
export interface M48SDetectorFrame {
resultId: string;
frameId: string;
sourceSequence: number;
cameraUrl: string;
imageWidth: 800;
imageHeight: 600;
comparisonThreshold: 0.5;
detections: Readonly<Record<M48SDetectorModel, readonly M48SDetection[]>>;
groundTruthAvailable: false;
authority: M48SAuthority;
}
export class M48SFixedClassDetectorContractError extends Error {}
function objectValue(value: unknown, label: string): Record<string, unknown> {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new M48SFixedClassDetectorContractError(`${label}: ожидался объект.`);
}
return value as Record<string, unknown>;
}
function arrayValue(value: unknown, label: string): readonly unknown[] {
if (!Array.isArray(value)) {
throw new M48SFixedClassDetectorContractError(`${label}: ожидался список.`);
}
return value;
}
function exact(value: unknown, expected: string | number | boolean, label: string): void {
if (value !== expected) {
throw new M48SFixedClassDetectorContractError(`${label}: нарушен контракт.`);
}
}
function textValue(value: unknown, label: string): string {
if (typeof value !== "string" || !value.trim()) {
throw new M48SFixedClassDetectorContractError(`${label}: ожидалась строка.`);
}
return value;
}
function numberValue(value: unknown, label: string): number {
if (typeof value !== "number" || !Number.isFinite(value)) {
throw new M48SFixedClassDetectorContractError(`${label}: ожидалось число.`);
}
return value;
}
function integerValue(value: unknown, label: string): number {
const result = numberValue(value, label);
if (!Number.isInteger(result) || result < 0) {
throw new M48SFixedClassDetectorContractError(`${label}: ожидалось целое число.`);
}
return result;
}
function booleanValue(value: unknown, label: string): boolean {
if (typeof value !== "boolean") {
throw new M48SFixedClassDetectorContractError(`${label}: ожидался флаг.`);
}
return value;
}
function enumValue<T extends string>(value: unknown, allowed: readonly T[], label: string): T {
if (typeof value !== "string" || !allowed.includes(value as T)) {
throw new M48SFixedClassDetectorContractError(`${label}: неизвестное значение.`);
}
return value as T;
}
function authorityValue(value: unknown, label: string): M48SAuthority {
const authority = objectValue(value, label);
exact(authority.actuation_allowed, false, `${label}.actuation_allowed`);
exact(authority.candidate_accepted, false, `${label}.candidate_accepted`);
exact(authority.commands_enabled, false, `${label}.commands_enabled`);
exact(authority.ground_truth, false, `${label}.ground_truth`);
exact(
authority.navigation_or_safety_accepted,
false,
`${label}.navigation_or_safety_accepted`,
);
return {
actuationAllowed: false,
candidateAccepted: false,
commandsEnabled: false,
groundTruth: false,
navigationOrSafetyAccepted: false,
};
}
function methodValue(value: unknown): M48SMethod {
const method = objectValue(value, "M4.8S.method");
exact(method.schema_version, "missioncore.laboratory-method/v1", "M4.8S.method.schema_version");
exact(method.completeness, "complete", "M4.8S.method.completeness");
exact(method.execution_class, "ai-inference", "M4.8S.method.execution_class");
return {
completeness: "complete",
executionClass: "ai-inference",
pipelineId: textValue(method.pipeline_id, "M4.8S.method.pipeline_id"),
components: arrayValue(method.components, "M4.8S.method.components").map((value, index) => {
const component = objectValue(value, `M4.8S.method.components[${index}]`);
return {
kind: enumValue(
component.kind,
["source", "tool", "model", "algorithm", "runtime"] as const,
`M4.8S.method.components[${index}].kind`,
),
name: textValue(component.name, `M4.8S.method.components[${index}].name`),
version: textValue(component.version, `M4.8S.method.components[${index}].version`),
role: textValue(component.role, `M4.8S.method.components[${index}].role`),
identitySha256: textValue(
component.identity_sha256,
`M4.8S.method.components[${index}].identity_sha256`,
),
};
}),
};
}
function countsValue(value: unknown, label: string): Readonly<Record<M48SDetectorModel, number>> {
const counts = objectValue(value, label);
return {
yolox: integerValue(counts.yolox, `${label}.yolox`),
dfine: integerValue(counts.dfine, `${label}.dfine`),
"rf-detr": integerValue(counts["rf-detr"], `${label}.rf-detr`),
};
}
function descriptorValue(value: unknown): M48SFrameDescriptor {
const frame = objectValue(value, "M4.8S.frame");
const frameId = textValue(frame.frame_id, "M4.8S.frame.frame_id");
if (!FRAME_ID.test(frameId)) {
throw new M48SFixedClassDetectorContractError("M4.8S.frame.frame_id: нарушена идентичность.");
}
return {
frameId,
sourceSequence: integerValue(frame.source_sequence, "M4.8S.frame.source_sequence"),
counts: countsValue(frame.counts, "M4.8S.frame.counts"),
};
}
function candidateValue(value: unknown): M48SDetectorCandidate {
const candidate = objectValue(value, "M4.8S.candidate");
const score = candidate.frame_253_dog_score;
if (score !== null && (typeof score !== "number" || !Number.isFinite(score))) {
throw new M48SFixedClassDetectorContractError("M4.8S.candidate.frame_253_dog_score: нарушен контракт.");
}
return {
id: enumValue(candidate.id, DETECTOR_MODES, "M4.8S.candidate.id"),
label: textValue(candidate.label, "M4.8S.candidate.label"),
providerId: textValue(candidate.provider_id, "M4.8S.candidate.provider_id"),
capacityFps: numberValue(candidate.capacity_fps, "M4.8S.candidate.capacity_fps"),
p95Ms: numberValue(candidate.p95_ms, "M4.8S.candidate.p95_ms"),
frame253DogDetected: booleanValue(
candidate.frame_253_dog_detected,
"M4.8S.candidate.frame_253_dog_detected",
),
frame253DogScore: score,
selected: booleanValue(candidate.selected, "M4.8S.candidate.selected"),
};
}
function integerRecordValue(value: unknown, label: string): Readonly<Record<string, number>> {
const record = objectValue(value, label);
return Object.fromEntries(
Object.entries(record).map(([key, item]) => [key, integerValue(item, `${label}.${key}`)]),
);
}
function integratedWorldStateValue(value: unknown): M48SIntegratedWorldState {
const integrated = objectValue(value, "M4.8S.metrics.integrated_world_state");
const queues = integerRecordValue(
integrated.queue_high_watermarks,
"M4.8S.integrated.queue_high_watermarks",
);
const advisory = integerRecordValue(
integrated.advisory_family_counts,
"M4.8S.integrated.advisory_family_counts",
);
const motion = integerRecordValue(
integrated.motion_counts,
"M4.8S.integrated.motion_counts",
);
for (const key of ["detector", "geometry", "temporal", "rolling", "threat"] as const) {
if (!(key in queues)) {
throw new M48SFixedClassDetectorContractError(`M4.8S.integrated.queue_high_watermarks.${key}: отсутствует.`);
}
}
for (const key of ["animal", "generic-obstacle", "light-road-user", "person", "vehicle"] as const) {
if (!(key in advisory)) {
throw new M48SFixedClassDetectorContractError(`M4.8S.integrated.advisory_family_counts.${key}: отсутствует.`);
}
}
for (const key of ["moving", "stationary", "unknown"] as const) {
if (!(key in motion)) {
throw new M48SFixedClassDetectorContractError(`M4.8S.integrated.motion_counts.${key}: отсутствует.`);
}
}
return {
durationSeconds: numberValue(integrated.duration_seconds, "M4.8S.integrated.duration_seconds"),
sourceFramesAdmitted: integerValue(integrated.source_frames_admitted, "M4.8S.integrated.source_frames_admitted"),
deliveredWorldStates: integerValue(integrated.delivered_world_states, "M4.8S.integrated.delivered_world_states"),
supersededFrames: integerValue(integrated.superseded_frames, "M4.8S.integrated.superseded_frames"),
effectiveWorldStateFps: numberValue(integrated.effective_world_state_fps, "M4.8S.integrated.effective_world_state_fps"),
worldStateCompletionAgeP95Ms: numberValue(integrated.world_state_completion_age_p95_ms, "M4.8S.integrated.world_state_completion_age_p95_ms"),
worldStateCompletionAgeP99Ms: numberValue(integrated.world_state_completion_age_p99_ms, "M4.8S.integrated.world_state_completion_age_p99_ms"),
worldStateCompletionAgeMaximumMs: numberValue(integrated.world_state_completion_age_maximum_ms, "M4.8S.integrated.world_state_completion_age_maximum_ms"),
localObstacleMapOutputAgeP95Ms: numberValue(integrated.local_obstacle_map_output_age_p95_ms, "M4.8S.integrated.local_obstacle_map_output_age_p95_ms"),
queueHighWatermarks: queues as M48SIntegratedWorldState["queueHighWatermarks"],
queueCapacity: integerValue(integrated.queue_capacity, "M4.8S.integrated.queue_capacity"),
gpuUtilizationMeanPercent: numberValue(integrated.gpu_utilization_mean_percent, "M4.8S.integrated.gpu_utilization_mean_percent"),
gpuUtilizationMaximumPercent: numberValue(integrated.gpu_utilization_maximum_percent, "M4.8S.integrated.gpu_utilization_maximum_percent"),
gpuMemoryMaximumMib: numberValue(integrated.gpu_memory_maximum_mib, "M4.8S.integrated.gpu_memory_maximum_mib"),
gpuPowerMaximumW: numberValue(integrated.gpu_power_maximum_w, "M4.8S.integrated.gpu_power_maximum_w"),
gpuTemperatureMaximumC: numberValue(integrated.gpu_temperature_maximum_c, "M4.8S.integrated.gpu_temperature_maximum_c"),
uniqueComponentCount: integerValue(integrated.unique_component_count, "M4.8S.integrated.unique_component_count"),
multiFrameComponentCount: integerValue(integrated.multi_frame_component_count, "M4.8S.integrated.multi_frame_component_count"),
maximumComponentPublications: integerValue(integrated.maximum_component_publications, "M4.8S.integrated.maximum_component_publications"),
duplicateComponentIdsWithinFrame: integerValue(integrated.duplicate_component_ids_within_frame, "M4.8S.integrated.duplicate_component_ids_within_frame"),
advisoryFamilyCounts: advisory as M48SIntegratedWorldState["advisoryFamilyCounts"],
semanticHintCounts: integerRecordValue(integrated.semantic_hint_counts, "M4.8S.integrated.semantic_hint_counts"),
motionCounts: motion as M48SIntegratedWorldState["motionCounts"],
additionalInferencePasses: integerValue(integrated.additional_inference_passes, "M4.8S.integrated.additional_inference_passes"),
failures: integerValue(integrated.failures, "M4.8S.integrated.failures"),
};
}
function parseResult(value: unknown, resultId: string): M48SFixedClassDetectorResult {
const payload = objectValue(value, "M4.8S");
exact(
payload.schema_version,
"missioncore.m48s-fixed-class-detector-result-view/v1",
"M4.8S.schema_version",
);
exact(payload.result_id, resultId, "M4.8S.result_id");
const status = enumValue(payload.status, RESULT_STATUSES, "M4.8S.status");
const integratedGate = status === "complete-reference-graph-shadow-passed-production-not-authorized";
exact(payload.bounded_question_accepted, true, "M4.8S.bounded_question_accepted");
exact(payload.ground_truth, false, "M4.8S.ground_truth");
exact(payload.access, "read-only", "M4.8S.access");
const source = objectValue(payload.source, "M4.8S.source");
const configuration = objectValue(payload.configuration, "M4.8S.configuration");
const metrics = objectValue(payload.metrics, "M4.8S.metrics");
const load = objectValue(metrics.detector_load, "M4.8S.metrics.detector_load");
const decision = objectValue(payload.decision, "M4.8S.decision");
const cameraRaster = arrayValue(source.camera_raster, "M4.8S.source.camera_raster");
if (cameraRaster.length !== 2) {
throw new M48SFixedClassDetectorContractError("M4.8S.source.camera_raster: нарушен размер.");
}
exact(cameraRaster[0], 800, "M4.8S.source.camera_raster[0]");
exact(cameraRaster[1], 600, "M4.8S.source.camera_raster[1]");
const displayModes = arrayValue(
configuration.display_modes,
"M4.8S.configuration.display_modes",
).map((mode, index) => enumValue(mode, MODES, `M4.8S.configuration.display_modes[${index}]`));
if (displayModes.join(",") !== MODES.join(",")) {
throw new M48SFixedClassDetectorContractError("M4.8S.configuration.display_modes: изменён контракт.");
}
exact(source.source_session_id, "RAVNOVES00", "M4.8S.source.source_session_id");
exact(source.camera_source_id, "sensor.camera.right", "M4.8S.source.camera_source_id");
exact(configuration.comparison_threshold, 0.5, "M4.8S.configuration.comparison_threshold");
exact(configuration.single_inference_per_frame, true, "M4.8S.configuration.single_inference_per_frame");
exact(configuration.geometry_owns_static_occupancy, true, "M4.8S.configuration.geometry_owns_static_occupancy");
exact(configuration.unknown_stationary_response, "route-around", "M4.8S.configuration.unknown_stationary_response");
exact(configuration.unknown_moving_response, "conservative-risk", "M4.8S.configuration.unknown_moving_response");
exact(decision.selected_candidate, "rf-detr", "M4.8S.decision.selected_candidate");
exact(decision.ready_for_reference_graph_shadow, true, "M4.8S.decision.ready_for_reference_graph_shadow");
exact(decision.integrated_world_state_gate_evaluated, integratedGate, "M4.8S.decision.integrated_world_state_gate_evaluated");
if (integratedGate) {
exact(decision.integrated_world_state_gate_passed, true, "M4.8S.decision.integrated_world_state_gate_passed");
exact(decision.detector_replacement_authorized, false, "M4.8S.decision.detector_replacement_authorized");
}
exact(decision.production_accepted, false, "M4.8S.decision.production_accepted");
const frames = arrayValue(payload.frames, "M4.8S.frames").map(descriptorValue);
const evidenceFrameCount = integerValue(source.evidence_frame_count, "M4.8S.source.evidence_frame_count");
if (frames.length !== evidenceFrameCount || new Set(frames.map((frame) => frame.frameId)).size !== frames.length) {
throw new M48SFixedClassDetectorContractError("M4.8S.frames: каталог изменён.");
}
return {
resultId,
createdAtUtc: textValue(payload.created_at_utc, "M4.8S.created_at_utc"),
status,
boundedQuestionAccepted: true,
groundTruth: false,
source: {
sourceSessionId: "RAVNOVES00",
cameraSourceId: "sensor.camera.right",
cameraRaster: [800, 600],
evidenceFrameCount,
},
configuration: {
comparisonThreshold: 0.5,
displayModes,
singleInferencePerFrame: true,
geometryOwnsStaticOccupancy: true,
unknownStationaryResponse: "route-around",
unknownMovingResponse: "conservative-risk",
},
method: methodValue(payload.method),
metrics: {
candidates: arrayValue(metrics.candidates, "M4.8S.metrics.candidates").map(candidateValue),
detectorLoad: {
durationSeconds: numberValue(load.duration_seconds, "M4.8S.load.duration_seconds"),
sourceFramesConsumed: integerValue(load.source_frames_consumed, "M4.8S.load.source_frames_consumed"),
sourceFrameReplacements: integerValue(load.source_frame_replacements, "M4.8S.load.source_frame_replacements"),
effectiveConsumedFps: numberValue(load.effective_consumed_fps, "M4.8S.load.effective_consumed_fps"),
endToEndP95Ms: numberValue(load.end_to_end_p95_ms, "M4.8S.load.end_to_end_p95_ms"),
completionAgeP95Ms: numberValue(load.completion_age_p95_ms, "M4.8S.load.completion_age_p95_ms"),
gpuUtilizationMeanPercent: numberValue(load.gpu_utilization_mean_percent, "M4.8S.load.gpu_utilization_mean_percent"),
gpuUtilizationMaximumPercent: numberValue(load.gpu_utilization_maximum_percent, "M4.8S.load.gpu_utilization_maximum_percent"),
gpuMemoryMaximumMib: numberValue(load.gpu_memory_maximum_mib, "M4.8S.load.gpu_memory_maximum_mib"),
queueMaximumDepth: integerValue(load.queue_maximum_depth, "M4.8S.load.queue_maximum_depth"),
queueCapacity: integerValue(load.queue_capacity, "M4.8S.load.queue_capacity"),
failures: integerValue(load.failures, "M4.8S.load.failures"),
},
integratedWorldState: integratedGate
? integratedWorldStateValue(metrics.integrated_world_state)
: null,
},
decision: {
selectedCandidate: "rf-detr",
readyForReferenceGraphShadow: true,
integratedWorldStateGateEvaluated: integratedGate,
integratedWorldStateGatePassed: integratedGate,
detectorReplacementAuthorized: false,
productionAccepted: false,
},
limitations: arrayValue(payload.limitations, "M4.8S.limitations").map((item, index) => textValue(item, `M4.8S.limitations[${index}]`)),
authority: authorityValue(payload.authority, "M4.8S.authority"),
frames,
};
}
function detectionValue(value: unknown, label: string): M48SDetection {
const detection = objectValue(value, label);
const bbox = arrayValue(detection.bbox_xyxy, `${label}.bbox_xyxy`).map((item, index) => numberValue(item, `${label}.bbox_xyxy[${index}]`));
if (
bbox.length !== 4
|| bbox[0]! < 0
|| bbox[1]! < 0
|| bbox[2]! > 800
|| bbox[3]! > 600
|| bbox[0]! >= bbox[2]!
|| bbox[1]! >= bbox[3]!
) {
throw new M48SFixedClassDetectorContractError(`${label}.bbox_xyxy: рамка недопустима.`);
}
const score = numberValue(detection.score, `${label}.score`);
if (score < 0.5 || score > 1) {
throw new M48SFixedClassDetectorContractError(`${label}.score: нарушен порог.`);
}
return {
label: textValue(detection.label, `${label}.label`),
score,
bboxXyxy: bbox as unknown as readonly [number, number, number, number],
};
}
function parseFrame(value: unknown, resultId: string, frameId: string): M48SDetectorFrame {
const payload = objectValue(value, "M4.8S frame");
exact(payload.schema_version, "missioncore.m48s-fixed-class-detector-frame/v1", "M4.8S frame.schema_version");
exact(payload.result_id, resultId, "M4.8S frame.result_id");
exact(payload.frame_id, frameId, "M4.8S frame.frame_id");
exact(payload.comparison_threshold, 0.5, "M4.8S frame.comparison_threshold");
exact(payload.ground_truth_available, false, "M4.8S frame.ground_truth_available");
exact(payload.access, "read-only", "M4.8S frame.access");
const camera = objectValue(payload.camera, "M4.8S frame.camera");
exact(camera.media_type, "image/jpeg", "M4.8S frame.camera.media_type");
exact(camera.width, 800, "M4.8S frame.camera.width");
exact(camera.height, 600, "M4.8S frame.camera.height");
exact(camera.exact_source_frame, true, "M4.8S frame.camera.exact_source_frame");
const detections = objectValue(payload.detections, "M4.8S frame.detections");
const parseModel = (model: M48SDetectorModel): readonly M48SDetection[] => arrayValue(
detections[model],
`M4.8S frame.detections.${model}`,
).map((item, index) => detectionValue(item, `M4.8S frame.detections.${model}[${index}]`));
return {
resultId,
frameId,
sourceSequence: integerValue(payload.source_sequence, "M4.8S frame.source_sequence"),
cameraUrl: `/api/v1/laboratory/m48s/fixed-class-detector/${encodeURIComponent(resultId)}/frames/${encodeURIComponent(frameId)}/camera`,
imageWidth: 800,
imageHeight: 600,
comparisonThreshold: 0.5,
detections: {
yolox: parseModel("yolox"),
dfine: parseModel("dfine"),
"rf-detr": parseModel("rf-detr"),
},
groundTruthAvailable: false,
authority: authorityValue(payload.authority, "M4.8S frame.authority"),
};
}
export async function fetchM48SFixedClassDetectorResult(
resultId: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<M48SFixedClassDetectorResult> {
if (!RESULT_ID.test(resultId)) {
throw new M48SFixedClassDetectorContractError("M4.8S result identity недопустима.");
}
const response = await fetcher(
`/api/v1/laboratory/m48s/fixed-class-detector/${encodeURIComponent(resultId)}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new M48SFixedClassDetectorContractError(`M4.8S недоступен: HTTP ${response.status}.`);
}
return parseResult(await response.json(), resultId);
}
export async function fetchM48SFixedClassDetectorFrame(
resultId: string,
frameId: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
): Promise<M48SDetectorFrame> {
if (!RESULT_ID.test(resultId) || !FRAME_ID.test(frameId)) {
throw new M48SFixedClassDetectorContractError("M4.8S frame identity недопустима.");
}
const response = await fetcher(
`/api/v1/laboratory/m48s/fixed-class-detector/${encodeURIComponent(resultId)}/frames/${encodeURIComponent(frameId)}`,
{ method: "GET", headers: { Accept: "application/json" }, signal },
);
if (!response.ok) {
throw new M48SFixedClassDetectorContractError(`M4.8S frame недоступен: HTTP ${response.status}.`);
}
return parseFrame(await response.json(), resultId, frameId);
}
@@ -133,6 +133,8 @@ export interface M4ThreatTimelineFrame {
sessionSeconds: number;
sourceAvailable: boolean;
spatialAvailable: boolean;
worldStateAvailable: boolean;
terminalOutcome: "delivered" | "superseded";
bodyFrame: {
originMapXyzM: M4Point3;
basisMapFromBody: M4Matrix3;
@@ -141,6 +143,11 @@ export interface M4ThreatTimelineFrame {
pointCloudSourceCount: number;
pointCloudSampleCount: number;
pointCloudLayer: "current-increment";
cameraProjectedPointsXyd: readonly (readonly [number, number, number])[];
cameraProjectedSourceCount: number;
cameraProjectedPointCount: number;
cameraProjectedSampleCount: number;
cameraProjection: "factory-kb4-exact" | null;
rollingMapComponentCount: number;
metricObstacles: readonly M4ThreatMetricVisual[];
cameraProposals: readonly M4ThreatCameraProposal[];
@@ -163,6 +170,11 @@ export interface M4ThreatTimeline {
pointSampleLimit: number;
maximumSourcePointsPerFrame: number;
pointDelivery: "exact-current-increment";
cameraPointDelivery: "factory-kb4-projected-current-increment" | null;
cameraPointSampleLimit: number;
worldStateDelivery: "source-paced-latest-wins" | null;
worldStateFrameCount: number;
supersededFrameCount: number;
sourceRepresentationId: "registered-map-increment-v1";
localSurfaceVisualization: {
derivation: "bounded-registered-increment-accumulation";
@@ -186,6 +198,7 @@ export interface M4ThreatTimelineChunk {
}
type LaboratoryFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
export const M4_THREAT_TIMELINE_ENDPOINT_ROOT = "/api/v1/laboratory/m4-threat/results";
class M4ThreatContractError extends Error {}
const object = (value: unknown, label: string): Record<string, unknown> => {
if (!value || typeof value !== "object" || Array.isArray(value)) {
@@ -553,10 +566,18 @@ export async function fetchM4ThreatVisual(
export async function fetchM4ThreatTimeline(
result: string,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
{
fetcher = fetch,
signal,
endpointRoot = M4_THREAT_TIMELINE_ENDPOINT_ROOT,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
endpointRoot?: string;
} = {},
): Promise<M4ThreatTimeline> {
const response = await fetcher(
`/api/v1/laboratory/m4-threat/results/${result}/timeline`,
`${endpointRoot}/${result}/timeline`,
{ headers: { Accept: "application/json" }, signal },
);
if (!response.ok) throw new M4ThreatContractError(`M4.6 timeline: HTTP ${response.status}.`);
@@ -626,6 +647,29 @@ export async function fetchM4ThreatTimeline(
"exact-current-increment",
"M4.6 point delivery",
),
cameraPointDelivery: payload.camera_point_delivery === undefined
? null
: exact(
payload.camera_point_delivery,
"factory-kb4-projected-current-increment",
"M4.6 camera point delivery",
),
cameraPointSampleLimit: payload.camera_point_sample_limit === undefined
? 0
: integer(payload.camera_point_sample_limit, "M4.6 camera point limit"),
worldStateDelivery: payload.world_state_delivery === undefined
? null
: exact(
payload.world_state_delivery,
"source-paced-latest-wins",
"M4.6 world-state delivery",
),
worldStateFrameCount: payload.world_state_frame_count === undefined
? frameCount
: integer(payload.world_state_frame_count, "M4.6 world-state frames"),
supersededFrameCount: payload.superseded_frame_count === undefined
? 0
: integer(payload.superseded_frame_count, "M4.6 superseded frames"),
sourceRepresentationId: "registered-map-increment-v1",
localSurfaceVisualization: {
derivation: exact(
@@ -668,14 +712,22 @@ export async function fetchM4ThreatTimelineChunk(
result: string,
startSequence: number,
frameCount: number,
{ fetcher = fetch, signal }: { fetcher?: LaboratoryFetch; signal?: AbortSignal } = {},
{
fetcher = fetch,
signal,
endpointRoot = M4_THREAT_TIMELINE_ENDPOINT_ROOT,
}: {
fetcher?: LaboratoryFetch;
signal?: AbortSignal;
endpointRoot?: string;
} = {},
): Promise<M4ThreatTimelineChunk> {
const params = new URLSearchParams({
start: String(startSequence),
count: String(frameCount),
});
const response = await fetcher(
`/api/v1/laboratory/m4-threat/results/${result}/timeline/chunk?${params}`,
`${endpointRoot}/${result}/timeline/chunk?${params}`,
{ headers: { Accept: "application/json" }, signal },
);
if (!response.ok) throw new M4ThreatContractError(`M4.6 timeline chunk: HTTP ${response.status}.`);
@@ -692,7 +744,7 @@ export async function fetchM4ThreatTimelineChunk(
throw new M4ThreatContractError("M4.6 timeline chunk start: нарушен контракт.");
}
const frames = array(payload.frames, "M4.6 timeline frames").map((raw, offset) =>
parseTimelineFrame(raw, result, parsedStart + offset));
parseTimelineFrame(raw, result, parsedStart + offset, endpointRoot));
const parsedCount = integer(payload.frame_count, "M4.6 timeline chunk count");
if (parsedCount !== frames.length || parsedCount > frameCount) {
throw new M4ThreatContractError("M4.6 timeline chunk count: нарушен контракт.");
@@ -712,6 +764,7 @@ function parseTimelineFrame(
value: unknown,
result: string,
expectedSequence: number,
endpointRoot: string,
): M4ThreatTimelineFrame {
const item = object(value, "M4.6 timeline frame");
exact(
@@ -742,7 +795,7 @@ function parseTimelineFrame(
throw new M4ThreatContractError("M4.6 timeline body basis: нарушен размер.");
}
const cameraUrl = text(item.camera_url, "M4.6 timeline camera URL");
if (!cameraUrl.includes(`/results/${result}/timeline/frames/${sequence}/camera`)) {
if (!cameraUrl.includes(`${endpointRoot}/${result}/timeline/frames/${sequence}/camera`)) {
throw new M4ThreatContractError("M4.6 timeline camera URL: нарушена идентичность.");
}
return {
@@ -752,6 +805,16 @@ function parseTimelineFrame(
sessionSeconds: number(item.session_seconds, "M4.6 timeline time"),
sourceAvailable: typeof item.source_available === "boolean" && item.source_available,
spatialAvailable,
worldStateAvailable: item.world_state_available === undefined
? true
: typeof item.world_state_available === "boolean" && item.world_state_available,
terminalOutcome: item.terminal_outcome === undefined
? "delivered"
: exact(
item.terminal_outcome,
item.world_state_available === false ? "superseded" : "delivered",
"M4.6 terminal outcome",
),
bodyFrame: bodyFrame === null || basis === null
? null
: {
@@ -771,6 +834,23 @@ function parseTimelineFrame(
"current-increment",
"M4.6 timeline point layer",
),
cameraProjectedPointsXyd: item.camera_projected_points_xyd === undefined
? []
: array(item.camera_projected_points_xyd, "M4.6 camera points").map(
(point) => vector(point, 3, "M4.6 camera point") as [number, number, number],
),
cameraProjectedSourceCount: item.camera_projected_source_count === undefined
? 0
: integer(item.camera_projected_source_count, "M4.6 camera point source count"),
cameraProjectedPointCount: item.camera_projected_point_count === undefined
? 0
: integer(item.camera_projected_point_count, "M4.6 projected point count"),
cameraProjectedSampleCount: item.camera_projected_sample_count === undefined
? 0
: integer(item.camera_projected_sample_count, "M4.6 projected point sample count"),
cameraProjection: item.camera_projection === undefined
? null
: exact(item.camera_projection, "factory-kb4-exact", "M4.6 camera projection"),
rollingMapComponentCount: integer(
item.rolling_map_component_count,
"M4.6 rolling components",