📜  ros2 呼叫服务 (1)

📅  最后修改于: 2023-12-03 15:04:55.738000             🧑  作者: Mango

ROS2 呼叫服务

在ROS2中,服务(Service)是一种允许节点之间进行请求-响应通信的机制。其操作类似于ROS1中的服务。在本文中,我们将介绍如何在ROS2中使用服务。

创建服务

在ROS2中,您可以使用ROS2的colcon构建系统或ament工具创建服务。服务消息是使用ROS2的接口定义语言(IDL)在colcon下生成的,这种语言使生成的消息类型跨语言兼容。

以下是您可以使用的步骤:

定义服务消息

定义您的服务消息的IDL,例如,在my_robot_interfaces包中定义名为SetSpeed的服务:

# 服务请求消息
int64 speed

# 服务响应消息
---
bool success
生成服务消息

使用ament,通过以下命令生成服务消息:

ament build --bundle-visual-studio --isolated --cmake-args -DCMAKE_BUILD_TYPE=Release

my_robot_interfaces/srv中生成SetSpeed.srv的头文件和源文件。

创建服务节点

接下来,创建一个新节点以设置机器人速度:

#include "my_robot_interfaces/srv/set_speed.hpp"
#include "rclcpp/rclcpp.hpp"

/* 根据 SetSpeed.srv 建立节点 */
class SetSpeedNode : public rclcpp::Node
{
public:
  SetSpeedNode() : Node("set_speed_node")
  {
    /* 创建服务 */
    auto set_speed_service = create_service<my_robot_interfaces::srv::SetSpeed>(
      "set_speed", std::bind(&SetSpeedNode::set_speed_callback, this, _1, _2, _3));
  }

private:
  void set_speed_callback(
    const std::shared_ptr<rmw_request_id_t> request_header,
    const std::shared_ptr<my_robot_interfaces::srv::SetSpeed::Request> request,
    std::shared_ptr<my_robot_interfaces::srv::SetSpeed::Response> response)
  {
    /* 调用设备的API设置机器人的速度 */
    bool success = setRobotSpeed(request->speed);
    response->success = success;
  }
};

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

在上面的代码中,我们创建了一个节点,并用set_speed作为服务名称。我们还定义了一个set_speed_callback回调函数,该回调函数会将服务请求中的速度发送到设备API以设置机器人的速度,并将成功的状态设置为响应消息。

运行节点

运行服务节点:

ros2 run my_robot_interfaces set_speed_node
调用服务

现在我们已经创建了一个服务,我们还需要知道如何使用它。在ROS2中,您可以使用ros::ServiceClient进行服务调用。

#include "my_robot_interfaces/srv/set_speed.hpp"
#include "rclcpp/rclcpp.hpp"

int main(int argc, char ** argv)
{
  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("service_client");

  /* 创建服务客户端 */
  auto client = node->create_client<my_robot_interfaces::srv::SetSpeed>("set_speed");

  while (!client->wait_for_service(std::chrono::seconds(1))) {
    if (!rclcpp::ok()) {
      RCLCPP_ERROR(node->get_logger(), "Interrupted while waiting for the service. Exiting.");
      return -1;
    }
    RCLCPP_INFO(node->get_logger(), "未能连接到服务,重试...");
  }

  /* 创建服务请求 */
  auto request = std::make_shared<my_robot_interfaces::srv::SetSpeed::Request>();
  request->speed = 20;

  /* 调用服务 */
  auto future = client->async_send_request(request);

  if (rclcpp::spin_until_future_complete(node, future) == rclcpp::executor::FutureReturnCode::SUCCESS) {
    auto response = future.get();
    if (response->success) {
      RCLCPP_INFO(node->get_logger(), "设备成功地设置机器人的速度");
    } else {
      RCLCPP_ERROR(node->get_logger(), "设备未能设置机器人的速度");
    }
  } else {
    RCLCPP_ERROR(node->get_logger(), "服务调用失败。");
  }

  rclcpp::shutdown();
  return 0;
}

在上述代码中,我们使用create_client方法创建了一个服务客户端。我们填充了请求中的速度,并使用async_send_request方法发送请求。

使用spin_until_future_complete方法使节点机一直保持活动状态,以等待服务的响应。如果返回值是SUCCESS,则我们将获取响应对象并检查请求是否成功。

结论

这就是关于在ROS2中使用服务的全部内容。您可以使用上面提供的代码模板开始创建自己的服务。务必注意,ROS2的服务机制与ROS1不同,您需要检查ROS2文档以获取更多相关信息。