131 lines
6.9 KiB
Markdown
131 lines
6.9 KiB
Markdown
# 测试说明
|
||
|
||
**用途:** 说明合成 pytest 与旧车 S2 线下试验的边界(避免误读)。日常跑通请先看根目录 [README](../README.md)。
|
||
|
||
| 试验 | 是否默认 pytest | 在证明什么 | 不在证明什么 |
|
||
|---|---|---|---|
|
||
| **合成数据** | 是 | 算法链路正确、能收回已知 yaw / δt | 实车安装精度、平移可交付 |
|
||
| **旧车 S2** | 否(线下手工) | 主机时间旧数据上流水线能跑完;质量门会拒绝坏结果 | 外参真值;新车可用性 |
|
||
|
||
---
|
||
|
||
## 1. 自动化测试(合成数据 / `pytest`)
|
||
|
||
入口:`tests/test_v1_pipeline.py`
|
||
命令:
|
||
|
||
```powershell
|
||
cd <仓库根目录>
|
||
python -m pytest -q
|
||
```
|
||
|
||
|
||
| 测试 | 输入 | 在测什么 | 期望结果 |
|
||
| ------------------------------------------------------------- | ------------ | ------------------- | ------------------------------------------ |
|
||
| `test_rotation_handeye_recovers_yaw` | 合成运动对(无点云) | 旋转手眼能否收回已知 yaw | 旋转误差 < 1° |
|
||
| `test_time_offset_on_synthetic` | 合成会话(故意加 δt) | 模长相关粗估时间偏置 | |δt 误差| < 0.05 s |
|
||
| `test_signed_time_offset_refine_improves_or_keeps` | 同上 + 真值 R | 有符号三轴 δt 精修 | 不比粗估明显更差 |
|
||
| `test_preintegration_bias_jacobian_matches_finite_difference` | 随机陀螺序列 | 旋转预积分 `J_bg` | 与有限差分一致(松阈值) |
|
||
| `test_imu_preintegration_recovers_constant_accel_translation` | 常值加速度 | 完整预积分 Δv/Δp | 接近解析值 |
|
||
| `test_imu_preintegration_bias_jacobian_finite_difference` | 随机 IMU | `J_bg`/`J_ba` 一阶修正 | 与重积分接近 |
|
||
| `test_synthetic_pipeline_rejects_noisy_icp_but_keeps_time_audit` | synthetic end-to-end | strict rotation quality gate + time audit | noisy ICP is blocked; delta-t remains accurate |
|
||
| `test_synthetic_pipeline_full_se3_smoke` | synthetic end-to-end | full-SE(3) smoke test | returns an explicit accepted/rejected/blocked status |
|
||
| `test_planar_yaw_is_not_full_rotation_or_translation_observable` | pure-yaw motion pairs | degeneracy detection | full rotation/translation observability is rejected |
|
||
| `test_multi_axis_motion_is_rotation_and_translation_observable` | multi-axis motion pairs | positive observability case | rotation and translation pass |
|
||
| `test_translation_prior_is_reported_but_not_accepted_when_unobservable` | planar motion + CAD prior | prior semantics | prior is reported but not accepted as calibration |
|
||
| `test_handeye_rejects_a_small_fraction_of_gross_rotation_outliers` | motion pairs with a gross outlier | residual-distribution gate | solve is rejected |
|
||
| `test_motion_pairs_reject_low_fitness` | low-fitness registration | fitness gate | no motion pair is emitted |
|
||
| `test_motion_pairs_reject_imu_and_lidar_discontinuities` | timestamp gaps | continuity gates | cross-gap pairs are rejected |
|
||
|
||
|
||
合成数据由 `tools/generate_synthetic_session.py` 生成(墙面点云 + 已知外参 yaw 与 δt)。
|
||
一键复现见根目录 README:`tools/reproduce_synthetic.py`。
|
||
|
||
---
|
||
|
||
|
||
|
||
## 2. 旧车 S2 线下试验(不在默认 pytest 里)
|
||
|
||
|
||
|
||
### 用了什么数据
|
||
|
||
|
||
| 项 | 内容 |
|
||
| ------- | -------------------------------------------------------------------------- |
|
||
| 车辆 / 批次 | 旧 **S2** 验证集(`S2_scheme1_validation`)数据在网盘的“室外车数据\IMU-雷达标定数据” |
|
||
| 典型路径 | `D:\IMU_calibration\work\S2_scheme1_validation\`(历史目录名;含 `imu.csv` + 雷达会话) |
|
||
| IMU 时间 | **主机 UTC 接收时间**(串口块到达时刻),不是 IMU 设备时间 |
|
||
| 雷达时间 | dlog 导出的主机侧 `unix_time_ns`,不是 MSOP 设备时间 |
|
||
| 帧率特征 | 雷达约 **1 Hz** 量级,关键帧间隔偏长 |
|
||
| 配置烟测 | `config/s2_old_smoke.yaml`(仅声明为旧数据烟测,不当交付) |
|
||
|
||
|
||
这些数据**只能用来验证流水线能否跑通**,不能当作新车外参真值来源。
|
||
`blocked` 是质量门的**预期结果**,不是「算法突然坏了」。
|
||
|
||
### 做了什么测试
|
||
|
||
对同一批 S2 中间格式多次跑 `cli run`,例如:
|
||
|
||
- 预积分加强后的输出目录(本机历史名如 `out_scheme2_preint`)
|
||
- 有符号 δt / 联合精修后的输出(本机历史名如 `out_scheme2_phaseA`)
|
||
- 用 `tools/compare_s2_runs.py` 对比两次 `summary.json`
|
||
|
||
命令形态(路径按本机实际修改;雷达会话目录若仍叫 `scheme2_session` 为历史命名):
|
||
|
||
```powershell
|
||
python -m imu_lidar.cli run `
|
||
--vehicle-config config\s2_old_smoke.yaml `
|
||
--imu D:\IMU_calibration\work\S2_scheme1_validation\imu.csv `
|
||
--lidar D:\IMU_calibration\work\S2_scheme1_validation\scheme2_session `
|
||
--output path\to\out_s2 `
|
||
--mode rotation_only `
|
||
--time-offset-search-s 2.0
|
||
|
||
python tools\compare_s2_runs.py path\to\out_old\summary.json path\to\out_new\summary.json
|
||
```
|
||
|
||
|
||
|
||
### 得到什么结果(记录摘要)
|
||
|
||
|
||
| 指标 | 预积分加强一轮 | 有符号 δt / 精修一轮 |
|
||
| -------- | ------------- | ------------------ |
|
||
| `status` | `blocked`(预期) | `blocked`(预期) |
|
||
| 手眼 RMS | 约 **15.0°** | 约 **14.5°** |
|
||
| 手眼中位数 | — | 约 **6.8°** |
|
||
| δt | 约 **−2.0 s** | 约 **−1.75 s**(有修正) |
|
||
| 相关峰 | 很弱(约 0.18) | 仍弱(约 0.13) |
|
||
| 结论 | 链路可跑 | 残差略降,但 **不当交付外参** |
|
||
|
||
|
||
原因归纳:
|
||
|
||
1. 时间戳是**主机时间**,相关峰弱,δt / yaw / 零偏互相耦合;
|
||
2. 雷达约 1 Hz,运动对间隔长,IMU 侧更易漂;
|
||
3. 质量门主动 `blocked`,避免把坏结果当成安装参数。
|
||
|
||
**正式标定**必须改用设备时间(IMU `device_timestamp`、雷达 MSOP 设备时)重新采集后再跑。
|
||
|
||
---
|
||
|
||
|
||
|
||
## 3. 配准结果怎么目视检查
|
||
|
||
标定跑完后(合成或实车):
|
||
|
||
```powershell
|
||
python tools\visualize_pair_3d.py `
|
||
--lidar examples\synthetic_session\lidar `
|
||
--imu examples\synthetic_session\imu.csv `
|
||
--summary examples\synthetic_session\out\summary.json `
|
||
--pair-index 0 `
|
||
--save-png examples\synthetic_session\out\pair0_overlay.png
|
||
```
|
||
|
||
交互窗口快捷键:`1`–`4` 切换叠点模式;`N`/`]` 下一运动对,`P`/`[` 上一运动对。
|
||
无显示器时加 `--no-gui --save-png ...` 只出俯视图 PNG。 |