机器人巡检仿真如何形成闭环:从任务到评测的完整数据流
系列 02/10从电厂机器狗案例理解 ROS 2、Gazebo 和 Nav2 如何组成一个可运行、可排错、可验收的系统定位以真实电厂机器狗巡检项目为贯穿案例提炼可迁移的机器人巡检仿真开发方法。适合读者机器人、自动化、计算机、电子信息等专业学生以及准备进入 ROS 2、机器人软件、仿真、导航或测试方向的求职者。系列总目录上一篇机器人仿真的第一原则先决定你要证明什么下一篇怎样构建场景、地图和机器人在 RViz 里点击一个巡检点几秒后Gazebo 中的机器狗开始转向、前进、绕开障碍物最后停在目标附近。从画面上看这件事像是“点一下机器人就动了”。但在系统内部这个动作至少经过了路线编辑、任务管理、路径规划、局部控制、安全门控、仿真执行、传感器反馈和结果评测。任何一段断开机器人都可能不动更麻烦的是机器人动起来也不代表整条链路是正确的。这篇文章不逐个介绍 ROS 2 API而是回答一个更有用的问题一个巡检目标究竟怎样变成机器人运动又怎样变成可以验收的任务结果我们仍以电厂机器狗项目为贯穿案例但重点是建立一张可以迁移到轮式机器人、无人机和其他巡检系统的全局地图。一、先用一次外卖配送理解机器人系统可以把机器人巡检类比成外卖配送。用户下单并填写地址对应创建巡检任务和目标点平台把订单分给骑手对应任务管理器向导航系统下发目标地图软件规划道路对应 Nav2 的全局路径规划骑手根据路口、行人和车辆实时调整对应局部控制与避障自行车真正向前运动GPS 和眼睛持续告诉骑手当前位置和路况对应里程计、TF 与 LiDAR 反馈送达、取消或超时被平台记录对应任务状态、事件和评测指标。这个类比最重要的地方不是角色一一对应而是说明规划软件并不会直接“移动”机器人。Nav2 只能根据目标和观测计算控制命令仿真器负责让命令产生运动新的运动又必须产生新的观测供下一轮规划和控制使用。于是系统形成循环目标 → 定位与环境观测 → 规划和控制 → 速度指令 → 机器人运动 → 新的定位与环境观测 → 下一轮规划和控制如果机器人位置只是被脚本直接移到目标点这条循环就被剪断了。画面虽然完成了“配送”但路线规划、控制、碰撞和反馈都没有真正参与。二、Gazebo、ROS 2 和 Nav2 分别负责什么很多人很容易把三者理解成三个功能相近的“大软件”。更准确的理解是它们处在不同职责层。1. Gazebo提供会响应动作的虚拟世界Gazebo 负责场景、机器人模型、物理运动、碰撞和传感器。它接收最终速度指令让机器人在物理世界中移动再生成里程计、IMU、RTK、LiDAR 和仿真时间。它回答的是当机器人执行这个动作时世界接下来会发生什么2. ROS 2连接模块并约定通信方式ROS 2 不替代规划算法也不替代仿真器。它提供节点、消息、Topic、Service、Action、参数和 TF 等基础设施让路线编辑器、Nav2、安全监控和评测器能够交换数据。它回答的是数据由谁产生、交给谁、采用什么类型和通信语义3. Nav2根据目标和观测持续计算怎样走Nav2 接收目标位姿读取静态地图、机器人位置、TF 和局部点云。全局规划器寻找一条可行路线局部控制器根据当前状态不断计算线速度和角速度并在环境变化时更新控制。它回答的是机器人现在在哪里目标在哪里下一小步应该怎样走4. 业务节点决定为什么走、先去哪里、到点后做什么Nav2 擅长“到达一个目标”却不知道整个巡检任务有几个点也不知道到达后应该停留、读表还是继续下一个点。在案例中route_editor负责创建、保存和显示路线inspection_manager负责逐航点执行、取消、超时、巡检动作和任务状态safety_monitor决定控制量是否可以送进仿真器evaluator收集真值、估计、事件和诊断生成评测结果RViz 用来创建目标和观察系统而不是导航算法本身。因此完整系统不是“Gazebo 加 Nav2”而是多个职责明确的节点通过 ROS 2 组成闭环。三、Topic、Service、Action 到底怎样选ROS 2 提供多种通信方式因为不同数据具有不同的时间特征。通信方式适合的问题案例中的使用Topic连续产生的数据流发布者不等待每个订阅者答复/odom、/sim/lidar/points、/cmd_vel、任务状态Service一次请求对应一次快速响应加载路线、开始、取消、重置Action耗时较长需要接受、反馈、取消和最终结果Nav2 的NavigateToPoseTopic持续广播LiDAR 和里程计会不断产生新数据。发布者只负责广播最新消息不应该等每个消费者逐一确认。Nav2、安全监控和评测器可以同时订阅同一个数据流各自完成不同工作。速度命令也使用 Topic因为控制器需要持续发布新指令。/cmd_vel中的Twist表达线速度和角速度期望不是“把机器人送到某个坐标”。Service短时独立请求“加载路线”或“重置任务”具有清晰的请求与响应。调用者关心这次操作是否受理不需要在几十秒里持续接收进度。如果一个操作执行时间很长或者中途需要取消就不适合仅用 Service 阻塞等待。Action长时持续动作从当前位置导航到目标可能需要几十秒。任务管理器需要知道Nav2 是否接受目标执行期间是否仍在运行用户能否取消最终是成功、失败还是被取消。这正是 Action 的语义。在我们的案例中也不会一次把全部航点丢给 Nav2而是逐个发送导航点收到当前结果并完成到点动作后再推进下一个航点。一个实用判断是连续状态用 Topic一次快速操作用 Service长时间且可反馈、可取消的任务用 Action。这不是绝对规则但足以帮助大家避免把所有交互都塞进同一种接口。四、一个巡检航点经历了什么现在把真实链路完整展开。第一步创建路线用户在 RViz 使用 Publish Point 工具点击地图。RViz 向/clicked_point发布PointStamped。route_editor检查坐标系是否为map再检查目标是否落入障碍物或不可通行区域。合法点被编号为WP_001、WP_002并通过/route/path和/route/markers显示出来。路线还可以保存到 YAML保留停留时间、到达半径和巡检动作等元数据。第二步任务管理器下发当前目标开始任务后inspection_manager从第一个航点构造导航点NavigateToPose.Goal。导航点Goal包含map坐标系中的位置目标朝向。超时、停留时间和到点后的巡检动作不会塞进 Nav2 Goal而是继续由任务管理器保管。这条边界很重要Nav2 只负责“怎样到达”任务管理器负责“为什么到达以及到达后做什么”。Nav2 接受 Goal 后任务管理器保存 Goal Handle。这个句柄使后续取消和结果查询成为可能。第三步Nav2 计算路径与局部控制Nav2 需要同时知道目标在哪里静态地图中哪里不可通行机器人当前在哪里机器人附近临时出现了什么障碍物机器人允许怎样运动。在本案例中这些信息分别来自目标 Goal、/map、/odom与 TF、/sim/lidar/points和机器人参数。全局规划器生成路径局部控制器持续输出速度。第四步速度指令经过两道门为了避免任何 Nav2 子模块绕过安全链Nav2 的输出被统一重映射到/cmd_vel_nav而不是直接发送给 Gazebo。真实控制链是Nav2 controller_server → /cmd_vel_nav → collision_monitor → /cmd_vel_raw → safety_monitor → /cmd_vel → ros_gz_bridge → Gazebo DiffDrive第一道门collision_monitor根据机器人附近的点云和安全区域对接近碰撞的控制量进行减速或停止。第二道门safety_monitor检查速度、加速度、点云、TF、控制器和/clock是否仍然正常。发生故障或命令过期时它持续发布零速度避免最后一条非零命令被仿真器继续执行。只有最终/cmd_vel会通过ros_gz_bridge进入 Gazebo。第五步Gazebo 执行动作并产生下一轮观测Gazebo 的差速运动代理执行线速度和角速度。机器人位置变化后LiDAR、RTK、IMU、里程计和 TF 也随之变化。这些数据通过桥接回到 ROS 2再次进入 Nav2、安全监控和评测器。至此运动闭环才真正闭合观测 → 决策 → 控制 → 物理响应 → 新观测第六步结果回到任务层Nav2 完成当前 Goal 后通过 Action 返回结果。任务管理器结合 Action 状态、机器人位置、到达半径、超时和安全状态决定进入到点巡检、重试、恢复还是失败。如果当前点完成状态机推进索引再发送下一个 Goal全部航点完成后才发布整个任务完成事件。五、到达目标为什么还不等于任务完成一个巡检系统至少同时存在三个闭环。证据闭环运动闭环任务闭环路线与航点NavigateToPose到达/失败/取消巡检动作与下一航点地图、定位、点云规划与控制安全门控Gazebo 物理运动真值、估计、控制、事件指标计算报告与能力结论运动闭环成功只能说明机器人抵达了某个位置。任务闭环还要判断到点后的业务动作和多航点推进。证据闭环则要回答这次成功是否满足预先定义的门限。案例中的evaluator同时订阅/ground_truth/pose机器人真实位置仅用于评测/odom算法侧使用的估计位置/cmd_vel最终执行的控制量/sim/lidar/points点云频率和数据连续性/inspection/events与/inspection/status任务开始、到点、失败和完成/diagnostics碰撞与系统诊断。这些数据最终形成轨迹、任务耗时、航点完成率、定位误差、碰撞次数、点云频率和报告。没有证据闭环“机器人到过终点”仍可能只是一次演示。六、两个小 Bug为什么能让完整系统给出错误结论系统联调中曾出现过两个很典型的问题。1. 机器人已经到达任务管理器却判断导航失败当时机器人在 Gazebo 中已经物理到达WP_001Nav2 也返回了结果但任务管理器把状态码解释错了进入恢复状态。这类问题很容易误导排查方向画面显示机器人能走开发者可能继续调规划器和控制器实际上错误位于 Action 结果到业务状态的映射。它提醒我们接口能收到消息不代表双方对消息含义的理解一致。除了消息类型还要核对枚举值、生命周期、取消语义和异常分支。2. 五个航点只执行了奇数点另一次问题中状态机完成巡检动作时已经把current_index加一发送下一目标的函数又加了一次导致索引每轮推进两格WP_002和WP_004被跳过。Nav2、Gazebo 和速度链都工作正常但整个巡检任务仍然错误。根因不在导航而在任务层对“谁负责推进状态”的边界不清。这也是为什么系统图不能只画传感器和cmd_vel。控制流、状态所有权和结果回传同样属于闭环。七、怎样画出自己的机器人系统图面对一个陌生 ROS 2 项目不要先把所有节点和 Topic 堆在一张图里。可以按五步缩小问题。第一步从业务入口开始找到任务由谁创建它可能来自 RViz、网页、文件或上位机。写清任务最初的数据类型和坐标系。第二步沿目标找到最终控制量从任务管理器追到导航 Action再追到速度、关节目标或执行器命令。确认中间是否经过限速、碰撞监控和安全门控。第三步从控制量追到环境反馈确认控制量由谁执行以及运动之后哪些传感器和状态会变化。若动作不会改变下一轮观测闭环很可能没有真正建立。第四步标出状态所有者谁决定当前航点谁判定到达谁推进下一点谁有权取消同一个状态只能有清晰的主要所有者。第五步补上证据流和故障路径把真值、日志、事件、指标和报告画出来同时标出点云断流、TF 超时或控制器退出后哪一个节点负责让系统进入安全状态。对于每条关键连线至少记录七项信息发布者 / 调用者 订阅者 / 服务端 接口名称 消息类型 频率或超时 坐标系与时间源 断流或失败后的行为这张表往往比一张塞满箭头的“架构大图”更适合排错。结语ROS 2、Gazebo 和 Nav2 的关系可以浓缩成一句话Gazebo 让动作产生后果Nav2 根据目标和观测决定下一步动作ROS 2 让目标、动作、观测、状态和证据在不同模块之间流动。但一个可验收的巡检系统还需要两个经常被忽略的部分任务状态必须形成闭环运行结果必须进入证据闭环。所以当你再次看到机器人在 Gazebo 中到达目标时不妨继续追问目标由谁创建Nav2 使用了哪些观测速度经过了哪些门控Action 结果如何变成业务状态最终又留下了什么可重复验证的证据能回答完整链路才算真正看懂这个系统。下一篇我们将进入 Gazebo 建模World、Model、Link、Joint、visual、collision 和 inertial 分别解决什么问题以及为什么“模型能显示出来”远远不等于“模型在物理上是正确的”。系列导航上一篇机器人仿真的第一原则先决定你要证明什么下一篇怎样构建场景、地图和机器人