合并并完善双链路标定文档
This commit is contained in:
@@ -1,69 +1,54 @@
|
||||
# 车辆多传感器外参标定
|
||||
|
||||
本仓库同时维护两条独立的外参标定链路:LiDAR–IMU 与 RTK–IMU。两条链路共享通用的几何和 IMU 预积分基础能力,但各自的观测模型、求解器、工具入口和验收结论独立管理。
|
||||
本仓库维护两条彼此独立的外参标定流程:**雷达–IMU** 和 **RTK–IMU**。两条流程复用少量通用的几何、IMU 读取和预积分代码,但不共用观测模型、求解器或验收结论。
|
||||
|
||||
## 当前应如何使用
|
||||
## 从这里开始
|
||||
|
||||
| 目标 | 推荐链路 | 当前可交付状态 |
|
||||
| 目标 | 阅读文档 | 当前可交付范围 |
|
||||
| --- | --- | --- |
|
||||
| LiDAR 与 IMU 的旋转、时间对齐 | LiDAR–IMU | 旋转与主机桥接时间对齐可冻结;完整平移不可交付。 |
|
||||
| RTK 天线相位中心与 IMU 的工程外参 | RTK–IMU | 旋转外参已求出,平移外参利用机械先验经动态数据一致性验证确定(不是纯靠数据求出)。 |
|
||||
| 需要完整 RTK–IMU 工程候选和复现方式 | RTK–IMU | 先阅读 [README_RTK_IMU.md](README_RTK_IMU.md)。 |
|
||||
| 标定雷达与 IMU | [雷达–IMU 标定](docs/雷达-IMU标定.md) | 旋转与时间关系已有实车候选;平移尚不可交付。 |
|
||||
| 标定双天线 RTK 与 IMU | [RTK–IMU 标定](docs/RTK-IMU标定.md) | 旋转已固定;杆臂以机械测量为基准,并完成动态一致性验证,尚未获得正式工程放行。 |
|
||||
|
||||
不要把任何一条链路未通过的平移结果当作已标定的 6DoF 外参。结果的接受状态以对应 JSON 中的 gate 为准。
|
||||
不要将任何一条流程中被拒绝的平移结果当作完整六自由度外参。是否接受结果,以相应结果 JSON 的 `accepted` 字段和门禁结论为准,而不是仅看优化是否收敛。
|
||||
|
||||
## 为什么同时保留两条链路
|
||||
## 两条流程的关系
|
||||
|
||||
LiDAR–IMU 链路通过点云相对运动与 IMU 预积分求手眼外参,适合旋转与时间对齐;但当前实车数据的加速度预积分位移,尤其 Z 分量,不足以支持可靠平移求解,且主要采集运动缺乏竖直激励。因此它的 `full_se3` 门禁未通过。
|
||||
```text
|
||||
雷达–IMU
|
||||
点云相对运动 + IMU 预积分
|
||||
→ 旋转与时间关系;平移受 IMU 位移误差和激励不足限制
|
||||
|
||||
RTK–IMU 链路直接利用双天线基线、GNSS 位置和 Doppler 速度,并以机械测量给出天线相位中心相对 IMU 的绝对杆臂。它不是“用 RTK 替代 LiDAR”,而是针对 LiDAR–IMU 平移不可观的问题,采用更直接的天线位置/速度观测做工程外参验证。
|
||||
RTK–IMU
|
||||
双天线基线 + GNSS 位置/速度 + IMU
|
||||
→ 天线相位中心相对 IMU 的旋转和杆臂一致性验证
|
||||
```
|
||||
|
||||
完整理由、两条模型的差异及当前结果见 [LiDAR→RTK–IMU 决策说明](docs/lidar_imu_to_rtk_imu.md)。
|
||||
选择 RTK–IMU 不是用 RTK 替换雷达。它用于解决“雷达–IMU 的平移在当前实车数据上不可可靠交付”这一独立问题;RTK–IMU 的外参也不能自动转换为雷达–IMU 外参。
|
||||
|
||||
## 仓库结构
|
||||
|
||||
```text
|
||||
calibration/
|
||||
├─ imu_lidar/ LiDAR–IMU 专用流程,以及双方共用基础模块
|
||||
├─ rtk_imu/ RTK–IMU 专用算法包
|
||||
├─ tools/ 两条链路的命令入口、导出和审计工具
|
||||
├─ tests/ 自动化测试
|
||||
├─ docs/ 详细方法、状态、采集与决策说明
|
||||
├─ artifacts/ 受审核的结果快照;大过程文件仅保留本地
|
||||
├─ imu_lidar/ 雷达–IMU 专用算法和命令行入口
|
||||
├─ rtk_imu/ RTK–IMU 专用算法
|
||||
├─ tools/ 原始数据导出、求解、审计和结果汇总入口
|
||||
├─ docs/ 两份规范说明:雷达–IMU、RTK–IMU
|
||||
├─ artifacts/ 已提交的结果摘要与审核证据
|
||||
├─ config/ 车辆安装与流程配置
|
||||
├─ README.md 本页:仓库总览
|
||||
└─ README_RTK_IMU.md RTK–IMU 当前工程流程、结果与复现
|
||||
└─ tests/ 自动化测试
|
||||
```
|
||||
|
||||
`rtk_imu/` 只依赖下列 `imu_lidar/` 通用模块:
|
||||
`rtk_imu/` 只允许复用 `imu_lidar/` 中的通用模块:`contracts.py`、`geometry.py`、`geodesy.py`、`imu_io.py`、`imu_preintegration.py` 与 `rotation_handeye.py`。它不依赖雷达专用的点云读取、去畸变、配准、雷达流程编排或雷达联合优化器。
|
||||
|
||||
- `contracts.py`:数据契约。
|
||||
- `geometry.py`:SO(3)、变换和坐标运算。
|
||||
- `geodesy.py`:地理坐标到 ENU。
|
||||
- `imu_io.py`:IMU 读取。
|
||||
- `imu_preintegration.py`:IMU 预积分、bias 修正与 whitening。
|
||||
- `rotation_handeye.py`:通用旋转手眼初值器。
|
||||
## 数据与过程文件
|
||||
|
||||
RTK–IMU 不得依赖 LiDAR 专用的 `lidar_io.py`、`lidar_deskew.py`、`registration.py`、`pipeline.py`、`phase_a.py` 或 `joint_optimizer.py`。
|
||||
原始 `.rscap`、统一导出数据、节点状态、检查点和调试中间结果只保留本地;仓库只提交可复核的代码、工具、配置、说明和结果摘要。RTK–IMU 的正式结果索引在 [artifacts/rtk_imu_calibration_v3/README.md](artifacts/rtk_imu_calibration_v3/README.md)。
|
||||
|
||||
## 文档入口
|
||||
## 开发与验证
|
||||
|
||||
| 文档 | 内容 |
|
||||
| --- | --- |
|
||||
| [README_RTK_IMU.md](README_RTK_IMU.md) | RTK–IMU 当前候选、状态、流程、审核证据和复现命令。 |
|
||||
| [docs/lidar_imu_to_rtk_imu.md](docs/lidar_imu_to_rtk_imu.md) | 为什么 LiDAR–IMU 暂不能交平移、为什么引入 RTK–IMU、两者边界与共享代码。 |
|
||||
| [rtk_imu/README.md](rtk_imu/README.md) | RTK–IMU 包的代码职责与 import 边界。 |
|
||||
| [docs/rtk_imu_multisource_v3.md](docs/rtk_imu_multisource_v3.md) | G90/HI13 统一导出及 R1b/R2V/R2G/R3 旋转链路。 |
|
||||
| [docs/rtk_imu_engineering_6dof.md](docs/rtk_imu_engineering_6dof.md) | node-state factor graph、机械先验、验收门禁。 |
|
||||
| [docs/IMU-LiDAR标定.md](docs/IMU-LiDAR标定.md) | LiDAR–IMU 方法与采集要求。 |
|
||||
| [docs/20260808_LiDAR-IMU标定现状与问题.md](docs/20260808_LiDAR-IMU标定现状与问题.md) | LiDAR–IMU 当前问题、证据和历史处置记录。 |
|
||||
```powershell
|
||||
python -m pip install -e ".[dev]"
|
||||
python -m pytest -q
|
||||
```
|
||||
|
||||
## 结果与过程文件
|
||||
|
||||
`artifacts/rtk_imu_calibration_v3/` 中只提交审核结论及其关键证据。原始 `.rscap`、统一导出数据、节点状态、checkpoint、调试 JSON 与旧版本过程产物均通过 `.gitignore` 保持本地,不应随提交或推送传播。
|
||||
|
||||
每次改动前先确认使用哪一条链路;每次交付前先读取相应 release JSON 中的 accepted gate,而不是仅凭优化器收敛、残差下降或一个看似合理的 4×4 矩阵下结论。
|
||||
|
||||
## LiDAR–IMU 专用运行指南
|
||||
|
||||
[README_Lidar_IMU.md](README_Lidar_IMU.md) 保留 LiDAR–IMU 的独立运行命令、合成复现与输入输出说明;它是远端原 README 的专用化重命名,不再承担仓库总导航职责。
|
||||
雷达点云处理需要时再安装可选依赖:`python -m pip install -e ".[open3d]"`。
|
||||
@@ -1,184 +0,0 @@
|
||||
# LiDAR–IMU 外参标定
|
||||
|
||||
用连续行驶中的 LiDAR 与 IMU 相对运动,估计安装外参与时间偏置:
|
||||
|
||||
```text
|
||||
p_IMU = T_IMU_lidar · p_lidar
|
||||
```
|
||||
|
||||
**当前阶段:** 算法与合成自检已闭环;已提供 `tools/export_rscap_to_v1.py`(N300 `.rscap` + H32 dlog/MSOP → 中间格式);**合格实车验收尚未完成**,故正式外参尚未对实车落盘交付。
|
||||
|
||||
---
|
||||
|
||||
## 先看什么(对外三份就够)
|
||||
|
||||
|
||||
| 顺序 | 文档 | 用途 |
|
||||
| --- | -------------------------------------- | -------------------- |
|
||||
| 1 | **本 README** | 做什么、怎么跑、结果怎么判 |
|
||||
| 2 | [docs/V1_数据格式.md](docs/V1_数据格式.md) | 中间格式 + 原始数据导出命令 |
|
||||
| 3 | [docs/标定流程与采集清单.md](docs/标定流程与采集清单.md) | 现场怎么采(合格数据要求) |
|
||||
|
||||
|
||||
其余(方法细述、测试说明、源码职责、CHANGELOG)给深入阅读 / 改代码时用,见文末。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 1. 输入 / 输出
|
||||
|
||||
|
||||
| 输入 | 说明 |
|
||||
| --------- | ----------------------------------------------------------- |
|
||||
| `imu.csv` | `t,gx,gy,gz,ax,ay,az`(秒;rad/s;m/s²);`t` 用设备时间 |
|
||||
| 雷达会话目录 | `frames_index.csv` + `frames/*.npz`(米制 XYZ) |
|
||||
| 车辆 YAML | 轴向与时间语义;外参真值可空(`config/vehicle_installation.template.yaml`) |
|
||||
|
||||
|
||||
|
||||
| 输出 | 说明 |
|
||||
| ------------------ | ---------------------- |
|
||||
| `T_IMU_lidar.json` | 外参 |
|
||||
| `time_offset.json` | `t_imu = t_lidar + δt` |
|
||||
| `summary.json` | 状态、残差、可观性 |
|
||||
|
||||
|
||||
新车原始数据导出(H32 dlog/zip + HI13 rscap):
|
||||
|
||||
```powershell
|
||||
python tools\export_rscap_to_v1.py `
|
||||
--imu-rscap path\to\hi13r4-imu.rscap `
|
||||
--imu-kind hi13 `
|
||||
--lidar-dlog path\to\session_or_recovered.zip `
|
||||
--host-start 2026-08-08T17:40:05 `
|
||||
--host-end 2026-08-08T17:45:15 `
|
||||
--out path\to\session_v1 `
|
||||
--require-difop
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 2. 一键复现(合成,不需实车)
|
||||
|
||||
```powershell
|
||||
cd <本仓库根目录>
|
||||
python -m pip install -e ".[dev]"
|
||||
python -m pip install -e ".[open3d]" # 推荐
|
||||
powershell -File tools\reproduce_synthetic.ps1
|
||||
```
|
||||
|
||||
证明:链路可跑通,能收回已知 yaw / δt。
|
||||
不证明:实车安装精度、平移可交付。
|
||||
|
||||
产物在 `examples/synthetic_session/out/`(含 `summary.json` 与 `motion_pairs.json`)。叠点查看:
|
||||
|
||||
```powershell
|
||||
# 优先读取 summary 同目录的 motion_pairs.json,按需加载点云(无需重算配准)
|
||||
python tools\visualize_pair_3d.py `
|
||||
--lidar examples\synthetic_session\lidar `
|
||||
--summary examples\synthetic_session\out\summary.json `
|
||||
--pair-index 0
|
||||
```
|
||||
|
||||
旧标定目录若缺少缓存,可只补导出运动对(不重求解外参):
|
||||
|
||||
```powershell
|
||||
python tools\export_motion_pairs_for_viz.py `
|
||||
--lidar path\to\lidar `
|
||||
--imu path\to\imu.csv `
|
||||
--summary path\to\out\summary.json
|
||||
```
|
||||
|
||||
键 `1`–`4` 切换叠点模式;`N`/`P` 切换运动对。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 3. 真实数据怎么跑
|
||||
|
||||
1. 按采集清单录制(设备时间;静止 + 低速转弯;有结构场景)
|
||||
2. 导出中间格式(第1节命令)
|
||||
3. 填写车辆 YAML 的轴向与时间语义
|
||||
4. 标定:
|
||||
|
||||
```powershell
|
||||
python -m imu_lidar.cli run `
|
||||
--vehicle-config config\vehicle_installation.template.yaml `
|
||||
--imu path\to\session_v1\imu.csv `
|
||||
--lidar path\to\session_v1\lidar `
|
||||
--output path\to\out `
|
||||
--mode rotation_only `
|
||||
--time-offset-search-s 2.0
|
||||
```
|
||||
|
||||
1. 看 `summary.json`,再叠点 / 用验证会话复核后才交付
|
||||
|
||||
|
||||
| 模式 | 交付 | 成功标志 |
|
||||
| ------------------- | ------- | --------------------------- |
|
||||
| `rotation_only`(先做) | 旋转 + δt | `rotation_only_accepted` |
|
||||
| `full_se3`(激励够再试) | + 可观平移 | `full_se3_accepted`(否则平移拒绝) |
|
||||
|
||||
|
||||
|
||||
| `summary.json` 状态 | 含义 |
|
||||
| ---------------------------------------------- | ----------- |
|
||||
| `rotation_only_accepted` / `full_se3_accepted` | 可进入验证 |
|
||||
| `full_se3_rejected_due_to_observability` | 旋转可用,平移不交 |
|
||||
| `blocked` | **不可作安装参数** |
|
||||
|
||||
|
||||
预期量级:旋转约 0.5°–2°;水平平移数厘米~十几厘米;无坡时竖直常不可观。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 4. 方法(一句话)
|
||||
|
||||
关键帧雷达配准得 **B**,同区间 IMU 预积分得 **A**,解 `R_A R_X ≈ R_X R_B`;再估 δt。可观时才在 `full_se3` 下交平移。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 5. 试验边界(勿误读)
|
||||
|
||||
|
||||
| | 合成 pytest | 旧车 S2 线下 |
|
||||
| ------ | ------------------------ | ----------------- |
|
||||
| 目的 | 回归算法 | 验证旧主机时间数据上链路能跑完 |
|
||||
| 期望 | `rotation_only_accepted` | `blocked`**(预期)** |
|
||||
| 当安装参数? | 否 | **否** |
|
||||
|
||||
|
||||
细节:[tests/README.md](tests/README.md)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 6. 仓库结构与其余文档
|
||||
|
||||
```text
|
||||
imu_lidar/ 算法与 CLI
|
||||
config/ 车辆配置模板
|
||||
docs/ 采集清单、数据格式、方法细述
|
||||
tools/ 导出、合成复现、可视化
|
||||
tests/ 自动化测试
|
||||
```
|
||||
|
||||
|
||||
| 文档 | 何时看 |
|
||||
| ------------------------------------------------ | ---------------- |
|
||||
| [docs/IMU-LiDAR标定.md](docs/IMU-LiDAR标定.md) | 要看方法约定与实现状态表 |
|
||||
| [tests/README.md](tests/README.md) | 要看合成用例 / S2 烟测记录 |
|
||||
| [imu_lidar/文件职责说明.md](imu_lidar/文件职责说明.md) | 要改源码 |
|
||||
| [imu_lidar/CHANGELOG.md](imu_lidar/CHANGELOG.md) | 要查改动史 |
|
||||
|
||||
|
||||
改算法请同步职责说明与 CHANGELOG;改对外用法请更新本 README。
|
||||
@@ -1,177 +0,0 @@
|
||||
# RTK-IMU 标定:流程、结果与复现
|
||||
|
||||
本文是本次 G90 双天线 RTK 与 HI13 IMU 标定的工程入口。算法代码在 `rtk_imu/`,命令入口在 `tools/`,正式审核结果在 `artifacts/rtk_imu_calibration_v3/`。原始 `.rscap`、统一导出数据、状态快照与 checkpoint 均只保留本地,不提交仓库。
|
||||
|
||||
## 一句话结论
|
||||
|
||||
RTK-IMU 旋转外参由双天线基线方向与水平静止重力约束获得;平移外参以机械测量为绝对基准,再通过 RTK+IMU 联合状态图、高动态转弯/坡道数据、独立 held-out 数据和旋转扰动测试进行一致性验证。
|
||||
|
||||
当前动态数据不足以独立高精度求出完整 XYZ 杆臂,因此它不是 data-only translation calibration。机械测量给出了杆臂的绝对值;在未参与标定的数据、转弯等杆臂敏感运动以及旋转外参扰动测试中,均未发现该机械外参存在明显矛盾或不稳定性。当前结果的正确表述是:**机械杆臂锚定,并经动态数据一致性验证的工程候选**。
|
||||
|
||||
## 当前工程候选与状态
|
||||
|
||||
坐标约定:`l_I = p_ANT1^I`,即 ANT1(主天线、左侧)相位中心在 IMU 坐标系中的位置。车体/RTK 安装坐标为:+X 为 ANT1(左)到 ANT2(右),+Y 为车辆前进方向且与 IMU +Y 同向,+Z 向上;GGA 参考点为 ANT1 相位中心,离地 `1.916499878 m`。
|
||||
|
||||
- 固定旋转来源:`R2G_gravity_level_prior`。
|
||||
- 固定旋转近似 RPY(X/Y/Z):`[0.454°, -0.003°, 0.012°]`。
|
||||
- 当前工程候选杆臂:`l_I = [-0.4518015159, -0.2644749820, 0.7314656115] m`。
|
||||
- 变换约定:`p_RTK = R_RTK_IMU * p_IMU + t_RTK_IMU`。
|
||||
- 对应候选 `T_RTK_IMU`(四舍五入到 6 位小数):
|
||||
|
||||
```text
|
||||
[[ 1.000000, -0.000214, -0.000044, 0.451777],
|
||||
[ 0.000214, 0.999969, -0.007929, 0.270363],
|
||||
[ 0.000046, 0.007929, 0.999969, -0.729325],
|
||||
[ 0.000000, 0.000000, 0.000000, 1.000000]]
|
||||
```
|
||||
|
||||
当前门禁状态必须同时保留:
|
||||
|
||||
- `data_only_translation_accepted=false`:数据本身没有提供足够稳定的完整平移可观性。
|
||||
- `engineering_translation_accepted=false`:独立传播验证仍存在公共加速度偏差,不能声称正式工程放行。
|
||||
- `independent_extrinsic_sensitive_validation_passed=true`:杆臂敏感的高动态验证未发现机械杆臂冲突。
|
||||
- `heldout_physical_validation_passed=true`、`rotation_sensitivity_passed=true`:固定候选在 held-out 物理残差和旋转扰动中保持一致。
|
||||
|
||||
因此不得描述为“data-only 标定平移”或“动态数据已精确细化机械杆臂”。完整、机器可读的结论见 [engineering_release_decision.json](artifacts/rtk_imu_calibration_v3/engineering_release_decision.json)。
|
||||
|
||||
## 求解流程
|
||||
|
||||
1. **统一原始数据导出。** 使用 G90/HI13 设备时间作为主时间轴;host receive time 仅用于诊断。G90 保留 GGA 质量、GNHPR 基线及质量、BESTNAVA Doppler velocity,必要时 PVTSLNA;HI13 保留 system time、gyro、accel、姿态/四元数和 host receive time。
|
||||
2. **R0 连续性与质量控制。** 校验 checksum、RTK Fixed、设备时间单调性、IMU 覆盖、baseline jump 与测量间隔。轨迹连续性由 IMU 设备时间和预积分覆盖决定;孤立 HPR 缺失/Q5 只禁用或降权 HPR factor,不切断 IMU 轨迹。
|
||||
3. **旋转外参。** R1b 从基线与 IMU 动态估计 ANT1→ANT2 在 IMU 中的 2DoF 方向;R2V 用基线与高质量 Doppler 速度作独立诊断;R2G 使用水平静止场地中的基线+重力+地面水平先验补齐完整旋转。R2G 是本次正式固定旋转来源,旧 GNHPR 三轴手眼只作诊断。
|
||||
4. **节点状态图。** 每个 GNSS node 包含 `R,p,v,bg,ba` 的 15DoF 状态;相邻 node 由 covariance-whitened IMU preintegration 和 bias random walk 连接。BEST 约束 XYZ,GGA 仅在 BEST 缺失时约束 XY,Doppler 约束速度,HPR 是可选姿态/基线因子。
|
||||
5. **机械锚定的平移验证。** 杆臂以机械值为基准,分别比较无先验 free、固定机械杆臂和软先验解。free 解只用于观测性诊断,不能因为数值收敛就替代机械值。
|
||||
6. **独立验证。** 使用 circle、left-right、slope 的高动态非重叠窗口;再使用剩余 held-out 窗口、旋转 ±扰动敏感性、独立 innovation 和 propagation-bias root-cause audit 复核。
|
||||
|
||||
## 证据与限制
|
||||
|
||||
47 个非重叠标定窗口上的 free/fixed/prior 对比表明机械先验与数据拟合相容,但 posterior/prior 方差比没有显示足够的数据驱动细化,因此 `translation_refined_by_data=false`。剩余 267 个 frozen held-out 窗口的物理验证通过;然而独立传播创新在低速、低角速度区间同时出现位置和 Doppler 的同向偏差,等效为约 `0.20 m/s²` 的公共传播加速度误差。
|
||||
|
||||
该误差在 `|omega|` 很小时不能优先归因于杆臂速度项 `R*(omega × l)`,因此它不单独否决高动态杆臂敏感验证;但在传播模型根因关闭前,也不能把候选杆臂标为正式工程已放行。
|
||||
|
||||
主要审核证据:
|
||||
|
||||
- [47 窗口机械分支](artifacts/rtk_imu_calibration_v3/mechanical_prior_engineering_47_window.json)
|
||||
- [held-out 验证](artifacts/rtk_imu_calibration_v3/mechanical_prior_engineering_heldout.json)
|
||||
- [独立创新审计](artifacts/rtk_imu_calibration_v3/heldout_independent_innovation.json)
|
||||
- [传播偏差根因审计](artifacts/rtk_imu_calibration_v3/propagation_bias_root_cause_audit.json)
|
||||
- [旋转敏感性](artifacts/rtk_imu_calibration_v3/mechanical_prior_rotation_sensitivity.json)
|
||||
|
||||
## 如何复现
|
||||
|
||||
### 1. 准备环境和原始数据
|
||||
|
||||
```powershell
|
||||
cd <repository-root>
|
||||
python -m pip install -e ".[dev]"
|
||||
```
|
||||
|
||||
将三批 G90/HI13 原始 `.rscap` 会话放到本机的数据位置。数据位置不写入仓库;`tools/export_rtk_imu_unified.py` 中的会话配对清单必须与实际采集文件一致。
|
||||
|
||||
```powershell
|
||||
$OUT = "artifacts\rtk_imu_calibration_v3\reproduce"
|
||||
python tools\export_rtk_imu_unified.py --output-root "$OUT\unified" --overwrite
|
||||
$MANIFEST = "$OUT\unified\manifest.json"
|
||||
```
|
||||
|
||||
导出后应检查每个会话目录中的 `export_summary.json`,并确认 `manifest.json` 中记录的传感器时间轴没有被 host receive time 替换。
|
||||
|
||||
### 2. 复现固定旋转
|
||||
|
||||
`<flat-static-session-id>` 必须是已确认地面水平、车辆静止的会话;可多次传入 `--level-static`。R2V 只作独立诊断,不替代 R2G。
|
||||
|
||||
```powershell
|
||||
python tools\run_rtk_imu_multisource.py `
|
||||
--manifest $MANIFEST `
|
||||
--level-static <flat-static-session-id> `
|
||||
--output "$OUT\r2g_multisource.json"
|
||||
```
|
||||
|
||||
检查输出的 R2G 旋转与本 README 的近似 RPY 一致后,将该旋转固定为后续 node graph 的 `--rotation-rpy-deg 0.454 -0.003 0.012`。若 R2G 不一致,应停止,先复核天线方向、场地水平和时间/轴定义,不应继续求杆臂。
|
||||
|
||||
### 3. 复现窗口选择与无先验诊断
|
||||
|
||||
从 circle、left-right、slope 三类会话中选择高质量窗口;窗口不可共享 IMU/GNSS/HPR 样本。仓库提交的 `lever_information_window_selection*.json` 是本次审核所用选择结果,可用于对照。
|
||||
|
||||
```powershell
|
||||
python tools\select_rtk_imu_windows_by_lever_information.py `
|
||||
--manifest $MANIFEST `
|
||||
--circle-session <circle-session-id> `
|
||||
--left-right-session <left-right-session-id> `
|
||||
--slope-session <slope-session-id> `
|
||||
--output "$OUT\selection.json" `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
|
||||
python tools\run_rtk_imu_node_graph_free_selected.py `
|
||||
--manifest $MANIFEST `
|
||||
--selection "$OUT\selection.json" `
|
||||
--output "$OUT\free_baseline.json" `
|
||||
--start-name all `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
```
|
||||
|
||||
free solve 的作用是输出边缘化杆臂信息、协方差、最弱方向和多初值稳定性;本次数据若仍未达到完整 XYZ 可观性,不得扩大无先验求解规模来强行放行。
|
||||
|
||||
### 4. 复现机械杆臂分支和 held-out 验证
|
||||
|
||||
固定工程候选杆臂并使用同一批非重叠标定窗口。`states.npz` 和 checkpoint-dir 是本地过程产物,应保持被 `.gitignore` 排除。
|
||||
|
||||
```powershell
|
||||
python tools\run_rtk_imu_mechanical_prior_branch.py `
|
||||
--manifest $MANIFEST `
|
||||
--selection "$OUT\selection.json" `
|
||||
--free-baseline "$OUT\free_baseline.json" `
|
||||
--output "$OUT\mechanical_47_window.json" `
|
||||
--state-output "$OUT\states.npz" `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
|
||||
python tools\run_rtk_imu_mechanical_prior_heldout.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection "$OUT\selection.json" `
|
||||
--all-selection <all-nonoverlapping-selection.json> `
|
||||
--engineering-result "$OUT\mechanical_47_window.json" `
|
||||
--output "$OUT\heldout.json" `
|
||||
--checkpoint-dir "$OUT\heldout_checkpoints" `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
```
|
||||
|
||||
随后运行独立 innovation、传播根因审计和旋转敏感性。它们不重新优化杆臂,不应被用于调 covariance、R2G 或机械先验。
|
||||
|
||||
```powershell
|
||||
python tools\audit_rtk_imu_heldout_innovation.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection "$OUT\selection.json" `
|
||||
--all-selection <all-nonoverlapping-selection.json> `
|
||||
--engineering-result "$OUT\mechanical_47_window.json" `
|
||||
--output "$OUT\heldout_innovation.json" `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
|
||||
python tools\audit_rtk_imu_propagation_bias_root_cause.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection "$OUT\selection.json" `
|
||||
--all-selection <all-nonoverlapping-selection.json> `
|
||||
--engineering-result "$OUT\mechanical_47_window.json" `
|
||||
--output "$OUT\propagation_bias_root_cause.json" `
|
||||
--rotation-rpy-deg 0.454 -0.003 0.012
|
||||
```
|
||||
|
||||
最终仅汇总已生成的结果,不在 release 阶段重新拟合:
|
||||
|
||||
```powershell
|
||||
python tools\finalize_rtk_imu_engineering_release.py `
|
||||
--calibration "$OUT\mechanical_47_window.json" `
|
||||
--heldout-postfit "$OUT\heldout.json" `
|
||||
--innovation "$OUT\heldout_innovation.json" `
|
||||
--sensitivity <rotation_sensitivity.json> `
|
||||
--convergence-retry <heldout_retry.json> `
|
||||
--propagation-root-cause "$OUT\propagation_bias_root_cause.json" `
|
||||
--output "$OUT\engineering_release_decision.json"
|
||||
```
|
||||
|
||||
## 相关文件
|
||||
|
||||
- [RTK-IMU 代码包](rtk_imu/README.md)
|
||||
- [多源导出与旋转 V3 说明](docs/rtk_imu_multisource_v3.md)
|
||||
- [engineering 6DoF 说明](docs/rtk_imu_engineering_6dof.md)
|
||||
- [历史链路审计](docs/rtk_imu_calibration.md)
|
||||
- [正式结果索引](artifacts/rtk_imu_calibration_v3/README.md)
|
||||
@@ -14,4 +14,4 @@
|
||||
- `translation_result.json`:杆臂、平移、齐次矩阵、协方差/秩、位置/速度残差、偏置和 LOO。
|
||||
- `summary.json`:供程序读取的最终状态和候选矩阵。
|
||||
|
||||
当前 `all_sessions/summary.json` 是 `diagnostic_not_accepted`。其中平移约 `[0.771, 0.569, -21.073] m` 明显不具机械真实性,禁止用于车辆配置。完整解释见 `docs/rtk_imu_calibration.md`。
|
||||
当前 `all_sessions/summary.json` 是 `diagnostic_not_accepted`。其中平移约 `[0.771, 0.569, -21.073] m` 明显不具机械真实性,禁止用于车辆配置。完整解释见 [RTK–IMU 标定说明](../../docs/RTK-IMU标定.md)。
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
# RTK-IMU V3 正式结果集
|
||||
# RTK–IMU V3 结果与审核证据
|
||||
|
||||
本目录只提交复现工程结论所需的审核结果。运行过程中的调试输出、状态快照、逐窗口 checkpoint 和旧版结果保留在本机,由仓库根目录 `.gitignore` 排除。
|
||||
本目录保存**已提交的审核快照**。它不是原始数据目录,也不是日常运行的输出目录;原始 `.rscap`、统一导出、节点状态、checkpoint 和调试文件均应保留在本地工作目录。
|
||||
|
||||
## 当前结论
|
||||
## 先读哪个文件
|
||||
|
||||
- 固定旋转来源:`R2G_gravity_level_prior`。
|
||||
- 工程候选杆臂:`l_I = p_ANT1^I = [-0.4518015159, -0.2644749820, 0.7314656115] m`。
|
||||
- `data_only_translation_accepted=false`。
|
||||
- `engineering_translation_accepted=false`,原因是独立传播验证仍受公共加速度偏差影响。
|
||||
- `independent_extrinsic_sensitive_validation_passed=true`;当前结果可描述为机械杆臂经动态数据一致性验证的工程候选,不得描述为 data-only 平移标定结果。
|
||||
1. `engineering_release_decision.json`:唯一的最终结论,包含候选杆臂、两个互逆变换、验收状态、禁止的表述和全部证据路径。
|
||||
2. `mechanical_prior_engineering_47_window.json`:47 个非重叠标定窗口中,无先验、固定机械杆臂和机械软约束结果的对比。
|
||||
3. `mechanical_prior_engineering_heldout.json`:267 个独立留出窗口的物理残差与收敛情况。
|
||||
4. `heldout_independent_innovation.json` 与 `propagation_bias_root_cause_audit.json`:解释最终未放行的独立传播误差。
|
||||
|
||||
## 文件说明
|
||||
## 文件分组
|
||||
|
||||
- `engineering_release_decision.json`:最终状态、变换和放行判定。
|
||||
- `mechanical_prior_engineering_47_window.json`:相同 47 个非重叠窗口上的 free/fixed/prior 对比。
|
||||
- `node_graph_free_information_selected_mechanical.json`:冻结的无先验 free-solve 基线。
|
||||
- `lever_information_window_selection*.json`:窗口选择及实际边缘信息复核。
|
||||
- `mechanical_prior_engineering_heldout.json`:未参与标定窗口的 held-out 验证。
|
||||
- `heldout_independent_innovation.json`、`heldout_nonconverged_retry.json`:独立创新与失败窗口重试结果。
|
||||
- `mechanical_prior_rotation_sensitivity.json`:固定候选杆臂的旋转扰动敏感性结果。
|
||||
- `propagation_bias_root_cause_audit.json`:独立传播公共加速度误差根因审计。
|
||||
| 分组 | 文件 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 发布结论 | `engineering_release_decision.json` | 当前唯一的放行判断。 |
|
||||
| 旋转与数据质量 | `multisource_result.json`、`bestnava_doppler_factor_yield_*.json`、`hpr_dropout_bridge_*.json` | 原始数据、旋转和双天线观测可用性的审核。 |
|
||||
| 杆臂与选窗 | `lever_information_window_selection*.json`、`node_graph_free_information_selected_mechanical.json`、`mechanical_prior_engineering_47_window.json` | 无先验可观性、固定窗口及机械杆臂一致性。 |
|
||||
| 独立验证 | `mechanical_prior_engineering_heldout.json`、`heldout_independent_innovation.json`、`heldout_nonconverged_retry.json`、`mechanical_prior_rotation_sensitivity.json` | 留出数据、创新、重试和旋转扰动检查。 |
|
||||
| 根因和历史审计 | `propagation_bias_root_cause_audit.json`、`motion_excitation_*.json`、`factor_consistency_audit.json` 等 | 帮助理解过程和未解决问题;不替代发布结论。 |
|
||||
|
||||
结果 JSON 是审核快照;需要重新生成时应通过 `tools/` 中相应入口运行,且不得提交运行产生的 checkpoint 或 `.npz` 状态文件。
|
||||
`lever_information_window_selection.json` 记录 47 个标定窗口;`lever_information_window_selection_refined.json` 记录 314 个全部非重叠窗口,可从中扣除前者得到 267 个留出窗口。`mechanical_prior_engineering_47_window_states.npz` 是历史缓存,不是必需输入,也不应重新提交。
|
||||
|
||||
当前结论、术语和可执行复现步骤见 [RTK–IMU 标定](../../docs/RTK-IMU标定.md)。
|
||||
@@ -1,209 +0,0 @@
|
||||
# 20260808 HI13 + H32:LiDAR–IMU 标定现状与问题
|
||||
|
||||
> 数据:`D:\data\calibration_usable_20260808`
|
||||
> 可用会话:`sessions_v1_host_aligned`(三优先窗)
|
||||
> 当前结果目录:各窗 `out_fixed_dt0/`
|
||||
> 清单:`sessions_v1_host_aligned/calibration_manifest_fixed_dt0.json`
|
||||
> 车辆配置:`config/vehicle_hi13_h32_20260808.yaml`
|
||||
> 约定外参:`p_IMU = T_IMU_lidar · p_lidar`
|
||||
|
||||
---
|
||||
|
||||
## 1. 一句话结论
|
||||
|
||||
**旋转 + 主机桥接时间对齐可以冻结;平移(full_se3)尚不可正式交付。**
|
||||
三窗 `rotation_only`(δt=0)结果跨窗一致,**不必因平移先验 Z 修正而重跑旋转**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前可用结果(`out_fixed_dt0`)
|
||||
|
||||
约定:`p_IMU = T_IMU_lidar · p_lidar`;本轮交付 **仅旋转**,`t = [0,0,0]`,`time_offset_s = 0`。
|
||||
|
||||
| 窗 | 状态 | δt | roll/pitch/yaw (°) | 手眼 RMS (°) | 手眼对数 | vs CAD prior |
|
||||
|----|------|----|---------------------|--------------|----------|--------------|
|
||||
| `priority_174005_174515` | `rotation_only_accepted` | 0 | −0.398 / +0.108 / **89.998** | 0.625 | 1374 | 0.413° |
|
||||
| `priority_174905_175450` | 同上 | 0 | −0.316 / −0.352 / **90.002** | 0.293 | 1182 | 0.473° |
|
||||
| `priority_175910_180530` | 同上 | 0 | −0.373 / −0.036 / **90.005** | 0.786 | 789 | 0.375° |
|
||||
|
||||
- 跨窗旋转互差约 **0.15°–0.47°**(相对三窗均值 ≤0.26°)。
|
||||
- CAD/安装平移先验只用于后续 SE3 / 校验,不写入本轮交付 `T`。
|
||||
- 原始摘要:各窗 `out_fixed_dt0/summary.json`;总表 `calibration_manifest_fixed_dt0.json`。
|
||||
|
||||
### 2.1 窗1 `priority_174005_174515` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_174005_174515\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.39806616272552936, 0.10842366761721789, 89.99788311264182]`
|
||||
- quaternion_xyzw:`[-0.0031254048203223084, -0.0017872288323561246, 0.7070914597978358, 0.707112936622415]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[ 3.6946588133e-05, -0.9999758655693408, -0.0069474393698490 ],
|
||||
[ 0.9999982088237712, 2.3798651350e-05, 0.0018925598731371 ],
|
||||
[-0.0018923488575947, -0.0069474968493909, 0.9999740753156198 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 2.2 窗2 `priority_174905_175450` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_174905_175450\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.31554362742542746, -0.35231680831805484, 90.00193338170823]`
|
||||
- quaternion_xyzw:`[0.00022698471903919405, -0.004121119694188399, 0.7071067019847445, 0.7070948146172911]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[-3.3743238552e-05, -0.9999848355714863, -0.0055070399001942 ],
|
||||
[ 0.9999810938467022, 1.2097239027e-07, -0.0061491421465438 ],
|
||||
[ 0.0061490495645171, -0.0055071432752239, 0.9999659297008071 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 2.3 窗3 `priority_175910_180530` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_175910_180530\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.37335575043737196, -0.03585856981709423, 90.00538974486676]`
|
||||
- quaternion_xyzw:`[-0.002082462199099642, -0.002525219418619018, 0.7071355299053291, 0.7070704554452735]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[-9.4068775206e-05, -0.9999787650354249, -0.0065161821101807 ],
|
||||
[ 0.9999997997313592, -8.9988606603e-05, -0.0006264497522950 ],
|
||||
[ 0.0006258500675082, -0.0065162397345547, 0.9999785732361544 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 相对历史失败轮次
|
||||
|
||||
| 轮次 | 问题 | 结果 |
|
||||
|------|------|------|
|
||||
| `sessions_v1_aligned` | 首帧强行对齐设备钟 | 三窗手眼失败,RMS ~9°–12° |
|
||||
| 自由估 δt + signed refine | 窗3 δt 漂到 −0.48 s;窗2 yaw≈19° | 跨窗 yaw 矛盾(81°/19°/93°) |
|
||||
| **本轮 fixed δt=0** | 主机桥接后冻结时间 | 三窗 yaw≈90°,可互证 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 已澄清并写入配置的坐标系 / 先验
|
||||
|
||||
### 3.1 车体与传感器
|
||||
|
||||
- 车体:X 前 / Y 左 / Z 上;雷达与 IMU 安装在 **X 正方向**(后轮轴前方)。
|
||||
- CAD 图纸可能画成 +X 朝后,那只是读图坐标系,**不是**车体真实轴。
|
||||
- IMU:HI13 RFU(X 右 / Y 前 / Z 上),原始数据不做轴向重映射。
|
||||
- 雷达 NPZ:假定与车体一致(X 前 / Y 左 / Z 上)。
|
||||
|
||||
### 3.2 安装量(`translation_m`)
|
||||
|
||||
| 传感器 | X / Y(后轮轴中心) | Z(离地) |
|
||||
|--------|---------------------|-----------|
|
||||
| IMU | 2.574 / 0.0365 m | 0.8925 + 0.294 = **1.1865 m** |
|
||||
| 雷达 | 2.522 / 0.00002 m | 相位中心离地 **1.994999879 m** |
|
||||
|
||||
- 后轮轴中心离地:**294 mm**(Z 用离地高时加在 CAD 轴心高上)。
|
||||
- 雷达 CAD `dZ=1.637499879 m`;相位中心离地还需加后轮轴离地 `0.294 m` 和相位中心偏移 `0.0635 m`,最终为 `1.994999879 m`。
|
||||
|
||||
### 3.3 导出外参先验
|
||||
|
||||
- `R_IMU_lidar` ≈ yaw 90°:`[[0,-1,0],[1,0,0],[0,0,1]]`(软约束 σ=15°)。
|
||||
- `t_IMU_lidar` ≈ **`[0.0365, -0.0518, 0.8085]` m**(相对 Z = 1.994999879 − 1.1865 = 0.808499879 m)。
|
||||
- **旋转先验不因 Z 修正改变**;平移先验 Z 更新为 0.808499879 m。
|
||||
|
||||
---
|
||||
|
||||
## 4. 现存问题清单
|
||||
|
||||
### P1. IMU 预积分平移 `Δp` 不可用(阻塞正式平移)
|
||||
|
||||
- 现象:可视化模式 4 若用完整 `X⁻¹ A X`,橙/蓝点云常呈**上下错层**(Z 差米级~几十米)。
|
||||
- 根因:加速度预积分缺少可靠重力/零偏处理,`t_A` 尤其 Z 发散;**不是旋转外参错了**。
|
||||
- 旁证:相对 GICP 的旋转残差中位约 0.16°;`|t_A|` 中位却常 >1 m。
|
||||
- 影响:`full_se3` / 依赖 IMU 位移的平移估计不可信。
|
||||
- 缓解(已做):`visualize_pair_3d.py` 对 `rotation_only` 默认模式 4 = **R 共轭 + GICP 的 t_B**(`--mode4-translation gicp|imu|auto`)。
|
||||
|
||||
### P2. 平面运动导致竖直平移弱可观
|
||||
|
||||
- 三优先窗以水平转弯为主,缺少缓坡/俯仰激励。
|
||||
- 流水线门控已给出 `translation_accepted=false`。
|
||||
- 即使打开平移先验(σ≈5 cm),弱激励下结果易变成**先验回显**,不宜当标定成功。
|
||||
|
||||
### P3. 时间偏移若再自由估计会被带偏(已规避,需保持)
|
||||
|
||||
- 主机 UTC 桥接(MSOP/IMU `HostReceiveUtc`)后,两路已在同一时间轴,残差通常几十毫秒量级。
|
||||
- 若再做有符号 δt 精修,会与错误/未收敛的 R 耦合,窗3 曾从约 −0.12 s 走到 **−0.48 s**。
|
||||
- **现行做法**:桥接会话使用 `--fixed-time-offset-s 0 --no-signed-time-refine`。
|
||||
|
||||
### P4. 单窗低残差 ≠ 外参正确(历史教训)
|
||||
|
||||
- 自由 δt 轮次中,窗2 手眼 RMS 最低(~0.3°)但 yaw≈19°,与 CAD/其他窗差 60°+。
|
||||
- 平面运动下 yaw 外参可出现多个能拟合 `R_A R_X ≈ R_X R_B` 的解。
|
||||
- **必须**做跨窗一致性 + 可视化叠点,不能只看单窗 RMS。
|
||||
|
||||
### P5. 旋转软先验尚未做无先验对照
|
||||
|
||||
- 当前 σ=15°;笔记显示 Tsai 初值本身已接近(约 0.3°–1.1° RMS),不像纯先验硬拽。
|
||||
- 仍缺一次:关闭先验或放大 `sigma_deg` 的对照,以排除「只是被拉到 90°」的疑虑。
|
||||
|
||||
### P6. 文档与操作约定未完全同步(工程)
|
||||
|
||||
- README 需明确写清:host-bridge 后固定 δt=0、禁用 signed refine、rotation_only 可视化用法。
|
||||
- 交付物目前缺一版「冻结的联合/中位 R + 使用说明」JSON/报告(旋转可交,平移明确不交)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 不该做 / 可以做
|
||||
|
||||
| 动作 | 建议 |
|
||||
|------|------|
|
||||
| 因 Z 先验修正重跑三窗 rotation_only | **不必**(R 未依赖新 t) |
|
||||
| 正式交付 6-DOF / 信赖当前 `Δp` 估 t | **不要** |
|
||||
| 试验性 `full_se3`(固定 R、δt=0、新 t 先验) | 可做,结果标「实验」 |
|
||||
| 可视化验收模式 3 vs 4(gicp 平移) | **建议做** |
|
||||
| 无先验 / 大 σ 旋转对照 | **建议做** |
|
||||
| 冻结交付 `R` + `δt=0` 说明 | **建议做** |
|
||||
| 补采缓坡或加强垂直尺寸约束后再估 t | 正式平移前需要 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议下一步顺序
|
||||
|
||||
1. **验收旋转**:三窗抽转弯运动对,模式 3/4 叠点;可选无先验对照。
|
||||
2. **定稿旋转**:三窗中位或联合手眼 → 交付 `R_IMU_lidar` +「δt=0(主机桥接)」说明;**明确不交 t**。
|
||||
3. **工程收尾**:README 主机桥接配方;需要时再整理联合标定脚本入口。
|
||||
4. **平移(靠后)**:改善 IMU 位移模型或改用更可靠的位移观测 + 竖直激励后,再用新 `t` 先验跑 SE3。
|
||||
|
||||
---
|
||||
|
||||
## 7. 常用路径与命令
|
||||
|
||||
```text
|
||||
数据根:
|
||||
D:\data\calibration_usable_20260808\sessions_v1_host_aligned\
|
||||
|
||||
结果:
|
||||
...\priority_XXXX\out_fixed_dt0\summary.json
|
||||
...\priority_XXXX\out_fixed_dt0\motion_pairs.json
|
||||
...\calibration_manifest_fixed_dt0.json
|
||||
```
|
||||
|
||||
```powershell
|
||||
# 可视化(rotation_only 默认模式4用 GICP 平移)
|
||||
python tools\visualize_pair_3d.py `
|
||||
--lidar D:\data\calibration_usable_20260808\sessions_v1_host_aligned\priority_174005_174515\lidar `
|
||||
--summary D:\data\calibration_usable_20260808\sessions_v1_host_aligned\priority_174005_174515\out_fixed_dt0\summary.json `
|
||||
--pair-index 0
|
||||
|
||||
# 若要看「坏 Δp」导致的错层效果:
|
||||
# --mode4-translation imu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 问题优先级(跟踪用)
|
||||
|
||||
| ID | 严重度 | 状态 | 标题 |
|
||||
|----|--------|------|------|
|
||||
| P1 | 高 | 未解决 | IMU `Δp` 不可用,阻塞正式平移 |
|
||||
| P2 | 高 | 未解决 | 平面运动,竖直 t 弱可观 |
|
||||
| P3 | 高 | 已规避 | 自由 δt / signed refine 带偏(需保持冻结) |
|
||||
| P4 | 中 | 已吸收教训 | 单窗低残差不可单独验收 |
|
||||
| P5 | 中 | 待做 | 无旋转先验对照 |
|
||||
| P6 | 低 | 待做 | README/交付物同步 |
|
||||
@@ -1,195 +0,0 @@
|
||||
# LiDAR–IMU 外参标定说明
|
||||
|
||||
**用途:** 方法约定与实现状态(深入阅读)。日常使用请先看根目录 [`README.md`](../README.md)。
|
||||
|
||||
本文说明标定目标、约定、流水线与实现状态。代码在 `imu_lidar/`。场地采集见 [`标定流程与采集清单.md`](标定流程与采集清单.md)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标与约定
|
||||
|
||||
估计安装外参:
|
||||
|
||||
```text
|
||||
p_IMU = T_IMU_lidar · p_lidar
|
||||
```
|
||||
|
||||
约定:`T_A_B` 表示把 **B 系点**变换到 **A 系**。
|
||||
|
||||
相对运动手眼模型:
|
||||
|
||||
```text
|
||||
A_ij ≈ IMU 在 [t_i, t_j] 的相对运动(预积分)
|
||||
B_ij ≈ LiDAR 在同时间段的相对运动(关键帧配准)
|
||||
A X ≈ X B
|
||||
X = T_IMU_lidar
|
||||
```
|
||||
|
||||
旋转子问题(常规主交付):
|
||||
|
||||
```text
|
||||
R_A R_X = R_X R_B
|
||||
→ R_IMU_lidar
|
||||
```
|
||||
|
||||
若已有完整六自由度外参,且另有 `T_RTK_lidar`,可链式得到:
|
||||
|
||||
```text
|
||||
T_lidar_IMU = inverse(T_IMU_lidar)
|
||||
T_RTK_IMU = T_RTK_lidar @ T_lidar_IMU
|
||||
```
|
||||
|
||||
**不要**把 IMU 加速度二次积分成轨迹,再当作绝对位姿去做完整六自由度手眼。
|
||||
|
||||
---
|
||||
|
||||
## 2. 交付分层
|
||||
|
||||
| 层级 | 交付 | 数据最低要求 |
|
||||
|---|---|---|
|
||||
| 第一步 | 旋转 + 时间偏置 δt | **设备时间戳**;静止 + 低速转弯 /「8」字;结构化场景 |
|
||||
| 第二步 | 上一步 + 可观的水平平移 | 更多转弯半径与加减速 |
|
||||
| 第三步 | 完整六自由度(含可靠竖直分量) | 缓坡俯仰激励,或外测垂直杆臂先验 |
|
||||
|
||||
可观性不过关 → 只交旋转,不强交“假精确”六自由度。
|
||||
仅主机接收时间、或残差未过门控的结果 → **不要当作正式安装参数**。
|
||||
|
||||
---
|
||||
|
||||
## 3. 总体原则
|
||||
|
||||
1. **时间同步优先于外参**:δt 未对齐时,旋转与平移都不可信。使用设备时间戳。
|
||||
2. **先求旋转,再求平移**:旋转通常更稳;平面运动下竖直平移常常不可观。
|
||||
3. **用连续运动标定**:停车多站、再靠站间长积分,不适合作为纯 IMU 外参主流程。
|
||||
4. **可观性门控**:过不了就降级交付。
|
||||
5. **残差小 ≠ 标定对**:需叠点云 / 跨会话等独立验证。
|
||||
6. **首轮建议低速**:先保证配准与时间对齐;点云去畸变可选。
|
||||
7. **安装参数不写死在源码**:轴向与时间语义进 YAML;机械尺寸可作检查,不能伪装成已标定平移。
|
||||
8. **注意耦合**:时间相关峰很弱时,δt、航向角与陀螺零偏可能互相补偿,结果不可当真。
|
||||
|
||||
---
|
||||
|
||||
## 4. 流水线(现行实现)
|
||||
|
||||
```text
|
||||
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](V1_数据格式.md)。改动史见 [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md)。
|
||||
|
||||
### 运行示例
|
||||
|
||||
```powershell
|
||||
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. 采集要点
|
||||
|
||||
单趟动态会话:
|
||||
|
||||
```text
|
||||
[静止 20–30 s] → [低速激励 3–8 min] → [再静止 10–20 s]
|
||||
```
|
||||
|
||||
优先激励:
|
||||
|
||||
- 低速「8」字 / 左右圆(旋转主激励)
|
||||
- 直线加减速(有助于时间对齐与水平平移)
|
||||
- 缓坡(仅完整六自由度需要):约 3°~8°,连续长度优先 ≥ 20~30 m
|
||||
|
||||
硬条件:IMU / LiDAR **设备时间戳**;结构化场景;标定全程安装不得改动。
|
||||
|
||||
更完整的现场清单见 [标定流程与采集清单.md](标定流程与采集清单.md)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 数学上允许与禁止
|
||||
|
||||
禁止:加速度二次积分当真值轨迹;把只有旋转的相对运动硬补成完整六自由度;用最终外参反向筛边掩盖失败。
|
||||
|
||||
允许:预积分旋转手眼求旋转;在可观时用预积分残差联合估计平移,并精修零偏等辅助量。
|
||||
|
||||
---
|
||||
|
||||
## 7. 车辆配置
|
||||
|
||||
使用 `--vehicle-config vehicle_installation.yaml`。
|
||||
模板中安装平移/旋转保持未标定状态,直至实测确认;禁止写死某车杆臂冒充结果。
|
||||
|
||||
---
|
||||
|
||||
## 8. 实现状态(当前阶段)
|
||||
|
||||
本仓库**仅此一条**标定路径:连续运动关键帧 + IMU 预积分。对外总览与「合成 / 旧车 / 合格数据预期」见根目录 [`README.md`](../README.md) §0。
|
||||
|
||||
| 项 | 状态 |
|
||||
|---|---|
|
||||
| 连续运动关键帧标定流水线 | 已实现(现行唯一路径) |
|
||||
| 加权预积分 / 加权手眼 | 已实现 |
|
||||
| 旋转预积分因子 + 有符号 δt 精修 | 已实现 |
|
||||
| 完整预积分(含速度/位移增量)与可观时的平移优化 | 已实现 |
|
||||
| 可观性门控 / `rotation_only` | 已实现 |
|
||||
| 合成数据 pytest / 一键复现 | 已实现(证明链路与已知 yaw/δt,不证明实车精度) |
|
||||
| 旧车主机时间烟测(S2) | 线下可跑;预期 `blocked`,不当交付 |
|
||||
| 设备时间新车数据正式验收 | **待做** |
|
||||
| 原生存储一键导出为中间格式 | 已提供 `tools/export_rscap_to_v1.py`(N300 rscap + H32 dlog/MSOP → V1;dlog 用 DIFOP 通道角) |
|
||||
|
||||
细项见 [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md)。
|
||||
|
||||
---
|
||||
|
||||
## 9. 相关文档
|
||||
|
||||
| 内容 | 路径 | 备注 |
|
||||
|---|---|---|
|
||||
| 对外总览(优先) | 根目录 [`README.md`](../README.md) | 日常入口 |
|
||||
| 采集清单 | [`标定流程与采集清单.md`](标定流程与采集清单.md) | 现场 |
|
||||
| 数据格式 / 导出 | [`V1_数据格式.md`](V1_数据格式.md) | 中间格式 |
|
||||
| 文件职责说明 | [`imu_lidar/文件职责说明.md`](../imu_lidar/文件职责说明.md) | 改代码 |
|
||||
| 改动史 | [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md) | 改代码 |
|
||||
@@ -0,0 +1,241 @@
|
||||
# RTK–IMU 标定
|
||||
|
||||
本文是本仓库 RTK–IMU 标定的唯一规范说明,覆盖数据、方法、当前结果、限制和复现。它不使用项目内部阶段代号作为前提。
|
||||
|
||||
## 结论与适用范围
|
||||
|
||||
本次标定的正确表述是:**双天线方向和水平静止时的重力约束给出了固定旋转;天线相位中心到 IMU 的平移以机械测量为绝对基准,RTK 与 IMU 动态数据对该安装关系完成了独立一致性与稳定性验证。** 动态数据未能独立、精确地估计完整三维杆臂,但没有发现机械测量值与真实运动矛盾。
|
||||
|
||||
| 项目 | 当前值或状态 |
|
||||
| --- | --- |
|
||||
| 天线相位中心相对 IMU 的杆臂 `l_I` | `[-0.4518015159, -0.2644749820, 0.7314656115] m` |
|
||||
| 固定旋转来源 | 水平静止时的双天线基线与重力约束 |
|
||||
| 固定旋转近似 RPY(X/Y/Z) | `[0.454°, -0.003°, 0.012°]` |
|
||||
| 仅由数据估计三维平移 | 未通过:`data_only_translation_accepted=false` |
|
||||
| 正式工程平移验收 | 未通过:`engineering_translation_accepted=false` |
|
||||
| 杆臂敏感的高动态独立验证 | 通过:未发现机械杆臂冲突 |
|
||||
|
||||
该候选可用于算法联调和工程验证,但不能称为“数据独立完成的完整六自由度标定”或“正式工程放行的外参”。低速、低角速度留出数据仍显示约 `0.20 m/s²` 的共同加速度传播误差;其根因未关闭前,工程放行保持为否。机器可读结论见 [工程发布决定](../artifacts/rtk_imu_calibration_v3/engineering_release_decision.json)。
|
||||
|
||||
## 安装与坐标定义
|
||||
|
||||
- 主天线为 ANT1,位于车辆前进方向左侧;从天线为 ANT2,位于右侧;两者平行安装。
|
||||
- 双天线报文的 heading 是**主天线到从天线**的方向。
|
||||
- IMU 的 `+Y` 指向车辆前进方向;天线基线因此指向车辆右侧。
|
||||
- GGA 的参考点为 ANT1 相位中心,离地 `1.916499878 m`。
|
||||
- `l_I = p_ANT1^I` 表示从 IMU 原点指向 ANT1 相位中心、并在 IMU 坐标系表达的向量。
|
||||
|
||||
输出变换的定义为:
|
||||
|
||||
```text
|
||||
p_RTK = R_RTK_IMU · p_IMU + t_RTK_IMU
|
||||
p_IMU = R_RTK_IMUᵀ · p_RTK + l_I
|
||||
t_RTK_IMU = -R_RTK_IMU · l_I
|
||||
```
|
||||
|
||||
RTK 原点就是 ANT1,所以 `T_IMU_RTK` 的平移等于 `l_I`,两个变换必须互逆。下游实现必须按这些公式检查方向和符号。
|
||||
|
||||
## 原始数据与统一导出
|
||||
|
||||
使用三个日期的 G90 双天线 RTK 与 HI13 IMU 原始 `.rscap`。按捕获开始时间在 1.5 秒内配对,共导出 55 组会话;0815 的一组无匹配 HI13,已记录为 unmatched,不参与联合求解。
|
||||
|
||||
| 批次 | 配对会话 | GNHPR | BESTNAVA | PVTSLNA | Q4 双天线方向 | Fixed Doppler |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| 0808 | 18 | 46,180 | 8,291 | 5,993 | 45,606 | 8,128 |
|
||||
| 0815 | 28 | 96,241 | 12,660 | 9,638 | 27,045 | 3,385 |
|
||||
| 0819 | 9 | 15,717 | 2,029 | 1,427 | 14,976 | 1,930 |
|
||||
|
||||
旧导出以 GGA 为中心,将最近的 GNHPR 合并到同一行,且没有保留 BESTNAVA/PVTSLNA;这会把异步报文伪装成同时观测,也不能独立使用 GNSS 位置和 Doppler 速度。
|
||||
|
||||
新导出保留每条异步报文:
|
||||
|
||||
| 文件 | 内容 |
|
||||
| --- | --- |
|
||||
| `imu.npz` | HI13 `system_time`、三轴陀螺/加速度、RPY、四元数、磁场、PPS、温度、气压和主机接收时间 |
|
||||
| `rtk.csv` | 各 GGA/GNHPR/BESTNAVA/PVTSLNA 的测量时间、质量、校验和和原始字段 |
|
||||
| `export_summary.json` | 报文统计、四元数检查与跨时钟诊断 |
|
||||
| `manifest.json` | 会话、批次、导出目录与未配对记录 |
|
||||
|
||||
HI13 `system_time` 是主时间轴。G90 的 GNSS UTC 或周/TOW 时间原样保留,并映射到此主时间轴;主机接收时间只用于时钟桥接、延迟和抖动诊断,绝不能作为采样时间。
|
||||
|
||||
## 求解与验证流程
|
||||
|
||||
```text
|
||||
统一导出原始报文
|
||||
→ 检查校验和、固定解、时间连续性和 IMU 预积分覆盖
|
||||
→ 由双天线基线和重力固定旋转
|
||||
→ 以节点状态图检查无机械先验时的杆臂可观性
|
||||
→ 以机械杆臂为基准进行动态一致性验证
|
||||
→ 使用未参与标定的数据和高动态转弯/坡道复核
|
||||
```
|
||||
|
||||
### 旋转
|
||||
|
||||
双天线基线只提供两个方向自由度,不能单独推出完整三维姿态。因此旋转经过三类检查:
|
||||
|
||||
1. 连续高质量基线与 IMU 相对转动,检查基线在 IMU 中的方向。
|
||||
2. 基线加高速近似直线 Doppler 速度,独立检查前向;因可用高速样本不足且与 IMU 航向存在不一致,它只作诊断。
|
||||
3. 明确真实水平、车辆静止的会话中,基线确定横向,HI13 重力确定竖直,叉乘得到前向。这是当前固定旋转的正式来源。
|
||||
|
||||
旧式“直接把 GNHPR 三轴姿态与 IMU 做手眼”仅作诊断,不再作为正式外参。
|
||||
|
||||
### 平移与杆臂
|
||||
|
||||
每个 GNSS 节点包含姿态、位置、速度、陀螺偏置和加速度偏置。相邻节点由带协方差的 IMU 预积分连接;BESTNAVA 约束三维位置,Doppler 约束速度,GGA 只在 BEST 缺失时补充水平位置,双天线方向是可选姿态观测。GGA 的 MSL 高程绝不用于 ENU 的 Z 轴。
|
||||
|
||||
```text
|
||||
p_ANT1^W = p_IMU^W + R_WI · l_I
|
||||
v_ANT1^W = v_IMU^W + R_WI · ((ω - b_g) × l_I)
|
||||
```
|
||||
|
||||
无机械先验求解只用来检查可观性:边缘化其他状态后,检查三维杆臂的信息矩阵、协方差、最弱方向和不同初值稳定性。本批数据不能稳定约束完整 XYZ,所以不会用其点估计替代机械值。
|
||||
|
||||
在同一批非重叠高动态窗口中,已比较无先验诊断解、固定机械杆臂和机械软约束解。机械值没有显著恶化位置、速度或双天线残差;但数据相对机械先验的信息增益不足,不能证明数据细化了杆臂。因此绝对值仍以机械测量为准。
|
||||
|
||||
## 如何使用结果
|
||||
|
||||
可以:固定本文旋转和机械杆臂,用于定位、融合或控制算法验证;并把“机械测量 + 动态一致性验证”写入配置或报告。
|
||||
|
||||
不能:把它描述为数据独立的三维平移标定、完整六自由度正式放行,或仅凭优化收敛就宣称杆臂真实。
|
||||
|
||||
## 结果文件与本地过程文件
|
||||
|
||||
`artifacts/rtk_imu_calibration_v3/` 是**本次提交的审核快照**,不是原始数据目录,也不是每次运行的工作目录。阅读顺序如下:
|
||||
|
||||
| 类别 | 主要文件 | 用途 |
|
||||
| --- | --- | --- |
|
||||
| 最终结论 | `engineering_release_decision.json` | 唯一的放行状态、候选杆臂、两个互逆变换和限制说明;下游首先读取它。 |
|
||||
| 旋转证据 | `multisource_result.json` | 双天线方向、重力和速度诊断的旋转结果。 |
|
||||
| 杆臂一致性 | `mechanical_prior_engineering_47_window.json` | 同一 47 个标定窗口上无先验、固定机械值和机械软约束三种结果的比较。 |
|
||||
| 独立验证 | `mechanical_prior_engineering_heldout.json`、`heldout_independent_innovation.json` | 未参与标定的 267 个窗口的物理残差和独立传播创新。 |
|
||||
| 稳定性与根因 | `mechanical_prior_rotation_sensitivity.json`、`propagation_bias_root_cause_audit.json` | 固定旋转扰动的影响,以及低速传播公共加速度误差的诊断。 |
|
||||
| 固定选窗输入 | `lever_information_window_selection.json`、`lever_information_window_selection_refined.json` | 分别记录 47 个标定窗口和 314 个全部非重叠窗口;后者用于从中扣除 47 个标定窗口,得到 267 个留出窗口。 |
|
||||
| 辅助审计 | `bestnava_doppler_factor_yield_*.json`、`hpr_dropout_bridge_*.json`、`motion_excitation_*.json` 等 | 记录数据保留率、双天线短缺口处理和运动激励检查;它们解释流程选择,不单独决定放行。 |
|
||||
|
||||
目录中还保留少量历史诊断和调试快照,文件名含 `debug`、`fast_diagnostic`、`p0` 或旧 node-graph 阶段。这些不是当前发布结论,阅读时应以 `engineering_release_decision.json` 及其 `evidence` 字段指向的文件为准。`mechanical_prior_engineering_47_window_states.npz` 是一次历史状态缓存;它不是复现的必要输入,也不应在后续运行中再次提交。
|
||||
|
||||
原始 `.rscap`、统一导出目录、运行中的 `.npz` 状态、checkpoint 和临时 JSON 应放在仓库外或被忽略的本地工作目录。不要把它们覆盖到 `artifacts/rtk_imu_calibration_v3/`,以免把正式审核快照和个人运行过程混在一起。
|
||||
|
||||
## 复现
|
||||
|
||||
### 复现范围
|
||||
|
||||
| 目标 | 是否需要原始数据 | 推荐操作 |
|
||||
| --- | --- | --- |
|
||||
| 核验当前发布结论 | 否 | 读取 `engineering_release_decision.json`,并按其 `evidence` 字段查看证据 JSON。 |
|
||||
| 重做数据导出和固定旋转 | 是 | 按下文步骤 1–2 运行;结果应与本文的会话数、时间规则和旋转量级一致。 |
|
||||
| 重做机械杆臂一致性与留出验证 | 是 | 按步骤 3–5 使用冻结选窗文件;计算量较大,所有输出放到本地工作目录。 |
|
||||
| 生成新的工程结论 | 是,且需新的审核决策 | 不要复用或覆盖当前发布快照;应新建工作目录和结果目录,并重新执行完整门禁。 |
|
||||
|
||||
以下命令用于重建本次发布所依据的流程。原始数据路径不提交仓库;导出脚本目前的三批默认来源定义在 `tools/export_rtk_imu_unified.py` 的 `DEFAULT_SOURCES`。若本机原始数据不在这些位置,应先在该常量中仅替换本地路径,保持批次和文件配对规则不变。
|
||||
|
||||
### 1. 导出 55 组统一数据
|
||||
|
||||
```powershell
|
||||
python -m pip install -e ".[dev]"
|
||||
$WORK = "D:\data\rtk_imu_reproduce" # 本地工作目录,不提交
|
||||
$UNIFIED = "$WORK\unified"
|
||||
python tools\export_rtk_imu_unified.py --output-root $UNIFIED --overwrite
|
||||
$MANIFEST = "$UNIFIED\manifest.json"
|
||||
```
|
||||
|
||||
检查 `manifest.json`:应有 55 个配对会话,0815 的一个单独 G90 记录在 `unmatched`;每个会话应包含 `imu.npz`、`rtk.csv` 和 `export_summary.json`。确认 HI13 `system_time` 是主时间轴,主机接收时间没有成为观测采样时间。
|
||||
|
||||
### 2. 重建固定旋转
|
||||
|
||||
本次发布使用两个明确水平、车辆静止的会话。两个 `--level-static` 参数都必须提供:
|
||||
|
||||
```powershell
|
||||
$ROTATION = "$WORK\rotation.json"
|
||||
python tools\run_rtk_imu_multisource.py `
|
||||
--manifest $MANIFEST `
|
||||
--level-static 0819_20260819_072130 `
|
||||
--level-static 0819_20260819_073045 `
|
||||
--output $ROTATION
|
||||
```
|
||||
|
||||
检查输出中“基线 + 重力 + 水平场地约束”的旋转是否接近 `[0.454°, -0.003°, 0.012°]`。如果差异明显,应停止后续步骤,先核对天线方向、会话是否真实水平和时间/坐标定义;不要直接求杆臂。
|
||||
|
||||
### 3. 选择并诊断 47 个标定窗口
|
||||
|
||||
本次种子运动分别是持续绕圈、左右转向和坡道。脚本会在不共享 IMU/GNSS/HPR 样本的前提下,按杆臂信息增益补充窗口;当前发布的固定结果为 47 个窗口。
|
||||
|
||||
```powershell
|
||||
$SEL47 = "$WORK\selection_47.json"
|
||||
python tools\select_rtk_imu_windows_by_lever_information.py `
|
||||
--manifest $MANIFEST `
|
||||
--circle-session 0808_20260808_092827 `
|
||||
--left-right-session 0808_20260808_082148 `
|
||||
--slope-session 0815_20260812_123424 `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--output $SEL47
|
||||
|
||||
$FREE47 = "$WORK\free_47.json"
|
||||
python tools\run_rtk_imu_node_graph_free_selected.py `
|
||||
--manifest $MANIFEST `
|
||||
--selection $SEL47 `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--start-name all `
|
||||
--output $FREE47
|
||||
```
|
||||
|
||||
`$FREE47` 只用于确认无机械先验时的可观性和多初值稳定性;它不是可交付杆臂,也不应因此修改机械值。
|
||||
|
||||
### 4. 重做机械杆臂一致性比较
|
||||
|
||||
```powershell
|
||||
$ENGINEERING = "$WORK\mechanical_47.json"
|
||||
python tools\run_rtk_imu_mechanical_prior_branch.py `
|
||||
--manifest $MANIFEST `
|
||||
--selection $SEL47 `
|
||||
--free-baseline $FREE47 `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--state-output "$WORK\mechanical_47_states.npz" `
|
||||
--output $ENGINEERING
|
||||
```
|
||||
|
||||
结果必须同时比较无先验、固定机械杆臂和机械软约束杆臂。`mechanical_47_states.npz` 仅为本地缓存,不提交。
|
||||
|
||||
### 5. 重做留出验证和发布汇总
|
||||
|
||||
本次留出验证使用 314 个冻结的全部非重叠窗口,其中 47 个是标定窗口、267 个是留出窗口。为了精确复现本次窗口划分,直接使用仓库中的 `lever_information_window_selection_refined.json`,不要重新选择或改变窗口。
|
||||
|
||||
```powershell
|
||||
$ALL314 = "artifacts\rtk_imu_calibration_v3\lever_information_window_selection_refined.json"
|
||||
$HELDOUT = "$WORK\heldout.json"
|
||||
python tools\run_rtk_imu_mechanical_prior_heldout.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection $SEL47 `
|
||||
--all-selection $ALL314 `
|
||||
--engineering-result $ENGINEERING `
|
||||
--checkpoint-dir "$WORK\heldout_checkpoints" `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--output $HELDOUT
|
||||
|
||||
python tools\audit_rtk_imu_heldout_innovation.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection $SEL47 `
|
||||
--all-selection $ALL314 `
|
||||
--engineering-result $ENGINEERING `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--output "$WORK\heldout_innovation.json"
|
||||
|
||||
python tools\audit_rtk_imu_propagation_bias_root_cause.py `
|
||||
--manifest $MANIFEST `
|
||||
--calibration-selection $SEL47 `
|
||||
--all-selection $ALL314 `
|
||||
--engineering-result $ENGINEERING `
|
||||
--rotation-rpy-deg 0.4543066225 -0.0026392019 0.0122384129 `
|
||||
--output "$WORK\propagation_bias_root_cause.json"
|
||||
```
|
||||
|
||||
旋转敏感性、未收敛窗口重试和最终汇总属于发布级验证;它们不重新拟合杆臂。若要重新生成最终发布 JSON,必须连同上述审计结果、旋转敏感性结果和重试结果一起传给 `tools/finalize_rtk_imu_engineering_release.py`。在没有完成这些验证时,不得将本地结果标为成功。
|
||||
## 代码边界与审核证据
|
||||
|
||||
RTK 专用代码位于 `rtk_imu/`,命令行和审计工具位于 `tools/`。它只复用 `imu_lidar/` 的通用几何、地理坐标、IMU 读取、预积分和旋转初始化模块;不依赖雷达点云、配准或雷达联合优化代码。
|
||||
|
||||
- [多源旋转结果](../artifacts/rtk_imu_calibration_v3/multisource_result.json)
|
||||
- [47 窗口机械杆臂比较](../artifacts/rtk_imu_calibration_v3/mechanical_prior_engineering_47_window.json)
|
||||
- [留出数据验证](../artifacts/rtk_imu_calibration_v3/mechanical_prior_engineering_heldout.json)
|
||||
- [独立创新审计](../artifacts/rtk_imu_calibration_v3/heldout_independent_innovation.json)
|
||||
- [传播误差根因审计](../artifacts/rtk_imu_calibration_v3/propagation_bias_root_cause_audit.json)
|
||||
-109
@@ -1,109 +0,0 @@
|
||||
# V1 标准中间数据格式
|
||||
|
||||
**用途:** 标定程序读入的 CSV/NPZ 约定,以及新车原始数据如何导出。总览见根目录 [README](../README.md)。
|
||||
|
||||
## 从原始数据导出
|
||||
|
||||
**推荐(新 H32 + HI13):** HI13 `.rscap` + 雷达 Medulla dlog / recovered zip(raw MSOP + DIFOP)。
|
||||
|
||||
```powershell
|
||||
python tools\export_rscap_to_v1.py `
|
||||
--imu-rscap path\to\hi13r4-imu.rscap `
|
||||
--imu-kind hi13 `
|
||||
--lidar-dlog path\to\session_or_dlog_or_recovered.zip `
|
||||
--host-start 2026-08-08T17:40:05 `
|
||||
--host-end 2026-08-08T17:45:15 `
|
||||
--out path\to\session_v1 `
|
||||
--frame-stride 5 `
|
||||
--require-difop
|
||||
```
|
||||
|
||||
`--lidar-dlog` 可为:标准 `dobject/`+`dobject_recording/` 目录,或 recovered zip(`indices.log` + `data.bin`)。
|
||||
`--imu-kind`:`hi13` / `n300` / `auto`(默认按文件名推断)。
|
||||
`--host-start/end`:按本地墙钟切窗(仅裁剪;标定主轴仍是设备时间)。
|
||||
默认 DObject:`frontlidar-msop-raw`、`frontlidar-difop-raw`。
|
||||
|
||||
**兼容旧 MSOP-only `.rscap`:**
|
||||
|
||||
```powershell
|
||||
python tools\export_rscap_to_v1.py `
|
||||
--imu-rscap path\to\n300.rscap `
|
||||
--lidar-rscap path\to\h32_msop.rscap `
|
||||
--out path\to\session_v1 `
|
||||
--frame-stride 1
|
||||
```
|
||||
|
||||
产出:`imu.csv`、`lidar/`(含 `frames_index.csv`)、`export_summary.json`。
|
||||
标定主轴仍是**设备时间**;同时写出**主机 UTC 接收时间**,用于把雷达帧桥接到 IMU 设备钟(禁止把两边设备时间第一帧强行重合)。
|
||||
|
||||
## IMU
|
||||
|
||||
文件:`imu.csv` 或 `imu.npz`
|
||||
|
||||
### CSV
|
||||
|
||||
```text
|
||||
t,gx,gy,gz,ax,ay,az,t_host_utc_s,receive_utc_ticks
|
||||
0.000000000,0.01,-0.02,0.00,0.05,-0.03,9.81,1754646005.123,6389...
|
||||
...
|
||||
```
|
||||
|
||||
| 列 | 含义 | 单位 |
|
||||
|---|---|---|
|
||||
| t | IMU 设备时钟时间 | s |
|
||||
| gx,gy,gz | 角速度 | rad/s |
|
||||
| ax,ay,az | 比力/加速度 | m/s² |
|
||||
| t_host_utc_s | 主机 UTC 接收时间(Unix) | s |
|
||||
| receive_utc_ticks | 同上,.NET UTC ticks | — |
|
||||
|
||||
### NPZ
|
||||
|
||||
数组:`t (N,)`, `gyro (N,3)`, `acc (N,3)`,含义同上。
|
||||
|
||||
> IMU 与 LiDAR 的时间原点可以不同。流水线会估计常值偏置:`t_imu = t_lidar + delta_t`。
|
||||
|
||||
## LiDAR
|
||||
|
||||
目录结构:
|
||||
|
||||
```text
|
||||
lidar_session/
|
||||
├── frames_index.csv
|
||||
└── frames/
|
||||
├── frame_00000.npz
|
||||
├── frame_00001.npz
|
||||
└── ...
|
||||
```
|
||||
|
||||
### frames_index.csv
|
||||
|
||||
```text
|
||||
frame_id,filename,t_start,t_end,host_receive_utc_ticks,t_host_utc_s,host_receive_utc_end_ticks,t_host_utc_end_s
|
||||
0,frames/frame_00000.npz,10.000,10.100,6389...,1754646005.12,6389...,1754646005.22
|
||||
```
|
||||
|
||||
| 列 | 含义 |
|
||||
|---|---|
|
||||
| t_start / t_end | H32 MSOP **设备时间**(秒) |
|
||||
| t_host_utc_s / t_host_utc_end_s | 帧首/末包 **HostReceiveUtcTicks** → Unix 秒 |
|
||||
|
||||
也兼容旧列名 `file`。对齐脚本用主机 UTC 把 `t_*` 重写到 IMU 设备钟后再跑标定。
|
||||
|
||||
### 每帧 NPZ
|
||||
|
||||
- `points`: `float64/float32`,形状 `(N, 3)`,LiDAR 直角坐标系,单位米
|
||||
|
||||
## 时间不同步能不能用?
|
||||
|
||||
可以,前提是:
|
||||
|
||||
1. 两边都覆盖同一段**有角速度激励**的物理运动(尤其是转弯);
|
||||
2. 偏置近似为**常数**(短会话);
|
||||
3. `--time-offset-search-s` 足够覆盖可能的偏移(默认 ±1 s,可加大)。
|
||||
|
||||
若两段数据完全不是同一趟行驶,或只有静止 IMU、没有重叠运动,则无法估 δt,标定会被 `blocked`。
|
||||
|
||||
## 最小可用会话
|
||||
|
||||
- IMU:建议含静止段 + 运动段,采样率稳定
|
||||
- LiDAR:建议 ≥ 20 帧,场景有墙/柱等结构,含转弯
|
||||
@@ -1,92 +0,0 @@
|
||||
# 从 LiDAR–IMU 平移困难到 RTK–IMU 工程外参
|
||||
|
||||
本文解释为什么仓库同时保留 LiDAR–IMU 与 RTK–IMU 两条链路、为什么本轮将天线–IMU 外参的工程验证重心转向 RTK–IMU,以及两条链路如何避免互相混淆。
|
||||
|
||||
## 决策结论
|
||||
|
||||
保留两条链路,不删除 LiDAR–IMU。LiDAR–IMU 仍然是雷达与 IMU 旋转/时间关系的有效工具,也记录了平移失败的具体证据;RTK–IMU 是针对“天线相位中心到 IMU 的杆臂”采用的独立观测模型。它们共享基础数学与 IMU 预积分,但不共享求解器或验收结论。
|
||||
|
||||
当前 RTK–IMU 结果应描述为:**机械测量锚定的杆臂,经 RTK+IMU 动态数据一致性验证的工程候选**。它不是 data-only 平移标定,也不是已正式 engineering 放行的结果。
|
||||
|
||||
## LiDAR–IMU 为什么暂时不能交平移
|
||||
|
||||
LiDAR–IMU 链路将相邻关键帧的点云配准相对运动,与同一区间 IMU 预积分运动做手眼/联合优化。当前实车数据中旋转和时间关系可得到稳定结果,但平移受两个独立问题限制:
|
||||
|
||||
1. **IMU 位移预积分不可靠。** 加速度积分对重力与加速度零偏敏感;当前 `Δp` 尤其 Z 分量会发散。已有证据显示点云相对旋转残差中位约 `0.16°`,而 IMU 位移增量模长常大于 `1 m`,说明这不是单纯旋转误差。
|
||||
2. **运动激励不足。** 现有重点窗口以水平转弯为主,缺少连续坡道/俯仰激励,竖直杆臂弱可观。即使加入很强的平移先验,求解也可能只是先验回显,而非数据观测。
|
||||
|
||||
因此 LiDAR–IMU 的状态是:旋转与时间对齐可用,`full_se3`/平移不可作为安装参数交付。详细证据在 [LiDAR–IMU 现状与问题](20260808_LiDAR-IMU标定现状与问题.md) 和 [问题清单](问题清单.md)。
|
||||
|
||||
## 为什么 RTK–IMU 更适合验证天线杆臂
|
||||
|
||||
RTK 直接给出天线相位中心的 GNSS 位置与 Doppler 速度;双天线还给出 ANT1→ANT2 基线方向。对固定旋转 `R_WI` 和杆臂 `l_I = p_ANT1^I`,观测模型为:
|
||||
|
||||
```text
|
||||
p_ANT1^W = p_IMU^W + R_WI * l_I
|
||||
v_ANT1^W = v_IMU^W + R_WI * ((omega - b_g) × l_I)
|
||||
```
|
||||
|
||||
转弯时的 `omega × l_I`、加减速和坡道中的姿态变化,都会直接增强杆臂可观性;这比把加速度二次积分当作唯一位移来源更适合做天线–IMU 一致性检查。
|
||||
|
||||
双天线基线本身只有 2DoF 方向信息,不能凭空构造完整三轴姿态。本项目采用:
|
||||
|
||||
1. R1b:以基线和 IMU 动态估计 ANT1→ANT2 在 IMU 中的 2DoF 方向。
|
||||
2. R2V:以基线和高质量 Doppler velocity 做独立诊断。
|
||||
3. R2G:在确认水平的静止场地,以基线 + 重力 + 地面水平先验补齐完整旋转。
|
||||
4. R3:跨会话、block-out、协方差和可观性复核。
|
||||
|
||||
正式固定旋转来源是 `R2G_gravity_level_prior`;旧式 GNHPR 三轴姿态手眼只保留为诊断,不作为正式外参。
|
||||
|
||||
## RTK–IMU 平移如何求解和验证
|
||||
|
||||
每个 GNSS node 使用 15DoF 状态 `(R,p,v,bg,ba)`,相邻 node 由 covariance-whitened IMU preintegration 与 bias random-walk 连接。因子包括:
|
||||
|
||||
- BESTNAVA:天线相位中心 XYZ;
|
||||
- GGA:仅在 BEST 缺失时约束 XY,不混用 MSL 高度到 ENU Z;
|
||||
- Doppler:天线速度;
|
||||
- HPR:可选基线/姿态观测,direct 与短 bridge 使用不同协方差;
|
||||
- 静止段:gravity candidate 与 ZUPT 分离,禁止将匀速直线误作 ZUPT。
|
||||
|
||||
杆臂的判断流程不是“优化器有数值就算成功”:
|
||||
|
||||
1. 先用无机械先验的 free solve 评估 Schur 边缘化后的 3×3 杆臂信息、协方差、最弱方向和多初值稳定性。
|
||||
2. 若完整 XYZ 不可观,冻结 free 结果为诊断基线,不继续无限增加非线性 free solve。
|
||||
3. 以机械测量作为绝对杆臂来源,比较 fixed-mechanical、soft-prior 与 free 的代价和物理残差。
|
||||
4. 在 circle、left-right、slope 高动态窗口,以及与标定窗口不重叠的 held-out 数据上固定杆臂验证。
|
||||
5. 做旋转扰动敏感性、独立 innovation 与 propagation root-cause audit;这些审计不重新优化杆臂。
|
||||
|
||||
## 本次结果应如何理解
|
||||
|
||||
- 当前固定工程候选:`l_I = [-0.4518015159, -0.2644749820, 0.7314656115] m`。
|
||||
- 机械测量决定杆臂绝对值;RTK+IMU 动态数据用于独立一致性和稳定性验证。
|
||||
- 47 个非重叠标定窗口表明机械先验与数据拟合相容,但没有足够的数据驱动信息去有意义地细化机械值。
|
||||
- held-out 物理验证和旋转敏感性通过;杆臂敏感的高动态数据没有发现机械外参明显冲突。
|
||||
- 低速、低角速度独立传播仍有约 `0.20 m/s²` 的公共加速度偏差;这更像 propagation nuisance,而不是由 `omega × l` 消失后的杆臂错误造成。该问题尚未关闭,故 `engineering_translation_accepted=false`。
|
||||
|
||||
这解释了两个同时成立的事实:机械外参没有被动态数据否定,但整个传播模型尚未达到正式放行标准。机器可读结果见 [工程 release 决策](../artifacts/rtk_imu_calibration_v3/engineering_release_decision.json)。
|
||||
|
||||
## 代码边界和共享模块
|
||||
|
||||
```text
|
||||
imu_lidar/
|
||||
lidar_io.py, lidar_deskew.py, registration.py, keyframes.py
|
||||
motion_pairs.py, phase_a.py, pipeline.py, joint_optimizer.py
|
||||
-> LiDAR–IMU 专用
|
||||
|
||||
rtk_imu/
|
||||
rtk_io.py, rtk_attitude.py, rtk_imu_rotation.py
|
||||
rtk_imu_multisource.py, rtk_imu_engineering.py, rtk_imu_node_graph.py
|
||||
-> RTK–IMU 专用
|
||||
|
||||
imu_lidar/contracts.py, geometry.py, geodesy.py, imu_io.py,
|
||||
imu_preintegration.py, rotation_handeye.py
|
||||
-> 两条链路可复用的基础能力
|
||||
```
|
||||
|
||||
RTK–IMU 只能 import 这 6 个共享模块,不应 import LiDAR 专用求解文件。命令入口都在 `tools/`,并按 `run_rtk_imu_*`、`audit_rtk_imu_*` 与 LiDAR 工具名称区分。
|
||||
|
||||
## 进一步工作
|
||||
|
||||
在宣称正式工程放行前,应优先关闭低速传播公共加速度偏差:区分图优化 nuisance accel bias 与可迁移物理 bias,复核静态 bias、重力泄漏和短时传播。不要用调机械先验、调 covariance 或扩大 free solve 来掩盖该问题。
|
||||
|
||||
RTK–IMU 的完整工程流程、当前变换和复现命令见 [README_RTK_IMU.md](../README_RTK_IMU.md)。
|
||||
@@ -1,168 +0,0 @@
|
||||
# RTK–IMU 标定链路审计与当前方案
|
||||
|
||||
> 2026-08-21 多源原始报文重构、R1b/R2V/R2G/R3 实现与三批数据实测结果,
|
||||
> 见 [rtk_imu_multisource_v3.md](rtk_imu_multisource_v3.md)。本页保留旧式
|
||||
> GGA/GNHPR 链路的审计背景;完整 HPR 手眼仍只允许作为诊断。
|
||||
|
||||
## 结论
|
||||
|
||||
当前数据可以验证“双天线基线方向与 IMU 的一致性”,但不能单独标定一个无歧义的完整三自由度 RTK 姿态外参。
|
||||
|
||||
G90 的 heading 表示主天线 ANT1 到从天线 ANT2 的基线方位。实车中主天线在左、从天线在右,因此该基线指向车体右侧,不是前进方向。IMU 的 +Y 指向车前;结合静止重力数据支持 IMU +Z 向上,可得到安装先验:IMU +X 指向车右,和 ANT1→ANT2 同向。
|
||||
|
||||
双天线只能观测这根基线的方位和仰角,绕基线自身的旋转不可观。GNHPR pitch 是横向基线的仰角,更接近车体横滚响应,不能当作坡道上的纵向车体 pitch;roll 字段也不是独立的第三姿态观测。因此,旧链路把 HPR 拼成完整 SO(3) 再做三轴手眼,是坡道 RMS、会话牵引和不稳定 yaw/pitch 的主要来源。
|
||||
|
||||
当前实现保留旧式完整 HPR 结果作为诊断量,但不允许它通过完整旋转门禁;平移在完整旋转通过前被硬冻结。
|
||||
|
||||
## 坐标系和参考点
|
||||
|
||||
统一输出约定:
|
||||
|
||||
```text
|
||||
p_RTK = R_RTK_IMU p_IMU + t_RTK_IMU
|
||||
```
|
||||
|
||||
RTK 车固坐标定义:
|
||||
|
||||
- +X:ANT1(主天线、左侧)→ ANT2(从天线、右侧),指向车右。
|
||||
- +Y:车辆前进方向,与 IMU +Y 同向。
|
||||
- +Z:车辆上方;静止重力数据支持 IMU +Z 向上。
|
||||
- 该完整三轴定义包含机械安装先验;GNHPR 实际直接观测的只有 +X 基线。
|
||||
|
||||
位置参考点:
|
||||
|
||||
- GGA 为 ANT1/主天线相位中心。
|
||||
- 相位中心离地高度为 1.916499878 m。
|
||||
|
||||
## 求解链路
|
||||
|
||||
### R0:协议、数据质量和时间
|
||||
|
||||
1. 校验 NMEA checksum。
|
||||
2. GGA 位置只接收 Q=4 固定解。
|
||||
3. GNHPR 姿态只接收 Q=4 固定解;Q=5 浮点解仅进入诊断统计,不参与标定。
|
||||
4. 保留 GNHPR 自己的卫星数、差分龄期和基站号,不能再用 GGA 卫星数替代 HPR 质量。
|
||||
5. 姿态使用 `hpr_measurement_utc_s` 映射后的 IMU 设备时间。
|
||||
6. 遇到 HPR 无效、浮点、时间间隔异常或基线跳变时切断连续段,运动对不得跨断点。
|
||||
|
||||
### T0:残余时间偏移
|
||||
|
||||
只使用可观测的有符号 heading 角速度与 IMU `gyro_z` 做相关扫描。角速度模长会混入不可观的绕基线旋转,不再作为时间审计依据。
|
||||
|
||||
时间偏移只用于初始化/诊断。只有相关峰足够高、与次峰分离且峰宽足够窄时才应用,否则保持 0 s。
|
||||
|
||||
### R1:双天线基线一致性
|
||||
|
||||
对每个连续固定解片段构造 0.75 s、1.5 s、3.0 s 的相对运动。以安装先验 `u_IMU=[1,0,0]` 检验:
|
||||
|
||||
```text
|
||||
angle(u_RTK(t0), u_RTK(t1))
|
||||
≈ angle(u_IMU, ΔR_IMU(t0,t1) u_IMU)
|
||||
```
|
||||
|
||||
该标量约束不虚构 RTK 的前向轴和上向轴。输出整体、逐会话 RMS/P95、分轴诊断及最坏时间区间。所有会话的总权重归一,避免高激励或样本更多的会话支配结果。
|
||||
|
||||
### R2:旧式完整 HPR 诊断
|
||||
|
||||
为兼容历史输出,将基线补成零 roll 的数学坐标架,再运行完整手眼。这个结果仅用于暴露符号错误、异常会话和旧结果变化,不能作为可交付外参。
|
||||
|
||||
LOO 删除一个会话后,会重新优化剩余会话的陀螺零偏,不再固定全量数据的 nuisance 参数。
|
||||
|
||||
### T1:平移
|
||||
|
||||
只有完整三自由度旋转“可观且通过”时,才允许进入杆臂和平移求解。当前条件不满足,因此:
|
||||
|
||||
- 不运行平移优化;
|
||||
- 不输出 `translation_result.json`;
|
||||
- `t_RTK_IMU_m` 和 `T_RTK_IMU` 为 null;
|
||||
- 历史巨大 Z、米级不确定度和约 1 m/s 速度残差不再消耗优化时间。
|
||||
|
||||
## 当前 8 会话结果
|
||||
|
||||
结果目录:`artifacts/rtk_imu_calibration_v2/all_sessions`。
|
||||
|
||||
```text
|
||||
可观测基线一致性:
|
||||
RMS / median / P95 = 0.593665 / 0.146040 / 1.212972 deg
|
||||
priority_175910 RMS / P95 = 1.316292 / 2.472570 deg
|
||||
slope RMS / P95 = 1.264514 / 2.475899 deg
|
||||
最坏区间 = priority_175910,约 5.084 deg
|
||||
baseline gate = passed
|
||||
|
||||
时间偏移:
|
||||
全局候选 = +0.005 s
|
||||
峰值相关 = 0.909019
|
||||
近峰宽度 = [-0.110, +0.170] s
|
||||
实际应用 = 0 s
|
||||
|
||||
旧式完整 HPR 诊断:
|
||||
RPY = [-0.132765, -0.297433, -1.558358] deg
|
||||
RMS / P95 = 1.172397 / 2.404977 deg
|
||||
std = [0.615416, 0.437419, 3.687145] deg
|
||||
priority_175910 re-optimized LOO = 1.698555 deg
|
||||
max re-optimized LOO = 1.699427 deg(删除 slope)
|
||||
legacy numeric gate = failed
|
||||
full attitude observable = false
|
||||
|
||||
平移:
|
||||
frozen / not run
|
||||
```
|
||||
|
||||
旧结果中的 `priority_175910` 条件 LOO 为 5.14°。严格剔除 Q5、会话等权、断段保护以及 LOO 重估零偏后,该会话完整诊断 LOO 降为 1.699°。它和坡道会话仍是主要异常源,但现在异常集中在基线仰角通道,而不是 heading:这更符合原始 HPR 中 Q5、低卫星数和 pitch 大幅波动的事实。
|
||||
|
||||
## 已排除或仍存在的漏洞
|
||||
|
||||
- 已修复:heading 误当车前方向。
|
||||
- 已修复:GNHPR pitch 误当纵向车体 pitch。
|
||||
- 已修复:不可观 roll 注入完整姿态。
|
||||
- 已修复:Q5 浮点 HPR 进入标定。
|
||||
- 已修复:HPR 质量字段在导出时丢失。
|
||||
- 已修复:相对运动跨越无效段或跳变。
|
||||
- 已修复:样本多的会话权重过大。
|
||||
- 已修复:LOO 固定全量会话零偏。
|
||||
- 已修复:时间相关使用三轴角速度模长。
|
||||
- 已修复:旋转未通过仍继续优化平移。
|
||||
- 仍存在:当前运动不能稳定地从 GGA 速度补全车前/车上方向。
|
||||
- 仍存在:基线绕轴自由度没有独立传感器观测。
|
||||
- 仍存在:`priority_175910` 和坡道的基线仰角存在局部异常。
|
||||
|
||||
## 如何得到可交付的完整旋转
|
||||
|
||||
按优先级建议:
|
||||
|
||||
1. 采一组专用数据:空旷区域、全程 RTK fixed、较长直线加减速、左右转、坡道上下行,保留原始 GGA/GNHPR/IMU 时间和全部质量字段。
|
||||
2. 用高质量前向速度补第二根轴。只在速度足够高、航向变化平缓的区间用 GGA course,并在同一优化中建模 ANT1 杆臂、非完整车辆侧向速度约束和时间偏移。
|
||||
3. 用静止重力补上向轴时,必须把“地面水平/车辆静止”写成显式先验,并将结果标记为安装先验约束解,而不是双天线数据独立解。
|
||||
4. 若能取得 G90 内部融合后的完整 INS 姿态、第三天线、轮速/转角或可靠车体姿态源,优先作为第二独立方向。
|
||||
5. 完整旋转通过留出验证后,才恢复平移;平移应同时估计杆臂、速度、加计偏置,并检查垂向高程基准。
|
||||
|
||||
当前数据上尝试用平滑 GGA 速度直接补全姿态,结果随平滑窗口明显变化,受低速、转弯杆臂和高程差分噪声影响,不能进入正式结果。
|
||||
|
||||
## 与主流开源方法的对应
|
||||
|
||||
- Kalibr:角速度相关适合作为时间偏移初始化,不应在宽峰时强行采用候选值。
|
||||
- iKalibr:采用连续时间轨迹联合估计时空参数,并强调充分激励;适合后续专用数据。
|
||||
- MINS:异步测量插值并把传感器外参、时间和 nuisance 状态一起估计。
|
||||
- GICI-LIB:因子图中显式进行 GNSS/INS 初始化、质量控制和异常值处理。
|
||||
|
||||
本项目暂不直接引入这些大型框架,而是吸收其原则:先保证物理可观测性和数据质量,再进行联合优化;不能用自由状态吸收错误模型。
|
||||
|
||||
参考:
|
||||
|
||||
- Unicore N4 Reference Commands Manual
|
||||
- Unicore UM982 User Manual
|
||||
- https://github.com/Unsigned-Long/iKalibr
|
||||
- https://github.com/ethz-asl/kalibr
|
||||
- https://github.com/rpng/MINS
|
||||
- https://github.com/chichengcn/gici-open
|
||||
|
||||
## 代码入口
|
||||
|
||||
- `rtk_imu/rtk_attitude.py`:GNHPR 基线语义及零 roll 数学补全。
|
||||
- `rtk_imu/rtk_io.py`:RTK CSV、Q4/Q5 和 checksum 质量门禁。
|
||||
- `rtk_imu/rtk_imu_rotation.py`:时间审计、连续段、基线审计、旧式诊断和重优化 LOO。
|
||||
- `rtk_imu/rtk_imu_replay.py`:坐标定义、参考点、平移冻结和 JSON 输出。
|
||||
- `tools/rscap_v2/g90_rtk.py`:原始 GNHPR 解析及质量字段。
|
||||
- `tools/export_g90_rtk_to_sessions.py`:GNHPR 质量字段导出。
|
||||
- `tools/run_rtk_imu_calibration.py`:端到端命令行入口。
|
||||
- `tests/test_rtk_imu_calibration.py`:轴定义、Q4/Q5、时间和预积分回归测试。
|
||||
@@ -1,108 +0,0 @@
|
||||
# RTK–IMU Engineering 6DoF 分支
|
||||
|
||||
该分支与 V3 `data_only` 严格链路并列,不改变其门禁结论:
|
||||
|
||||
```text
|
||||
data_only_6dof_accepted = false
|
||||
```
|
||||
|
||||
工程分支固定使用真实水平静止场地得到的 R2G 旋转,默认参考值为
|
||||
`RPY=[0.4543066, -0.0026392, 0.0122384] deg`,输出始终记录:
|
||||
|
||||
```text
|
||||
rotation_source = R2G_gravity_level_prior
|
||||
translation_conditional_on_rotation = true
|
||||
```
|
||||
|
||||
## 条件模型
|
||||
|
||||
估计量是 `l_I = p_ANT1^I`。每个连续质量段使用 HI13 设备时间、raw gyro/acc 动态预积分,融合 RTK Fixed 的 GGA/BESTNAVA 位置、BESTNAVA Doppler velocity 和 Q4 GNHPR 的 ANT1→ANT2 基线。逐段 nuisance state 包含初始姿态、IMU 原点初始位置、速度、gyro bias 和 acc bias。HI13 absolute quaternion/RPY(尤其 absolute yaw)不进入机械外参因子;R2V 仅作诊断。
|
||||
|
||||
静止相关因子分为两类:
|
||||
|
||||
- `gravity_candidate`:连续约 1.5 s 的低角速度、gyro/acc 方差稳定且加速度模长接近重力;它不能等价为静止。
|
||||
- `zupt_static`:在 gravity candidate 基础上,必须同时有至少约 1 s 的连续 BESTNAVA Doppler 速度接近 0。高速或匀速直线不会加入 ZUPT。
|
||||
|
||||
连续段复用 R0 质量断点:checksum 无效、定位非 Fixed、GNHPR 非 Q4、设备时间回跳、HPR 测量间隙、baseline jump、位置测量间隙或 IMU gap 都会切段,禁止跨断点预积分。 断后片段还必须至少包含 6 个求解节点且持续不少于 5 s;更短的局部欠约束微段不会跨断点拼接,而是直接不进入杆臂优化。
|
||||
|
||||
## 高程与残差口径
|
||||
|
||||
- GGA 只约束 XY;GGA MSL altitude 不定义也不参与 ENU-Z。
|
||||
- ENU-Z reference 只来自有效 Fixed BESTNAVA altitude;BESTNAVA 才约束 XYZ。
|
||||
- 输出分别为 `gga_xy_residual`、`bestnava_xyz_residual` 和 `doppler_velocity_residual`。未进入 Z factor 的 GGA 高度不进入垂向残差统计。
|
||||
|
||||
## 可观性与验收
|
||||
|
||||
杆臂可观性不再使用全状态最小奇异向量。状态分为杆臂 `l` 与 nuisance state,对优化 Hessian 计算 Schur complement:
|
||||
|
||||
```text
|
||||
H_l_marg = H_ll - H_ln pinv(H_nn) H_nl
|
||||
```
|
||||
|
||||
只对该 3×3 marginal lever information 做 SVD,并输出:
|
||||
|
||||
- `l_I_marginal_covariance_m2`、`l_I_std_m`
|
||||
- `lever_information_singular_values`
|
||||
- `lever_information_condition_number`
|
||||
- `lever_precision_rank`
|
||||
- `weakest_lever_direction_I`
|
||||
|
||||
门禁分为两层:
|
||||
|
||||
- `solver_health_gates` 只判断优化是否收敛、数值是否有限且残差未发散。
|
||||
- `engineering_acceptance_gates` 使用更严格的杆臂 marginal std/information/rank/condition、BESTNAVA XYZ、GGA XY、Doppler velocity、LOO、bootstrap、旋转敏感性和可选手量一致性。
|
||||
|
||||
任一核心门禁失败时,`engineering_6dof_accepted=false`。没有完整执行 bootstrap 和 18 组旋转敏感性时,两项门禁明确为 false,不会把阶段性 base/LOO 结果误标为正式放行。
|
||||
|
||||
Bootstrap 按 session 有放回抽样,并保留重复 session 的 multiplicity;重复抽中的 session 会重复贡献其全部连续段。
|
||||
|
||||
## 机械杆臂软先验与双解输出
|
||||
|
||||
`--manual-l-i-m` 仅在同时提供 `--manual-l-i-std-m` 或完整
|
||||
`--manual-l-i-covariance-m2` 时才成为白化高斯软因子。求解器始终先运行无先验
|
||||
`free_solution`,再运行 `prior_constrained_solution`;输出还包含机械参考及两者到
|
||||
参考的差值。当前活动 engineering 解为 prior-constrained 解(若启用),但 acceptance
|
||||
额外要求 free-solve 也与机械参考一致,软先验不能掩盖不可观或数据矛盾。
|
||||
|
||||
示例(数值需使用实际机械测量的 1σ,不可把示例值当作默认):
|
||||
|
||||
```powershell
|
||||
--manual-l-i-m -0.45072 -0.25682 0.73208 `
|
||||
--manual-l-i-std-m <sigma_x_m> <sigma_y_m> <sigma_z_m>
|
||||
```
|
||||
## 坐标转换
|
||||
|
||||
```text
|
||||
T_RTK_IMU: p_RTK = R_RTK_IMU p_IMU - R_RTK_IMU l_I
|
||||
T_IMU_RTK: p_IMU = R_RTK_IMU^T p_RTK + l_I
|
||||
```
|
||||
|
||||
RTK 原点是 ANT1,因此 `T_IMU_RTK.translation == l_I`,两矩阵必须互逆。
|
||||
|
||||
## 分阶段运行
|
||||
|
||||
第一阶段默认只运行 base fit、marginal observability、residual audit 和 LOO:
|
||||
|
||||
```powershell
|
||||
python tools/run_rtk_imu_engineering_6dof.py `
|
||||
--manifest D:\data\rtk_imu_unified_v3\manifest.json `
|
||||
--output artifacts/rtk_imu_calibration_v3/engineering_6dof_base_loo.json `
|
||||
--session <session-a> `
|
||||
--session <session-b> `
|
||||
--session <session-c>
|
||||
```
|
||||
|
||||
只有 base/LOO 合理后,才显式启动全量验证:
|
||||
|
||||
```powershell
|
||||
python tools/run_rtk_imu_engineering_6dof.py `
|
||||
--manifest D:\data\rtk_imu_unified_v3\manifest.json `
|
||||
--output artifacts/rtk_imu_calibration_v3/engineering_6dof_full.json `
|
||||
--session <session-a> `
|
||||
--session <session-b> `
|
||||
--session <session-c> `
|
||||
--run-bootstrap --bootstrap-repetitions 40 --bootstrap-seed 0 `
|
||||
--run-rotation-sensitivity
|
||||
```
|
||||
|
||||
正式会话应覆盖直行加减速、左右转、坡道和明确水平静止段。不得为了运行时间降低验收门禁或把未完成验证标为成功。
|
||||
@@ -1,175 +0,0 @@
|
||||
# RTK–IMU 多源原始数据与旋转标定 V3
|
||||
|
||||
## 可行性结论
|
||||
|
||||
重构方向正确且必要。原始捕获中确实存在旧导出链路忽略的 BESTNAVA、
|
||||
PVTSLNA 和 HI13 姿态/四元数。它们可以补充速度、质量、绝对姿态和静止
|
||||
重力约束,但本批数据尚不能通过完整旋转门禁:
|
||||
|
||||
- BESTNAVA 约 0.8–1 Hz,严格高速样本很少。
|
||||
- 当前动态主要是平面 yaw,R1b 的两个倾斜自由度仍弱可观。
|
||||
- HI13 四元数与 GNSS 真北存在稳定但非机械的 yaw 偏差,可能来自磁偏角或
|
||||
内部导航融合。
|
||||
- 两个明确水平静止会话的 R2G 很稳定,但它是水平/重力先验约束解。
|
||||
|
||||
因此,本次重构显著提高了诊断能力,也防止错误外参进入平移;它没有把信息
|
||||
不足包装成“标定成功”。
|
||||
|
||||
## 三批原始数据
|
||||
|
||||
扫描根目录:
|
||||
|
||||
- 0808:D:\data\raw_serial_capture_v2,仅选 20260808。
|
||||
- 0815:D:\data\0815\raw_serial_capture_v2;目录实际包含 20260812–14。
|
||||
- 0819:D:\data\0819\raw_serial_capture_v2。
|
||||
|
||||
按文件名捕获开始时间在 1.5 s 内一一配对:
|
||||
|
||||
| 批次 | G90/HI13 配对 | GNHPR | BESTNAVA | PVTSLNA | Q4 HPR | Fixed Doppler |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| 0808 | 18 | 46,180 | 8,291 | 5,993 | 45,606 | 8,128 |
|
||||
| 0815 | 28 | 96,241 | 12,660 | 9,638 | 27,045 | 3,385 |
|
||||
| 0819 | 9 | 15,717 | 2,029 | 1,427 | 14,976 | 1,930 |
|
||||
|
||||
共完成 55 组统一导出。0815 有一组 G90 没有匹配 HI13,manifest 将其列为
|
||||
unmatched。发现一条 NMEA 时间为 0913A:保留原始行,设备时间留空并隔离,
|
||||
没有回退到 host receive time。
|
||||
|
||||
速度不等于高速激励。增加速度 ≥1.5 m/s、水平速度标准差 ≤0.25 m/s 后,
|
||||
三个批次分别只剩 44、8、0 条候选。
|
||||
|
||||
## 统一导出
|
||||
|
||||
输出根目录:D:\data\rtk_imu_unified_v3。
|
||||
|
||||
每组捕获:
|
||||
|
||||
- imu.npz:HI13 system_time、gyro、accel、RPY、WXYZ quaternion、磁场、
|
||||
PPS stamp、温度、气压和 host receive UTC。
|
||||
- rtk.csv:每条原生异步 GGA/GNHPR/BESTNAVA/PVTSLNA 单独成行,不再把
|
||||
HPR/BEST/PVT 最近邻挂到 GGA。
|
||||
- export_summary.json:原始捕获摘要、报文数量、四元数范数和设备到 host
|
||||
的仿射时钟诊断。
|
||||
- manifest.json:全部会话、批次、目录和 unmatched 记录。
|
||||
|
||||
时间规则:
|
||||
|
||||
1. HI13 system_time 是 IMU 主时间轴。
|
||||
2. BESTNAVA/PVTSLNA 使用 GNSS week/TOW 和 leap seconds。
|
||||
3. GGA/GNHPR 使用报文自己的 UTC time-of-day。
|
||||
4. RTK GNSS 测量时刻通过 HI13 device→host 仿射模型映射进 HI13 设备时钟。
|
||||
5. host receive time 只用于跨时钟桥接、延迟和抖动诊断,绝不替代采样时刻。
|
||||
6. checksum 无效、时间畸形或非固定解记录保留,但不进入求解。
|
||||
|
||||
## 新旋转链路
|
||||
|
||||
### R1b:基线在 IMU 中的 2DoF 方向
|
||||
|
||||
对连续 Q4 GNHPR 基线和 HI13 陀螺相对旋转使用不变量:
|
||||
|
||||
angle(b_ENU(t0), b_ENU(t1))
|
||||
= angle(b_IMU, DeltaR_IMU b_IMU)
|
||||
|
||||
估计 b_IMU 的两个倾斜自由度及逐会话陀螺零偏。安装信息只用于选择 +X
|
||||
半球,并施加明确记录的弱 20° 先验。按会话等权,输出残差、协方差和信息
|
||||
奇异值。
|
||||
|
||||
### R2V:基线 + Doppler velocity
|
||||
|
||||
筛选条件:
|
||||
|
||||
- BESTNAVA position 为 SOL_COMPUTED/NARROW_INT;
|
||||
- velocity 为 SOL_COMPUTED/DOPPLER_VELOCITY;
|
||||
- checksum 有效;
|
||||
- 水平速度 ≥1.5 m/s、速度标准差 ≤0.25 m/s;
|
||||
- |IMU gyro_z| ≤3°/s;
|
||||
- 速度方向与横向基线接近正交;
|
||||
- GNHPR Q4,并有时间邻近的合法 HI13 quaternion。
|
||||
|
||||
基线给车右,Doppler velocity 给车前,叉积给车上。HI13 quaternion 的
|
||||
body/world 和 ENU/NED 候选全部评分,只保留残差最小者。该方法会把 HI13
|
||||
导航 yaw 偏差带入候选,因此必须和 R2G 交叉验证。
|
||||
|
||||
### R2G:基线 + 水平静止重力
|
||||
|
||||
只允许调用方明确标记的水平静止会话。本次使用:
|
||||
|
||||
- 0819_20260819_072130(flat_static_hdg207)
|
||||
- 0819_20260819_073045(flat_static_hdg082)
|
||||
|
||||
每 10 s 分块,要求 gyro norm ≤0.35°/s,且加速度模长距标准重力不超过
|
||||
0.15 m/s²。R1b 提供车右,加速度中值提供车上,叉积得到车前。
|
||||
|
||||
### R3:稳定性与正式门禁
|
||||
|
||||
R2V/R2G 都输出:
|
||||
|
||||
- 样本和会话数量;
|
||||
- SO(3) RMS/P95;
|
||||
- 旋转向量样本标准差和均值协方差;
|
||||
- leave-one-session;
|
||||
- 10 样本或 10 s block-out。
|
||||
|
||||
只有 R1b 可观、R2V 和 R2G 各自稳定、二者差异 ≤2° 时,才将
|
||||
translation_unlocked 设为 true。旧 GNHPR 三轴手眼不参与正式门禁。
|
||||
|
||||
## 首轮实测
|
||||
|
||||
R1b:
|
||||
|
||||
b_IMU = [0.999999976, -0.000213959, -0.000044368]
|
||||
tilt_yz = [-0.0123, -0.0025] deg
|
||||
pairs = 2091
|
||||
RMS / P95 = 0.8086 / 1.7105 deg
|
||||
information singular values = [1.176e-2, 8.476e-4]
|
||||
std = [27.77, 7.47] deg
|
||||
gate = failed
|
||||
|
||||
点估计接近 +X 是安装先验与名义轴一致的结果;巨大协方差说明不能宣称
|
||||
数据独立估出了这两个小角。
|
||||
|
||||
R2V:
|
||||
|
||||
qualifying samples / sessions = 41 / 2
|
||||
selected quaternion convention = HI13_q_body_to_ENU
|
||||
RPY = [0.7532, 0.0708, -9.2944] deg
|
||||
RMS / P95 = 1.8436 / 3.4975 deg
|
||||
max leave-one-session = 3.4519 deg
|
||||
gate = failed
|
||||
|
||||
R2G:
|
||||
|
||||
level-static blocks / sessions = 53 / 2
|
||||
RPY = [0.4543, -0.0026, 0.0122] deg
|
||||
RMS / P95 = 0.2542 / 0.2732 deg
|
||||
max leave-one-session = 0.2688 deg
|
||||
gate = passed (level/gravity-prior constrained)
|
||||
|
||||
R2V 与 R2G 的 SO(3) 差异为 9.3119°。R3 最终:
|
||||
|
||||
full_rotation_accepted = false
|
||||
translation_unlocked = false
|
||||
|
||||
## 下一轮数据要求
|
||||
|
||||
1. BESTNAVA 改为至少 10 Hz,并确认 Doppler velocity 与 GNHPR 使用同一
|
||||
GNSS week/TOW 输出周期。
|
||||
2. 每个日期都录制多段 ≥3 m/s、持续 20–30 s 的正向直线;包含不同方位,
|
||||
避免单一磁环境和单一会话支配。
|
||||
3. 为 R1b 增加可控的 roll/pitch 激励;只有平面 yaw 无法稳定估出横向
|
||||
基线的两个微小倾斜角。
|
||||
4. 每个日期至少录两种车头方位的明确水平静止段,检验 HI13 重力和绝对
|
||||
quaternion 的跨日期稳定性。
|
||||
5. 若 HI13 quaternion 的 yaw 来自磁融合,应获取其导航坐标定义、磁偏角
|
||||
设置和融合状态;否则 R2V 只使用其 roll/pitch,yaw 由 GNSS 基线和速度
|
||||
决定。
|
||||
6. 上述门禁通过前继续冻结杆臂和平移。
|
||||
|
||||
## 实现入口
|
||||
|
||||
- tools/rscap_v2/g90_rtk.py:GGA/GNHPR/BESTNAVA/PVTSLNA 和双 checksum。
|
||||
- tools/rscap_v2/hi13_imu.py:HI91 system_time、惯性、姿态和四元数。
|
||||
- tools/export_rtk_imu_unified.py:55 组配对、原生异步导出和断点续导。
|
||||
- rtk_imu/rtk_imu_multisource.py:R1b/R2V/R2G/R3。
|
||||
- tools/run_rtk_imu_multisource.py:多源旋转命令行入口。
|
||||
- artifacts/rtk_imu_calibration_v3/multisource_result.json:首轮 R3 结果。
|
||||
@@ -1,157 +0,0 @@
|
||||
# 纯 LiDAR–IMU:标定流程与采集清单
|
||||
|
||||
**用途:** 现场怎么采合格数据(看完根目录 [README](../README.md) 后再看本文即可)。
|
||||
算法命令与结果判读以 README 为准;改动史见 [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md)。
|
||||
|
||||
仅有激光雷达与 IMU、无 RTK/绝对位姿时的推荐采集与流程要点。
|
||||
目标外参:`p_IMU = T_IMU_lidar · p_lidar`(`T_A_B` 表示把 B 系点变到 A 系)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 原则(先读)
|
||||
|
||||
1. **时间对齐优先**:时钟偏置未对准时,旋转与平移都不可信;正式数据用**设备时间戳**。
|
||||
2. **先旋转,再平移**:旋转通常更稳;平面低速时竖直方向平移常常不可观。
|
||||
3. **用连续运动**:停车多站适合 RTK 手眼,不适合作为纯 IMU 外参主流程。
|
||||
4. **可观才交平移**:激励不够就只交旋转,不强交“假精确”六自由度。
|
||||
5. **残差小 ≠ 标定对**:需叠点云、跨会话等独立验证。
|
||||
|
||||
相对运动模型:
|
||||
|
||||
```text
|
||||
A ≈ IMU 预积分相对运动(关键帧区间)
|
||||
B ≈ 雷达关键帧配准相对运动
|
||||
R_A · R_X ≈ R_X · R_B → 先求旋转
|
||||
完整模式且可观时再求平移 t
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 端到端流程(与现行代码一致)
|
||||
|
||||
```text
|
||||
确认轴向 / 单位 / 时间语义
|
||||
→ 现场采集(首尾静止 + 低速多转弯;建议 ≥2 段独立会话)
|
||||
→ 导出标准中间格式(imu.csv + lidar 会话目录)
|
||||
→ 质检(时间 / IMU)不通过则停
|
||||
→ 粗估时间偏置 δt
|
||||
→ 关键帧 → 配准得 B;完整 IMU 预积分得 A(旋转/速度/位移增量)
|
||||
→ 加权旋转手眼得 R
|
||||
→ 用 R 精修 δt,必要时重新组对再解 R(可交替数轮)
|
||||
→ 联合精修 R 与常值陀螺零偏
|
||||
→ full_se3 且可观:再估重力、关键帧速度、时变零偏与平移 t
|
||||
→ 写出 T / δt / summary → 叠点云 / 跨会话验证后交付
|
||||
```
|
||||
|
||||
|
||||
| 步骤 | 现行模块 | 说明 |
|
||||
| --- | -------------------------------------------------------------------- | --------------------------------------- |
|
||||
| 质检 | `timestamp_audit` / `imu_audit` | 含静止段陀螺零偏初值 |
|
||||
| 时间 | `time_offset` | 模长相关粗估 + 有符号三轴精修 |
|
||||
| 运动对 | `keyframes` / `registration` / `imu_preintegration` / `motion_pairs` | 预积分始终算满;手眼先用旋转 |
|
||||
| 旋转 | `rotation_handeye` | 加权手眼 |
|
||||
| 精修 | `joint_optimizer` / `observability` | `rotation_only` 到旋转为止;`full_se3` 可观才碰平移 |
|
||||
|
||||
|
||||
点云去畸变(`lidar_deskew`)可选;低速首轮可不依赖。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 3. 采集设计
|
||||
|
||||
|
||||
|
||||
### 3.1 单趟会话结构
|
||||
|
||||
```text
|
||||
静止 20–30 s → 连续运动 3–8 min → 再静止 10–20 s
|
||||
```
|
||||
|
||||
运动优先:低速「8」字 / 左右圆;再补加减速直线。
|
||||
要可靠竖直方向外参时,另加缓坡(约 3°~8°,有效长度优先 ≥20~30 m),或改用外测垂直尺寸先验。
|
||||
|
||||
### 3.2 会话安排
|
||||
|
||||
|
||||
| 会话 | 作用 |
|
||||
| ----- | ---------------------------------- |
|
||||
| A | 主标定 |
|
||||
| B | 独立验证(**同一场地**换一条不完全相同的路线即可,不参与求外参) |
|
||||
| C(可选) | 不同速度/路线,测稳定性 |
|
||||
|
||||
|
||||
安装全程不得改动。多会话不要跨会话拼运动对。
|
||||
|
||||
### 3.3 录制字段(原始,勿先做姿态融合)
|
||||
|
||||
- IMU:设备时间、陀螺、加速度(建议同时留主机接收时间便于排查)
|
||||
- LiDAR:每帧起止时间(最好有包级/逐点时间)、原始点云
|
||||
|
||||
中间格式见 `[V1_数据格式.md](V1_数据格式.md)`。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 4. 现场 Checklist
|
||||
|
||||
**出发前**
|
||||
|
||||
- [ ] 安装固定;草图/卷尺粗测仅作参考,不当真值
|
||||
- [ ] 单位与轴向确认;设备时间可写盘
|
||||
- [ ] 结构化路线(墙/杆/路缘),避开空旷无特征区
|
||||
- [ ] 存储与供电充足
|
||||
|
||||
**录制中**
|
||||
|
||||
- [ ] 首尾静止;中间有明显左右转与加减速
|
||||
- [ ] 不改安装、不切换时间源
|
||||
- [ ] 记录会话 ID、天气、异常(急刹、掉包等)
|
||||
|
||||
**当场快查**
|
||||
|
||||
- [ ] IMU 静止段平稳,转弯时角速度明显
|
||||
- [ ] 点云帧数/点数正常,无明显大面积丢帧
|
||||
- [ ] 雷达与 IMU 时间覆盖同一时段
|
||||
|
||||
**回实验室**
|
||||
|
||||
- [ ] 已导出中间格式并通过质检
|
||||
- [ ] 本次目标:`rotation_only` 还是尝试 `full_se3`
|
||||
- [ ] 若要竖直方向:确认真有俯仰/高度激励,否则降级交付
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 5. 精度预期
|
||||
|
||||
|
||||
| 量 | 较现实范围 | 说明 |
|
||||
| ---------- | --------- | ---------------- |
|
||||
| 旋转 | 约 0.5°–2° | 最精确部分 |
|
||||
| 水平平移 | 数厘米~十几厘米 | 强依赖配准、激励与同步 |
|
||||
| 竖直 / 部分杠杆臂 | 往往更差甚至不可观 | 无高度激励时无法得出“精确 z” |
|
||||
|
||||
|
||||
如果条件有限,优先交付:**可靠旋转 + δt + 可观的平移分量(若有)+ 明确限制说明**。
|
||||
|
||||
满足条件后的模式与成功标志见根目录 [`README.md`](../README.md) §0。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 6. 交付物建议
|
||||
|
||||
程序默认写出:`T_IMU_lidar.json`、`time_offset.json`、`summary.json`。
|
||||
完整报告目录还可补充:可观性结论、跨会话对比、运动对质量表、限制说明(尤其竖直方向与时间同步方式)。
|
||||
|
||||
```text
|
||||
静止 + 激励录制(多会话)
|
||||
→ 质检 → 估 δt → 关键帧 A/B → 先解 R
|
||||
→ 精修 δt 与 R → 可观则求 t → 验证后交付
|
||||
```
|
||||
|
||||
-209
@@ -1,209 +0,0 @@
|
||||
# 20260808 HI13 + H32:LiDAR–IMU 标定现状与问题
|
||||
|
||||
> 数据:`D:\data\calibration_usable_20260808`
|
||||
> 可用会话:`sessions_v1_host_aligned`(三优先窗)
|
||||
> 当前结果目录:各窗 `out_fixed_dt0/`
|
||||
> 清单:`sessions_v1_host_aligned/calibration_manifest_fixed_dt0.json`
|
||||
> 车辆配置:`config/vehicle_hi13_h32_20260808.yaml`
|
||||
> 约定外参:`p_IMU = T_IMU_lidar · p_lidar`
|
||||
|
||||
---
|
||||
|
||||
## 1. 一句话结论
|
||||
|
||||
**旋转 + 主机桥接时间对齐可以冻结;平移(full_se3)尚不可正式交付。**
|
||||
三窗 `rotation_only`(δt=0)结果跨窗一致,**不必因平移先验 Z 修正而重跑旋转**。
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前可用结果(`out_fixed_dt0`)
|
||||
|
||||
约定:`p_IMU = T_IMU_lidar · p_lidar`;本轮交付 **仅旋转**,`t = [0,0,0]`,`time_offset_s = 0`。
|
||||
|
||||
| 窗 | 状态 | δt | roll/pitch/yaw (°) | 手眼 RMS (°) | 手眼对数 | vs CAD prior |
|
||||
|----|------|----|---------------------|--------------|----------|--------------|
|
||||
| `priority_174005_174515` | `rotation_only_accepted` | 0 | −0.398 / +0.108 / **89.998** | 0.625 | 1374 | 0.413° |
|
||||
| `priority_174905_175450` | 同上 | 0 | −0.316 / −0.352 / **90.002** | 0.293 | 1182 | 0.473° |
|
||||
| `priority_175910_180530` | 同上 | 0 | −0.373 / −0.036 / **90.005** | 0.786 | 789 | 0.375° |
|
||||
|
||||
- 跨窗旋转互差约 **0.15°–0.47°**(相对三窗均值 ≤0.26°)。
|
||||
- CAD/安装平移先验只用于后续 SE3 / 校验,不写入本轮交付 `T`。
|
||||
- 原始摘要:各窗 `out_fixed_dt0/summary.json`;总表 `calibration_manifest_fixed_dt0.json`。
|
||||
|
||||
### 2.1 窗1 `priority_174005_174515` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_174005_174515\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.39806616272552936, 0.10842366761721789, 89.99788311264182]`
|
||||
- quaternion_xyzw:`[-0.0031254048203223084, -0.0017872288323561246, 0.7070914597978358, 0.707112936622415]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[ 3.6946588133e-05, -0.9999758655693408, -0.0069474393698490 ],
|
||||
[ 0.9999982088237712, 2.3798651350e-05, 0.0018925598731371 ],
|
||||
[-0.0018923488575947, -0.0069474968493909, 0.9999740753156198 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 2.2 窗2 `priority_174905_175450` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_174905_175450\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.31554362742542746, -0.35231680831805484, 90.00193338170823]`
|
||||
- quaternion_xyzw:`[0.00022698471903919405, -0.004121119694188399, 0.7071067019847445, 0.7070948146172911]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[-3.3743238552e-05, -0.9999848355714863, -0.0055070399001942 ],
|
||||
[ 0.9999810938467022, 1.2097239027e-07, -0.0061491421465438 ],
|
||||
[ 0.0061490495645171, -0.0055071432752239, 0.9999659297008071 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 2.3 窗3 `priority_175910_180530` — `R_IMU_lidar`
|
||||
|
||||
- 路径:`...\priority_175910_180530\out_fixed_dt0\summary.json`
|
||||
- rpy_deg_xyz:`[-0.37335575043737196, -0.03585856981709423, 90.00538974486676]`
|
||||
- quaternion_xyzw:`[-0.002082462199099642, -0.002525219418619018, 0.7071355299053291, 0.7070704554452735]`
|
||||
|
||||
```text
|
||||
R =
|
||||
[[-9.4068775206e-05, -0.9999787650354249, -0.0065161821101807 ],
|
||||
[ 0.9999997997313592, -8.9988606603e-05, -0.0006264497522950 ],
|
||||
[ 0.0006258500675082, -0.0065162397345547, 0.9999785732361544 ]]
|
||||
t = [0, 0, 0]
|
||||
```
|
||||
|
||||
### 相对历史失败轮次
|
||||
|
||||
| 轮次 | 问题 | 结果 |
|
||||
|------|------|------|
|
||||
| `sessions_v1_aligned` | 首帧强行对齐设备钟 | 三窗手眼失败,RMS ~9°–12° |
|
||||
| 自由估 δt + signed refine | 窗3 δt 漂到 −0.48 s;窗2 yaw≈19° | 跨窗 yaw 矛盾(81°/19°/93°) |
|
||||
| **本轮 fixed δt=0** | 主机桥接后冻结时间 | 三窗 yaw≈90°,可互证 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 已澄清并写入配置的坐标系 / 先验
|
||||
|
||||
### 3.1 车体与传感器
|
||||
|
||||
- 车体:X 前 / Y 左 / Z 上;雷达与 IMU 安装在 **X 正方向**(后轮轴前方)。
|
||||
- CAD 图纸可能画成 +X 朝后,那只是读图坐标系,**不是**车体真实轴。
|
||||
- IMU:HI13 RFU(X 右 / Y 前 / Z 上),原始数据不做轴向重映射。
|
||||
- 雷达 NPZ:假定与车体一致(X 前 / Y 左 / Z 上)。
|
||||
|
||||
### 3.2 安装量(`translation_m`)
|
||||
|
||||
| 传感器 | X / Y(后轮轴中心) | Z(离地) |
|
||||
|--------|---------------------|-----------|
|
||||
| IMU | 2.574 / 0.0365 m | 0.8925 + 0.294 = **1.1865 m** |
|
||||
| 雷达 | 2.522 / 0.00002 m | 相位中心离地 **1.994999879 m** |
|
||||
|
||||
- 后轮轴中心离地:**294 mm**(Z 用离地高时加在 CAD 轴心高上)。
|
||||
- 雷达 CAD `dZ=1.637499879 m`;相位中心离地还需加后轮轴离地 `0.294 m` 和相位中心偏移 `0.0635 m`,最终为 `1.994999879 m`。
|
||||
|
||||
### 3.3 导出外参先验
|
||||
|
||||
- `R_IMU_lidar` ≈ yaw 90°:`[[0,-1,0],[1,0,0],[0,0,1]]`(软约束 σ=15°)。
|
||||
- `t_IMU_lidar` ≈ **`[0.0365, -0.0518, 0.8085]` m**(相对 Z = 1.994999879 − 1.1865 = 0.808499879 m)。
|
||||
- **旋转先验不因 Z 修正改变**;平移先验 Z 更新为 0.808499879 m。
|
||||
|
||||
---
|
||||
|
||||
## 4. 现存问题清单
|
||||
|
||||
### P1. IMU 预积分平移 `Δp` 不可用(阻塞正式平移)
|
||||
|
||||
- 现象:可视化模式 4 若用完整 `X⁻¹ A X`,橙/蓝点云常呈**上下错层**(Z 差米级~几十米)。
|
||||
- 根因:加速度预积分缺少可靠重力/零偏处理,`t_A` 尤其 Z 发散;**不是旋转外参错了**。
|
||||
- 旁证:相对 GICP 的旋转残差中位约 0.16°;`|t_A|` 中位却常 >1 m。
|
||||
- 影响:`full_se3` / 依赖 IMU 位移的平移估计不可信。
|
||||
- 缓解(已做):`visualize_pair_3d.py` 对 `rotation_only` 默认模式 4 = **R 共轭 + GICP 的 t_B**(`--mode4-translation gicp|imu|auto`)。
|
||||
|
||||
### P2. 平面运动导致竖直平移弱可观
|
||||
|
||||
- 三优先窗以水平转弯为主,缺少缓坡/俯仰激励。
|
||||
- 流水线门控已给出 `translation_accepted=false`。
|
||||
- 即使打开平移先验(σ≈5 cm),弱激励下结果易变成**先验回显**,不宜当标定成功。
|
||||
|
||||
### P3. 时间偏移若再自由估计会被带偏(已规避,需保持)
|
||||
|
||||
- 主机 UTC 桥接(MSOP/IMU `HostReceiveUtc`)后,两路已在同一时间轴,残差通常几十毫秒量级。
|
||||
- 若再做有符号 δt 精修,会与错误/未收敛的 R 耦合,窗3 曾从约 −0.12 s 走到 **−0.48 s**。
|
||||
- **现行做法**:桥接会话使用 `--fixed-time-offset-s 0 --no-signed-time-refine`。
|
||||
|
||||
### P4. 单窗低残差 ≠ 外参正确(历史教训)
|
||||
|
||||
- 自由 δt 轮次中,窗2 手眼 RMS 最低(~0.3°)但 yaw≈19°,与 CAD/其他窗差 60°+。
|
||||
- 平面运动下 yaw 外参可出现多个能拟合 `R_A R_X ≈ R_X R_B` 的解。
|
||||
- **必须**做跨窗一致性 + 可视化叠点,不能只看单窗 RMS。
|
||||
|
||||
### P5. 旋转软先验尚未做无先验对照
|
||||
|
||||
- 当前 σ=15°;笔记显示 Tsai 初值本身已接近(约 0.3°–1.1° RMS),不像纯先验硬拽。
|
||||
- 仍缺一次:关闭先验或放大 `sigma_deg` 的对照,以排除「只是被拉到 90°」的疑虑。
|
||||
|
||||
### P6. 文档与操作约定未完全同步(工程)
|
||||
|
||||
- README 需明确写清:host-bridge 后固定 δt=0、禁用 signed refine、rotation_only 可视化用法。
|
||||
- 交付物目前缺一版「冻结的联合/中位 R + 使用说明」JSON/报告(旋转可交,平移明确不交)。
|
||||
|
||||
---
|
||||
|
||||
## 5. 不该做 / 可以做
|
||||
|
||||
| 动作 | 建议 |
|
||||
|------|------|
|
||||
| 因 Z 先验修正重跑三窗 rotation_only | **不必**(R 未依赖新 t) |
|
||||
| 正式交付 6-DOF / 信赖当前 `Δp` 估 t | **不要** |
|
||||
| 试验性 `full_se3`(固定 R、δt=0、新 t 先验) | 可做,结果标「实验」 |
|
||||
| 可视化验收模式 3 vs 4(gicp 平移) | **建议做** |
|
||||
| 无先验 / 大 σ 旋转对照 | **建议做** |
|
||||
| 冻结交付 `R` + `δt=0` 说明 | **建议做** |
|
||||
| 补采缓坡或加强垂直尺寸约束后再估 t | 正式平移前需要 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 建议下一步顺序
|
||||
|
||||
1. **验收旋转**:三窗抽转弯运动对,模式 3/4 叠点;可选无先验对照。
|
||||
2. **定稿旋转**:三窗中位或联合手眼 → 交付 `R_IMU_lidar` +「δt=0(主机桥接)」说明;**明确不交 t**。
|
||||
3. **工程收尾**:README 主机桥接配方;需要时再整理联合标定脚本入口。
|
||||
4. **平移(靠后)**:改善 IMU 位移模型或改用更可靠的位移观测 + 竖直激励后,再用新 `t` 先验跑 SE3。
|
||||
|
||||
---
|
||||
|
||||
## 7. 常用路径与命令
|
||||
|
||||
```text
|
||||
数据根:
|
||||
D:\data\calibration_usable_20260808\sessions_v1_host_aligned\
|
||||
|
||||
结果:
|
||||
...\priority_XXXX\out_fixed_dt0\summary.json
|
||||
...\priority_XXXX\out_fixed_dt0\motion_pairs.json
|
||||
...\calibration_manifest_fixed_dt0.json
|
||||
```
|
||||
|
||||
```powershell
|
||||
# 可视化(rotation_only 默认模式4用 GICP 平移)
|
||||
python tools\visualize_pair_3d.py `
|
||||
--lidar D:\data\calibration_usable_20260808\sessions_v1_host_aligned\priority_174005_174515\lidar `
|
||||
--summary D:\data\calibration_usable_20260808\sessions_v1_host_aligned\priority_174005_174515\out_fixed_dt0\summary.json `
|
||||
--pair-index 0
|
||||
|
||||
# 若要看「坏 Δp」导致的错层效果:
|
||||
# --mode4-translation imu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 问题优先级(跟踪用)
|
||||
|
||||
| ID | 严重度 | 状态 | 标题 |
|
||||
|----|--------|------|------|
|
||||
| P1 | 高 | 未解决 | IMU `Δp` 不可用,阻塞正式平移 |
|
||||
| P2 | 高 | 未解决 | 平面运动,竖直 t 弱可观 |
|
||||
| P3 | 高 | 已规避 | 自由 δt / signed refine 带偏(需保持冻结) |
|
||||
| P4 | 中 | 已吸收教训 | 单窗低残差不可单独验收 |
|
||||
| P5 | 中 | 待做 | 无旋转先验对照 |
|
||||
| P6 | 低 | 待做 | README/交付物同步 |
|
||||
@@ -0,0 +1,166 @@
|
||||
# 雷达–IMU 标定
|
||||
|
||||
本文是本仓库雷达–IMU 标定的唯一规范说明,覆盖目标、数据格式、运行方式、当前实车结果和采集要求。
|
||||
|
||||
## 目标与当前结论
|
||||
|
||||
目标是求雷达坐标系到 IMU 坐标系的安装关系:
|
||||
|
||||
```text
|
||||
p_IMU = T_IMU_lidar · p_lidar
|
||||
```
|
||||
|
||||
`T_A_B` 表示把 B 坐标系中的点变换到 A 坐标系。流程利用连续行驶中的相对运动,而不是把 IMU 加速度二次积分的长时间轨迹当作绝对真值。
|
||||
|
||||
当前 2026-08-08 实车数据的结论是:**旋转和主机桥接后的时间关系可作为候选冻结;完整平移不可交付。** 不应把旋转结果和零平移拼成看似完整的 4×4 外参,更不能把当前 IMU 位移预积分用于正式平移标定。
|
||||
|
||||
| 项目 | 当前状态 |
|
||||
| --- | --- |
|
||||
| 连续运动雷达–IMU 流程 | 已实现并有合成测试 |
|
||||
| 实车旋转候选 | 三个窗口一致,可用于进一步验证 |
|
||||
| 实车时间关系 | 主机桥接后冻结为 `0 s`,不再自由精修 |
|
||||
| 实车完整平移 | 不可观且受预积分位移误差影响,拒绝交付 |
|
||||
|
||||
## 方法概览
|
||||
|
||||
```text
|
||||
设备时间与惯性质量检查
|
||||
→ 估计或确认两传感器时间关系
|
||||
→ 雷达关键帧配准得到相对运动
|
||||
→ 同一时间区间的 IMU 预积分得到相对运动
|
||||
→ 先求旋转手眼关系
|
||||
→ 只有平移可观时才进入完整六自由度优化
|
||||
```
|
||||
|
||||
对关键帧区间 `[i, j]`:
|
||||
|
||||
```text
|
||||
A_ij ≈ IMU 预积分相对运动
|
||||
B_ij ≈ 雷达点云配准相对运动
|
||||
A_ij · X ≈ X · B_ij
|
||||
X = T_IMU_lidar
|
||||
```
|
||||
|
||||
旋转子问题为 `R_A · R_X = R_X · R_B`。旋转通常比平移稳定:加速度偏置和重力方向的微小误差会在位移积分中快速累积,平面转弯又难以提供竖直杆臂信息。因此,完整六自由度只有在残差、跨会话一致性和可观性同时通过时才允许输出。
|
||||
|
||||
## 当前实车结果与限制
|
||||
|
||||
当前可用的三段优先窗口均在主机时间桥接后固定 `time_offset_s=0`,并禁用自由的有符号时间精修:
|
||||
|
||||
| 会话窗口 | roll / pitch / yaw(°) | 手眼旋转 RMS(°) |
|
||||
| --- | --- | ---: |
|
||||
| `priority_174005_174515` | `-0.398 / 0.108 / 89.998` | 0.625 |
|
||||
| `priority_174905_175450` | `-0.316 / -0.352 / 90.002` | 0.293 |
|
||||
| `priority_175910_180530` | `-0.373 / -0.036 / 90.005` | 0.786 |
|
||||
|
||||
三段旋转相互差约为 `0.15°–0.47°`。但以下问题阻止平移放行:
|
||||
|
||||
1. IMU 预积分的位移,尤其竖直分量,会出现米级甚至更大的漂移;它不能作为可靠平移观测。
|
||||
2. 当前重点会话以平面转弯为主,缺少持续坡道或俯仰激励,竖直平移弱可观。
|
||||
3. 允许时间偏移自由精修时,时间与旋转曾发生相互补偿,产生跨窗口矛盾的航向。因此桥接后的偏移固定为零,而不是再次为降低残差调整它。
|
||||
4. 单一窗口残差小不等于外参正确;必须检查跨窗口一致性与点云叠加。
|
||||
|
||||
这也是仓库增加 RTK–IMU 流程的原因:不是替代雷达旋转标定,而是为天线相位中心到 IMU 的平移提供更直接的 GNSS 位置和速度观测。两条流程边界见仓库 [README](../README.md)。
|
||||
|
||||
## 输入、输出与配置
|
||||
|
||||
### 输入
|
||||
|
||||
```text
|
||||
imu.csv
|
||||
t,gx,gy,gz,ax,ay,az
|
||||
单位:秒、rad/s、m/s²;t 应为设备时间
|
||||
|
||||
lidar_session/
|
||||
frames_index.csv 帧编号、文件名、开始/结束时间
|
||||
frames/frame_XXXXX.npz 米制 XYZ 点云
|
||||
|
||||
vehicle_installation.yaml
|
||||
坐标轴、时间语义、可选机械安装信息
|
||||
```
|
||||
|
||||
原始 HI13 IMU `.rscap` 和 H32 雷达 dlog/MSOP 可转换为上述格式:
|
||||
|
||||
```powershell
|
||||
python tools\export_rscap_to_v1.py `
|
||||
--imu-rscap path\to\hi13-imu.rscap `
|
||||
--imu-kind hi13 `
|
||||
--lidar-dlog path\to\session_or_recovered.zip `
|
||||
--host-start 2026-08-08T17:40:05 `
|
||||
--host-end 2026-08-08T17:45:15 `
|
||||
--out path\to\session_v1 `
|
||||
--require-difop
|
||||
```
|
||||
|
||||
### 输出
|
||||
|
||||
| 文件 | 含义 |
|
||||
| --- | --- |
|
||||
| `T_IMU_lidar.json` | 通过验收时的外参;仅旋转模式下不能把其中平移当交付值 |
|
||||
| `time_offset.json` | 定义为 `t_imu = t_lidar + δt` 的时间关系 |
|
||||
| `summary.json` | 状态、残差、可观性和拒绝原因 |
|
||||
| `motion_pairs.json` | 用于复核和点云可视化的相对运动对 |
|
||||
|
||||
## 运行与判读
|
||||
|
||||
安装依赖:
|
||||
|
||||
```powershell
|
||||
python -m pip install -e ".[dev]"
|
||||
python -m pip install -e ".[open3d]" # 点云处理需要时安装
|
||||
```
|
||||
|
||||
先运行仅旋转模式:
|
||||
|
||||
```powershell
|
||||
python -m imu_lidar.cli run `
|
||||
--vehicle-config config\vehicle_installation.template.yaml `
|
||||
--imu path\to\session_v1\imu.csv `
|
||||
--lidar path\to\session_v1\lidar `
|
||||
--output path\to\out `
|
||||
--mode rotation_only `
|
||||
--time-offset-search-s 2.0
|
||||
```
|
||||
|
||||
| `summary.json` 状态 | 含义 |
|
||||
| --- | --- |
|
||||
| `rotation_only_accepted` | 旋转与时间关系可进入独立验证;不代表平移可用 |
|
||||
| `full_se3_accepted` | 仅当完整平移可观且门禁通过时,才可交付完整外参 |
|
||||
| `full_se3_rejected_due_to_observability` | 旋转可用,平移拒绝 |
|
||||
| `blocked` | 时间、质量或模型门禁失败,不能作安装参数 |
|
||||
|
||||
合成复现可验证软件链路,不证明实车精度:
|
||||
|
||||
```powershell
|
||||
powershell -File tools\reproduce_synthetic.ps1
|
||||
python -m pytest -q
|
||||
```
|
||||
|
||||
## 采集要求
|
||||
|
||||
单次有效会话建议:
|
||||
|
||||
```text
|
||||
静止 20–30 s → 连续低速多方向转弯 3–8 min → 静止 10–20 s
|
||||
```
|
||||
|
||||
- 必须保留雷达和 IMU 的设备时间戳;不能仅依赖主机接收时间。
|
||||
- 在结构化环境采集,保证点云配准具有稳定几何约束。
|
||||
- 旋转标定优先包含左右圆或“8”字;直线加减速有助于时间和水平平移。
|
||||
- 若要尝试完整平移,增加连续缓坡、俯仰或其他竖直激励;仅平面运动通常不足。
|
||||
- 标定全过程不得改变两传感器安装关系。
|
||||
|
||||
## 代码结构
|
||||
|
||||
`imu_lidar/` 是雷达–IMU 专用实现:
|
||||
|
||||
| 组件 | 作用 |
|
||||
| --- | --- |
|
||||
| `cli.py`、`pipeline.py` | 命令行入口与流程编排 |
|
||||
| `lidar_io.py`、`registration.py`、`keyframes.py` | 点云读取、配准和关键帧 |
|
||||
| `timestamp_audit.py`、`imu_audit.py`、`time_offset.py` | 时间和 IMU 质量检查、时间关系估计 |
|
||||
| `imu_preintegration.py`、`motion_pairs.py` | IMU 预积分与相对运动对 |
|
||||
| `rotation_handeye.py`、`joint_optimizer.py`、`observability.py` | 旋转求解、联合优化和可观性门禁 |
|
||||
| `finalize.py` | 结果写出 |
|
||||
|
||||
历史改动见 [imu_lidar/CHANGELOG.md](../imu_lidar/CHANGELOG.md),自动化测试说明见 [tests/README.md](../tests/README.md)。
|
||||
@@ -103,7 +103,7 @@
|
||||
- **原本**:对外说明仍偶发「方案二」等旧称呼;根 README 缺少一眼可读的阶段 / 合成 vs 旧车 / 合格数据预期;烟测配置与对比脚本文件名带 `scheme2`。
|
||||
- **改成**:
|
||||
- 根 `[README.md](../README.md)` 增加 §0「现状一览」;明确仓库只有一条连续运动标定路径。
|
||||
- `[tests/README.md](../tests/README.md)`、`[docs/IMU-LiDAR标定.md](../docs/IMU-LiDAR标定.md)`、本目录说明同步边界与阶段。
|
||||
- `[tests/README.md](../tests/README.md)`、`[docs/雷达-IMU标定.md](../docs/雷达-IMU标定.md)`、本目录说明同步边界与阶段。
|
||||
- `config/s2_old_smoke.yaml`、`tools/compare_s2_runs.py` 替换旧 `*scheme2*` 命名。
|
||||
|
||||
---
|
||||
@@ -131,7 +131,7 @@
|
||||
|
||||
### 文档同步 + 合成数据一键复现
|
||||
|
||||
- **原本**:`docs/标定流程与采集清单.md` 仍偏旧版「待写代码 / 因子图设想」;根 README 缺少清晰的一键复现入口与输入输出总表。
|
||||
- **原本**:采集与流程说明仍偏旧版「待写代码 / 因子图设想」;根 README 缺少清晰的一键复现入口与输入输出总表。
|
||||
- **改成**:
|
||||
- 采集清单与现行流水线对齐(完整预积分、δt↔R 交替、可观时再估平移)。
|
||||
- 新增 `tools/reproduce_synthetic.py` / `.ps1`、`tools/show_calibration_report.py`;合成生成写入 `meta.json`;根 README 增加「系统输入输出 + 一键复现」。
|
||||
@@ -148,8 +148,8 @@
|
||||
|
||||
- **原本**:根 README / `docs` / 包说明仍对照已删除的静站路径与内部阶段黑话;`pyproject` 仍声明已删除的 `static_station` 包。
|
||||
- **改成**:
|
||||
- 删除旧静站文档;采集清单定为 `[docs/标定流程与采集清单.md](../docs/标定流程与采集清单.md)`。
|
||||
- 根 `[README.md](../README.md)`、`[docs/IMU-LiDAR标定.md](../docs/IMU-LiDAR标定.md)`、本目录说明改为对外可读,只保留连续运动标定路径。
|
||||
- 删除旧静站文档;采集清单并入规范说明。
|
||||
- 根 `[README.md](../README.md)`、`[docs/雷达-IMU标定.md](../docs/雷达-IMU标定.md)`、本目录说明改为对外可读,只保留连续运动标定路径。
|
||||
- `pyproject.toml` 仅保留 `imu_lidar` / `tools`。
|
||||
|
||||
---
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
# `imu_lidar` 模块说明
|
||||
|
||||
**用途:** 改 `imu_lidar/` 源码时查阅。对外用法见根目录 [`README.md`](../README.md)。
|
||||
|
||||
本包实现 LiDAR–IMU 外参标定:在连续行驶数据上选取关键帧,用 IMU 预积分与雷达配准构造相对运动对,求解安装外参。
|
||||
|
||||
```text
|
||||
A ≈ 关键帧间 IMU 相对运动(预积分:旋转 / 速度增量 / 位移增量)
|
||||
B ≈ 关键帧间雷达配准
|
||||
解 R_A R_X = R_X R_B → 旋转外参(手眼阶段只用旋转)
|
||||
再精修旋转与陀螺零偏;在完整六自由度模式下,可观时再估计平移等
|
||||
```
|
||||
|
||||
入口:
|
||||
|
||||
```powershell
|
||||
python -m imu_lidar.cli plan
|
||||
python -m imu_lidar.cli run --vehicle-config ... --imu ... --lidar ... --output ...
|
||||
```
|
||||
|
||||
整体流程由 `pipeline.py` 串联。
|
||||
修改本目录代码时,请同步更新本说明,并在 [`CHANGELOG.md`](CHANGELOG.md) 追加「时间戳 + 原本 → 改成」。
|
||||
|
||||
---
|
||||
|
||||
## 流水线顺序与文件
|
||||
|
||||
|
||||
| 顺序 | 文件 | 作用 |
|
||||
| --- | ----------------------- | ----------------------------- |
|
||||
| 0 | `contracts.py` | 公共数据类型与状态枚举 |
|
||||
| 0 | `geometry.py` | 刚体变换与旋转工具 |
|
||||
| 0 | `vehicle_config.py` | 读取并校验车辆 YAML |
|
||||
| 1 | `imu_io.py` | 读标准 IMU 中间格式 |
|
||||
| 1 | `lidar_io.py` | 读标准雷达会话目录 |
|
||||
| 2 | `timestamp_audit.py` | 时间单调 / 频率 / 空洞检查 |
|
||||
| 3 | `imu_audit.py` | 静止零偏、加速度模长检查、建议竖直轴 |
|
||||
| 4 | `time_offset.py` | 粗估时间偏置 δt,并用旋转外参精修 |
|
||||
| 5 | `registration.py` | 帧间点云配准 |
|
||||
| 5 | `keyframes.py` | 按运动量抽取关键帧 |
|
||||
| 5 | `lidar_deskew.py` | 可选点云去畸变(低速可关) |
|
||||
| 6 | `imu_preintegration.py` | IMU 预积分(旋转及速度/位移增量、协方差、零偏雅可比) |
|
||||
| 6 | `motion_pairs.py` | 构造运动对;手眼使用其中的旋转 |
|
||||
| 6 | `motion_pairs_io.py` | 运动对 JSON 缓存读写(供可视化直读) |
|
||||
| 7 | `rotation_handeye.py` | 加权旋转手眼 |
|
||||
| 8 | `observability.py` | 旋转 / 平移可观性检查 |
|
||||
| 8 | `joint_optimizer.py` | 联合精修;完整模式下可估计平移、重力、速度与时变零偏 |
|
||||
| 9 | `finalize.py` | 写出结果 JSON(含 `motion_pairs.json`) |
|
||||
| — | `pipeline.py` | 编排全流程 |
|
||||
| — | `cli.py` | 命令行入口 |
|
||||
| — | `CHANGELOG.md` | 改动记录 |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 运行模式要点
|
||||
|
||||
- **运动对**始终计算完整预积分量(旋转、速度增量、位移增量及不确定度)。
|
||||
- `--mode rotation_only`:只精修旋转与常值陀螺零偏,交付旋转与时间偏置。
|
||||
- `--mode full_se3`:当前完成 Phase-A 后明确拒绝平移;待 Phase-B/C 会话状态重构完成后再恢复完整 SE(3) 交付。
|
||||
|
||||
---
|
||||
|
||||
## 输入格式
|
||||
|
||||
```text
|
||||
imu.csv # t,gx,gy,gz,ax,ay,az(建议设备时间)
|
||||
lidar_session/
|
||||
frames_index.csv # frame_id,filename,t_start,t_end
|
||||
frames/frame_XXXXX.npz # points: (N,3) 米
|
||||
```
|
||||
|
||||
原始 N300 `.rscap` + H32 dlog(或旧 MSOP `.rscap`)用仓库工具导出:`python tools/export_rscap_to_v1.py ...`(见 [`docs/V1_数据格式.md`](../docs/V1_数据格式.md))。
|
||||
|
||||
---
|
||||
|
||||
## 当前能力
|
||||
|
||||
- 本包是仓库**唯一**标定路径:质检 → 时间偏置 → 关键帧配对 → 旋转手眼 → 联合精修 →(可选)完整六自由度 → 报告
|
||||
- 点云去畸变:可选
|
||||
- 阶段与用法见根目录 [`README.md`](../README.md)
|
||||
- 改动史:[`CHANGELOG.md`](CHANGELOG.md)
|
||||
@@ -1,13 +0,0 @@
|
||||
# RTK-IMU Calibration Package
|
||||
|
||||
`rtk_imu/` contains the independent RTK-IMU calibration pipeline: G90 observation I/O, antenna-baseline rotation, V1 replay, V3 multisource stages, engineering 6DoF, and the node-state factor graph.
|
||||
|
||||
## Boundary
|
||||
|
||||
This package may import only shared `imu_lidar` utilities: `contracts`, `geometry`, `geodesy`, `imu_io`, `imu_preintegration`, and the generic `rotation_handeye` initializer.
|
||||
|
||||
It must not import LiDAR-specific modules such as `lidar_io`, `lidar_deskew`, `registration`, `pipeline`, `phase_a`, or `joint_optimizer`. The LiDAR-IMU pipeline remains in `imu_lidar/`.
|
||||
|
||||
## Entrypoints
|
||||
Use `tools/run_rtk_imu_*.py` and `tools/audit_rtk_imu_*.py`; these scripts import from `rtk_imu.*`.
|
||||
For the engineering procedure, current result, acceptance boundary, and reproduction commands, see [`README_RTK_IMU.md`](../README_RTK_IMU.md).
|
||||
Reference in New Issue
Block a user