Files
massive-cloud/alg/delivery_v1.2/coupler_panel_release/USAGE.md
lipan cec0766e67 feat: 升级算法包 delivery_v1.1 → v1.2,新增任务级 CAD 与测距面板
- 算法包替换为 delivery_v1.2(coupler_panel 新增 autotune/layer_select,underframe_deflection 新增 single_beam 管线),删除 delivery_v1.1
- manifests/adapters 的 PYTHONPATH 与版本说明同步更新到 v1.2
- 新增任务级 CAD 文件支持(task_cad_files 表、上传/读取路由、TaskManager 全选与加载显示)
- 新增 train-measurement 自定义前端面板(YAML 编辑器 + 可视化 ROI 配置 + 3D 取点)
- PointCloudViewer 支持 PLY 叠加层渲染与 ROI 拾取
- Dockerfile 改用 Miniforge 安装 pythonocc-core,修复 libgomp/libstdc++ 依赖
2026-06-11 02:30:04 +00:00

11 KiB
Raw Blame History

coupler_panel — 集成开发者使用指南

高铁车钩面板偏转角测量算法

主输入:ROI JSON + 点云 PLY + CAD STP(三件套) 主输出:含两个方向偏转角的 Excel 报表


1. 一句话集成

from coupler_panel.pipeline import run_coupler_measurement_pipeline
from coupler_panel.roi_select import load_roi_json

result = run_coupler_measurement_pipeline(
    input_cloud = "train_2_1T.ply",                    # 待测点云(可为整车,内部按 ROI 流式裁剪)
    out_dir     = "runs/today",                        # 中间产物 + report.json 落盘
    profile     = "train2_coupler",                    # 该零件 profile
    roi_spec    = load_roi_json("roi.json"),           # ROI = 裁剪超参数 ./examples/roi_train2_coupler.json
)
print(result.theta_right_deg, result.theta_ref_deg)    # 两个偏转角
print(result.dx_y_max_mm,     result.dx_z_max_mm)      # 最大 x 偏差

要直接产出 Excel,用集成入口脚本(§3)。


2. 安装

python -m pip install -r requirements.txt   # 锁定版本(Python 3.10 验证)
pip install -e ".[all]"                      # core + cloud + cad + viz + report

按需子集见 pyproject.toml 的 extras:[cloud] [cad] [viz] [report]。


3. 集成入口(三文件 → Excel)

examples/run_integration.py 是给集成方的标准入口:

python examples/run_integration.py \
    --roi   examples/roi_train2_coupler.json \      # ROI JSON
    --cloud /path/to/train_2_1T.ply \               # 整车点云(可多 GB)
    --stp   /path/to/asm.stp \                      # CAD STP(审计)
    --out   runs/train2 \                           # 输出目录
    --profile train2_coupler

产出 runs/train2/eval_report.xlsx(30 列,见 §7)+ 全部中间产物。

可选参数:--gt-theta-right / --gt-theta-ref(已知理论偏转,用于误差列,默认 0)、--sample-id、--config。


4. 三件输入说明

4.1 ROI JSON(裁剪超参数)

6-key 轴对齐包围盒,坐标系必须与点云一致,单位 mm:

{
  "x_min": 11526.0, "x_max": 11733.0,
  "y_min":   588.0, "y_max":  1192.0,
  "z_min":  -950.0, "z_max":   950.0
}
  • 点 (x,y,z) 保留条件:x_min<=x<=x_max ∧ y_min<=y<=y_max ∧ z_min<=z<=z_max
  • 必须 min<max,否则报 ValueError;多余 key(如 comment)忽略
  • 算法直接拿这六个数裁剪。当输入是二进制 PLY 且 ROI 是有限 bbox 时,走流式裁剪(memmap 分块,不整体加载),可处理 GB 级整车点云
  • 想全保留:传 roi_json=None 或 roi_spec=default_roi_spec()(±∞)
  • 裁剪诊断写到 out_dir/roi.json(mode、n_in、n_out、bbox)

坐标系坑(必读):ROI 的六个边界写在点云自己的坐标系里。若点云是 x=车长 / y=车高 / z=车宽(部分整车数据集如此),ROI 也按此填。ROI 裁出 0 点时算法抛 InsufficientPointsError 并提示检查坐标系。

4.2 点云 PLY

  • 支持 .ply(二进制/ASCII)/ .pcd / .xyz / .txt / .csv
  • 单位 mm;算法只读 x/y/z 前三列(颜色/法向等额外列容忍)
  • 可为整车扫描(多 GB)——ROI 流式裁剪后才进入算法
  • 算法不做配准:假设上游扫描端外参已标定、点云已在 CAD/车体帧(原因见 §8)

4.3 CAD STP

当前 STP 的角色取决于规模:

  • 单零件 STP:可被 parse_cad 解析,用于提供面板法向 seed + 自动整定检测参数(见 §6)。传 cad_stp_path=...。
  • 整车装配 STP(数百 MB、数千实例):项目的 parse_cad(单零件设计)无法处理,此时 STP 仅作审计/可追溯输入(路径记入报表),不参与计算——检测参数由 profile 提供、法向用 PCA。

若将来需要从整车 STP 提取目标几何,需另写装配级 XCAF 解析(不能复用单零件 parse_cad)。


5. 主入口 API

def run_coupler_measurement_pipeline(
    input_cloud : str | Path,                  # 必填:点云路径(可整车)
    out_dir     : str | Path,                  # 必填:输出目录
    *,
    config_path : str | Path | None = None,    # 可选:自定义 YAML / dict
    profile     : str = "auto",                # 可选:preset profile
    cad_stp_path: str | Path | None = None,    # 可选:单零件 STP(法向 + autotune)
    roi_spec    : ROISpec | None    = None,    # 二选一:内存 ROI 对象
    roi_json    : str | Path | None = None,    # 二选一:ROI JSON 路径
    progress    : Callable[[str, float], None] | None = None,
) -> CouplerMeasurement

算法链路:

crop_ply_bbox(流式 ROI 裁剪)
  → [layer_select]   沿法向隔离前层(profile 开关,去多层重叠)
  → [autotune]       从 CAD 孔径 + 点距自整定(仅默认 profile + 单零件 CAD 时)
  → denoise_cloud
  → compute_coupler_measurement
       validate → detect 4 holes → build frame
                → extract ROI → fit plane(RANSAC+SVD) → metrics

profile 选择:

  • 有匹配 profile(如 train2_coupler / lu1_af4)→ 直接指定,最稳。
  • 无 profile 但传了单零件 cad_stp_path → profile="auto",走自动整定(§6)。

配置覆盖:config_path 可传 dict 覆盖任意 configs/default.yaml 字段。

5.1 返回值 CouplerMeasurement

theta_right_deg, theta_ref_deg          # 两个偏转角(度)
D_y_max_mm, D_z_max_mm                   # 两方向最大距中心偏差
dx_y_max_mm, dx_z_max_mm                 # 最大 x 向偏差
center_C, normal                         # 面板中心、拟合法向(n_x>0)
holes, plane, frame                      # 4 孔 / 平面 / 参考系子结构
quality_flags, timings, report           # 诊断;report == out_dir/report.json
result.to_dict()                         # 完全 JSON 化

5.2 异常

CouplerError
├── InvalidPointCloudError / UnsupportedFormatError   输入非法 / 格式不支持
├── InsufficientPointsError                            点数过少 / ROI 裁出 0 点
├── CADParseError                                      STP 解析失败
├── HoleDetectionError                                 4 孔检测失败
└── PlaneFitError                                      平面拟合失败

非致命问题在 result.quality_flags(如 plane_inlier_ratio_low)。


6. 检测参数:profile vs 自动整定

不同零件的定位孔半径、是否有中心孔、点云密度都不同,检测参数必须匹配,否则报 HoleDetectionError: only N hole-shaped cavities found。两种适配方式:

  1. per-part profile(推荐用于已知零件):configs/profiles/<name>.yaml 写死该零件的孔径带、面积窗、是否前层隔离等。已有 train2_coupler(整车车钩面板)、lu1_af4(单零件车钩面板)。
  2. autotune(单零件 + 默认 profile 时):传单零件 cad_stp_path 且 profile=auto、无 config,算法从 CAD 定位孔半径 + 去噪后点距自动推导检测参数(coupler_panel/detection/autotune.py)。指定具体 profile 或 config 时完全跳过。

整车场景用 profile(train2_coupler),因为整车 STP 不能 parse、autotune 不可用。


7. 输出

7.1 Excel 报表(out_dir/eval_report.xlsx,30 列)

样本标识、输入 PLY、ROI kind、θ_right / θ_ref 的 GT/预测/误差、D_y/D_z_max、dx_y/dx_z_max、中心 C(x/y/z)、法向 n(x/y/z)、平面内点率/残差、配准 RMSE/最大残差(主路径恒空)、ROI 前后点数、quality_flags、算法运行时间 Algorithm runtime (s)(输入→返回整段 wall-clock)、内核阶段累计、算法/schema 版本。

多组结果用 coupler_panel.reporting.write_excel_report(rows, path) 合并成一张表。

7.2 落盘中间产物(out_dir/)

文件 内容
config.resolved.yaml 实际生效的合并配置
roi.json ROI spec + 裁剪诊断
01_gt.json (单零件 CAD parse 时)审计 GT
02_sampled.ply ROI 裁剪后的点云
transformed.ply (前层隔离开启时)隔离后的层
05_denoised.ply 去噪后点云(喂给测量算法的最终点云)
report.json 完整结果,等于 result.to_dict()

8. 为什么不做配准

车钩面板的 4 个定位孔与面板一起刚体旋转。用「扫到的 4 孔 → CAD 原始 4 孔」做 Kabsch,会精确解出「扫描器位姿 · 面板偏转」的复合刚体变换并反向作用,把偏转随位姿误差一起消掉,下游再读不到偏转——这是几何性质,不是 bug。

故主算法假设上游扫描端外参标定、点云已在车体帧。研究路径 run_from_cad_pipeline(含 Kabsch + 注入 oracle)完整保留作上限对照。


9. 集成模板

import logging, time, json
from pathlib import Path
from coupler_panel.pipeline import run_coupler_measurement_pipeline
from coupler_panel.roi_select import load_roi_json
from coupler_panel.reporting import build_row_from_summary, write_excel_report
from coupler_panel.exceptions import CouplerError

log = logging.getLogger(__name__)

def measure(cloud, roi_json, stp, out_dir, profile="train2_coupler"):
    t0 = time.perf_counter()
    try:
        r = run_coupler_measurement_pipeline(
            input_cloud=cloud, out_dir=out_dir,
            profile=profile, roi_spec=load_roi_json(roi_json))
    except CouplerError as e:
        log.error("measurement failed: %s", e)
        return None
    dt = time.perf_counter() - t0

    diag = json.loads((Path(out_dir)/"roi.json").read_text(encoding="utf-8"))["diagnostics"]
    row = build_row_from_summary(
        sample_id=Path(cloud).stem, ply_path=str(cloud), roi_kind="aabb",
        measured=r.to_dict(), gt_angles=(0.0, 0.0), registration=None,
        n_points_in=diag.get("n_in", 0), n_points_after_roi=diag.get("n_out", 0),
        pipeline_seconds=dt)
    write_excel_report([row], Path(out_dir)/"eval_report.xlsx")
    return r

10. 坐标 & 单位速查

量 单位 说明
点云坐标 mm 轴含义由数据集决定(见 README / §4.1)
偏转角 度 θ_right=atan2(n_y,n_x)、θ_ref=atan2(n_z,n_x)
法向 单位向量 强制 n_x>0
right_axis_sign ±1 右方向符号(profile metrics 配置)

11. 版本兼容

标识 含义
coupler_panel.__version__ 包版本(语义化)
coupler_panel.ALGORITHM_VERSION 算法版本,升级时数值可能变化
coupler_panel.SCHEMA_VERSION 结果结构版本,仅破坏性变更递增

建议:落库时记录 algorithm_version;反序列化 report.json 时校验 schema_version 主版本。