ros笔记02--从零体验ros2中的服务通信方式

ros笔记02--从零体验ros2中的服务通信方式

介绍

在ROS 2中,服务指的是远程过程调用,client调用server,server节点收到数据后计算出结果并返回给client.

服务通常期望能快速返回,因此不应当用于处理长时间的任务; 若有长时间的任务可以考虑使用 ros2 中的行为 act.

在ros2中,服务的请求和响应结构通常被定义到一个 .srv 的文件中。本文基于python案例,从零开始创建一个计算 a + b 的服务。

创建步骤

  1. 新建 dev_ws 并初始化依赖信息

    bash 复制代码
    $ mkdir -p dev_ws/src
    $ cd dev_ws
    $ rosdep install -i --from-path src --rosdistro jazzy -y
    输出: #All required rosdeps installed successfully
  2. 创建 interfaces, 新增 AddTwoInts.srv

    2.1 创建 pkg 并新增 srv/AddTwoInts.srv

    bash 复制代码
    $ 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中新增依赖

    bash 复制代码
    $ 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下新增如下内容

    yaml 复制代码
    <buildtool_depend>rosidl_default_generators</buildtool_depend>
    <exec_depend>rosidl_default_runtime</exec_depend>
    <member_of_group>rosidl_interface_packages</member_of_group>
  3. 创建service包

    在 src目录创建包

    bash 复制代码
    $ 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.py

    py 复制代码
    from example_interfaces.srv import AddTwoInts
    
    import rclpy
    from rclpy.node import Node
    
    
    class 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.b
            self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))
    
            return response
    
    
    def 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.py

    py 复制代码
    import sys
    
    from example_interfaces.srv import AddTwoInts
    import rclpy
    from rclpy.node import Node
    
    
    class 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 = a
            self.req.b = b
            return 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 新增如下内容

    py 复制代码
      'service = py_srvcli.service_member_function:main',
      'client = py_srvcli.client_member_function:main',
  4. 编译运行

    bash 复制代码
    $ 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

注意事项

  1. 安装ros2的python版本最好和编译使用使用的python版本一致,否则会出现类似 Assertion `PyUnicode_IS_READY(name_attr)' failed. 的错误

    bash 复制代码
    笔者安装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 服务

相关推荐
xybDIY3 小时前
基于 Tuya.AI 开源的大模型构建智能聊天机器人
人工智能·机器人·开源
Tipriest_10 小时前
典型的 ROS 2 ament_cmake构建CMake脚本中ament相关指令解释
ros2·ament_cmake
沫儿笙12 小时前
IGM焊接机器人节气设备
人工智能·机器人
aitoolhub17 小时前
重塑机器人未来:空间智能驱动产业智能化升级
大数据·人工智能·深度学习·机器学习·机器人·aigc
放羊郎17 小时前
机器人自主导航方案概述
人工智能·算法·机器人·slam·建图
Tipriest_1 天前
详细介绍colcon和ament的关系,以及它们在 ROS 2 构建系统中的角色和区别
ros2·colcon·ament
lqqjuly1 天前
Lidar调试记录Ⅳ之Ubuntu22.04+ROS2+Livox_SDK2环境下编译Livox ROS Driver 2
人工智能·机器人·自动驾驶
机器觉醒时代1 天前
“干活”机器人“教练”登场:宇树机器人推出首款轮式机器人G1-D
人工智能·机器学习·机器人·人形机器人
数据与后端架构提升之路2 天前
小鹏VLA 2.0的“神秘涌现”:从痛苦到突破,自动驾驶与机器人如何突然“开窍”?
人工智能·机器人·自动驾驶
机器人行业研究员2 天前
机器人“小脑”萎缩,何谈“大脑”智慧?六维力/关节力传感器才是“救命稻草”
人工智能·机器人·人机交互·六维力传感器·关节力传感器