7.1 KiB
LiDAR–IMU 外参标定说明
用途: 方法约定与实现状态(深入阅读)。日常使用请先看根目录 README.md。
本文说明标定目标、约定、流水线与实现状态。代码在 imu_lidar/。场地采集见 标定流程与采集清单.md。
1. 目标与约定
估计安装外参:
p_IMU = T_IMU_lidar · p_lidar
约定:T_A_B 表示把 B 系点变换到 A 系。
相对运动手眼模型:
A_ij ≈ IMU 在 [t_i, t_j] 的相对运动(预积分)
B_ij ≈ LiDAR 在同时间段的相对运动(关键帧配准)
A X ≈ X B
X = T_IMU_lidar
旋转子问题(常规主交付):
R_A R_X = R_X R_B
→ R_IMU_lidar
若已有完整六自由度外参,且另有 T_RTK_lidar,可链式得到:
T_lidar_IMU = inverse(T_IMU_lidar)
T_RTK_IMU = T_RTK_lidar @ T_lidar_IMU
不要把 IMU 加速度二次积分成轨迹,再当作绝对位姿去做完整六自由度手眼。
2. 交付分层
| 层级 | 交付 | 数据最低要求 |
|---|---|---|
| 第一步 | 旋转 + 时间偏置 δt | 设备时间戳;静止 + 低速转弯 /「8」字;结构化场景 |
| 第二步 | 上一步 + 可观的水平平移 | 更多转弯半径与加减速 |
| 第三步 | 完整六自由度(含可靠竖直分量) | 缓坡俯仰激励,或外测垂直杆臂先验 |
可观性不过关 → 只交旋转,不强交“假精确”六自由度。
仅主机接收时间、或残差未过门控的结果 → 不要当作正式安装参数。
3. 总体原则
- 时间同步优先于外参:δt 未对齐时,旋转与平移都不可信。使用设备时间戳。
- 先求旋转,再求平移:旋转通常更稳;平面运动下竖直平移常常不可观。
- 用连续运动标定:停车多站、再靠站间长积分,不适合作为纯 IMU 外参主流程。
- 可观性门控:过不了就降级交付。
- 残差小 ≠ 标定对:需叠点云 / 跨会话等独立验证。
- 首轮建议低速:先保证配准与时间对齐;点云去畸变可选。
- 安装参数不写死在源码:轴向与时间语义进 YAML;机械尺寸可作检查,不能伪装成已标定平移。
- 注意耦合:时间相关峰很弱时,δt、航向角与陀螺零偏可能互相补偿,结果不可当真。
4. 流水线(现行实现)
vehicle_config
→ timestamp_audit
→ imu_audit(静止零偏等)
→ time_offset:粗估 δt
→ keyframes / [可选] deskew
→ motion_pairs:完整 IMU 预积分 + 配准 B
→ rotation_handeye:加权求解 R
→ (有候选 R 时)精修 δt,必要时交替重建运动对
→ joint_optimizer:精修旋转与陀螺零偏;可观且 full_se3 时再估平移等
→ finalize
| 模块 | 文件 | 职责 |
|---|---|---|
| 配置 | vehicle_config.py |
读安装 YAML |
| IO | imu_io.py / lidar_io.py |
标准 CSV / 帧目录 |
| 质检 | timestamp_audit.py / imu_audit.py |
时间域、静止零偏 |
| δt | time_offset.py |
粗估 + 有符号精修 |
| 运动 | keyframes.py / registration.py / lidar_deskew.py |
关键帧、配准、可选去畸变 |
| IMU 侧 | imu_preintegration.py / motion_pairs.py |
预积分与运动对 |
| 求解 | rotation_handeye.py / joint_optimizer.py / observability.py |
手眼、联合精修、门控 |
| 编排 | pipeline.py / cli.py / finalize.py |
入口与落盘 |
输入中间格式见 V1_数据格式.md。改动史见 imu_lidar/CHANGELOG.md。
运行示例
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
合成自检:python tools\generate_synthetic_session.py 后跑 CLI,再 python -m pytest -q。
结果状态
| status | 含义 |
|---|---|
rotation_only_accepted |
旋转过门,可交旋转与报告中的 δt |
full_se3_accepted |
可观且联合优化通过,可交完整 T |
full_se3_rejected_due_to_observability |
旋转可用,平移未接受 |
blocked |
质检 / δt / 手眼残差等硬门失败,不交付 |
rotation_only 模式下:不要把未标定的机械平移拼进 4×4 伪装成完整标定。
5. 采集要点
单趟动态会话:
[静止 20–30 s] → [低速激励 3–8 min] → [再静止 10–20 s]
优先激励:
- 低速「8」字 / 左右圆(旋转主激励)
- 直线加减速(有助于时间对齐与水平平移)
- 缓坡(仅完整六自由度需要):约 3°~8°,连续长度优先 ≥ 20~30 m
硬条件:IMU / LiDAR 设备时间戳;结构化场景;标定全程安装不得改动。
更完整的现场清单见 标定流程与采集清单.md。
6. 数学上允许与禁止
禁止:加速度二次积分当真值轨迹;把只有旋转的相对运动硬补成完整六自由度;用最终外参反向筛边掩盖失败。
允许:预积分旋转手眼求旋转;在可观时用预积分残差联合估计平移,并精修零偏等辅助量。
7. 车辆配置
使用 --vehicle-config vehicle_installation.yaml。
模板中安装平移/旋转保持未标定状态,直至实测确认;禁止写死某车杆臂冒充结果。
8. 实现状态(当前阶段)
本仓库仅此一条标定路径:连续运动关键帧 + IMU 预积分。对外总览与「合成 / 旧车 / 合格数据预期」见根目录 README.md §0。
| 项 | 状态 |
|---|---|
| 连续运动关键帧标定流水线 | 已实现(现行唯一路径) |
| 加权预积分 / 加权手眼 | 已实现 |
| 旋转预积分因子 + 有符号 δt 精修 | 已实现 |
| 完整预积分(含速度/位移增量)与可观时的平移优化 | 已实现 |
可观性门控 / rotation_only |
已实现 |
| 合成数据 pytest / 一键复现 | 已实现(证明链路与已知 yaw/δt,不证明实车精度) |
| 旧车主机时间烟测(S2) | 线下可跑;预期 blocked,不当交付 |
| 设备时间新车数据正式验收 | 待做 |
| 原生存储一键导出为中间格式 | 已提供 tools/export_rscap_to_v1.py(N300+H32 MSOP → V1;MSOP-only 用默认垂直角) |
9. 相关文档
| 内容 | 路径 | 备注 |
|---|---|---|
| 对外总览(优先) | 根目录 README.md |
日常入口 |
| 采集清单 | 标定流程与采集清单.md |
现场 |
| 数据格式 / 导出 | V1_数据格式.md |
中间格式 |
| 文件职责说明 | imu_lidar/文件职责说明.md |
改代码 |
| 改动史 | imu_lidar/CHANGELOG.md |
改代码 |