Files
calibration/README.md
T

14 KiB
Raw Blame History

LiDARIMU 外参标定

用车上的**激光雷达(LiDAR惯性测量单元(IMU)**在连续行驶中的相对运动,估计二者之间的安装关系(外参),并估计两路传感器的时间差。

p_IMU = T_IMU_lidar · p_lidar

实现包:[imu_lidar/](imu_lidar/)。文件职责说明:[imu_lidar/文件职责说明.md](imu_lidar/文件职责说明.md)

本仓库只有这一条标定路径(连续运动关键帧 + IMU 预积分)。不直接解析原始 .rscap / dlog,需先导出为中间格式。


0. 现状一览(先读)

说明
仓库做什么 输入标准中间格式(IMU CSV + 雷达会话),输出 LiDARIMU 正式安装外参 T_IMU_lidar 与时间偏置 δt。合格数据且过质量门 → 可交付(常规先交旋转 + δt;激励够再交可观平移);数据不合格或未过门 → blocked,不交外参
当前阶段 算法链路已闭环,合成自检通过;尚缺合格实车数据验收,故正式外参尚未对实车落盘交付(生产级原始录制→中间格式导出仍待完善)
合成数据测什么 证明链路能跑通,并能收回已知旋转(yaw)与 δt不证明实车安装精度或平移交付
旧车 S2 测什么 仅线下烟测:主机时间旧数据上流水线能否跑完;结果预期为 blocked不当作外参真值
合格数据 见下方定义;拿到后即可按正式标定流程跑通,期望得到可交付外参(先旋转 + δt)

什么叫合格数据

同时满足下列条件,才视为可用于正式标定(与旧车主机时间烟测数据区分):

类别 要求
时间戳 IMU、雷达均用设备时间写入中间格式的 t / t_start/t_end(可另留主机接收时间作排查,但标定主轴不用主机时)
会话结构 单趟:静止 2030 s低速连续运动 38 min再静止 1020 s;运动含明显左右转(如「8」字 / 圆)及适量加减速
场景 有墙、柱、路缘等结构,避免空旷无特征;雷达帧率与点数正常、无明显大面积丢帧
覆盖 两路传感器覆盖同一段物理行驶;安装全程不得改动
格式 已导出本仓库中间格式:imu.csv + lidar_session/(见 docs/V1_数据格式.md
验证会话(建议) 另录一段独立路线 B,只做叠点/一致性检查,不参与求外参

不算合格(举例): 仅主机接收时间;只有静止、无转弯;IMU 与雷达不是同一趟;未导出中间格式;时间相关极弱仍强行当安装参数。

完整现场清单见 docs/标定流程与采集清单.md

合格数据拿到后 → 正式外参与预期效果

仓库目标产物就是可安装使用的外参(再加 δt)。合格数据过门后:

模式 跑法 正式交付内容 较现实预期 成功标志
rotation_only(第一步,必做) --mode rotation_only 旋转外参 + δt 旋转约 0.5°–2°;δt 随同步与激励质量变化 summary.jsonrotation_only_accepted
full_se3(激励够再试) --mode full_se3 上一项 + 可观的平移 水平平移约数厘米~十几厘米;竖直常更差或不可观(需缓坡或垂直先验) full_se3_accepted;否则旋转仍可交付、平移拒绝

交付前须叠点云 / 跨会话独立验证;blocked 一律不可用作安装参数。
当前尚未完成的是「用合格实车数据跑出并验收这份外参」,不是「合格数据也交不出外参」。

两类试验对照

合成数据(默认 pytest / 一键复现) 旧车 S2(线下,非默认测试)
目的 回归算法正确性 验证实车 IO/链路可跑
时间戳 可控、带已知 δt 主机接收时间(非设备时间)
是否合格数据 否(合成,仅对照) (主机时间,预期拒绝)
期望结果 rotation_only_accepted;δt / yaw 接近真值 blocked(质量门拒绝)
能否当安装参数

细节见 tests/README.md。实现状态细表见 docs/IMU-LiDAR标定.md §8。


目录

  1. 现状一览(先读)
  2. 系统输入 / 输出
  3. 一键复现(合成数据)
  4. 能求出什么
  5. 方法概要
  6. 分步求值
  7. 程序流程
  8. 真实数据怎么跑
  9. 结果判读
  10. 仓库结构与文档

1. 系统输入 / 输出

输入

输入 说明
imu.csv 列:t,gx,gy,gz,ax,ay,az(秒;陀螺 rad/s;加速度 m/s²)
雷达点云 frames_index.csv + frames/frame_XXXXX.npz(点云米制)
车辆配置 YAML 轴向与时间语义;不必事先填外参真值(模板:config/vehicle_installation.template.yaml

中间格式细节见 docs/V1_数据格式.md。原始 .rscap 等需先导出。

输出(--output 目录)

文件 内容
T_IMU_lidar.json 外参矩阵、平移、四元数、欧拉角
time_offset.json δt,定义 t_imu = t_lidar + δt
summary.json 状态、残差、可观性、各阶段细节
report_preview.png 一键复现时生成的简易指标图(可选)

2. 一键复现(合成数据)

不需要实车数据。脚本会:生成合成 IMU/雷达 → 跑标定 → 打印报告并出预览图 → 跑 pytest

这一趟证明什么: 全流程可复现;能收回合成真值中的旋转(yaw)与时间偏置。
不证明什么: 实车安装精度、平移外参可交付、主机时间旧数据可用。

推荐(Windows

cd <本仓库根目录>
python -m pip install -e ".[dev]"
python -m pip install -e ".[open3d]"   # 可选,配准更稳;未装则用内置 ICP
# 预览图需要 matplotlib(没有则跳过绑图,不影响标定)
python -m pip install matplotlib

powershell -File tools\reproduce_synthetic.ps1

只要标定、跳过测试:

powershell -File tools\reproduce_synthetic.ps1 -SkipPytest

尝试完整六自由度模式:

powershell -File tools\reproduce_synthetic.ps1 -Mode full_se3 -SkipPytest

等价 Python 入口

python tools\reproduce_synthetic.py
python tools\reproduce_synthetic.py --mode full_se3 --skip-pytest

这一趟用了什么、产出什么

INPUT
  examples/synthetic_session/imu.csv
  examples/synthetic_session/lidar/
  config/vehicle_installation.template.yaml
  examples/synthetic_session/meta.json      # 合成真值(δt、yaw),仅用于对照

OUTPUT
  examples/synthetic_session/out/T_IMU_lidar.json
  examples/synthetic_session/out/time_offset.json
  examples/synthetic_session/out/summary.json
  examples/synthetic_session/out/report_preview.png

单独查看已有结果:

python tools\show_calibration_report.py `
  --summary examples\synthetic_session\out\summary.json `
  --truth-meta examples\synthetic_session\meta.json `
  --plot examples\synthetic_session\out\report_preview.png

配准结果 3D / 俯视可视化

蓝=目标帧,橙=源帧。

按键 作用
1 / 2 / 3 / 4 原始 / IMU(X=I) / 雷达配准 B / 标定预测 X⁻¹AX
N] 下一运动对
P[ 上一运动对
python tools\visualize_pair_3d.py `
  --lidar examples\synthetic_session\lidar `
  --imu examples\synthetic_session\imu.csv `
  --summary examples\synthetic_session\out\summary.json `
  --pair-index 0 `
  --save-png examples\synthetic_session\out\pair0_overlay.png

--pair-index 只决定起始对;窗口内可继续按 N/P 切换。无 GUI 时加 --no-gui。封装:tools\view_pair.ps1


3. 能求出什么

结果 含义 说明
旋转外参 雷达相对 IMU 的朝向差 常规主交付
时间偏置 δt 两路时钟差(秒) 与旋转一并给出
平移外参 安装位置差(米) 激励足够且质量门通过才接受,否则置零
零偏等 辅助量 改善积分/优化,一般不当安装外参交付

4. 方法概要

  1. 低速多转弯行驶(如「8」字),首尾各留静止段。
  2. 雷达关键帧配准得相对运动 B
  3. 同一时段 IMU 预积分得 A(先用旋转)。
  4. 手眼关系:R_A · R_X ≈ R_X · R_B
  5. 时间与旋转稳定后,若 --mode full_se3 且可观,再估计平移(用加速度预积分、重力、速度与时变零偏)。

5. 分步求值

步骤 交付 典型要求
第一步 旋转 + δt 设备时间戳;静止 + 低速转弯;有结构的场景
第二步 + 水平平移 更多转弯半径与加减速
第三步 完整六自由度 缓坡等俯仰激励,或垂直安装尺寸先验
  • --mode rotation_only:第一步
  • --mode full_se3:尝试完整刚体;平移仍可能被拒绝

质量门未通过时,不能当正式安装参数。


6. 程序流程

读入 → 时间/IMU 质检 → 粗估 δt
  → 关键帧配准 B + IMU 预积分 A → 旋转手眼 R
  → 用 R 精修 δt(可交替组对)
  → 联合精修 R / 常值陀螺零偏
  →(full_se3 且可观)重力、速度、时变零偏、平移 t
  → 写出 JSON

「可观」:程序检查转轴是否够多样、相对位移是否够丰富;不够则只保留旋转。


7. 真实数据怎么跑

python -m pip install -e ".[dev]"
python -m pip install -e ".[open3d]"

python -m imu_lidar.cli plan --mode rotation_only

python -m imu_lidar.cli run `
  --vehicle-config config\vehicle_installation.template.yaml `
  --imu path\to\imu.csv `
  --lidar path\to\lidar_session `
  --output path\to\output `
  --mode rotation_only `
  --time-offset-search-s 2.0

采集与现场清单:docs/标定流程与采集清单.md

旧车 S2 主机时间烟测(预期 blocked,不当交付):配置见 config/s2_old_smoke.yaml,步骤见 [tests/README.md](tests/README.md)


8. 结果判读

summary.json 状态 含义
rotation_only_accepted 旋转可用(该模式下平移置零)
full_se3_accepted 含平移的完整外参通过
full_se3_rejected_due_to_observability 旋转可用,平移未接受
blocked 前序失败,不可用作安装参数

请同时看手眼残差、时间相关、可观性说明,并做点云叠加等独立验证。


9. 仓库结构与文档

imu_lidar/     标定算法与 CLI
config/        车辆配置模板
docs/          流程、数据格式、方法说明
tools/         合成数据、一键复现、报告查看
tests/         自动化测试
文档 内容
imu_lidar/文件职责说明.md 各源文件职责
imu_lidar/CHANGELOG.md 算法改动记录
docs/标定流程与采集清单.md 现场采集与分步流程(与现行实现对齐)
docs/V1_数据格式.md 中间数据格式
docs/IMU-LiDAR标定.md 方法约定与实现状态
tests/README.md 自动化测试说明 + S2 旧数据线下试验结果

改算法请同步更新 imu_lidar/文件职责说明.mdCHANGELOG.md;改安装/运行/对外说明时更新本文件。