补充RTK-IMU标定结果与复现说明
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
# 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)
|
||||
@@ -9,3 +9,5 @@ This package may import only shared `imu_lidar` utilities: `contracts`, `geometr
|
||||
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