Files
ASER-NAV/Doc/code_review_report.md

193 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 导航代码审查报告
日期: 2026-04-03
范围:
- `App/nav/global_nav.c`
- `App/nav/track_map.c`
- `App/nav/track_map.h`
- `App/robot_params.h`
- `App/app_tasks.c`
- `App/preproc/corridor_preproc.c`
## 结论
当前版本的 S 型拓扑和左右转向表整体上与地图理解一致,没有再发现明显的左右方向写反问题。
主要风险集中在以下几类:
- 时间基准过度依赖 IMU 时间戳
- 连续确认逻辑复用了同一帧 VL53 数据
- 入场段过度依赖固定起始摆放位置
- 阶段切换存在 1 个控制周期的旧命令残留
- 连接段提前转向策略较激进
## Findings
### 1. 高: IMU 时间戳卡住时,超时与里程都会冻结
位置:
- `App/nav/global_nav.c:430-445`
- `App/nav/global_nav.c:471`
- `App/nav/global_nav.c:628-630`
- `App/nav/global_nav.c:657-659`
现象:
- `GlobalNav_Update()``board->imu_wz.timestamp_ms` 作为内部时间基准
- `odom_distance_accum` 的积分和 `elapsed_ms` 的推进都依赖这个时间戳
风险:
- 如果 IMU 仍被判定为在线,但时间戳停更,导航状态机会继续输出控制命令
- 同时阶段超时保护不会推进
- 里程积分也不会推进
可能后果:
- `ENTRY_STRAIGHT``LINK_STRAIGHT``EXIT_STRAIGHT` 长时间不退出
- 转向超时失效,机器人可能持续原地转
说明:
- 这是行为级问题,不是单纯的调参问题
- 文档中也提到了该项仍是 TODO但当前实现里确实已经构成运行风险
### 2. 高: “连续 N 拍确认”实际在重复消费同一帧 VL53 数据
位置:
- `App/app_tasks.c:285-286`
- `App/app_tasks.c:299-347`
- `App/nav/global_nav.c:516-523`
- `App/nav/global_nav.c:615-620`
- `App/robot_params.h:398-399`
现象:
- 导航循环周期约为 `20ms`
- VL53 任务推送周期约为 `100ms`
- `REACQUIRE` 的连续 `5` 拍确认和 `LINK_STRAIGHT` 的连续 `2` 拍确认,都是按导航循环计数
风险:
- 同一帧 VL53 观测会被导航层重复读取多次
- 于是“连续确认”并不等于“连续多个独立观测确认”
可能后果:
- `REACQUIRE` 可能只靠 1 帧侧向数据就进入 `CORRIDOR_TRACK`
- 沟口检测的 2 拍确认也可能只是一帧瞬时失效被重复消费
说明:
- 这会削弱你现在新设计的联合判定可靠性
- 当前问题核心不是阈值,而是采样独立性不足
### 3. 中: 入场段强依赖起始摆放位置,缺少几何确认
位置:
- `App/nav/global_nav.c:484-495`
- `App/robot_params.h:382-385`
- `App/app_tasks.c:302-306`
- `Doc/map.md:9`
- `Doc/map.md:53-59`
现象:
- `ENTRY_STRAIGHT` 现在只用 `里程 >= 0.30m 或 超时` 进入第一次右转
- 启动后直接 `GlobalNav_Start()`,没有专门的“出启动区口再开始计段”动作
风险:
- 这要求机器人初始位置必须比较稳定,且接近你假设的起跑点
可能后果:
- 如果车放在 100cm 深启动区内更靠后位置,可能在到达 `C1` 入口前就右转
- 如果车放得更靠前,也可能转得偏晚
说明:
- 当前实现修掉了“侧墙始终有效导致误触发”的问题
- 但引入了“对起点一致性要求很高”的新假设
### 4. 中: 阶段切换发生后,本周期仍可能执行旧阶段指令
位置:
- `App/nav/global_nav.c:242-266`
- `App/nav/global_nav.c:491-495`
- `App/nav/global_nav.c:623-625`
- `App/nav/global_nav.c:706-710`
现象:
- 若本周期内先生成了旧阶段控制命令,再满足切段条件并 `transition_to()`
- `out->stage` 在函数末尾会更新成新阶段
- 但本周期发出去的速度命令可能还是旧阶段的
风险:
- 状态显示与实际执行在一个周期内不完全一致
可能后果:
- 转向完成后多转一个控制周期
- 直行段满足切换条件后,当拍仍会继续向前推进一小段
说明:
- 这通常是 20ms 量级的小偏差
- 但在靠近入口边缘、转向容差较紧时会放大几何误差
### 5. 中: 连接段允许仅凭前激光位移提前触发下一次转向
位置:
- `App/nav/global_nav.c:590-625`
- `App/robot_params.h:406-409`
- `App/nav/track_map.h:36-37`
现象:
- `LINK_STRAIGHT` 的逻辑是 `B || (A && C)`
- 其中 `A``B` 都采用 `0.70m * 0.85 = 0.595m` 作为触发阈值
- 也就是前激光变化量到达约 `59.5cm` 就可直接触发转向
风险:
- 机器人可能在标称 `70cm` 沟间距之前约 `10.5cm` 就开始转向
可能后果:
- 若前激光初值记录稍晚、转出后航向略偏、或前激光看到的并非理想正对围栏面,可能提前转向
- 提前量叠加转向半径误差后,可能更接近垄背边缘而非下一条沟中心
说明:
- 这不是硬 bug更像策略上偏激进
- 若实车转向余量很大,可能仍可工作;若几何余量小,则风险会明显上升
## 正向观察
### 1. 转向拓扑表当前与地图理解一致
位置:
- `App/nav/track_map.c:34-47`
说明:
- `C1` 右转入、左转出
- `C2` 左转入、右转出
- 奇偶沟交替
- `C6` 左转出场
这一版没有再看到此前那种第一条沟转向方向写反的问题。
### 2. 连接段已经避免把“贴围栏侧 VL53 常亮”当作入口触发
位置:
- `App/nav/global_nav.c:108-144`
- `App/nav/global_nav.c:557-625`
说明:
- 你已经把“非围栏侧 VL53 沟口检测”显式建模出来
- 同时结合前激光和里程计做联合判定
这比此前的 `side_walls_detected()` 直接触发要合理得多。
## 开放问题
1. 比赛摆车是否保证机器人车头在启动区出口附近,而不是启动区任意位置?
2. 传感器黑板中的 `is_valid` 是否有基于时间戳的失效机制,还是生产者停更后仍可能保持有效?
3. 连接段的目标是“到下一沟中心线再转”,还是“进入下一沟开口就允许转”?当前 0.85 容差会显著影响这个定义。
## 总体评价
当前版本比前一版明显更接近真实场地几何,尤其是:
- 地图方向理解正确
- S 型左右转表正确
- 连接段不再依赖错误的侧墙常亮判据
但如果从比赛稳定性角度看,当前还存在两个最值得优先处理的问题:
- 时间基准不能完全绑死在 IMU 时间戳上
- 连续确认不能重复消费同一帧侧向观测
如果这两点不处理,现场表现会比较依赖传感器健康状态与偶然时序,稳定性风险较高。