feat(lab): separate current increment from rolling map

This commit is contained in:
DCCONSTRUCTIONS
2026-08-05 21:12:54 +03:00
parent 7aa3ce55c0
commit 31313c3c96
7 changed files with 165 additions and 37 deletions
@@ -18,6 +18,7 @@ export interface M4ThreatReplayResult {
evidence: {
cameraOnly: number;
currentMetric: number;
rollingMapRetained: number;
staleOrHeld: number;
};
fixtures: {
@@ -69,7 +70,7 @@ export interface M4ThreatAssessment {
export interface M4ThreatMetricVisual {
componentId: string;
state: "current" | "held" | "expired";
state: "current" | "retained" | "held" | "expired";
motion: M4ThreatMotion;
centroidBodyXyzM: M4Point3;
cellCentersBodyXyzM: readonly M4Point3[];
@@ -96,6 +97,8 @@ export interface M4ThreatVisualFrame {
pointCloudBodyXyzM: readonly M4Point3[];
pointCloudSourceCount: number;
pointCloudSampleCount: number;
pointCloudLayer: "current-increment";
rollingMapComponentCount: number;
metricObstacles: readonly M4ThreatMetricVisual[];
cameraProposals: readonly M4ThreatCameraProposal[];
rig: {
@@ -296,6 +299,9 @@ export async function fetchM4ThreatReplayResult({
evidence: {
cameraOnly: integer(evidence["camera-only"], "M4.6 camera-only"),
currentMetric: integer(evidence["current-metric"], "M4.6 metric"),
rollingMapRetained: evidence["rolling-map-retained"] === undefined
? 0
: integer(evidence["rolling-map-retained"], "M4.6 rolling map"),
staleOrHeld: integer(evidence["stale-or-held"], "M4.6 stale"),
},
fixtures: {
@@ -389,7 +395,14 @@ export async function fetchM4ThreatVisual(
);
if (!response.ok) throw new M4ThreatContractError(`M4.6 visual frame: HTTP ${response.status}.`);
const item = object(await response.json(), "M4.6 visual frame");
exact(item.schema_version, "missioncore.perception-threat-visual-frame/v1", "M4.6 frame schema");
const frameSchema = text(item.schema_version, "M4.6 frame schema");
if (
frameSchema !== "missioncore.perception-threat-visual-frame/v1"
&& frameSchema !== "missioncore.perception-threat-visual-frame/v2"
) {
throw new M4ThreatContractError("M4.6 frame schema: нарушен контракт.");
}
const rollingMapV2 = frameSchema === "missioncore.perception-threat-visual-frame/v2";
exact(item.result_id, result, "M4.6 frame result");
const rig = object(item.rig, "M4.6 visual rig");
const corridor = object(item.corridor, "M4.6 visual corridor");
@@ -404,10 +417,21 @@ export async function fetchM4ThreatVisual(
),
pointCloudSourceCount: integer(item.point_cloud_source_count, "M4.6 source points"),
pointCloudSampleCount: integer(item.point_cloud_sample_count, "M4.6 sample points"),
pointCloudLayer: rollingMapV2
? exact(item.point_cloud_layer, "current-increment", "M4.6 point layer")
: "current-increment",
rollingMapComponentCount: rollingMapV2
? integer(item.rolling_map_component_count, "M4.6 rolling components")
: 0,
metricObstacles: array(item.metric_obstacles, "M4.6 metric visuals").map((raw) => {
const value = object(raw, "M4.6 metric visual");
const state = text(value.state, "M4.6 temporal state");
if (state !== "current" && state !== "held" && state !== "expired") {
if (
state !== "current"
&& state !== "retained"
&& state !== "held"
&& state !== "expired"
) {
throw new M4ThreatContractError("M4.6 temporal state: неизвестное состояние.");
}
return {