ROS2 任务状态机、视觉桥接与安全控制闭环复盘:从 /perception/target 到 /cmd_vel 的机器人目标搜索与靠近实现
一、FSM 的基本概念
FSM 是 Finite State Machine,有限状态机。
在机器人任务中,FSM 用来描述机器人处于哪个任务阶段,以及收到事件后应该切换到哪个状态。
核心公式可以理解为:
当前状态 + 输入事件 = 下一个状态
例如机器人执行“寻找目标并靠近”的任务时,不应该一直发布同一个速度,而是要经历:
空闲 → 准备 → 搜索 → 靠近 → 停止
FSM 的价值是把复杂任务拆成清晰状态,避免控制逻辑写成一堆混乱的 if-else。
二、状态和事件的区别
FSM 中最重要的是区分 状态 state 和 事件 event。
|
概念 |
含义 |
项目例子 |
|
状态 |
机器人当前处于什么阶段 |
|
|
事件 |
触发状态变化的输入 |
|
状态表示“现在是什么”。 事件表示“发生了什么”。
在我的项目里:
|
topic |
含义 |
|
|
输入给 FSM 的事件 |
|
|
FSM 输出的当前状态 |
所以 /task/event 和 /task/state 不能混用。前者是触发条件,后者是任务结果。
三、FSM 状态设计
我项目中设计了 7 个状态。
|
状态 |
中文含义 |
任务含义 |
|
|
空闲 |
等待任务开始 |
|
|
站立准备 |
模拟机器人进入准备姿态 |
|
|
搜索 |
原地旋转寻找目标 |
|
|
靠近 |
发现目标后向目标靠近 |
|
|
停止 |
到达目标后停止 |
|
|
汇报 |
可扩展为任务完成上报 |
|
|
异常 |
安全保护触发后的异常状态 |
主状态转移关系:
|
当前状态 |
事件 |
下一个状态 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
异常转移关系:
|
当前状态 |
事件 |
下一个状态 |
|
任意运行状态 |
|
|
|
|
|
|
注意:stand_done 只在 STAND 状态下有效。如果机器人还在 IDLE,直接发送 stand_done 被忽略是正常现象。
四、task_fsm_node 的职责
task_fsm_node 是状态机节点。
它只负责一件事:
接收任务事件,更新任务状态,发布当前状态。
|
项目 |
内容 |
|
订阅 |
|
|
发布 |
|
|
输入 |
|
|
输出 |
|
它不直接发布 /cmd_vel。
这样设计的核心思想是:
FSM 负责“任务决策”,不负责“底层运动”。
也就是说:
|
节点 |
负责问题 |
|
|
机器人现在应该处于哪个任务阶段 |
|
|
这个状态下应该怎么动 |
|
|
如何把速度交给底层 driver |
|
|
如何模拟机器人执行 |
这种分层让后续升级更容易。比如以后把 APPROACH 从固定前进改成视觉跟随,不需要重写 FSM。
五、视觉桥接节点的作用
视觉节点输出的是感知结果,例如是否检测到目标、置信度、目标框大小、目标位置等。
但 FSM 不应该直接处理复杂视觉字段。
所以需要 vision_fsm_bridge_node,它的作用是:
把视觉检测结果转换成 FSM 能理解的任务事件。
|
输入 |
作用 |
|
|
接收目标检测结果 |
|
|
判断当前 FSM 状态 |
|
|
发布任务事件 |
核心逻辑:
|
当前状态 |
视觉条件 |
发布事件 |
|
|
检测到有效目标 |
|
|
|
目标面积足够大 |
|
|
|
长时间没看到目标 |
|
这样视觉层不会直接控制机器人,而是通过事件影响 FSM,再由 FSM 影响运动。
六、目标检测字段与任务事件
/perception/target 中常见字段如下。
|
字段 |
含义 |
用途 |
|
|
是否检测到目标 |
判断有没有目标 |
|
|
检测置信度 |
过滤不可靠检测 |
|
|
目标框面积占图像比例 |
判断目标是否足够近 |
|
|
目标中心横坐标 |
可用于左右方向判断 |
|
|
目标相对中心的偏移 |
可用于转向控制 |
|
|
目标类别 |
YOLO 中区分物体类别 |
|
|
坐标系名称 |
后续结合 TF 使用 |
三个核心事件:
|
事件 |
含义 |
常见状态变化 |
|
|
搜索时发现目标 |
|
|
|
目标已经足够近 |
|
|
|
靠近过程中目标丢失 |
|
其中 area_ratio 是一个简化距离判断方法。
目标越靠近相机,通常检测框越大;因此 area_ratio 越大,可以认为目标越近。
七、task_motion_node 的职责
task_motion_node 负责把任务状态转换成速度命令。
|
输入 |
输出 |
|
|
|
它不关心视觉细节,也不关心事件来源,只关心当前状态。
当前运动规则:
|
FSM 状态 |
运动行为 |
|
|
停止 |
|
|
停止 |
|
|
原地旋转 |
|
|
低速前进 |
|
|
停止 |
|
|
停止 |
|
|
停止 |
这体现了一个重要工程原则:决策和控制分离。
FSM 只决定“现在是什么状态”,motion 节点负责“这个状态下发什么速度”。
尤其要注意:ERROR 状态下必须输出零速度,因为异常时默认行为应该是停止,而不是继续运动。
八、robot_control_node、driver 与 heartbeat
robot_control_node 是 ROS2 速度命令和底层机器人 driver 之间的桥。
|
上层输入 |
中间节点 |
底层执行 |
|
|
|
|
这样上层控制逻辑不需要知道具体机器人 SDK 的细节。
上层只发布标准 ROS2 速度命令,底层 driver 负责适配具体机器人。
heartbeat 是控制安全机制。
|
heartbeat 状态 |
控制行为 |
|
正常 |
执行 |
|
超时 |
忽略 |
|
未启动 |
认为不安全,不执行速度 |
heartbeat 的意义是:
防止上层节点异常退出后,机器人继续执行旧速度命令。
九、安全保护节点
task_safety_node 是独立安全监控节点。
它不直接发布 /cmd_vel,而是把异常转换成 FSM 事件。
|
订阅 |
作用 |
|
|
判断机器人本体是否安全 |
|
|
判断任务是否卡住或超时 |
|
发布 |
内容 |
|
|
|
安全处理链路:
|
异常 |
安全节点输出 |
FSM 状态 |
运动结果 |
|
低电量 |
|
|
停止 |
|
急停 |
|
|
停止 |
|
任务超时 |
|
|
停止 |
这个设计的好处是:
安全节点不抢控制权,而是让 FSM 进入 ERROR,再由 motion 节点统一输出零速度。
这样系统不会出现多个节点同时发布 /cmd_vel 的控制冲突。
十、完整任务系统的数据流
主任务链路:
/perception/target → vision_fsm_bridge_node → /task/event → task_fsm_node → /task/state → task_motion_node → /cmd_vel → robot_control_node → MockDogDriver
安全保护链路:
/robot/state + /task/state → task_safety_node → /task/event:error → task_fsm_node → ERROR → task_motion_node → /cmd_vel=0
对应工程分层:
|
层级 |
项目模块 |
|
感知层 |
AprilTag / YOLO / |
|
事件桥接层 |
|
|
决策层 |
|
|
控制层 |
|
|
执行层 |
|
|
安全层 |
heartbeat + |
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)