算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3 适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新 后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动 前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复 文档: 新增5份算法性能分析报告
7.3 KiB
整车配准算法性能分析报告
分析时间:2026-06-25
算法版本:整车配准v1.3
入口函数:translate_align_by_front_tail(translate_align_pointcloud_to_cad.py)
测试环境:INTEL SSDSC2KB01(SATA SSD,~394 MB/s);A100 40 GB;CPU 128 核
实测数据:12 GB / 10 亿点 binary PLY 输入,总耗时 10 min 24 s
执行流程总览
translate_align_by_front_tail()
├─ 1. CAD STEP → mesh → 30k 点云采样 ← 实测 6 min 30 s(无 cache 时)
│ └─ [cache 命中] 直接加载 .ply ← 实测 ~5 s
├─ 2. 加载原始点云(Open3D binary PLY) ← 实测 1 min 17 s
├─ 3. 车头 / 车尾裁剪 × 4 ← 实测 2 min 17 s
├─ 4. 车头 / 车尾局部采样(1000 pts × 4)← 实测 7.6 ms
├─ 5. 平移估计(点集质心差) ← 实测 1.3 ms
├─ 6. ICP 精配准(采样 20 万点) ← 实测 1.9 s
├─ 7. 应用变换 + 写入配准结果 PLY ← 实测 12.8 s
└─ 8. 对齐误差统计(采样 10 万点 KNN) ← 实测 977 ms
各步骤详细说明与时间估算
第一阶段:CAD 准备(STEP → 采样点云)
| # | 步骤 | 代码位置 | 说明 | 无 cache | 有 cache |
|---|---|---|---|---|---|
| 1a | read_step_file(OCC 加载) |
translate_align...py:73 |
OCC STEPControl_Reader 读 STEP |
~10 s | 跳过 |
| 1b | BRepMesh_IncrementalMesh(tessellate) |
translate_align...py:147 |
OCC 三角剖分,147,275 个面 | ~6 min | 跳过 |
| 1c | 提取顶点/三角形数组 | translate_align...py:100 |
Python for loop 遍历所有面 | ~15 s | 跳过 |
| 1d | o3d.PointCloud + 均匀采样 30k 点 |
translate_align...py:155 |
从 mesh 均匀采样 cad_sample_points=30000 |
~3 s | 跳过 |
| 1e | 加载 cache PLY(useCadCache=true) |
translate_align...py:510 |
直接读 1.4 MB PLY,30k 点 | — | ~1 s |
CAD cache 机制:首次运行时 STEP tessellate 需约 6 分钟,生成
cad_cache/<hash>.ply(1.4 MB)。后续所有运行直接加载 cache,耗时降至 1 秒以内。务必开启useCadCache=true(已默认开启),且不要删除cad_cache/目录。
第二阶段:加载原始点云
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 2 | o3d.io.read_point_cloud(binary PLY) |
translate_align...py:547 |
Open3D C++ 读 12 GB binary PLY,直接构造 PointCloud | ~1 min 17 s |
Open3D 读取速度约 158 MB/s(受限于磁盘顺序读速 ~394 MB/s + float 转换)。12 GB 需要约 75 秒,无法进一步优化除非换更快的磁盘。
第三阶段:车头 / 车尾裁剪(主要瓶颈)
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 3 | crop_end_region_by_ratio × 4 |
translate_align...py:180 |
对 10 亿点 Open3D PointCloud 做 4 次 pcd.crop(AABB)(CAD 前/后 + 扫描前/后) |
~2 min 17 s |
虽然 o3d.crop 是 C++ 实现,但对 10 亿点的 PointCloud 内部仍需遍历全量点做 AABB 测试(O(N) × 4 次),实测每次约 34 秒,4 次共计 137 秒。
裁剪后车头/尾各只有 ~几千到几万点(ratio=0.01,即取前 1% 长度),所以裁剪结果本身非常小,耗时全部来自对全量 10 亿点的遍历。
第四阶段:局部采样 + 粗配准
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 4 | sample_farthest_points_simple × 4 |
translate_align...py:235 |
随机采样 1000 点;裁剪后点数已很少,O(M) | 7.6 ms |
| 5 | 平移估计 | translate_align...py:638 |
车头质心差 + 车尾质心差均值估计初始平移 | 1.3 ms |
第五阶段:ICP 精配准
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 6 | sample_farthest_points_simple(20 万点采样) |
translate_align...py:355 |
从 10 亿点随机采样 icp_sample_points=200000 |
< 1 s |
| 7 | o3d.registration.registration_icp |
translate_align...py:375 |
Point-to-point ICP,source 20 万点 → target CAD 30k 点,最多 50 次迭代;Open3D C++ | 1.9 s |
ICP 本身非常快,因为:
- source 只用 20 万点(采样)
- target CAD 只有 30k 点
- Open3D ICP 是 C++ SIMD 实现
第六阶段:应用变换 + 写入结果
| # | 步骤 | 代码位置 | 说明 | 实测时间 |
|---|---|---|---|---|
| 8 | aligned_pcd.transform(T_final) |
translate_align...py:704 |
对 10 亿点做 4×4 矩阵变换(Open3D C++,SIMD) | ~2 s |
| 9 | write_point_cloud_float32_xyz |
translate_align...py:314 |
分块写 binary PLY,float32,12 GB → 分 1000 个 chunk 写 | ~10 s |
| 10 | 误差统计(compute_error_stats) |
translate_align...py:740 |
采样 10 万点,KNN 建树 + 查询,scipy C++ | 977 ms |
实测时间汇总
| 阶段 | 实测时间 | 占比 |
|---|---|---|
| CAD 采样(无 cache) | 6 min 30 s | 63% |
| CAD 采样(有 cache) | ~1 s | <1% |
| 加载原始点云(Open3D) | 1 min 17 s | 12% |
| 车头/尾裁剪 × 4(Open3D C++ crop) | 2 min 17 s | 22% |
| 局部采样 + 平移估计 | <0.01 s | <1% |
| ICP 精配准(20 万点) | 1.9 s | <1% |
| 写 12 GB 结果 PLY | 12.8 s | 2% |
| 误差统计 | 977 ms | <1% |
| 总计(有 cache) | ~10 min 24 s | — |
| 总计(无 cache,首次) | ~17 min | — |
主要瓶颈分析
瓶颈 1:车头/尾裁剪 2 min 17 s(无法简单绕过)
pcd.crop(AABB) 是 Open3D C++ 全量遍历,10 亿点 × 4 次不可避免。
缓解方案:将 crop_ratio 从 0.01 增大到 0.02–0.05,
提取更多点用于粗配准,同时不影响裁剪本身速度(依然 O(N))。
根本方案:将 Open3D PointCloud 替换为 numpy 数组,
4 次 crop 变为 4 次 numpy 布尔索引,
并行化(4 个 crop 独立,可多线程),
估计可从 2 min 17 s 降至 ~30 s。
瓶颈 2:加载原始点云 1 min 17 s(I/O 受限)
Open3D 读 12 GB 文件,受限于 SATA SSD 394 MB/s 顺序读速,理论下限约 30 s(NVMe),实测 77 s 说明还有额外开销(float 类型转换)。升级到 NVMe 可降至 ~35 s。
瓶颈 3:CAD tessellate 6 min(首次,已有 cache 机制解决)
OCC 对 147,275 个面的 CAD 做三角剖分只需要跑一次,结果缓存为 1.4 MB PLY。只要 useCadCache=true 且 CAD 文件未更换,后续每次配准这一步只需 1 秒。
优化目标
| 场景 | 当前 | 优化后目标 |
|---|---|---|
| 有 cache,12 GB 输入 | 10 min 24 s | ~4 min(crop 多线程 + numpy 化) |
| 首次运行(无 cache) | ~17 min | ~4 min + 6 min(CAD build 无法优化) |
GPU 使用情况
| 模块 | GPU 使用 |
|---|---|
| STEP 解析 / tessellate(OCC) | ❌ CPU |
| 点云读取(Open3D) | ❌ CPU(I/O 受限) |
| crop / transform(Open3D) | ❌ CPU(C++ SIMD) |
| ICP 精配准(Open3D) | ❌ CPU(Open3D ICP 不使用 CUDA) |
| 误差统计(scipy KNN) | ❌ CPU |
整车配准全程不使用 GPU,A100 完全闲置。ICP 最有潜力用 GPU 加速(Open3D 有 registration_colored_icp + CUDA),但当前输入只有 20 万点,ICP 本身已是 1.9 s,瓶颈在 I/O 和 crop,GPU 化 ICP 收益有限。