ros2-如何创建一个简单的服务

ROS2Python:服务通讯教程:节点间交互与反馈机制,
部署运行你感兴趣的模型镜像

服务通讯是ROS 2中节点通讯的另一种方式,与话题通讯不同,服务通讯具有反馈机制,即客户端发送请求后,服务器处理请求并返回结果。这在需要确认操作结果的场景中非常有用。以下是如何使用Python实现ROS 2节点之间的服务通讯的详细说明。

步骤概述

  1. 创建工作空间和包
  2. 编写服务端节点
  3. 编写客户端节点
  4. 配置和编译包
  5. 运行服务和客户端

1. 创建工作空间和包

首先,在你的工作目录中创建一个ROS 2工作空间:

# 复制代码

mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build

然后,在工作空间中创建一个新的ROS 2包:

复制代码

cd ~/ros2_ws/src ros2 pkg create --build-type ament_python my_service_package

2. 编写服务端节点

my_service_package目录下,创建一个新的Python脚本,例如service_node.py

# my_service_package/my_service_package/service_node.py

import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts

class AddTwoIntsService(Node):

    def __init__(self):
        super().__init__('add_two_ints_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(f'Incoming request: a={request.a}, b={request.b}, sum={response.sum}')
        return response

def main(args=None):
    rclpy.init(args=args)
    service = AddTwoIntsService()
    rclpy.spin(service)
    service.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

3. 编写客户端节点

my_service_package目录下,创建另一个Python脚本,例如client_node.py

# my_service_package/my_service_package/client_node.py

import sys
import rclpy
from rclpy.node import Node
from example_interfaces.srv import AddTwoInts

class AddTwoIntsClient(Node):

    def __init__(self):
        super().__init__('add_two_ints_client')
        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):
        self.req.a = int(sys.argv[1])
        self.req.b = int(sys.argv[2])
        self.future = self.cli.call_async(self.req)
        rclpy.spin_until_future_complete(self, self.future)
        return self.future.result()

def main(args=None):
    rclpy.init(args=args)
    client = AddTwoIntsClient()
    response = client.send_request()
    client.get_logger().info(f'Result of add_two_ints: {response.sum}')
    client.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

4. 配置和编译包

更新setup.py文件,添加入口点以便于启动节点:

from setuptools import setup

package_name = 'my_service_package'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='Your Name',
    maintainer_email='yourname@example.com',
    description='Examples of ROS 2 service communication',
    license='Apache License 2.0',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'service_node = my_service_package.service_node:main',
            'client_node = my_service_package.client_node:main',
        ],
    },
)

确保package.xml中包含以下依赖项:

<exec_depend>rclpy</exec_depend>
<exec_depend>example_interfaces</exec_depend>

在工作空间的根目录下编译包:

cd ~/ros2_ws colcon build

5. 运行服务和客户端

编译完成后,运行服务节点:

source ~/ros2_ws/install/setup.bash 
ros2 run my_service_package service_node

在另一个终端中,运行客户端节点:

source ~/ros2_ws/install/setup.bash
ros2 run my_service_package client_node 5 3

这里,client_node脚本会发送两个整数(5和3)到服务端,服务端将返回它们的和,并在客户端打印结果。

总结

通过以上步骤,你可以使用Python成功实现ROS 2中的服务通讯。服务端节点负责处理请求并返回结果,而客户端节点发送请求并接收结果。这种通讯方式适用于需要确认操作结果的场景,例如生成对象、计算任务等。

您可能感兴趣的与本文相关的镜像

Python3.9

Python3.9

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

使用C++在ROS2创建客户端可按以下步骤操作: 1. **创建功能包**:打开新终端,设置环境变量使ros2命令能正常工作,进入`dev_ws/src`文件夹,运行创建功能包的指令,如创建一个名为`cpp_srvcli`的功能包: ```bash ros2 pkg create --build-type ament_cmake cpp_srvcli --dependencies rclcpp example_interfaces ``` 此步骤依据创建新功能包的通用操作,是后续开发的基础[^2]。 2. **编写客户端代码**:客户端代码的关键部分包括初始化ROS2 C++客户端库、创建节点、创建客户端对象、发送服务请求并处理响应。以下是一个简单示例: ```cpp #include <rclcpp/rclcpp.hpp> #include <example_interfaces/srv/add_two_ints.hpp> #include <chrono> #include <cstdlib> #include <memory> using namespace std::chrono_literals; int main(int argc, char **argv) { rclcpp::init(argc, argv); if (argc != 3) { RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "usage: add_two_ints_client X Y"); return 1; } std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("add_two_ints_client"); auto client = node->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints"); auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>(); request->a = atoll(argv[1]); request->b = atoll(argv[2]); while (!client->wait_for_service(1s)) { if (!rclcpp::ok()) { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting."); return 0; } RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again..."); } auto result = client->async_send_request(request); // Wait for the result. if (rclcpp::spin_until_future_complete(node, result) == rclcpp::FutureReturnCode::SUCCESS) { RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Sum: %ld", result.get()->sum); } else { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service add_two_ints"); } rclcpp::shutdown(); return 0; } ``` 此代码初始化ROS2客户端库,创建客户端节点和客户端对象,发送服务请求并等待响应,最后输出结果。其中`async_send_request`函数用于异步发送服务请求,属于`rclcpp::Client`类,会返回一个`Future`对象以便稍后处理响应[^5]。 3. **编译功能包**:在工作空间根目录下运行编译命令: ```bash colcon build --packages-select cpp_srvcli ``` 编译功能包可将编写的代码转换为可执行文件。 4. **运行客户端**:打开终端,设置环境变量,运行客户端节点: ```bash source install/setup.sh ros2 run cpp_srvcli client 123 456 ``` 运行客户端节点可验证客户端是否正常工作,若一切正常,会输出服务调用的结果,如`Sum: 579` [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值