From 4ff176d1846130866fdb600b6a24539556ce4847 Mon Sep 17 00:00:00 2001 From: "lichun.qu" <16975270+zzqlc@user.noreply.gitee.com> Date: Mon, 3 Aug 2026 17:39:39 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E7=AE=80=E5=AF=B9=E5=A4=96=E6=96=87?= =?UTF-8?q?=E6=A1=A3=EF=BC=9A=E4=BB=A5=20README=20=E4=B8=BA=E7=9F=AD?= =?UTF-8?q?=E5=85=A5=E5=8F=A3=E5=B9=B6=E6=A0=87=E6=98=8E=E5=90=84=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E7=94=A8=E9=80=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- README.md | 373 ++++++++++--------------------------- docs/IMU-LiDAR标定.md | 21 ++- docs/V1_数据格式.md | 15 +- docs/标定流程与采集清单.md | 7 +- imu_lidar/CHANGELOG.md | 82 +++++++- imu_lidar/文件职责说明.md | 13 +- tests/README.md | 16 +- 7 files changed, 211 insertions(+), 316 deletions(-) diff --git a/README.md b/README.md index aaaa09f..3c793ee 100644 --- a/README.md +++ b/README.md @@ -1,350 +1,171 @@ # LiDAR–IMU 外参标定 -用车上的**激光雷达(LiDAR)**与**惯性测量单元(IMU)**在连续行驶中的相对运动,估计二者之间的安装关系(外参),并估计两路传感器的时间差。 +用连续行驶中的 LiDAR 与 IMU 相对运动,估计安装外参与时间偏置: ```text p_IMU = T_IMU_lidar · p_lidar ``` -实现包:`[imu_lidar/](imu_lidar/)`。文件职责说明:`[imu_lidar/文件职责说明.md](imu_lidar/文件职责说明.md)`。 - -本仓库**只有这一条标定路径**(连续运动关键帧 + IMU 预积分)。不直接解析原始 `.rscap` / dlog,需先导出为中间格式。 +**当前阶段:** 算法与合成自检已闭环;已提供 `tools/export_rscap_to_v1.py`(N300+H32 → 中间格式);**合格实车验收尚未完成**,故正式外参尚未对实车落盘交付。 --- -## 0. 现状一览(先读) +## 先看什么(对外三份就够) -| 项 | 说明 | -| ------------- | ------------------------------------------------------------------------ | -| **仓库做什么** | 输入标准中间格式(IMU CSV + 雷达会话),输出 LiDAR–IMU **正式安装外参** `T_IMU_lidar` 与时间偏置 `δt`。合格数据且过质量门 → 可交付(常规先交旋转 + δt;激励够再交可观平移);数据不合格或未过门 → `blocked`,不交外参 | -| **当前阶段** | 算法链路已闭环,合成自检通过;**尚缺合格实车数据验收**,故正式外参尚未对实车落盘交付(生产级原始录制→中间格式导出仍待完善) | -| **合成数据测什么** | 证明链路能跑通,并能收回**已知**旋转(yaw)与 δt;**不证明**实车安装精度或平移交付 | -| **旧车 S2 测什么** | 仅线下烟测:主机时间旧数据上流水线能否跑完;结果预期为 `blocked`,**不当作外参真值** | -| **合格数据** | 见下方定义;拿到后即可按正式标定流程跑通,期望得到可交付外参(先旋转 + δt) | +| 顺序 | 文档 | 用途 | +| --- | -------------------------------------- | -------------------- | +| 1 | **本 README** | 做什么、怎么跑、结果怎么判 | +| 2 | [docs/V1_数据格式.md](docs/V1_数据格式.md) | 中间格式 + `.rscap` 导出命令 | +| 3 | [docs/标定流程与采集清单.md](docs/标定流程与采集清单.md) | 现场怎么采(合格数据要求) | - - -### 什么叫合格数据 - -同时满足下列条件,才视为可用于正式标定(与旧车主机时间烟测数据区分): - - -| 类别 | 要求 | -| ------------ | ----------------------------------------------------------------------------- | -| **时间戳** | IMU、雷达均用**设备时间**写入中间格式的 `t` / `t_start`/`t_end`(可另留主机接收时间作排查,但标定主轴不用主机时) | -| **会话结构** | 单趟:`静止 20–30 s` → `低速连续运动 3–8 min` → `再静止 10–20 s`;运动含明显左右转(如「8」字 / 圆)及适量加减速 | -| **场景** | 有墙、柱、路缘等结构,避免空旷无特征;雷达帧率与点数正常、无明显大面积丢帧 | -| **覆盖** | 两路传感器覆盖**同一段**物理行驶;安装全程不得改动 | -| **格式** | 已导出本仓库中间格式:`imu.csv` + `lidar_session/`(见 [docs/V1_数据格式.md](docs/V1_数据格式.md)) | -| **验证会话(建议)** | 另录一段独立路线 B,只做叠点/一致性检查,不参与求外参 | - - -**不算合格(举例):** 仅主机接收时间;只有静止、无转弯;IMU 与雷达不是同一趟;未导出中间格式;时间相关极弱仍强行当安装参数。 - -完整现场清单见 [docs/标定流程与采集清单.md](docs/标定流程与采集清单.md)。 - -### 合格数据拿到后 → 正式外参与预期效果 - -仓库目标产物就是**可安装使用的外参**(再加 δt)。合格数据过门后: - - -| 模式 | 跑法 | 正式交付内容 | 较现实预期 | 成功标志 | -| ----------------------- | ---------------------- | ----------- | --------------------------------- | ----------------------------------------- | -| `rotation_only`(第一步,必做) | `--mode rotation_only` | 旋转外参 + δt | 旋转约 **0.5°–2°**;δt 随同步与激励质量变化 | `summary.json` → `rotation_only_accepted` | -| `full_se3`(激励够再试) | `--mode full_se3` | 上一项 + 可观的平移 | 水平平移约数厘米~十几厘米;竖直常更差或不可观(需缓坡或垂直先验) | `full_se3_accepted`;否则旋转仍可交付、平移拒绝 | - - -交付前须叠点云 / 跨会话独立验证;`blocked` 一律不可用作安装参数。 -**当前尚未完成的是「用合格实车数据跑出并验收这份外参」**,不是「合格数据也交不出外参」。 - -### 两类试验对照 - - -| | 合成数据(默认 pytest / 一键复现) | 旧车 S2(线下,非默认测试) | -| ------- | -------------------------------------- | ---------------- | -| 目的 | 回归算法正确性 | 验证实车 IO/链路可跑 | -| 时间戳 | 可控、带已知 δt | 主机接收时间(非设备时间) | -| 是否合格数据 | 否(合成,仅对照) | **否**(主机时间,预期拒绝) | -| 期望结果 | `rotation_only_accepted`;δt / yaw 接近真值 | `blocked`(质量门拒绝) | -| 能否当安装参数 | 否 | **否** | - - -细节见 [tests/README.md](tests/README.md)。实现状态细表见 [docs/IMU-LiDAR标定.md](docs/IMU-LiDAR标定.md) §8。 +其余(方法细述、测试说明、源码职责、CHANGELOG)给深入阅读 / 改代码时用,见文末。 --- -## 目录 +## 1. 输入 / 输出 -1. [现状一览(先读)](#0-现状一览先读) -2. [系统输入 / 输出](#1-系统输入--输出) -3. [一键复现(合成数据)](#2-一键复现合成数据) -4. [能求出什么](#3-能求出什么) -5. [方法概要](#4-方法概要) -6. [分步求值](#5-分步求值) -7. [程序流程](#6-程序流程) -8. [真实数据怎么跑](#7-真实数据怎么跑) -9. [结果判读](#8-结果判读) -10. [仓库结构与文档](#9-仓库结构与文档) + +| 输入 | 说明 | +| --------- | ----------------------------------------------------------- | +| `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` | 状态、残差、可观性 | + + +新车原始数据导出: + +```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 +``` --- -## 1. 系统输入 / 输出 - - - -### 输入 - - -| 输入 | 说明 | -| --------- | --------------------------------------------------------------------- | -| `imu.csv` | 列:`t,gx,gy,gz,ax,ay,az`(秒;陀螺 rad/s;加速度 m/s²) | -| 雷达点云 | `frames_index.csv` + `frames/frame_XXXXX.npz`(点云米制) | -| 车辆配置 YAML | 轴向与时间语义;**不必事先填外参真值**(模板:`config/vehicle_installation.template.yaml`) | - - -中间格式细节见 [docs/V1_数据格式.md](docs/V1_数据格式.md)。原始 `.rscap` 等需先导出。 - -### 输出(`--output` 目录) - - -| 文件 | 内容 | -| -------------------- | ---------------------------- | -| `T_IMU_lidar.json` | 外参矩阵、平移、四元数、欧拉角 | -| `time_offset.json` | δt,定义 `t_imu = t_lidar + δt` | -| `summary.json` | 状态、残差、可观性、各阶段细节 | -| `report_preview.png` | 一键复现时生成的简易指标图(可选) | - - ---- - - - -## 2. 一键复现(合成数据) - -不需要实车数据。脚本会:**生成合成 IMU/雷达 → 跑标定 → 打印报告并出预览图 → 跑 pytest**。 - -**这一趟证明什么:** 全流程可复现;能收回合成真值中的旋转(yaw)与时间偏置。 -**不证明什么:** 实车安装精度、平移外参可交付、主机时间旧数据可用。 - -### 推荐(Windows) +## 2. 一键复现(合成,不需实车) ```powershell cd <本仓库根目录> python -m pip install -e ".[dev]" -python -m pip install -e ".[open3d]" # 可选,配准更稳;未装则用内置 ICP -# 预览图需要 matplotlib(没有则跳过绑图,不影响标定) -python -m pip install matplotlib - +python -m pip install -e ".[open3d]" # 推荐 powershell -File tools\reproduce_synthetic.ps1 ``` -只要标定、跳过测试: - -```powershell -powershell -File tools\reproduce_synthetic.ps1 -SkipPytest -``` - -尝试完整六自由度模式: - -```powershell -powershell -File tools\reproduce_synthetic.ps1 -Mode full_se3 -SkipPytest -``` - - - -### 等价 Python 入口 - -```powershell -python tools\reproduce_synthetic.py -python tools\reproduce_synthetic.py --mode full_se3 --skip-pytest -``` - - - -### 这一趟用了什么、产出什么 - -```text -INPUT - examples/synthetic_session/imu.csv - examples/synthetic_session/lidar/ - config/vehicle_installation.template.yaml - examples/synthetic_session/meta.json # 合成真值(δt、yaw),仅用于对照 - -OUTPUT - examples/synthetic_session/out/T_IMU_lidar.json - examples/synthetic_session/out/time_offset.json - examples/synthetic_session/out/summary.json - examples/synthetic_session/out/report_preview.png -``` - -单独查看已有结果: - -```powershell -python tools\show_calibration_report.py ` - --summary examples\synthetic_session\out\summary.json ` - --truth-meta examples\synthetic_session\meta.json ` - --plot examples\synthetic_session\out\report_preview.png -``` - - - -### 配准结果 3D / 俯视可视化 - -蓝=目标帧,橙=源帧。 - - -| 按键 | 作用 | -| --------------------- | ------------------------------------- | -| `1` / `2` / `3` / `4` | 原始 / IMU(X=I) / 雷达配准 B / 标定预测 `X⁻¹AX` | -| `N` 或 `]` | 下一运动对 | -| `P` 或 `[` | 上一运动对 | +证明:链路可跑通,能收回已知 yaw / δt。 +不证明:实车安装精度、平移可交付。 +产物在 `examples/synthetic_session/out/`。叠点查看: ```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 + --pair-index 0 ``` -`--pair-index` 只决定起始对;窗口内可继续按 `N`/`P` 切换。无 GUI 时加 `--no-gui`。封装:`tools\view_pair.ps1`。 +键 `1`–`4` 切换叠点模式;`N`/`P` 切换运动对。 --- -## 3. 能求出什么 +## 3. 真实数据怎么跑 - -| 结果 | 含义 | 说明 | -| ------- | ------------- | ------------------ | -| 旋转外参 | 雷达相对 IMU 的朝向差 | 常规主交付 | -| 时间偏置 δt | 两路时钟差(秒) | 与旋转一并给出 | -| 平移外参 | 安装位置差(米) | 激励足够且质量门通过才接受,否则置零 | -| 零偏等 | 辅助量 | 改善积分/优化,一般不当安装外参交付 | - - ---- - - - -## 4. 方法概要 - -1. 低速多转弯行驶(如「8」字),首尾各留静止段。 -2. 雷达关键帧配准得相对运动 **B**。 -3. 同一时段 IMU 预积分得 **A**(先用旋转)。 -4. 手眼关系:`R_A · R_X ≈ R_X · R_B`。 -5. 时间与旋转稳定后,若 `--mode full_se3` 且可观,再估计平移(用加速度预积分、重力、速度与时变零偏)。 - ---- - - - -## 5. 分步求值 - - -| 步骤 | 交付 | 典型要求 | -| --- | ------- | ---------------------- | -| 第一步 | 旋转 + δt | 设备时间戳;静止 + 低速转弯;有结构的场景 | -| 第二步 | + 水平平移 | 更多转弯半径与加减速 | -| 第三步 | 完整六自由度 | 缓坡等俯仰激励,或垂直安装尺寸先验 | - - -- `--mode rotation_only`:第一步 -- `--mode full_se3`:尝试完整刚体;平移仍可能被拒绝 - -质量门未通过时,不能当正式安装参数。 - ---- - - - -## 6. 程序流程 - -```text -读入 → 时间/IMU 质检 → 粗估 δt - → 关键帧配准 B + IMU 预积分 A → 旋转手眼 R - → 用 R 精修 δt(可交替组对) - → 联合精修 R / 常值陀螺零偏 - →(full_se3 且可观)重力、速度、时变零偏、平移 t - → 写出 JSON -``` - -「可观」:程序检查转轴是否够多样、相对位移是否够丰富;不够则只保留旋转。 - ---- - - - -## 7. 真实数据怎么跑 +1. 按采集清单录制(设备时间;静止 + 低速转弯;有结构场景) +2. 导出中间格式(第1节命令) +3. 填写车辆 YAML 的轴向与时间语义 +4. 标定: ```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 ` + --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 ``` -采集与现场清单:[docs/标定流程与采集清单.md](docs/标定流程与采集清单.md)。 +1. 看 `summary.json`,再叠点 / 用验证会话复核后才交付 -旧车 S2 主机时间烟测(预期 `blocked`,不当交付):配置见 `config/s2_old_smoke.yaml`,步骤见 `[tests/README.md](tests/README.md)`。 + +| 模式 | 交付 | 成功标志 | +| ------------------- | ------- | --------------------------- | +| `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°;水平平移数厘米~十几厘米;无坡时竖直常不可观。 --- -## 8. 结果判读 +## 4. 方法(一句话) - -| `summary.json` 状态 | 含义 | -| ---------------------------------------- | ----------------- | -| `rotation_only_accepted` | 旋转可用(该模式下平移置零) | -| `full_se3_accepted` | 含平移的完整外参通过 | -| `full_se3_rejected_due_to_observability` | 旋转可用,平移未接受 | -| `blocked` | 前序失败,**不可用作安装参数** | - - -请同时看手眼残差、时间相关、可观性说明,并做点云叠加等独立验证。 +关键帧雷达配准得 **B**,同区间 IMU 预积分得 **A**,解 `R_A R_X ≈ R_X R_B`;再估 δt。可观时才在 `full_se3` 下交平移。 --- -## 9. 仓库结构与文档 +## 5. 试验边界(勿误读) + + +| | 合成 pytest | 旧车 S2 线下 | +| ------ | ------------------------ | ----------------- | +| 目的 | 回归算法 | 验证旧主机时间数据上链路能跑完 | +| 期望 | `rotation_only_accepted` | `blocked`**(预期)** | +| 当安装参数? | 否 | **否** | + + +细节:[tests/README.md](tests/README.md)。 + +--- + + + +## 6. 仓库结构与其余文档 ```text -imu_lidar/ 标定算法与 CLI -config/ 车辆配置模板 -docs/ 流程、数据格式、方法说明 -tools/ 合成数据、一键复现、报告查看 -tests/ 自动化测试 +imu_lidar/ 算法与 CLI +config/ 车辆配置模板 +docs/ 采集清单、数据格式、方法细述 +tools/ 导出、合成复现、可视化 +tests/ 自动化测试 ``` -| 文档 | 内容 | -| ------------------------------------------------ | ---------------------- | -| [imu_lidar/文件职责说明.md](imu_lidar/文件职责说明.md) | 各源文件职责 | -| [imu_lidar/CHANGELOG.md](imu_lidar/CHANGELOG.md) | 算法改动记录 | -| [docs/标定流程与采集清单.md](docs/标定流程与采集清单.md) | 现场采集与分步流程(与现行实现对齐) | -| [docs/V1_数据格式.md](docs/V1_数据格式.md) | 中间数据格式 | -| [docs/IMU-LiDAR标定.md](docs/IMU-LiDAR标定.md) | 方法约定与实现状态 | -| [tests/README.md](tests/README.md) | 自动化测试说明 + S2 旧数据线下试验结果 | +| 文档 | 何时看 | +| ------------------------------------------------ | ---------------- | +| [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) | 要查改动史 | -改算法请同步更新 `imu_lidar/文件职责说明.md` 与 `CHANGELOG.md`;改安装/运行/对外说明时更新本文件。 \ No newline at end of file +改算法请同步职责说明与 CHANGELOG;改对外用法请更新本 README。 \ No newline at end of file diff --git a/docs/IMU-LiDAR标定.md b/docs/IMU-LiDAR标定.md index 9d0a8eb..ef54514 100644 --- a/docs/IMU-LiDAR标定.md +++ b/docs/IMU-LiDAR标定.md @@ -1,7 +1,8 @@ # LiDAR–IMU 外参标定说明 -本文说明本仓库采用的标定目标、约定、流水线与实现状态。 -代码位于本仓库的 `imu_lidar/` 包。场地采集细则可另见项目侧的采集需求文档。 +**用途:** 方法约定与实现状态(深入阅读)。日常使用请先看根目录 [`README.md`](../README.md)。 + +本文说明标定目标、约定、流水线与实现状态。代码在 `imu_lidar/`。场地采集见 [`标定流程与采集清单.md`](标定流程与采集清单.md)。 --- @@ -177,7 +178,7 @@ python -m imu_lidar.cli run ` | 合成数据 pytest / 一键复现 | 已实现(证明链路与已知 yaw/δt,不证明实车精度) | | 旧车主机时间烟测(S2) | 线下可跑;预期 `blocked`,不当交付 | | 设备时间新车数据正式验收 | **待做** | -| 原生存储一键导出为中间格式 | **待完善** | +| 原生存储一键导出为中间格式 | 已提供 `tools/export_rscap_to_v1.py`(N300+H32 MSOP → V1;MSOP-only 用默认垂直角) | 细项见 [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md)。 @@ -185,10 +186,10 @@ python -m imu_lidar.cli run ` ## 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) | +| 内容 | 路径 | 备注 | +|---|---|---| +| 对外总览(优先) | 根目录 [`README.md`](../README.md) | 日常入口 | +| 采集清单 | [`标定流程与采集清单.md`](标定流程与采集清单.md) | 现场 | +| 数据格式 / 导出 | [`V1_数据格式.md`](V1_数据格式.md) | 中间格式 | +| 文件职责说明 | [`imu_lidar/文件职责说明.md`](../imu_lidar/文件职责说明.md) | 改代码 | +| 改动史 | [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md) | 改代码 | diff --git a/docs/V1_数据格式.md b/docs/V1_数据格式.md index f548417..5564c8a 100644 --- a/docs/V1_数据格式.md +++ b/docs/V1_数据格式.md @@ -1,6 +1,19 @@ # V1 标准中间数据格式 -第一版流水线**不直接读** dlog / rscap。请先把数据整理成下列格式。 +**用途:** 标定程序读入的 CSV/NPZ 约定,以及新车 `.rscap` 如何导出。总览见根目录 [README](../README.md)。 + +## 从原始 `.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`。 +时间轴为**设备时间**:N300 `device_timestamp_us`→秒;H32 MSOP `device_timestamp_ms`→秒。主机接收时间不写入标定主轴。 ## IMU diff --git a/docs/标定流程与采集清单.md b/docs/标定流程与采集清单.md index b9e8ef6..a7ff5cc 100644 --- a/docs/标定流程与采集清单.md +++ b/docs/标定流程与采集清单.md @@ -1,9 +1,10 @@ # 纯 LiDAR–IMU:标定流程与采集清单 -仅有激光雷达与 IMU、无 RTK/绝对位姿时的推荐流程。 -目标外参:`p_IMU = T_IMU_lidar · p_lidar`(`T_A_B` 表示把 B 系点变到 A 系)。 +**用途:** 现场怎么采合格数据(看完根目录 [README](../README.md) 后再看本文即可)。 +算法命令与结果判读以 README 为准;改动史见 [`imu_lidar/CHANGELOG.md`](../imu_lidar/CHANGELOG.md)。 -算法实现与命令见根目录 `[README.md](../README.md)`;改动史见 `[imu_lidar/CHANGELOG.md](../imu_lidar/CHANGELOG.md)`。 +仅有激光雷达与 IMU、无 RTK/绝对位姿时的推荐采集与流程要点。 +目标外参:`p_IMU = T_IMU_lidar · p_lidar`(`T_A_B` 表示把 B 系点变到 A 系)。 --- diff --git a/imu_lidar/CHANGELOG.md b/imu_lidar/CHANGELOG.md index 2ce1d79..5ed034b 100644 --- a/imu_lidar/CHANGELOG.md +++ b/imu_lidar/CHANGELOG.md @@ -5,40 +5,77 @@ --- +## 2026-08-03 17:30 (UTC+8) + +### 文档:精简对外阅读路径 + +- **原本**:README 很长,多份文档职责不清,外人易觉复杂。 +- **改成**:README 改为短入口 +「对外三份就够」;采集清单 / 方法说明 / 测试说明 / 职责说明文首标明用途;细节仍保留在原文件。 + +--- + +## 2026-08-03 11:40 (UTC+8) + +### 新增:N300/H32 `.rscap` → V1 中间格式导出 + +- **原本**:标定只接受 CSV/NPZ;新车原始录制需手工转换,无仓库内导出器。 +- **改成**: + - 新增 `tools/rscap_v2/`(V2 读取、N300 IMU、H32 MSOP 拼帧)与 `tools/export_rscap_to_v1.py`。 + - 导出写入设备时间轴的 `imu.csv` + `lidar/`;支持 `--frame-stride` / `--max-points-per-frame`。 + - 单元测试 `tests/test_export_rscap_helpers.py`。 + +--- + + + ## 2026-08-01 11:40 (UTC+8) + + ### 文档:现状一览补充「合格数据」定义 - **原本**:§0 只写「合格数据拿到后」怎么跑,未写清何为合格。 -- **改成**:根 [`README.md`](../README.md) §0 增加「什么叫合格数据」表(时间戳 / 会话 / 场景 / 格式 / 反例)及拿到后的模式与预期。 +- **改成**:根 `[README.md](../README.md)` §0 增加「什么叫合格数据」表(时间戳 / 会话 / 场景 / 格式 / 反例)及拿到后的模式与预期。 --- + + ## 2026-08-01 11:30 (UTC+8) + + ### 文档:现状一览 + 去掉「方案」二分表述 - **原本**:对外说明仍偶发「方案二」等旧称呼;根 README 缺少一眼可读的阶段 / 合成 vs 旧车 / 合格数据预期;烟测配置与对比脚本文件名带 `scheme2`。 - **改成**: - - 根 [`README.md`](../README.md) 增加 §0「现状一览」;明确仓库只有一条连续运动标定路径。 - - [`tests/README.md`](../tests/README.md)、[`docs/IMU-LiDAR标定.md`](../docs/IMU-LiDAR标定.md)、本目录说明同步边界与阶段。 + - 根 `[README.md](../README.md)` 增加 §0「现状一览」;明确仓库只有一条连续运动标定路径。 + - `[tests/README.md](../tests/README.md)`、`[docs/IMU-LiDAR标定.md](../docs/IMU-LiDAR标定.md)`、本目录说明同步边界与阶段。 - `config/s2_old_smoke.yaml`、`tools/compare_s2_runs.py` 替换旧 `*scheme2*` 命名。 --- + + ## 2026-07-31 18:10 (UTC+8) + + ### 配准可视化工具 + tests 说明(含 S2 线下记录) - **原本**:无类似 RTK 仓库的运动对叠点 3D 查看;`tests/` 未说明合成 pytest 与 S2 旧数据线下试验的区别与结果。 - **改成**: - 新增 `tools/visualize_pair_3d.py` / `view_pair.ps1`(键 1–4:原始 / IMU(X=I) / 雷达 B / `X⁻¹AX`;可 `--save-png`)。 - - 新增 [`tests/README.md`](../tests/README.md):自动化用例表 + S2 主机时间数据做了什么、结果为何 `blocked`。 + - 新增 `[tests/README.md](../tests/README.md)`:自动化用例表 + S2 主机时间数据做了什么、结果为何 `blocked`。 --- + + ## 2026-07-31 17:20 (UTC+8) + + ### 文档同步 + 合成数据一键复现 - **原本**:`docs/标定流程与采集清单.md` 仍偏旧版「待写代码 / 因子图设想」;根 README 缺少清晰的一键复现入口与输入输出总表。 @@ -48,20 +85,28 @@ --- + + ## 2026-07-31 16:30 (UTC+8) + + ### 文档:移除已删除的静站路径表述,对外 README 重写 - **原本**:根 README / `docs` / 包说明仍对照已删除的静站路径与内部阶段黑话;`pyproject` 仍声明已删除的 `static_station` 包。 - **改成**: - - 删除旧静站文档;采集清单定为 [`docs/标定流程与采集清单.md`](../docs/标定流程与采集清单.md)。 - - 根 [`README.md`](../README.md)、[`docs/IMU-LiDAR标定.md`](../docs/IMU-LiDAR标定.md)、本目录说明改为对外可读,只保留连续运动标定路径。 + - 删除旧静站文档;采集清单定为 `[docs/标定流程与采集清单.md](../docs/标定流程与采集清单.md)`。 + - 根 `[README.md](../README.md)`、`[docs/IMU-LiDAR标定.md](../docs/IMU-LiDAR标定.md)`、本目录说明改为对外可读,只保留连续运动标定路径。 - `pyproject.toml` 仅保留 `imu_lidar` / `tools`。 --- + + ## 2026-07-31 14:00 (UTC+8) + + ### Phase-C:完整 IMU 预积分 + 重力/速度/动态零偏(full_se3) - **原本**: @@ -75,8 +120,12 @@ --- + + ## 2026-07-31 11:20 (UTC+8) + + ### 文档维护约定 + README 与现行实现对齐 - **原本**:根 README 与已删除的静站目录说明仍按「双路径并行」表述;部分模块说明未写明有符号 δt;改代码时 README 更新不完整。 @@ -86,8 +135,12 @@ --- + + ## 2026-07-31 09:40 (UTC+8) + + ### 流水线:手眼未过门时仍尝试有符号 δt 精修 - **原本**:`rotation_handeye.ok=false`(如 RMS>5°)时立即 `blocked` 返回,阶段 A 的有符号 δt 精修根本不会执行。 @@ -95,8 +148,12 @@ --- + + ## 2026-07-31 09:20 (UTC+8) + + ### 阶段 A:标准旋转预积分因子 + 精确时间边界 + 有符号 δt 精修 - **原本**: @@ -104,15 +161,19 @@ - δt 仅靠角速度模长互相关粗估;手眼得到 `R` 后不再回头精修时间。 - 联合精修对零偏多用重积分或 `Exp(-δbΔt)` 近似,残差未按协方差白化,也无 `δb` 先验。 - **改成**: - - `imu_preintegration.preintegrate_gyro`:区间端点 **线性插值** 到精确 `t0/t1`;离散中值更新同时传播 **`cov(Σ)`** 与 **`J_bg`**(`ΔR(b+δb)≈ΔR Exp(J_bg δb)`);weight 由 `trace(Σ)` + 激励/时长构造。 + - `imu_preintegration.preintegrate_gyro`:区间端点 **线性插值** 到精确 `t0/t1`;离散中值更新同时传播 `cov(Σ)` 与 `J_bg`(`ΔR(b+δb)≈ΔR Exp(J_bg δb)`);weight 由 `trace(Σ)` + 激励/时长构造。 - `motion_pairs` metadata 增加 `cov`、`J_bg`,modeling 标记为 `gyro_preintegration_factor_phase_a`。 - `time_offset.refine_time_offset_signed`:用当前 `R_IMU_lidar` 把 LiDAR 角速度变到 IMU 系,在粗 δt 邻域做 **三轴有符号 MSE 精修**;仅当 MSE 下降且 **模长相关不劣化** 时才接受,避免 ICP 噪声带偏;`pipeline` 在手眼后与构对交替最多 2 轮。 - `joint_optimizer`:残差按 `Σ` **信息白化**;零偏用 `J_bg` 一阶修正;增加弱 `δb` 先验。 --- + + ## 2026-07-30 17:50 (UTC+8) + + ### 第 1 步:帧间 IMU 轻量加强(加权预积分手眼) - **原本**:`motion_pairs` 用 `integrate_gyro_rotation` 直接得到 `R_A`,各运动对等权进入 `rotation_handeye`;手眼残差不区分长短间隔与激励强弱。 @@ -121,6 +182,8 @@ - `motion_pairs` 改为调用 `preintegrate_gyro`,在 `metadata` 写入 `weight/duration_s/mean_gyro_norm/preint_sigma_rad/t_*_imu_s`,并增加 A/B 转角粗一致性过滤。 - `rotation_handeye` 改为 **√weight 加权** 的 Tsai 初值与 Huber 非线性精修;报告仍给未加权 RMS/中位数便于解读。 + + ### 第 2 步:预积分残差联合精修(外参 + 陀螺零偏) - **原本**:`joint_optimizer` 在手眼 `R_X` 基础上,仅在可观时用离散手眼平移式尝试 SE(3);旋转侧不再用 IMU 过程模型,也不联合估零偏。 @@ -130,6 +193,8 @@ - `pipeline` 把 `imu`、静止零偏、`δt` 传入 joint;summary 增加 `gyro_bias_rad_s`。 - 平移仍受可观性门控;`rotation_only` 时不交付平移。 + + ### 文档 - **原本**:`imu_lidar/README.md` 仅模块列表,无逐次改动史。 @@ -137,6 +202,8 @@ --- + + ## 模板(以后追加用) ```markdown @@ -147,3 +214,4 @@ - **原本**:... - **改成**:... ``` + diff --git a/imu_lidar/文件职责说明.md b/imu_lidar/文件职责说明.md index 6ad0068..10a1f75 100644 --- a/imu_lidar/文件职责说明.md +++ b/imu_lidar/文件职责说明.md @@ -1,5 +1,7 @@ # `imu_lidar` 模块说明 +**用途:** 改 `imu_lidar/` 源码时查阅。对外用法见根目录 [`README.md`](../README.md)。 + 本包实现 LiDAR–IMU 外参标定:在连续行驶数据上选取关键帧,用 IMU 预积分与雷达配准构造相对运动对,求解安装外参。 ```text @@ -50,8 +52,6 @@ python -m imu_lidar.cli run --vehicle-config ... --imu ... --lidar ... --output --- - - ## 运行模式要点 - **运动对**始终计算完整预积分量(旋转、速度增量、位移增量及不确定度)。 @@ -60,8 +60,6 @@ python -m imu_lidar.cli run --vehicle-config ... --imu ... --lidar ... --output --- - - ## 输入格式 ```text @@ -71,16 +69,13 @@ lidar_session/ frames/frame_XXXXX.npz # points: (N,3) 米 ``` -原始录制格式不在本包内解析,需先导出为上述中间格式。详见 `[docs/V1_数据格式.md](../docs/V1_数据格式.md)`。 +原始 `.rscap` 用仓库工具导出:`python tools/export_rscap_to_v1.py ...`(见 [`docs/V1_数据格式.md`](../docs/V1_数据格式.md))。 --- - - ## 当前能力 - 本包是仓库**唯一**标定路径:质检 → 时间偏置 → 关键帧配对 → 旋转手眼 → 联合精修 →(可选)完整六自由度 → 报告 - 点云去畸变:可选 -- 阶段与试验边界见根目录 [`README.md`](../README.md) §0 +- 阶段与用法见根目录 [`README.md`](../README.md) - 改动史:[`CHANGELOG.md`](CHANGELOG.md) - diff --git a/tests/README.md b/tests/README.md index 125d467..5d2aee6 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,15 +1,11 @@ # 测试说明 -本目录说明两类试验的**边界**,避免把「合成通过」或「旧车 blocked」误读成实车外参已交付 / 算法不可用。 - -总览见根目录 `[README.md](../README.md)` §0。 - - -| 试验 | 是否默认 pytest | 在证明什么 | 不在证明什么 | -| --------- | ----------- | ------------------------ | ------------ | -| **合成数据** | 是 | 算法链路正确、能收回已知 yaw / δt | 实车安装精度、平移可交付 | -| **旧车 S2** | 否(线下手工) | 主机时间旧数据上流水线能跑完;质量门会拒绝坏结果 | 外参真值;新车可用性 | +**用途:** 说明合成 pytest 与旧车 S2 线下试验的边界(避免误读)。日常跑通请先看根目录 [README](../README.md)。 +| 试验 | 是否默认 pytest | 在证明什么 | 不在证明什么 | +|---|---|---|---| +| **合成数据** | 是 | 算法链路正确、能收回已知 yaw / δt | 实车安装精度、平移可交付 | +| **旧车 S2** | 否(线下手工) | 主机时间旧数据上流水线能跑完;质量门会拒绝坏结果 | 外参真值;新车可用性 | --- @@ -52,7 +48,7 @@ python -m pytest -q | 项 | 内容 | | ------- | -------------------------------------------------------------------------- | -| 车辆 / 批次 | 旧 **S2** 验证集(`S2_scheme1_validation`)数据在网盘的“室外车数据\IMU-雷达标定数据中” | +| 车辆 / 批次 | 旧 **S2** 验证集(`S2_scheme1_validation`)数据在网盘的“室外车数据\IMU-雷达标定数据” | | 典型路径 | `D:\IMU_calibration\work\S2_scheme1_validation\`(历史目录名;含 `imu.csv` + 雷达会话) | | IMU 时间 | **主机 UTC 接收时间**(串口块到达时刻),不是 IMU 设备时间 | | 雷达时间 | dlog 导出的主机侧 `unix_time_ns`,不是 MSOP 设备时间 |