news 2026/8/26 17:32:18

ROS2 Action通信实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ROS2 Action通信实战

文章目录

    • Action通信
    • 编写Action服务端
    • 编写Action客户端

Action通信

Action是ROS中最强大的一种核心通信机制,是ROS2在底层利用多个 Topic 和 Service 组合封装而成,专门用于长耗时、需反馈、可取消的任务。

下面使用ROS2内置的Fibonacci Action 接口进行实战测试。

在具体实现Topic通信的功能之前,先创建工作空间,具体可参考节点通信-创建工作空间。

编写Action服务端

在内层restaurant_robot中编写action_server.py,内容如下

importrclpyfromrclpy.nodeimportNodefromrclpy.actionimportActionServerfromexample_interfaces.actionimportFibonacciimporttimeclassFibonacciActionServer(Node):def__init__(self):super().__init__('fibonacci_action_server')# 创建 Action Server# 参数:节点实例, Action类型, Action名称, 执行回调函数self._action_server=ActionServer(self,Fibonacci,'fibonacci_action',self.execute_callback)self.get_logger().info('Action Server start...')defexecute_callback(self,goal_handle):# goal_handle 包含了客户端发来的目标信息order=goal_handle.request.order self.get_logger().info(f'received goal, calculate the first{order}items')feedback_msg=Fibonacci.Feedback()sequence=[0,1]# 模拟长耗时任务(循环计算)foriinrange(1,order):# 【核心机制 1】:检查客户端是否请求取消ifgoal_handle.is_cancel_requested:goal_handle.canceled()# 标记任务为已取消self.get_logger().info('goal canceled')returnFibonacci.Result()# 返回空结果# 计算下一项sequence.append(sequence[i]+sequence[i-1])feedback_msg.sequence=sequence# 【核心机制 2】:发布实时反馈self.get_logger().info(f'publish feedback{feedback_msg.sequence}')goal_handle.publish_feedback(feedback_msg)# 模拟计算耗时(每秒计算一项)time.sleep(1.0)# 【核心机制 3】:任务完成,标记为成功并返回最终结果goal_handle.succeed()result=Fibonacci.Result()result.sequence=sequence self.get_logger().info('任务完成,返回最终结果')returnresultdefmain(args=None):rclpy.init(args=args)node=FibonacciActionServer()try:rclpy.spin(node)exceptKeyboardInterrupt:passfinally:node.destroy_node()rclpy.shutdown()if__name__=='__main__':main()

退回上一级目录,打开 setup.py,在 console_scripts 列表中添加:

'run_action_server = restaurant_robot.action_server:main',

接下来在工作空间最上层文件夹编译并运行

colcon build source install/setup.bash ros2 run restaurant_robot run_action_server

编写Action客户端

客户端发送目标后,需要注册三个回调函数:处理服务端的“接受/拒绝”响应、处理“实时反馈”、处理“最终结果”。

在同目录下,新建文件 action_client.py:

importrclpyfromrclpy.nodeimportNodefromrclpy.actionimportActionClientfromexample_interfaces.actionimportFibonacciclassFibonacciActionClient(Node):def__init__(self):super().__init__('fibonacci_action_client')# 创建 Action Clientself._action_client=ActionClient(self,Fibonacci,'fibonacci_action')defsend_goal(self,order):goal_msg=Fibonacci.Goal()goal_msg.order=order self.get_logger().info('wwait Action Server...')self._action_client.wait_for_server()self.get_logger().info(f'send goal: calculate the first{order}items')# 异步发送目标,并绑定反馈回调函数self._send_goal_future=self._action_client.send_goal_async(goal_msg,feedback_callback=self.feedback_callback)# 当服务端返回“是否接受目标”的响应时,触发 goal_response_callbackself._send_goal_future.add_done_callback(self.goal_response_callback)# 处理服务端的接受/拒绝响应defgoal_response_callback(self,future):goal_handle=future.result()ifnotgoal_handle.accepted:self.get_logger().error('goal reffused')rclpy.shutdown()returnself.get_logger().info('goal accepted')# 异步请求最终结果,绑定结果回调函数self._get_result_future=goal_handle.get_result_async()self._get_result_future.add_done_callback(self.res_callback)# 处理实时反馈(在任务执行过程中会被多次触发)deffeedback_callback(self,feedback_msg):self.get_logger().info(f'received feedback:{feedback_msg.feedback.sequence}')# 处理最终结果(任务结束时触发一次)defres_callback(self,future):res=future.result().result self.get_logger().info(f'received result:{res.sequence}')rclpy.shutdown()# 任务完成,关闭节点defmain(args=None):rclpy.init(args=args)node=FibonacciActionClient()# 发送目标:计算前 5 项node.send_goal(5)# 保持节点运行,以处理异步回调rclpy.spin(node)if__name__=='__main__':main()

同样在setup.py的console_scripyts列表中添加

'run_action_client = restaurant_robot.action_client:main',

至此,在两个终端里分别运行服务端和客户端

colcon build source install/setup.bash ros2 run restaurant_robot run_action_client

运行结果如下

[INFO][1785120497.952368565][fibonacci_action_client]:waitAction Server...[INFO][1785120498.527255191][fibonacci_action_client]: send goal: calculate the first5iterms[INFO][1785120498.530859965][fibonacci_action_client]: goal accepted[INFO][1785120498.535033490][fibonacci_action_client]: received feedback:array('i',[0,1,1])[INFO][1785120499.540644497][fibonacci_action_client]: received feedback:array('i',[0,1,1,2])[INFO][1785120500.544228609][fibonacci_action_client]: received feedback:array('i',[0,1,1,2,3])[INFO][1785120501.546219522][fibonacci_action_client]: received feedback:array('i',[0,1,1,2,3,5])[INFO][1785120502.549324776][fibonacci_action_client]: receved result: array('i',[0,1,1,2,3,5])
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 17:31:20

告别手工分表:金仓时序数据库超表架构落地的一次实战复盘

一、金仓时序数据库超表架构,难在哪 先撂个结论:手工分表这套办法,毛病不在“分”上,在于分完之后,所有的活儿都得你自己干。 做过时序数据的人应该都懂。按月建表嘛,xxx_202501、xxx_202502,一…

作者头像 李华
网站建设 2026/8/26 17:30:17

数据结构:选择排序

上一篇我们讲了插入排序,这一篇我们来讲选择排序。因为堆排序之前我们有详细讲过,所以这里只给出堆排序的思路,有兴趣的可以看一看。 选择排序 选择排序就是从数组中选出最小值和最大值,最小值放在第一个位置,最大值放…

作者头像 李华
网站建设 2026/8/26 17:30:09

边界消融之后:当AI几乎什么都会,人类还剩什么?

边界消融之后:当AI几乎什么都会,人类还剩什么? 你有没有在深夜想过这个问题——AI已经能写代码、能作诗、能解微积分、能描述失恋的痛苦……它从未吃过一口饭,却能写出米其林三星主厨级别的菜谱。 三年前,我们担心AI会…

作者头像 李华
网站建设 2026/8/26 17:29:46

2026论文AIGC检测避坑指南:AI率居高不下的真实原因与最优解决办法

大量学生使用降AI工具、人工改写之后依旧AIGC率超标,各类降AIGC软件效果参差不齐。想要稳定完成论文AI降重、AI率和重复率双降,必须分清AIGC检测逻辑、选对适配的AIGC去痕工具。本篇以真实痛点为导向,拒绝简单工具罗列,结合实测拆…

作者头像 李华
网站建设 2026/8/26 17:26:35

Java 第k个最小元素(K’th Smallest Element)

目录 【朴素方法】使用排序——时间复杂度为 O(n log(n)),空间复杂度为 O(1) 【预期方法】使用最大堆 - 时间复杂度为 O(n * log(k)),空间复杂度为 O(k) 【替代方案 1】使用快速选择 【替代方案 2】使用计数排序 如果您喜欢此文章,请收藏…

作者头像 李华
网站建设 2026/8/26 17:25:52

毕得医药(688073.SH)深度研究报告

摘要本报告围绕毕得医药(688073.SH)展开深度分析,从投资要点、公司概况、行业格局、财务表现、核心竞争力、未来增长点及风险提示等维度进行系统梳理。公司聚焦药物分子砌块和科学试剂领域,凭借产品品类丰富、仓储物流高效和客户结…

作者头像 李华