ros笔记02--从零体验ros2中的服务通信方式
- 介绍
- 创建步骤
- 注意事项
- 说明
介绍
在ROS 2中,服务指的是远程过程调用,client调用server,server节点收到数据后计算出结果并返回给client.
服务通常期望能快速返回,因此不应当用于处理长时间的任务; 若有长时间的任务可以考虑使用 ros2 中的行为 act.
在ros2中,服务的请求和响应结构通常被定义到一个 .srv 的文件中。本文基于python案例,从零开始创建一个计算 a + b 的服务。
创建步骤
-
新建 dev_ws 并初始化依赖信息
$ mkdir -p dev_ws/src $ cd dev_ws $ rosdep install -i --from-path src --rosdistro jazzy -y 输出: #All required rosdeps installed successfully
-
创建 interfaces, 新增 AddTwoInts.srv
2.1 创建 pkg 并新增 srv/AddTwoInts.srv$ cd dev_ws/src $ ros2 pkg create --build-type ament_cmake --license Apache-2.0 example_interfaces cd dev_ws/src/example_interfaces $ mkdir srv $ vim srv/AddTwoInts.srv int64 a int64 b --- int64 sum
2.2 在CMakeLists中新增依赖
$ cd dev_ws/src/example_interfaces $ vim CMakeLists.txt # 新增如下内容 find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME}"srv/AddTwoInts.srv")
2.3 在package.xml下新增如下内容
<buildtool_depend>rosidl_default_generators</buildtool_depend> <exec_depend>rosidl_default_runtime</exec_depend> <member_of_group>rosidl_interface_packages</member_of_group>
-
创建service包
在 src目录创建包$ cd dev_ws/src $ ros2 pkg create --build-type ament_python --license Apache-2.0 py_srvcli --dependencies rclpy example_interfaces
3.1 新增 service_member_function.py
vim py_srvcli/py_srvcli/service_member_function.pyfrom example_interfaces.srv import AddTwoIntsimport rclpy from rclpy.node import Nodeclass MinimalService(Node):def __init__(self):super().__init__('minimal_service')self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)def add_two_ints_callback(self, request, response):response.sum = request.a + request.bself.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))return responsedef main():rclpy.init()minimal_service = MinimalService()rclpy.spin(minimal_service)rclpy.shutdown()if __name__ == '__main__':main()
3.2 新增 client_member_function.py
vim py_srvcli/py_srvcli/client_member_function.pyimport sysfrom example_interfaces.srv import AddTwoInts import rclpy from rclpy.node import Nodeclass MinimalClientAsync(Node):def __init__(self):super().__init__('minimal_client_async')self.cli = self.create_client(AddTwoInts, 'add_two_ints')while not self.cli.wait_for_service(timeout_sec=1.0):self.get_logger().info('service not available, waiting again...')self.req = AddTwoInts.Request()def send_request(self, a, b):self.req.a = aself.req.b = breturn self.cli.call_async(self.req)def main():rclpy.init()minimal_client = MinimalClientAsync()future = minimal_client.send_request(int(sys.argv[1]), int(sys.argv[2]))rclpy.spin_until_future_complete(minimal_client, future)response = future.result()minimal_client.get_logger().info('Result of add_two_ints: for %d + %d = %d' %(int(sys.argv[1]), int(sys.argv[2]), response.sum))minimal_client.destroy_node()rclpy.shutdown()if __name__ == '__main__':main()
3.3 在 setup.py的console_scripts 新增如下内容
'service = py_srvcli.service_member_function:main','client = py_srvcli.client_member_function:main',
-
编译运行
$ cd dev_ws $ colcon build # 输出 ... This may be promoted to an error in a future release of colcon-override-check. Starting >>> example_interfaces Finished <<< example_interfaces [4.11s] Starting >>> py_srvcli Finished <<< py_srvcli [1.01s] Summary: 2 packages finished [5.21s] $ source install/setup.bash $ ros2 run py_srvcli service $ ros2 run py_srvcli client 2 3
输出结果如下,service收到 2 和 3, client得到结果 5
注意事项
- 安装ros2的python版本最好和编译使用使用的python版本一致,否则会出现类似 Assertion `PyUnicode_IS_READY(name_attr)’ failed. 的错误
笔者安装ros2的时候使用的python3.12 , 最初系统conda中python为3.10, 编译成功后运行client报错$ ros2 run py_srvcli client 2 3 python3: /home/xg/files/code/gitee/learn-ros/dev_ws/build/example_interfaces/rosidl_generator_py/example_interfaces/srv/_add_two_ints_s.c:34: example_interfaces__srv__add_two_ints__request__convert_from_py: Assertion `PyUnicode_IS_READY(name_attr)' failed. [ros2run]: Aborted经过多次测试发现是由于编译的时候python版本和和安装时候不一致导致的,重新使用conda准备python3.12后恢复正常
说明
软件系统:
ubuntu24.04 Desktop
ros2 jazzy
python 3.12.4(conda)
参考文档:
Writing a simple service and client (Python)
Concepts/Basic/About-Services.html
理解 ROS2 服务