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 服务

相关推荐
x-cmd19 小时前
[260412] x-cmd v0.8.13:x free 新增进程内存显示,feishu、telegram REPL 机器人齐上线!
linux·macos·机器人·内存·x-cmd·telegram·feishu
kyle~20 小时前
FANUC 机械臂 --- 配置字
网络·c++·机器人·ros2
ZPC821020 小时前
RViz 虚拟机械臂 / 真实机械臂 / Gazebo 仿真
linux·人工智能·机器人
放羊郎20 小时前
多机器人协同全覆盖路径规划
机器人
MIXLLRED1 天前
Ubuntu22.04 + ROS2 Humble + ORB-SLAM3 保存地图格式为.pcd文件
pcl·ros2·pcd·humble·orb_slam3
kobesdu1 天前
「ROS2实战-2」集成大语言模型:ollama_ros_chat 本地智能对话功能包部署和使用解析
人工智能·语言模型·自然语言处理·机器人·ros
weixin_513449961 天前
EXTREME-PARKOUR项目学习记录
人工智能·学习·算法·机器人
人机与认知实验室1 天前
《人-机器人交互导论》第二版译者序
机器人
煜bart1 天前
多智能体系统破解AI幻觉难题
人工智能·机器人·ai编程
kyle~1 天前
FANUC机器人与3D相机网络连接冲突错误排查报告(Linux默认路由冲突)
数码相机·3d·机器人