返回专辑
·Johan·4 分钟阅读

Nav2 Progress Checker:卡死要能失败,而不能永远「运行中」

用可解释的位移窗口触发恢复;与碰撞监测分工,避免误触与永不失败。

Nav2 Progress Checker:卡死要能失败,而不能永远「运行中」

1. FollowPath 永远 RUNNING 的保险丝

机器人贴障空转、cmd_vel 仍有非零输出,但 30 秒位移不到 5 cm——bt_navigatorFollowPath 节点状态一直是 RUNNING,recovery 链从未触发,电池持续消耗。没有 progress checker,行为树缺少「卡住」这一可失败条件,恢复策略再漂亮也轮不到。Progress checker 是卡死的保险丝:把「是否在有效移动」变成硬失败,从而触发 BT 的 clear/spin/abort 分支。

2. 机制:SimpleProgressChecker

Nav2 默认用 nav2_controller::SimpleProgressChecker,在 controller_server 下配置:

yaml
controller_server:
  ros__parameters:
    progress_checker_plugin: "progress_checker"
    progress_checker:
      plugin: "nav2_controller::SimpleProgressChecker"
      required_movement_radius: 0.5   # 窗口内至少移动 0.5 m
      movement_time_allowance: 10.0   # 超过 10 s 未达则 FAILURE

逻辑:在 movement_time_allowance 秒内,若机器人距上次有效位置未超过 required_movement_radius,控制器返回 FAILURE。BT 收到 FAILURE 后进入 recovery 或向上层报告——不再空转。

3. 参数标定:误触与漏检的权衡

参数过紧过松
required_movement_radius颠簸地面误触 FAILURE真卡死不触发
movement_time_allowance慢速合法导航误触空转时间过长才失败

标定方法:在目标地面类型上,让机器人正常慢速跟路径,记录窗口内最小位移;required_movement_radius 取该值的 50–70%。movement_time_allowance 应大于「窄道减速通过」的合理耗时,但小于「空转可接受上限」(通常 10–30 s)。

4. 与碰撞监测、看门狗的分工

三者不可糊成一个参数:

组件检测什么触发后
ProgressChecker窗口内无有效位移controller FAILURE → BT recovery
CollisionMonitor进入危险/致命区减速、停、上报
执行器看门狗节点无心跳硬件急停

Progress 管「没动」,碰撞管「危险」,看门狗管「节点死了」。Progress 失败不应触发急停——那是碰撞监测的职责。日志字段应能区分三种原因。

5. 与 BT recovery 的接口

Progress 失败应是 BT 可区分的失败原因码,从而选择不同恢复策略:

  • 卡住(有路径、无位移) → clear local costmap → spin → backup。
  • 目标不可达(GoalChecker 超时) → 直接 FAILURE 给上层,不做 spin。
  • 定位丢失(协方差超阈) → relocalization 分支。

区分「卡住」与「不可达」能少做很多无用旋转。在 BT XML 里用 ProgressChecker FAILURE 与 GoalChecker FAILURE 走不同 recovery 子树。

6. 验收

  • 人为挡住机器人:在 movement_time_allowance 内 controller 返回 FAILURE,日志写明 progress 原因。
  • 正常慢速导航:误触发率 0(20 次重复)。
  • 真卡死(贴障空转):必触发 FAILURE,不是永远 RUNNING。
  • Progress 失败最终能触达安全停策略(经 BT 上限),不是无限 recovery 循环。

7. 案例:阈值过紧导致颠簸误触

某项目 required_movement_radius: 0.1movement_time_allowance: 5.0,颠簸地面每 5 s 误触一次 recovery,BT 在 clear/spin 间振荡。放宽到 0.4 / 15.0 并单独测真卡死场景——误触归零,真卡死仍能在 15 s 内失败。改两个数,比加三个 recovery 节点有效。

7. 地面类型与速度联动

required_movement_radius 不是 universal 常数:光滑地面低速通过窄道时,合法位移可能只有 0.3 m/15 s;粗糙地面颠簸时,静止抖动可能误计为位移。标定时用同一 max_vel_x 与同一目标路径,分别测正常通过和真卡死两种场景,取交集作为阈值。改 max_vel_x 后应重验 progress 阈值——速度上限变了,合法位移窗口也变。

8. GoalChecker 与 ProgressChecker 配合

到点判定由 GoalChecker 负责,默认 SimpleGoalChecker

yaml
goal_checker:
  plugin: "nav2_controller::SimpleGoalChecker"
  xy_goal_tolerance: 0.25
  yaw_goal_tolerance: 0.25
  stateful: true

Progress 管「动没动」,Goal 管「到没到」。机器人在目标附近微调时,progress 可能因位移小触发 FAILURE,但 goal 已 SUCCESS——BT 应正确处理这种边界。stateful: true 时到达后不再重复检查,避免到点后仍判 progress 失败。

PoseProgressChecker 同时看位移与转角,适合全向底盘;差速车通常 SimpleProgressChecker 足够。换 checker 插件时,BT recovery 分支不必改,但阈值要重标定。

9. 与录包复盘

导航事故袋应含 /controller_server/transition_event 或 BT 黑盒日志,才能区分「progress 失败」与「碰撞停止」。缺 progress 状态,复盘只能猜「为什么空转」——证据链不完整。

10. 地面标定窗口

阈值不是抄默认:用已知「故意卡住」与「慢速通过窄门」两段地面轨迹标定 required_movement_radius 与时间窗口。窗口过短会把合法微调当失败;过长会让真卡死拖太久。改足迹或最大速度后重标定,不要只改膨胀。

← 全部文章

johan's blog