Files
ASER/Doc/GLOBAL_NAV_REQUIREMENT.md

668 lines
21 KiB
Markdown
Raw Normal View History

2026-04-03 07:57:57 +08:00
# 固定场地条件下的赛道级导航需求说明
## 1. 问题背景
当前项目已经具备较完整的“单条垄沟内局部导航”能力,包括:
- 侧向测距支撑的走廊横向定位
- IMU / EKF 支撑的航向估计
- 前向距离触发的到端检测
- 原地转向
- 走廊内闭环控制
但正式比赛要求并不是“在一条走廊里走稳”这么简单,而是:
- 遍历全部 `6` 条垄沟
- 在端部完成换沟
- 最终从唯一出入口驶离场地
- 再停回启动区
因此,真正的问题已经从“局部走廊控制”升级成了“赛道级导航”。
本文件针对一个新的核心顾虑做说明:
- 左右 `VL53L0X` 是近场侧向传感器,实际有效距离有限
- 当小车走完第一条通道、完成转向、准备去第二条通道口时,下一条通道口可能仍在数米之外
- 此时无法指望左右侧向 VL53 直接识别远处的下一条通道入口
由此引出新的设计问题:
- 是否需要把当前导航从“局部走廊式”升级为“固定地图下的全局式导航”
本文件只做需求分析与方案建议,不修改现有代码。
## 2. 比赛场地与问题是否成立
根据比赛规则文件 `附件6B类“马铃薯捡拾机器人竞技”比赛及评审规则.md`
- 场地尺寸:`390cm x 300cm`
- 共有 `5` 条田垄
- 每条田垄:长 `220cm`、宽 `30cm`
- 围栏与田垄之间、相邻田垄之间均为 `40cm` 垄沟
- 实际需要遍历的是 `6` 条垄沟
- 场地尺寸允许误差:`+-5%`
结合 `HANDOFF.md` 的赛道理解:
- 当前赛道本质上是 `6` 段平行窄走廊
- 其间通过端部动作完成换沟
- 最终还要完成出场和停回启动区
因此,你的顾虑是成立的:
- 左右侧向 VL53 的作用域主要是在“贴着垄沟/墙体附近”时建立局部几何约束
- 一旦小车离开当前垄沟、进入端部开阔区或横向换沟区,下一条垄沟入口往往不在 VL53 的可靠观测范围内
- 所以不能把“下一条通道入口识别”这个任务建立在左右 VL53 的远距离探测能力上
这里需要特别澄清一个容易说错的点:
- 赛道级运动并不一定是“在端部开阔区横移很长一段,再去远距离搜索下一条垄沟入口”
- 更符合当前场地理解的运动方式,是一种 **S 型串行入沟**
1. 从出发区直行到第 1 条垄沟入口附近
2. 第 1 条垄沟在车体一侧(例如右侧)
3. 原地右转 `90°` 对准垄沟后入沟
4. 沿垄沟通过
5. 到端后原地左转 `90°`,进入端部直线连接段
6. 再前进一小段到下一条垄沟入口附近
7. 再原地左转 `90°` 入下一条垄沟
8. 之后重复形成 S 型遍历
也就是说:
- 下一条垄沟并不是完全未知目标
- 它通常位于“端部连接直线段之后的固定相邻位置”
- 问题核心不是远距离搜索,而是 **按固定几何完成 90° 转向 + 短直线推进 + 再次 90° 入沟**
换句话说:
- `VL53` 适合做局部跟墙/居中
- 不适合独立承担赛道级换沟导航
## 3. 当前项目的能力边界
`HANDOFF.md` 已经明确指出:
- 当前项目更像“单垄沟闭环验证系统”
- 还不是完整的 `6` 垄沟遍历赛道导航系统
当前已经具备的能力主要是:
1. 垄沟内定位与控制
2. 到端检测
3. 原地转向
4. 安全停车
当前还缺失的关键能力是:
1. 多垄沟拓扑状态管理
2. 端部换沟策略
3. 下一目标垄沟的判定逻辑
4. 出场与停回启动区的赛道级动作编排
所以,这不是某一个传感器量程的小补丁问题,而是系统层次已经需要从“局部控制”提升到“地图引导下的赛道导航”。
## 4. 为什么仅靠局部传感器闭环不够
### 4.1 局部闭环擅长的任务
局部闭环擅长的是:
-`40cm` 垄沟里保持居中
- 在局部几何约束下控制横向误差和航向误差
- 在接近端部时停车或转向
这些任务的共同特征是:
- 机器人周围可观测到明确的近场结构
- 当前目标由附近环境直接决定
### 4.2 换沟问题的本质不同
从第一条垄沟换到第二条垄沟,不只是“继续沿墙走”,而是要回答以下更高层的问题:
1. 我当前已经完成了第几条垄沟
2. 下一条目标垄沟是哪一条
3. 这次应该左移还是右移
4. 端部 `90°` 转向后需要前进多少连接距离
5. 下一次 `90°` 转向应朝哪一侧入沟
6. 什么时候说明我已经对准并进入了下一条垄沟,可以重新切回局部走廊跟踪模式
这些问题都不是单次近场测距能直接回答的。
它们需要:
- 赛道拓扑信息
- 段落状态
- 距离累计
- 转向后姿态保持
- 已完成进度记忆
所以,换沟本质上是“任务级导航问题”,不是“单纯传感器观测问题”。
## 5. 是否需要全局导航
### 5.1 需要,但不一定是 SLAM 式全局导航
你提出“地图是固定的,是否要改成全局式导航”,我的判断是:
- 需要“全局导航思想”
- 但不需要上“通用移动机器人 SLAM”那种全局导航系统
原因是这个比赛场地有几个重要特征:
1. 地图是固定结构
- 场地拓扑不变
- 垄沟数量固定
- 宽度和相对排列固定
2. 尺寸有误差但不是完全未知
- 规则允许 `+-5%`
- 说明不能死信纯几何标称值
- 但也不代表你需要从零建图
3. 导航目标是离散段落式的
- 进入第 1 条垄沟
- 沿垄沟前进
- 到端
- 换到相邻垄沟
- 重复
- 最后出场并停回启动区
这类问题更适合:
- 固定地图
- 拓扑状态机
- 局部感知闭环
- 少量里程/姿态积分
而不是:
- 实时全局建图
- 通用路径规划
- 自由空间导航
### 5.2 更准确的说法:需要“赛道级固定地图导航”
如果用更工程化的语言描述,真正需要的不是传统 SLAM而是
- 固定地图下的赛道级导航
- 或者:拓扑-度量混合导航
它的含义是:
1. 上层知道整张赛道的结构
2. 下层在当前局部段里做高频闭环
3. 段与段之间的切换靠预定义几何、里程推进和事件触发完成
这比“纯局部反应式导航”强很多,但比“完整 SLAM”简单得多也更符合比赛实际。
## 6. 为什么不建议直接走完整 SLAM / 全局自由导航
### 6.1 赛场结构太规则SLAM 的收益不高
比赛场地不是开放未知环境,而是高度规则的固定赛道。
如果直接上完整 SLAM会遇到两个问题
1. 复杂度远大于实际收益
2. 还要处理对称结构导致的重定位歧义
因为 `6` 条垄沟本身非常相似:
- 走廊宽度相同
- 垄长相同
- 多个局部观测在不同位置上可能长得很像
这对通用 SLAM 来说并不天然友好。
### 6.2 规则里存在地毯与尺寸误差,纯度量导航也不能硬信
比赛规则明确说明:
- 随机会在 `2` 条垄沟铺设地毯模拟松软路面
- 场地尺寸允许 `+-5%` 误差
这意味着:
- 纯里程计距离不能被绝对相信
- 纯固定距离脚本也不能完全相信
所以最合理的方案不是“只靠地图”,而是:
- 地图负责告诉你要去哪一段
- 传感器负责告诉你你是否已经贴近那一段并进入局部闭环条件
## 7. 推荐的导航架构
我建议把系统分成三层。
### 7.1 第 1 层:局部走廊控制层
职责:
- 在垄沟内保持稳定行驶
- 利用侧向 VL53 和 IMU 控制 `e_y``e_th`
- 处理贴墙、居中、偏置行走等局部任务
这层继续使用你现在已经有的能力即可。
### 7.2 第 2 层:端部与换沟动作层
职责:
- 识别到端
- 完成 `90°` 转向
- 保持连接段朝向直线推进
- 在下一条垄沟入口处再执行一次 `90°` 转向入沟
- 在接近下一条垄沟入口时重新捕获局部走廊结构
这一层的主要依赖不应再是“直接看到很远处的下一条通道口”,而应是:
- IMU 航向保持
- 编码器里程推进
- 前向/后向长距测距作安全与事件辅助
- 重新捕获两侧结构时切回走廊模式
### 7.3 第 3 层:赛道级拓扑/地图层
职责:
- 记录当前是第几条垄沟
- 决定下一条目标垄沟编号
- 决定换沟方向
- 决定当前所处阶段:入场、走廊、端部、换沟、再入沟、退出、回停
- 在最终阶段规划如何从最后一条垄沟回到唯一出口并停回启动区
这层就是“全局导航思想”的承载层。
## 8. 具体到你的顾虑:第二通道口怎么判定
这个问题不应该被设计成:
- “我在端部一转身,然后用 VL53 去远距离搜索第二通道口在哪里”
更合理的设计应该是:
### 8.1 已知目标法
系统在上层已经知道:
- 当前完成的是第 `i` 条垄沟
- 下一个目标是第 `i+1` 条或第 `i-1` 条垄沟
也就是说,目标不是“搜索未知入口”,而是“按已知地图去下一个入口”。
### 8.2 动作脚本法
在端部动作中执行一段有结构的换沟脚本,例如:
1. 到端停车
2. 原地转 `90°` 到端部连接段朝向
3. 用 IMU 保持该朝向直行一小段
4. 用里程计累计连接段推进距离
5. 到达下一条垄沟入口附近后再原地转 `90°`
6. 一旦两侧 VL53 重新形成新垄沟的局部几何特征,则确认入沟成功
7. 切回局部走廊跟踪
如果按你描述的实际拓扑,更准确的理解是:
- 换沟动作不是“横向平移到另一条沟”
- 而是“端部出沟后走一段连接直线,再 90° 入下一沟”
- 整体轨迹更接近规则的 S 型遍历
### 8.3 重新捕获法
下一条垄沟入口的确认,最可靠的时刻往往不是“远处看见”,而是“进入附近后重新捕获到局部走廊结构”。
也就是说:
- 上层负责把车带到“应该接近下一条垄沟入口”的区域
- 下层负责在近场把入口真正锁住
这比远距离直接识别入口更稳。
## 9. 哪些传感器在赛道级导航里应该扮演什么角色
### 9.1 左右 VL53L0X
适合:
- 垄沟内横向定位
- 局部几何重捕获
- 判断自己是否已经重新进入某条垄沟
不适合:
- 远距离寻找下一条通道口
- 独立承担赛道级换沟导航
### 9.2 IMU
适合:
- 转向控制
- 端部横移/换沟时的航向保持
- 跨局部无墙约束阶段的短时姿态维持
### 9.3 编码器 / 里程计
适合:
- 换沟距离推进
- 已走段长估计
- 作为脚本动作的度量输入
缺点:
- 地毯和打滑会导致累计误差
所以它应作为:
- 主推进量
- 但不是唯一最终确认依据
### 9.4 前后长距测距
当前硬件里前后测距量程远大于 VL53理论上更适合
- 到端检测
- 判断前方是否接近围栏
- 在开阔区提供安全保护
- 对某些段落提供事件辅助
它不一定直接告诉你“第二通道口在这”,但可以帮助判断:
- 是否还在端部开阔区
- 是否已经逼近另一侧围栏或终点边界
- 是否应减速/停止/切换动作阶段
## 10. 推荐的总体方案
### 10.1 推荐方向:固定地图 + 拓扑状态机 + 局部闭环
这是我最推荐的方向。
其核心思想是:
- 地图不是在线建出来的,而是事先已知
- 机器人不需要理解“任意世界坐标”
- 机器人只需要知道自己当前位于哪个赛道段、下一步要切到哪个段
可以把整张赛道抽象成若干固定段:
1. 启动区
2. 入口对准段
3. 垄沟 1
4. 端部连接段 1
5. 垄沟 2
6. 端部连接段 2
7. ...
8. 垄沟 6
9. 出场段
10. 启动区停车段
如果按运动学动作再细分,每一个“端部连接段”内部实际上可以拆成:
1. 到端停车
2. 第一次 `90°` 转向
3. 连接直线推进
4. 第二次 `90°` 转向
5. 入沟重捕获
每个段有自己的:
- 目标朝向
- 目标推进方向
- 退出条件
- 允许使用的观测
- 安全策略
### 10.2 这不是“纯全局”,而是“全局指导下的局部控制”
这种方案的优势在于:
- 不会把所有问题都压给近场传感器
- 不会过度依赖里程计的绝对精度
- 保留你当前局部走廊控制代码的大部分价值
- 更贴合固定场地赛事的工程实际
## 11. 不推荐的方案
### 11.1 不推荐:继续纯局部反应式地扩当前逻辑
如果只是继续把当前“单垄沟往返”逻辑往外补,仍然不引入上层赛道状态,那么很容易遇到:
- 转完向不知道该去第几条沟
- 明明应该换沟,却又回到原来那条沟附近
- 因地毯或打滑导致脚本距离错位
- 无法稳定完成最终出场与回停
### 11.2 不推荐:直接上完整 SLAM / 通用全局路径规划
这对当前赛题来说过重,收益不一定匹配复杂度。
## 12. 对当前项目的直接结论
结合当前代码与比赛规则,可以得出以下结论:
1. 你的顾虑成立
- 左右 VL53 无法独立解决“数米外下一条垄沟入口识别”问题
2. 当前项目确实缺少赛道级导航层
- 当前更偏向单垄沟局部验证系统
3. 后续必须补上固定地图下的全局段落管理
- 否则无法可靠完成正式比赛要求的 `6` 垄沟遍历
4. 但不建议走完整 SLAM 路线
- 更合适的是固定地图 + 拓扑状态机 + 局部感知闭环
## 13. 后续实施建议
如果后续开始真正改造导航系统,建议优先级如下:
1. 先定义完整赛道拓扑和段落状态机
2. 明确每一段的进入条件、退出条件、目标朝向和目标距离
3. 让局部走廊控制只负责“在某条已知垄沟里跑稳”
4. 让换沟段由 IMU + 里程计 + 长距测距辅助来完成
5. 用左右 VL53 做“重新捕获下一条垄沟”确认,而不是远距离搜寻入口
6. 最后再考虑是否需要引入更强的全局定位增强手段
### 13.1 建议分 5 步走
结合当前项目现状,建议不要一口气重写整套导航,而是按“先把单段动作语义补完整,再把赛道级层叠上去”的顺序推进。
推荐拆成 `5` 步。
### 第 1 步:先把现有局部导航链路补到“可复用”
这一步不是做全局导航,而是先把现有单垄沟能力整理成后续可调用的稳定基础模块。
优先要补或改的模块:
1. `App/nav/segment_fsm.c/.h`
- 增加“动作语义”或“模式感知”输入
- 区分:走廊前进、原地转向、横向换沟、退出直线
- 解决当前 `TURN_AT_END` 可能被安全层整段按死的问题
2. `App/nav/nav_script.c/.h`
- 不再把它视为最终比赛脚本
- 先把它收敛成“单段动作编排器”或“局部验证脚本”
- 明确哪些能力未来会上移到赛道级状态机
3. `App/preproc/corridor_msgs.h`
- 补充动作模式、段类型、重捕获结果等跨模块消息定义
- 避免后面继续把语义塞进零散布尔量里
4. `App/app_tasks.c`
- 补齐导航启动前的 ready 判定
- 明确 navTask 每周期里:局部控制输出、赛道级输出、安全层输出的优先级
这一阶段的目标不是“遍历 6 条垄沟”,而是:
- 让“走廊跟踪 / 到端 / 原地转向 / 安全仲裁”这几个局部动作变成可被上层稳定调用的基础能力
### 第 2 步:新增赛道级拓扑状态机模块
这一步开始真正引入“全局导航思想”,但仍然基于固定地图,不做 SLAM。
建议新增模块:
1. `App/nav/global_nav_fsm.c/.h`
- 负责赛道级阶段推进
- 记录当前是第几条垄沟
- 决定下一条目标垄沟编号
- 决定下一次是左转入沟还是右转入沟
- 决定当前处于:启动、入沟、走沟、到端、换沟、再入沟、出场、回停 的哪一阶段
2. `App/nav/track_map.c/.h`
- 保存固定赛道的拓扑和名义几何
- 例如:垄沟数量、编号顺序、相邻关系、换沟方向、出口所在侧、启动区相对位置
- 不追求通用地图系统,只做当前赛题所需的固定地图描述
3. `App/preproc/corridor_msgs.h`
- 增加赛道级状态输出结构
- 例如:当前 corridor_id、target_corridor_id、segment_type、progress_state
为什么这一步要单独拆出来:
- 当前项目最大缺口不是局部控制,而是“不知道自己在整张赛道里进行到哪一步”
- 这个职责不能继续堆在 `nav_script.c` 里,否则会越改越像一份超长 if-else 脚本
### 第 3 步:新增换沟动作层模块
这一层负责跨出当前垄沟、去相邻垄沟入口附近、再把局部控制权交还给走廊跟踪层。
建议新增模块:
1. `App/nav/lane_change_executor.c/.h`
- 输入:当前赛道级目标、目标换沟方向、目标段参数
- 输出:本周期期望动作 `v/w`
- 内部实现典型动作序列:
- 到端停车
- 第一次 `90°` 转向到连接段朝向
- 维持航向直线推进
- 按里程推进到预计下一沟入口区域
- 第二次 `90°` 转向入沟
- 减速搜索并等待局部结构重捕获
2. `App/nav/heading_hold.c/.h` 或并入 `lane_change_executor`
- 用 IMU 做连接直线阶段短时航向保持
- 与走廊控制器解耦,避免把“无侧墙阶段”继续硬塞进 `corridor_ctrl.c`
3. `App/nav/reacquire_detector.c/.h`
- 负责判断是否已重新进入一条有效垄沟
- 典型判据:左右 VL53 重新同时形成合理几何、置信度恢复、持续若干拍成立
这一阶段的核心目标是:
- 不依赖“远距离看到下一条垄沟入口”
- 而是“按固定地图推进到预计区域,再由局部传感器完成重捕获确认”
### 第 4 步:补出场与回停模块
前 3 步完成后,系统已经具备:
- 走一条垄沟
- 到端
- 换到相邻垄沟
但正式比赛还需要最后的:
- 从最后一条垄沟驶离
- 回到唯一出口
- 停回启动区
建议新增模块:
1. `App/nav/exit_planner.c/.h`
- 定义从最后有效垄沟切到出场段的固定动作逻辑
- 决定离场时的目标朝向、推进距离、退出条件
2. `App/nav/start_zone_dock.c/.h`
- 负责最终回停启动区
- 可以做成简化版固定脚本,不需要复杂路径规划
这一阶段不要追求炫技,重点是:
- 流程完整
- 可解释
- 可调参
- 能在赛场误差下稳定完成收尾动作
### 第 5 步:最后再做统一调参与验证支撑
当前项目已经有局部参数,但赛道级导航落地后,还需要把“段参数”和“地图参数”系统化管理。
建议补的模块或整理项:
1. `App/robot_params.h`
- 补充赛道级参数
- 例如:换沟名义距离、减速搜索距离、重捕获持续拍数、回停距离等
2. `App/nav/global_nav_debug.c/.h` 或临时调试结构
- 给 CubeMonitor / 日志暴露关键内部量
- 例如:当前 corridor_id、stage、target_heading、reacquire_flag、lane_change_progress
3. `HANDOFF.md` / `GLOBAL_NAV_REQUIREMENT.md`
- 随代码同步更新
- 保证后续调试时文档和实现一致
这一阶段的目标是:
- 把“能跑”变成“能调、能解释、能复现”
### 13.2 各步的交付标准
为了避免后续开发一直停留在“看起来写了很多模块”,建议每一步都设一个明确交付标准。
第 1 步交付标准:
- 原地转向不再被安全层错误清零
- 走廊前进 / 原地转向 / 退出直行三类动作有清晰安全语义
- 局部导航链路在架空测试中行为稳定可解释
第 2 步交付标准:
- 系统能够明确输出“当前第几条垄沟、下一条目标是哪条、当前赛道阶段是什么”
- 不再依赖单个脚本文件隐式记录全局进度
第 3 步交付标准:
- 能从一条垄沟末端稳定切换到相邻垄沟入口附近
- 能通过 VL53 重捕获确认重新入沟
第 4 步交付标准:
- 能在完成全部目标垄沟后可靠离场
- 能完成最终回停启动区
第 5 步交付标准:
- 参数、日志、状态可观测性完整
- 可以支持正式场地反复调参与问题定位
### 13.3 为什么是这个顺序
这个顺序的核心原则是:
1. 先补“动作语义一致性”,再补“赛道级状态记忆”
2. 先解决端部动作可用性,再扩展多垄沟遍历
3. 先做固定地图和拓扑状态机,再考虑任何更重的全局定位增强
如果顺序反过来,例如一开始就写完整 6 垄沟状态机,但底层转向和换沟动作还不稳定,那么上层状态再完整也只会变成“会卡在某一步的复杂脚本”。
因此,最合理的开发路径不是“先把全局状态机写满”,而是:
- 第 1 步:把局部动作做成稳固积木
- 第 2 步:加赛道级任务管理
- 第 3 步:补跨段动作
- 第 4 步:补最终出场与回停
- 第 5 步:统一调参与调试支撑
## 14. 一句话结论
你的问题本质上说明:当前系统已经不能只靠“局部走廊导航”来思考了。
真正需要补的是“固定地图下的赛道级导航层”,而不是盲目把 VL53 当成远距离入口探测器,也不是直接上复杂 SLAM。