ROS 2 服务通信

10 篇文章 0 订阅

ROS 2 服务通信

1. 简介

ROS 2(Robot Operating System 2) 是一个用于机器人系统开发的开源框架,提供了许多工具和库来简化复杂机器人应用的开发。在 ROS 2 中,服务(Service)是一种同步的通信机制,允许节点之间进行请求-响应模式的通信。这与话题(Topics)中的异步通信方式不同,服务更适合那些需要明确请求和相应结果的应用场景。

在这篇文章中,我们将介绍如何使用 C++ 创建和使用 ROS 2 服务,包括服务端(Service Server)和客户端(Service Client)的实现。

2. 什么是 ROS 2 服务?

ROS 2 服务是一种基于请求-响应的通信模式,通常用于需要立即得到响应的场景。服务由两个部分组成:

  • 服务端(Server): 提供服务,等待客户端的请求,并返回相应的结果。
  • 客户端(Client): 发送请求到服务端,并等待服务端返回结果。

服务的通信是同步的,这意味着客户端在等待服务端响应时会阻塞当前线程。

3. 创建自定义服务类型

在 ROS 2 中,服务类型定义了请求和响应的消息结构。可以使用 .srv 文件来定义自定义服务类型。以下是一个简单的服务类型定义示例:

AddTwoInts.srv

int64 a
int64 b
---
int64 sum

这个服务类型表示客户端会发送两个 int64 类型的整数(ab),服务端返回它们的和(sum)。

以下内容在 CMakeLists.txt添加

rosidl_generate_interfaces(${PROJECT_NAME}
 "msg/PositionSpeed.msg"
 "srv/ComputeArea.srv"
 #添加这一行
 "srv/AddTwoInts.srv"
 "action/Factorial.action"
 DEPENDENCIES *# Add packages that above messages depend on*
)
4. 创建服务端(Service Server)

创建服务端节点需要使用 ROS 2 提供的 rclcpp 库。在 C++ 中实现服务端的如下:

#include "rclcpp/rclcpp.hpp"
#include "my_custom_msgs/srv/add_two_ints.hpp"

class AddTwoIntsServer : public rclcpp::Node
{
public:
    AddTwoIntsServer() : Node("add_two_ints_server")
    {
        service_ = this->create_service<my_custom_msgs::srv::AddTwoInts>(
            "add_two_ints", std::bind(&AddTwoIntsServer::handle_add_two_ints, this, std::placeholders::_1, std::placeholders::_2));
    }

private:
    void handle_add_two_ints(
        const std::shared_ptr<my_custom_msgs::srv::AddTwoInts::Request> request,
        std::shared_ptr<my_custom_msgs::srv::AddTwoInts::Response> response)
    {
        response->sum = request->a + request->b;
        RCLCPP_INFO(this->get_logger(), "Request: a = %ld, b = %ld", request->a, request->b);
        RCLCPP_INFO(this->get_logger(), "Sending back response: [%ld]", response->sum);
    }

    rclcpp::Service<my_custom_msgs::srv::AddTwoInts>::SharedPtr service_;
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<AddTwoIntsServer>());
    rclcpp::shutdown();
    return 0;
}

定义服务端节点类。在这个例子中,我们创建了一个名为 add_two_ints_server 的节点,它提供了一个名为 add_two_ints 的服务。服务处理函数 handle_add_two_ints 计算两个整数的和,并将结果返回给客户端。

5. 创建客户端(Service Client)

客户端的实现与服务端类似,也需要使用 rclcpp 库。以下是实现:

#include "rclcpp/rclcpp.hpp"
#include "my_custom_msgs/srv/add_two_ints.hpp"  // 替换为自定义服务类型的头文件

class AddTwoIntsClient : public rclcpp::Node
{
public:
    AddTwoIntsClient() : Node("add_two_ints_client")
    {
        client_ = this->create_client<my_custom_msgs::srv::AddTwoInts>("add_two_ints");

        // 等待服务端准备就绪
        while (!client_->wait_for_service(std::chrono::seconds(1))) {
            RCLCPP_INFO(this->get_logger(), "Waiting for service to be available...");
        }

        auto request = std::make_shared<my_custom_msgs::srv::AddTwoInts::Request>();
        request->a = 5;
        request->b = 3;

        auto result = client_->async_send_request(request);

        // 等待结果
        if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result) ==
            rclcpp::FutureReturnCode::SUCCESS)
        {
            RCLCPP_INFO(this->get_logger(), "Result: %ld", result.get()->sum);
        } else {
            RCLCPP_ERROR(this->get_logger(), "Failed to call service");
        }
    }

private:
    rclcpp::Client<my_custom_msgs::srv::AddTwoInts>::SharedPtr client_;
};

int main(int argc, char **argv)
{
    rclcpp::init(argc, argv);
    rclcpp::spin(std::make_shared<AddTwoIntsClient>());
    rclcpp::shutdown();
    return 0;
}

在这个例子中,我们创建了一个名为 add_two_ints_client 的节点,发送两个整数给服务端,并打印出返回的结果。

6. 编译和运行

使用 CMake 编译上述服务端和客户端代码。以下是 CMakeLists.txt 的示例:

cmake_minimum_required(VERSION 3.8)
project(my_server)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(my_custom_msgs REQUIRED)
find_package(rclcpp REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

add_executable(AddTwoIntsServer_node src/AddTwoIntsServer.cpp)
ament_target_dependencies(AddTwoIntsServer_node rclcpp my_custom_msgs)

add_executable(AddTwoIntsClient_node src/AddTwoIntsClient.cpp)
ament_target_dependencies(AddTwoIntsClient_node rclcpp my_custom_msgs)

install(TARGETS
AddTwoIntsServer_node
AddTwoIntsClient_node
  DESTINATION lib/${PROJECT_NAME})

ament_package()

编译后,运行服务端和客户端节点以观察通信效果。

在这里插入图片描述

7. 总结

在这篇文章中,我们详细介绍了如何使用 C++ 在 ROS 2 中创建和使用服务。通过创建服务端和客户端节点,开发者可以轻松实现同步的请求-响应通信模式。这种模式适用于机器人系统中那些需要立即得到响应的场景,如命令执行、传感器数据获取等。

希望这篇文章能帮助你更好地理解和使用 ROS 2 服务!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值