返回

ROS2 C++ 轻松实现服务端与客户端

后端

服务端和客户端 ROS2 C++ 编程指南

引言:服务在 ROS2 中的重要性

在 ROS2 图形中,服务是一种节点之间通信的重要方式,它基于呼叫和响应模型,与发布者-订阅者模型截然不同。服务允许节点进行点对点通信,在需要时发出请求并获取响应,而不是持续不断地发布和订阅数据流。这使得服务非常适合处理需要按需进行的特定任务或获取特定信息的情况。

服务端和客户端的角色

在服务通信中,服务端负责提供特定功能或服务,而客户端则负责请求这些服务。服务端通常通过定义一个服务类型并实现相应的功能来实现,而客户端则通过创建服务客户端并调用服务来访问这些功能。

编写服务端和客户端的步骤

  1. 定义服务类型:首先,您需要定义一个服务类型,该类型定义了服务的功能和数据结构。这包括定义请求消息和响应消息,它们用于在服务端和客户端之间传递数据。

  2. 实现服务端:接下来,您需要实现服务端。这包括创建服务类并实现请求处理函数,该函数负责处理来自客户端的请求并返回响应。

  3. 创建服务客户端:编写完服务端后,您需要创建一个服务客户端。这包括创建服务客户端类并初始化它以连接到服务端。

  4. 使用服务客户端:一旦服务客户端创建成功,您就可以使用它来调用服务端提供的服务。这包括发送请求并等待响应。

示例代码

// 服务端代码

#include <rclcpp/rclcpp.hpp>
#include <std_srvs/srv/empty.hpp>

class EmptyService : public rclcpp::Service<std_srvs::srv::Empty>
{
public:
  EmptyService()
  : Service("empty_service") {}

  rclcpp::Response<std_srvs::srv::Empty::Response> handle_request(
    const std_srvs::srv::Empty::Request::SharedPtr request)
  {
    (void)request;
    auto response = std::make_shared<std_srvs::srv::Empty::Response>();
    return rclcpp::Response<std_srvs::srv::Empty::Response>(response);
  }
};

int main(int argc, char **argv)
{
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("empty_service_node");
  auto service = std::make_shared<EmptyService>();
  node->add_service(service);
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}

// 客户端代码

#include <rclcpp/rclcpp.hpp>
#include <std_srvs/srv/empty.hpp>

int main(int argc, char **argv)
{
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("empty_client_node");
  auto client = node->create_client<std_srvs::srv::Empty>("empty_service");
  while (!client->wait_for_service(std::chrono::seconds(1)))
  {
    if (!rclcpp::ok())
    {
      return 1;
    }
    RCLCPP_INFO(node->get_logger(), "Waiting for service to become available...");
  }

  auto request = std::make_shared<std_srvs::srv::Empty::Request>();
  auto future_result = client->async_send_request(request);

  while (!future_result.wait_for(std::chrono::seconds(1)))
  {
    if (!rclcpp::ok())
    {
      return 1;
    }
    RCLCPP_INFO(node->get_logger(), "Waiting for response...");
  }

  auto result = future_result.get();
  RCLCPP_INFO(node->get_logger(), "Service call completed successfully");
  rclcpp::shutdown();
  return 0;
}

结语

掌握了服务的使用方法,您就能够在 ROS2 节点之间进行更灵活、更有效的通信。无论您是初学者还是经验丰富的开发者,都可以尝试使用服务来构建更复杂的 ROS2 应用程序。