feat(perception): integrate vegetation policy review
This commit is contained in:
@@ -55,7 +55,9 @@ export interface VegetationVideoSemanticClass {
|
||||
classId: number;
|
||||
label: string;
|
||||
colorRgb: readonly [number, number, number];
|
||||
disposition: "prediction" | "undefined";
|
||||
disposition: "labeled" | "ambiguous" | "prediction" | "undefined";
|
||||
materialClass: string | null;
|
||||
evidenceState: string | null;
|
||||
}
|
||||
|
||||
export interface VegetationRouteVideo {
|
||||
@@ -67,8 +69,12 @@ export interface VegetationRouteVideo {
|
||||
height: 600;
|
||||
centerCropXyxy: readonly [100, 0, 700, 600];
|
||||
outsideCropState: "undefined";
|
||||
viewKind: "fine-semantic-prediction" | "coarse-material-policy-review";
|
||||
linkedTgsResultId: string | null;
|
||||
taxonomy: readonly VegetationVideoSemanticClass[];
|
||||
aggregatePredictionPixels: readonly number[];
|
||||
policyPresets: Readonly<Record<string, Readonly<Record<string, string>>>> | null;
|
||||
fusionMode: "synchronised-multilayer-review" | null;
|
||||
}
|
||||
|
||||
export interface VegetationShadowResult {
|
||||
@@ -257,6 +263,9 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
|
||||
"vegetation.route_video.m47_reference_graph_result_id",
|
||||
);
|
||||
const baseM4ResultId = textValue(row.base_m4_result_id, "vegetation.route_video.base_m4_result_id");
|
||||
const viewKind = row.view_kind === undefined
|
||||
? "fine-semantic-prediction"
|
||||
: textValue(row.view_kind, "vegetation.route_video.view_kind");
|
||||
if (
|
||||
!/^lab-v1-ravnoves-video-ddrnet-[a-f0-9]{64}$/.test(workerResultId)
|
||||
|| !/^m47-reference-graph-lab-[a-f0-9]{64}$/.test(m47ReferenceGraphResultId)
|
||||
@@ -264,6 +273,15 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
|
||||
) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: identity invalid.");
|
||||
}
|
||||
if (viewKind !== "fine-semantic-prediction" && viewKind !== "coarse-material-policy-review") {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: view kind invalid.");
|
||||
}
|
||||
const linkedTgsResultId = viewKind === "coarse-material-policy-review"
|
||||
? textValue(row.linked_tgs_result_id, "vegetation.route_video.linked_tgs_result_id")
|
||||
: null;
|
||||
if (linkedTgsResultId && !/^m49-tgs-full-shadow-[a-f0-9]{64}$/.test(linkedTgsResultId)) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: TGS identity invalid.");
|
||||
}
|
||||
exact(row.frame_count, 4489, "vegetation.route_video.frame_count");
|
||||
exact(row.width, 800, "vegetation.route_video.width");
|
||||
exact(row.height, 600, "vegetation.route_video.height");
|
||||
@@ -279,11 +297,9 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: crop contract changed.");
|
||||
}
|
||||
const taxonomy = objectValue(row.taxonomy, "vegetation.route_video.taxonomy");
|
||||
exact(
|
||||
taxonomy.schema_version,
|
||||
"missioncore.lab-v1-vegetation-taxonomy/v1",
|
||||
"vegetation.route_video.taxonomy.schema",
|
||||
);
|
||||
exact(taxonomy.schema_version, viewKind === "coarse-material-policy-review"
|
||||
? "missioncore.lab-v1-terrain-policy-taxonomy/v1"
|
||||
: "missioncore.lab-v1-vegetation-taxonomy/v1", "vegetation.route_video.taxonomy.schema");
|
||||
const classes = arrayValue(taxonomy.classes, "vegetation.route_video.taxonomy.classes")
|
||||
.map((value, expectedId): VegetationVideoSemanticClass => {
|
||||
const item = objectValue(value, `vegetation.route_video.taxonomy[${expectedId}]`);
|
||||
@@ -296,36 +312,78 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
|
||||
if (color.length !== 3 || color.some((channel) => channel > 255)) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: taxonomy color invalid.");
|
||||
}
|
||||
const disposition: VegetationVideoSemanticClass["disposition"] = expectedId === 0
|
||||
? "undefined"
|
||||
: "prediction";
|
||||
if (item.disposition !== disposition) {
|
||||
const disposition = item.disposition;
|
||||
if (
|
||||
disposition !== "labeled"
|
||||
&& disposition !== "ambiguous"
|
||||
&& disposition !== "prediction"
|
||||
&& disposition !== "undefined"
|
||||
) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: taxonomy disposition changed.");
|
||||
}
|
||||
if (
|
||||
viewKind === "fine-semantic-prediction"
|
||||
&& disposition !== (expectedId === 0 ? "undefined" : "prediction")
|
||||
) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: fine taxonomy disposition changed.");
|
||||
}
|
||||
const materialClass = item.material_class === null || item.material_class === undefined
|
||||
? null
|
||||
: textValue(item.material_class, `vegetation.route_video.material[${expectedId}]`);
|
||||
const evidenceState = item.evidence_state === null || item.evidence_state === undefined
|
||||
? null
|
||||
: textValue(item.evidence_state, `vegetation.route_video.evidence[${expectedId}]`);
|
||||
return {
|
||||
classId,
|
||||
label: textValue(item.label, `vegetation.route_video.label[${expectedId}]`),
|
||||
colorRgb: color as unknown as readonly [number, number, number],
|
||||
disposition,
|
||||
materialClass,
|
||||
evidenceState,
|
||||
};
|
||||
});
|
||||
if (classes.length !== 64) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: taxonomy must contain 64 classes.");
|
||||
const expectedClassCount = viewKind === "coarse-material-policy-review" ? 9 : 64;
|
||||
if (classes.length !== expectedClassCount) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: taxonomy size changed.");
|
||||
}
|
||||
const aggregatePredictionPixels = arrayValue(
|
||||
row.aggregate_prediction_pixels,
|
||||
"vegetation.route_video.aggregate_prediction_pixels",
|
||||
).map((value, index) => integerValue(value, `vegetation.route_video.pixels[${index}]`));
|
||||
if (aggregatePredictionPixels.length !== 64) {
|
||||
if (aggregatePredictionPixels.length !== expectedClassCount) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: class accounting changed.");
|
||||
}
|
||||
const maskArchive = objectValue(row.mask_archive, "vegetation.route_video.mask_archive");
|
||||
exact(maskArchive.path, "video/ddrnet-semantic-masks.zip", "vegetation.route_video.mask_archive.path");
|
||||
exact(maskArchive.path, viewKind === "coarse-material-policy-review"
|
||||
? "video/coarse-material-policy-masks.zip"
|
||||
: "video/ddrnet-semantic-masks.zip", "vegetation.route_video.mask_archive.path");
|
||||
const archiveSha256 = textValue(maskArchive.sha256, "vegetation.route_video.mask_archive.sha256");
|
||||
if (!SHA256.test(archiveSha256)) {
|
||||
throw new VegetationShadowContractError("vegetation.route_video: archive digest invalid.");
|
||||
}
|
||||
integerValue(maskArchive.byte_length, "vegetation.route_video.mask_archive.byte_length");
|
||||
let policyPresets: VegetationRouteVideo["policyPresets"] = null;
|
||||
let fusionMode: VegetationRouteVideo["fusionMode"] = null;
|
||||
if (viewKind === "coarse-material-policy-review") {
|
||||
const policy = objectValue(row.policy, "vegetation.route_video.policy");
|
||||
const presets = objectValue(policy.presets, "vegetation.route_video.policy.presets");
|
||||
policyPresets = Object.fromEntries(Object.entries(presets).map(([presetId, rawRules]) => {
|
||||
const rules = objectValue(rawRules, `vegetation.route_video.policy.${presetId}`);
|
||||
return [presetId, Object.fromEntries(Object.entries(rules).map(([material, action]) => [
|
||||
material,
|
||||
textValue(action, `vegetation.route_video.policy.${presetId}.${material}`),
|
||||
]))];
|
||||
}));
|
||||
const fusion = objectValue(row.fusion, "vegetation.route_video.fusion");
|
||||
exact(fusion.pixel_raster_fusion, false, "vegetation.route_video.fusion.pixel_raster_fusion");
|
||||
exact(fusion.camera_semantic_temporal_filter, "none", "vegetation.route_video.fusion.camera_filter");
|
||||
exact(
|
||||
fusion.mode,
|
||||
"synchronised-multilayer-review",
|
||||
"vegetation.route_video.fusion.mode",
|
||||
);
|
||||
fusionMode = "synchronised-multilayer-review";
|
||||
}
|
||||
return {
|
||||
workerResultId,
|
||||
m47ReferenceGraphResultId,
|
||||
@@ -335,8 +393,12 @@ function routeVideoValue(value: unknown): VegetationRouteVideo | null {
|
||||
height: 600,
|
||||
centerCropXyxy: [100, 0, 700, 600],
|
||||
outsideCropState: "undefined",
|
||||
viewKind,
|
||||
linkedTgsResultId,
|
||||
taxonomy: classes,
|
||||
aggregatePredictionPixels,
|
||||
policyPresets,
|
||||
fusionMode,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user