在很多机器人项目中,“自主导航”常常被理解成一件很直接的事:给机器人一个目标点,然后让它自己走过去。

但当机器人真正进入服务场景后,问题会变得复杂得多。用户并不只是希望机器人“移动到某个坐标”,而是希望它能理解指令、确认环境、选择路线、避开障碍,并在关键时刻给出明确反馈。

比如在一个展馆、校园、园区或室内服务空间中,用户可能会说:

请带我去目标区域 A。

机器人需要完成的不只是导航到 A。它还要知道当前定位是否可靠,路线是否安全,沿途是否有障碍,目标区域是否到达,是否需要根据现场标识选择不同路线,以及什么时候应该通过语音提醒用户。

这篇文章结合一个基于 ROS 2 的四足机器人系统,聊聊一个更接近真实落地的问题:

如何把“导航到坐标点”升级成“面向人的安全引导流程”。


一、引导型机器人和普通导航机器人的区别

普通导航系统的核心目标是:

从当前位置移动到目标点。

而引导型机器人要解决的问题更接近:

在可感知、可解释、可反馈的前提下,带用户完成一段空间任务。

这两者的差别很大。

普通导航关注路径是否可达,规划器是否能生成轨迹,控制器是否能让机器人跟随路径。

引导型机器人除了这些,还要关注几个更具体的问题:

  • 用户的指令从哪里来?
  • 目标点是否需要语义解释?
  • 机器人是否需要在中途观察环境?
  • 当前路线是否由视觉结果决定?
  • 遇到障碍物时,是否需要提醒用户?
  • 到达目标点后,机器人如何确认任务状态?
  • 如果识别失败或导航失败,机器人应该继续、等待还是停止?

所以,这套系统并没有把机器人设计成一个单纯的“移动底盘”,而是把它组织成一个围绕任务状态运行的引导系统。

它的核心并不是某一个算法,而是一个完整闭环

在这个闭环里,Nav2 负责“怎么走”,视觉模块负责“看到了什么”,语音模块负责“如何和人沟通”,任务管理器负责“现在该做什么”。


二、把空间任务拆成可执行的状态

如果只做单点导航,代码通常很简单:收到目标点,调用 NavigateToPose,等待结果。

但真实服务流程往往不是一个点,而是一串带条件的动作。例如:

  1. 先去 A 区域;
  2. 到达后观察标识牌;
  3. 根据标识牌数字选择不同路线;
  4. 沿路线到达 B 区域;
  5. 再从 B 区域去 C 区域;
  6. 全程根据障碍物和边界状态进行安全约束;
  7. 每个关键节点通过语音反馈给用户。

这类流程如果全部写成临时 if else,后期会非常难维护。所以系统把完整流程抽象成一组任务状态:

SELF_CHECK
GO_TO_A
READ_SIGN
GO_TO_B
GO_TO_C
COMPLETE
ABORTED

每个状态只负责一件事。

SELF_CHECK 负责等待系统准备完成,包括 Nav2 action server 是否可用、关键 lifecycle 节点是否 active。

GO_TO_A 负责发送 A 点导航目标。

READ_SIGN 负责等待视觉模块给出稳定识别结果。

GO_TO_B 负责按照已经选定的路线逐个发送途经点。

GO_TO_C 负责从 B 点继续前往最终目标点。

COMPLETEABORTED 则分别表示任务完成和安全中止。

这种设计的好处是,系统不会因为某个模块临时返回异常就进入混乱状态。每个节点都可以通过统一状态知道机器人当前正在做什么。


三、路线不是写死的动作,而是可切换的途经点序列

在服务场景中,机器人有时不能只按照一条固定路线走。现场标识、用户指令、区域限制或者安全策略,都可能决定机器人应该选择不同路径。

当前系统中,路线选择采用的是一种非常朴素但实用的方式:

预设多条途经点路线,由视觉结果决定走哪一条。

参数文件中定义了两条路线:

route_odd:
  - "-1.65,-0.70,0.0,path_I_upper_left"
  - "0.45,-0.70,-1.57,path_I_upper_mid"
  - "0.45,-2.60,0.0,path_I_lower_mid"
  - "2.55,-2.75,0.0,B"

route_even:
  - "-2.85,-0.80,1.57,path_II_entry"
  - "-1.45,1.35,0.0,path_II_mid"
  - "1.35,2.65,0.0,path_II_upper"
  - "3.85,1.25,-1.57,path_II_return"
  - "2.55,-2.75,0.0,B"

每一项都是一个导航点:

x, y, yaw, label

也就是说,路线并不是底盘控制指令,而是一组地图坐标。

代码做的事情是选择路线,Nav2 做的事情是规划每一段怎么走。

当视觉模块识别到标识牌数字后,任务管理器会判断数字奇偶:

odd = int(digit) % 2 == 1
selected_path = "I" if odd else "II"
route_param = "route_odd" if odd else "route_even"

如果数字是奇数,就加载 route_odd;如果是偶数,就加载 route_even

加载完成后,系统不会一次性把整条路线交给底层控制,而是按顺序发送每个途经:

这样设计比“写死速度控制”稳定得多。因为每两个途经点之间仍然由 Nav2 根据地图、costmap 和当前定位进行路径规划。如果局部环境出现变化,Nav2 仍然有机会重新规划。

换句话说:

代码决定走哪条路线,Nav2 决定这条路线上的每一段具体怎么走。


四、视觉识别的价值不只是“看懂牌子”

很多人一提到机器人视觉,就会直接想到 OCR、目标检测或者深度学习模型。

但在引导型机器人里,视觉识别不只是为了“识别出文字”,更重要的是让视觉结果参与任务决策。

当前系统中的视觉模块负责处理摄像头画面,并输出结构化结果:

{
  "valid": true,
  "stable": true,
  "digit": 5,
  "letter": "A",
  "digit_color": "red",
  "letter_color": "blue",
  "confidence": 0.82
}

任务管理器并不直接处理图像,也不关心 OCR 或模板匹配细节。它只关心这个结果是否有效、是否稳定、数字是多少。

这就是一个很重要的工程分层:

视觉节点:负责从图像中提取语义
任务节点:负责根据语义决定下一步动作
导航节点:负责执行空间移动

这种结构让系统后期很容易升级。

如果一开始使用 OpenCV 模板匹配,后续想换成 PaddleOCR,只要视觉节点输出格式不变,任务管理器不需要改。

如果后续要加入二维码、红绿灯、颜色目标搜索,也可以沿用同样思路:视觉节点发布结构化语义结果,任务状态机根据结果切换状态。

真正重要的不是某个识别算法有多复杂,而是视觉结果能不能变成机器人可执行的决策条件。


五、安全不是一个节点的事,而是一条控制链路

四足机器人在真实环境中移动时,最怕的不是“不够智能”,而是“不受控”。

比如导航规划正常,但前方突然出现障碍物;或者地图边界附近有围挡,雷达一直检测到近距离物体;再或者上层节点还在发速度,但某个安全状态已经要求机器人停止。

如果所有节点都直接控制 /cmd_vel,系统很容易出现冲突。因此当前系统把速度控制链路拆成几层:

Nav2 controller
    ↓
cmd_vel_nav
    ↓
velocity_smoother
    ↓
cmd_vel_safety_in
    ↓
safety_velocity_filter
    ↓
/cmd_vel

Nav2 负责生成导航速度。

velocity_smoother 负责让速度更平滑,避免四足机器人急加速、急减速。

safety_velocity_filter 是最后一道安全过滤。它会读取激光雷达 /scan,同时监听外部安全 hold 消息。如果前方距离过近,就降低前进速度;如果进入硬停止距离,就把前进速度压到 0,并根据左右空间给出转向倾向。

这意味着系统不是盲目相信规划器,而是在真正发给机器人之前,再做一次贴近硬件安全的判断。

这层设计对四足机器人尤其重要。轮式机器人急停可能只是打滑,四足机器人急停或急转可能带来姿态不稳。因此速度控制需要更温和、更保守。


六、障碍物提醒要服务于“人”,而不只是服务于算法

机器人自己知道前方有障碍物还不够。如果它承担的是引导任务,它还需要把环境变化告诉用户。

当前系统中,障碍物感知节点会读取激光雷达数据,计算前方、左侧、右侧的最近距离,并根据连续帧变化判断是否可能是动态障碍。

它输出的不只是“有障碍物”这个布尔值,而是更丰富的状态:

{
  "obstacle_ahead": true,
  "emergency": false,
  "dynamic_likely": true,
  "front_distance": 0.63,
  "recommended_side": "left"
}

这类状态可以同时服务两个对象:

  1. 给系统使用:是否要限速,是否要避让,是否进入安全状态。
  2. 给用户使用:是否需要语音提醒,提醒内容是什么。

例如静态障碍可以播报:

前方发现障碍物,正在绕行,请小心行走。

动态障碍可以播报:

注意,前方有移动物体,正在避让。

这两句话背后的技术差别可能只是几行距离变化判断,但对用户体验来说,差别很大。

因为用户关心的不是“雷达检测到一个点云簇”,而是“前面发生了什么,我该不该小心”。

这也是服务机器人和普通移动机器人最大的区别之一:
它必须把机器可理解的信息,转化成人能理解的反馈。


七、边界保护让机器人知道“哪里不能去”

在实际空间里,可通行区域通常不是无限大的。

机器人可能运行在一个限定区域内,四周有围挡、玻璃、展台、墙面或者不可进入区域。即使导航算法认为某个方向可行,机器人也应该遵守场地边界。

因此系统中单独设计了边界保护节点。

这个节点通过 TF 查询机器人在 map 坐标系下的位置,然后判断当前位置距离边界还有多远:

min_x: -4.80
max_x: 4.80
min_y: -3.70
max_y: 3.70
warn_margin: 0.35
stop_margin: 0.12

如果机器人接近边界,就发布警告;如果距离边界过近,就发布安全 hold。

这类逻辑看起来简单,但非常实用。因为很多真实环境中的风险并不是来自复杂障碍,而是来自“机器人走出了它不该走的区域”。

边界保护的意义在于,它给系统增加了一层空间规则:

不是所有可规划路径都应该被执行。


八、语音反馈让机器人行为变得可解释

对于一个引导型机器人来说,“默默执行”并不是最好的交互方式。

如果机器人突然停下,用户不知道它是在等待、识别、避障,还是系统卡住了。
如果机器人突然转向,用户也不知道它是在绕障,还是定位出了问题。

所以系统把语音播报作为任务流程的一部分,而不是额外装饰。

在关键节点上,机器人会主动播报:

  • 系统自检完成;
  • 已到达目标点;
  • 标识牌上的数字和颜色;
  • 当前选择哪条路线;
  • 前方发现障碍物;
  • 动态物体正在避让;
  • 任务完成或任务中止。

这类播报让机器人的行为变得可解释。

更重要的是,播报内容不是分散写在各个节点里随便播放,而是通过统一的 /d1_assist/say 话题发送给语音播报节点。

也就是说,业务节点只负责发布“要说什么”,播报节点负责“怎么说”。

这让语音系统可以独立升级:可以换播放器、换音频资源、换播报策略,而不影响导航和感知逻辑。


九、真实落地时,系统最需要的是“可调”

很多机器人系统在演示视频里看起来很顺,但一到现场就问题不断。原因通常不是算法完全不行,而是现场条件和开发环境不一样。

光照不同,视觉阈值要调。

地面材质不同,机器人速度要调。

空间边界不同,安全区域要调。

障碍物距离不同,播报阈值要调。

因此当前系统把大量关键参数放在 YAML 中,而不是写死在代码里。

例如:

sign_timeout_sec: 5.0
goal_timeout_sec: 75.0
max_goal_retries: 2

warn_distance: 1.05
hard_distance: 0.42
dynamic_rate_threshold: 0.45

sign_min_confidence: 0.45
sign_stable_min_votes: 3
sign_vote_window_sec: 1.2

这些参数让系统具备现场调试能力。

当机器人过于敏感,总是误报障碍物,可以调小 warn_distance

当视觉识别不稳定,可以增加 sign_stable_min_votes 或调整置信度阈值。

当导航时间较长,可以增加 goal_timeout_sec

可调参数本身不是高级技术,但它决定了系统能不能在真实环境中快速适配。

对于服务机器人来说,落地能力很大程度上取决于:
系统是否允许你在不改代码的情况下完成现场适配。


十、从功能模块到行为系统

回到最开始的问题:机器人如何从“去某个点”升级成“安全引导”?

关键不在于单独增加某个算法,而在于把多个能力组织成一个行为系统。

在这套 ROS 2 架构中,各模块分工非常明确:

语音输入:把人的指令转成系统命令
任务管理:维护当前流程状态
视觉识别:把图像转成结构化语义
Nav2:完成路径规划和目标导航
障碍感知:判断前方环境变化
边界保护:限制机器人活动范围
安全滤波:约束最终速度输出
语音播报:把系统状态反馈给用户

这些模块单独看都不复杂,但组合起来,就形成了一个完整的引导闭环。

它不只是“能走”,而是知道什么时候走、走哪条路线、什么时候停、为什么停、如何告诉用户当前发生了什么。

这才是服务机器人真正落地时需要具备的能力。


写在最后

机器人系统从实验室走向真实空间,最大的变化不是算法名字变多,而是系统必须开始面对人的需求、环境的不确定性和硬件的安全边界。

一个真正可用的引导型机器人,不应该只是把路径规划跑起来,而应该具备三个能力:

第一,能理解任务。
它知道当前不是在随机移动,而是在执行一个有顺序、有条件、有反馈的空间服务流程。

第二,能解释行为。
它会告诉用户自己到达了哪里、看到了什么、为什么选择某条路线、遇到障碍时正在做什么。

第三,能约束风险。
它不会把所有决策都交给规划器,而是在速度输出、边界判断、障碍检测等多个层面增加保护。

从这个角度看,ROS 2 的价值不只是提供通信框架,而是让我们能够把语音、视觉、导航、安全和任务逻辑组织成一个清晰的系统。

当机器人能够把“坐标点”理解成“服务目标”,把“传感器数据”转化成“环境语义”,把“规划路径”变成“可解释的引导行为”,它才真正开始接近可落地的服务机器人形态。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐