# 算法交付与测量结果输出规范 版本:1.0.0 状态:自 2026-08-13 起,新交付算法必须遵循;存量算法逐步迁移。 适用范围:`alg/` 下所有向宏量点云处理平台输出测量结果的算法。 ## 1. 目的 本规范统一算法 `result.json` 中正式测量结果的表达,解决以下问题: - 任务号被写在名称字符串里,例如 `任务46_车体横断面对角线差值`; - 同一任务的多个测量位置无法分组,例如任务 5 的左梁和右梁; - 头车、中车使用不同任务号,但结果中没有检测对象上下文; - `dx_y`、`dx_z` 等计算中间量混入正式测量结果; - 前端只能解析中文名称,无法稳定排序、筛选、统计和生成报告。 平台进程、进度事件、产物文件等接入方式仍参考 [`docs/algorithm-integration-spec.md`](../../docs/algorithm-integration-spec.md)。涉及测量结果字段时,**以本规范为准**。 ## 2. 基本原则 1. **任务号结构化**:正式测量项必须提供 `taskNo`,不得只写进 `name`。 2. **名称不编码**:`name` 只写项目名称,不包含 `任务XX_`、左右位置或车型前缀。 3. **指标编码稳定**:每项结果必须有稳定的 `metricCode`,程序关联以它为准,不能依赖中文名称。 4. **一个测量值一条记录**:同一任务存在左/右、前/后等多个结果时,保留多条记录并使用 `position` 区分,`taskNo` 相同。 5. **正式结果与中间量隔离**:只有可交付、可判定、可进入报告的值才能进入 `measurements`;中间量放入 `extra.intermediateMetrics`。 6. **不猜任务号**:任务号必须来自经确认的业务任务清单。无法确定时应阻止正式交付并请求确认,不能按数组序号或名称相似度推断。 7. **值和单位分离**:`value` 必须是 JSON 数值或 `null`;禁止输出 `"0.073/700mm"` 这样的混合字符串。 8. **JSON 必须标准合法**:禁止 `NaN`、`Infinity`;失败且无有效值时使用 `null`。 ## 3. 职责边界 ### 3.1 业务/产品负责人 - 提供并确认正式任务清单:`taskNo`、项目名称、适用检测对象、理论值、公差、单位; - 审批任务号变更,算法工程师不得自行重新编号。 ### 3.2 平台/集成人员 - 在算法输入或适配层提供 `inspectionObject`,例如 `head`(头车)、`middle`(中车); - 将经确认的业务任务清单配置为映射表; - 校验最终 `result.json`,不让缺少任务号的正式结果进入业务表格。 ### 3.3 算法工程师 - 为算法指标定义稳定的 `metricCode` 和准确的 `name`; - 输出 `position` 等算法能够确定的测量位置; - 在已获得检测对象和任务映射时输出正确的 `taskNo`; - 只把最终可交付结果放进 `measurements`,中间量放进 `extra.intermediateMetrics`; - 交付前运行本目录的校验脚本。 > 最终写入平台的 `result.json` 必须满足本规范。若算法核心包不负责业务任务号,平台薄适配层必须在写出 `result.json` 前补齐,不能交给前端猜测。 ## 4. 顶层结构 ```json { "schemaVersion": 1, "measurementContractVersion": "1.0", "status": "completed", "message": "测量完成", "context": { "inspectionObject": "head", "inspectionObjectName": "头车" }, "measurements": [], "extra": { "intermediateMetrics": [] } } ``` 字段说明: | 字段 | 必填 | 说明 | |---|---:|---| | `schemaVersion` | 是 | 平台插件结果版本;当前平台存量插件仍使用 `1` | | `measurementContractVersion` | 是 | 本测量结果规范版本,当前固定为 `"1.0"` | | `status` | 是 | `completed` 或 `error` | | `message` | 否 | 面向用户的简短说明 | | `context` | 有对象差异时必填 | 本次测量的业务上下文 | | `measurements` | 完成时必填 | 正式测量结果;允许空数组,不允许混入调试指标 | | `extra` | 否 | 算法报告、质量信息、中间量等非正式结果 | `schemaVersion` 与 `measurementContractVersion` 含义不同,不得互相替代。 ## 5. 正式测量项 `measurements[]` 推荐完整结构: ```json { "taskNo": "5", "metricCode": "underframe.longitudinal_beam.vertical_deflection", "name": "纵向梁到直线的垂直偏差(挠度)", "position": "左梁", "value": 0.265, "unit": "mm", "tolerance": 7.0, "toleranceLabel": "±7 mm", "status": "pass" } ``` | 字段 | 必填 | 类型/取值 | 说明 | |---|---:|---|---| | `taskNo` | 是 | 字符串 | 正式业务任务号;即使全是数字也必须用字符串 | | `metricCode` | 是 | 字符串 | 稳定指标编码,建议 `<域>.<部件>.<指标>`,仅用小写字母、数字、点、下划线和短横线 | | `name` | 是 | 字符串 | 纯项目名称,不带 `任务XX_` 和位置前缀 | | `position` | 多位置时必填 | 字符串 | 如 `左梁`、`右梁`、`一位端`;不适用时省略 | | `value` | 是 | 数值或 `null` | 测量值;无有效结果时为 `null` | | `unit` | 有量纲时必填 | 字符串 | 如 `mm`、`°`、`%`;无量纲使用 `"1"` | | `theoreticalValue` | 否 | 数值 | 理论值,与 `unit` 相同 | | `baseline` | 斜率形式时必填 | 正数 | 基准长度,单位为 mm | | `tolerance` | 简单对称公差时使用 | 非负数 | `±tolerance`,与 `unit` 相同;斜率形式表示分子公差 | | `toleranceLower` | 非对称公差时使用 | 数值 | 相对理论值的下偏差 | | `toleranceUpper` | 非对称公差时使用 | 数值 | 相对理论值的上偏差 | | `toleranceLabel` | 复杂公差时使用 | 字符串 | 报告展示原文,例如 `+8.5/-3 mm` | | `status` | 是 | `pass` / `warning` / `fail` | 正式结果不得使用 `info` | | `qualityFlags` | 否 | 字符串数组 | 质量告警代码,不替代 `status` | 约束: - 同一 `taskNo + metricCode + position` 在一次结果中必须唯一; - `name` 不得匹配 `^任务\s*\d+`; - `status=pass|warning|fail` 必须基于已确认的公差规则; - `value=null` 时不得判为 `pass`; - 若尚未获得正式任务号,该项不得进入最终 `measurements`。 ## 6. 检测对象与任务号映射 当同一指标在不同检测对象上对应不同任务号时,必须先根据 `context.inspectionObject` 选择任务号。 本次已确认的映射如下: | 检测对象 | 指标 | `taskNo` | |---|---|---:| | 任意 | 纵向梁到直线的垂直偏差(左、右挠度) | 5 | | 头车 `head` | 车钩面板到参考面的右偏转角 | 8 | | 中车 `middle` | 车钩面板到参考面的右偏转角 | 9 | | 头车 `head` | 车钩面板到纵向中心的右偏转角 | 10 | | 中车 `middle` | 车钩面板到纵向中心的右偏转角 | 12 | 任务 5 的左右梁应输出两条记录:两条的 `taskNo` 和 `metricCode` 相同,`position` 分别为 `左梁`、`右梁`。 如果输入中没有头车/中车信息,车钩算法不得自行默认成头车;应报契约错误,或由平台适配层在具备检测对象信息后完成映射。 ## 7. 斜率形式与角度值 车钩“右偏转角”目前存在两种可能的交付口径,必须由业务任务清单明确: ### 7.1 以角度交付 ```json { "value": 0.0063, "unit": "°", "tolerance": 0.08 } ``` ### 7.2 以偏差值/基准长度交付 ```json { "value": 0.073, "unit": "mm", "baseline": 700, "tolerance": 1.0, "toleranceLabel": "1/700 mm" } ``` 禁止把 `value` 写成字符串 `"0.073/700mm"`。角度值和换算后的偏差值不能共用同一个 `metricCode`;如两者都需保留,一个作为正式结果,另一个放入中间量并使用不同编码。 ## 8. 中间数据与诊断数据 以下数据通常不属于正式测量项:拟合系数、法向量、点数、残差、`dx_y`、`dx_z`、`D_y`、`D_z`、ICP fitness、RMSE 等。 统一放入: ```json { "extra": { "intermediateMetrics": [ { "metricCode": "coupler.panel.dx_y_max", "name": "Y 方向计算用最大 X 偏差", "value": 0.0101, "unit": "mm" } ] } } ``` 中间量: - 不需要 `taskNo`; - 不设置业务 `status` 和公差; - 不进入“算法结果”项数、合格率和正式报告; - 可用于日志、排障和算法复核。 ## 9. 禁止的旧写法 ```json { "measurements": [ { "name": "任务46_车体横断面对角线差值", "value": 0.592 }, { "name": "左梁 · 纵向梁到直线的垂直偏差(挠度)", "value": 0.265 }, { "name": "最大 x 偏差 dx_y", "value": 0.010, "status": "pass" } ] } ``` 问题分别是:任务号嵌入名称、位置嵌入名称、中间量冒充正式结果。 正确写法见 [`examples/head-car-coupler-and-deflection.result.json`](examples/head-car-coupler-and-deflection.result.json)。 ## 10. 兼容与迁移 - 本规范是**目标输出契约**。当前平台前端尚未使用所有新增字段时,也必须保留这些字段,不能因此退回名称拼接方案; - 存量 `任务46_xxx` 等结果允许历史回放,但算法下一版本应拆为 `taskNo="46"` 和纯 `name`; - 平台适配层可以暂时从经确认的旧配置中迁移任务号,但不得长期正则解析中文名称; - 修改任务号、单位、换算口径、公差或 `metricCode` 均属于接口变更,必须在算法版本说明中记录; - 核心计算方法未变、只调整输出结构时,也应至少提升算法补丁版本并注明“输出契约迁移”。 ## 11. 交付检查清单 算法工程师提交前逐项确认: - [ ] `result.json` 是 UTF-8 标准 JSON,无 `NaN`/`Infinity` - [ ] 顶层包含 `measurementContractVersion: "1.0"` - [ ] 每个正式测量项都有 `taskNo`、`metricCode`、纯 `name`、`value`、`status` - [ ] 多位置结果使用相同任务号并通过 `position` 区分 - [ ] 头车/中车任务号来自 `context.inspectionObject`,没有默认猜测 - [ ] `measurements` 中没有 `info` 状态和算法中间量 - [ ] 单位、公差、理论值和换算口径与正式任务清单一致 - [ ] `extra.intermediateMetrics` 中的指标不参与合格判定 - [ ] 已执行:`python3 validate_result.py result.json` - [ ] 版本说明记录了输出字段变化 ## 12. 校验方式 本目录提供两种校验: ```bash # 零第三方依赖,执行本规范的关键业务规则校验 python3 validate_result.py /path/to/result.json # 如本机安装了 jsonschema,可进行完整 JSON Schema 校验 python3 -m jsonschema -i /path/to/result.json result.schema.json ``` 示例自检: ```bash python3 validate_result.py examples/head-car-coupler-and-deflection.result.json ```