当前位置: 首页 > java >正文

ROS2学习(8)------ROS2 服务说明

  • 操作系统:ubuntu22.04
  • IDE:Visual Studio Code
  • 编程语言:C++11
  • ROS版本:2

ROS 2(Robot Operating System 2)中的服务是一种允许节点之间进行请求/响应式通信的机制。与话题(Topics)不同,话题主要用于发布/订阅模式的持续数据流传输,而服务更适合于一次性或偶尔的数据交换场景,比如查询状态、执行操作等。

ROS2服务的基本概念

  • 服务类型:每个服务都有其类型,这定义了请求和响应消息的数据结构。服务类型由两个部分组成:请求消息类型和响应消息类型。

  • 服务客户端(Client):发起请求的一方,发送特定类型的请求并等待响应。

  • 服务端(Server):接收请求并处理后返回响应的一方。

  • srv文件:服务的消息格式通过.srv文件定义,位于包的srv/目录下。一个.srv文件定义了一个服务的请求和响应格式。

在这里插入图片描述

创建和使用ROS 2服务

定义服务消息

首先,你需要为你的服务创建一个.srv文件。例如,创建一个名为MyService.srv的服务,用于计算两个整数的和:

int64 a
int64 b
---
int64 sum

上面的文件定义了一个接受两个长整型数字作为输入,并返回它们的和的服务。

修改package.xml

确保在package.xml中添加对rosidl_default_runtime以及任何你用到的消息包(如std_msgs)的依赖:

<?xml version="1.0"?>
<package format="3"><name>robot_nodes</name><version>0.0.0</version><description>My multi-node ROS 2 package</description><maintainer email="76457551@qq.com">User Name</maintainer><license>Apache-2.0</license><buildtool_depend>ament_cmake</buildtool_depend><build_depend>rosidl_default_generators</build_depend><exec_depend>rosidl_default_runtime</exec_depend><depend>rclcpp</depend><depend>std_msgs</depend><depend>geometry_msgs</depend><depend>example_interfaces</depend><member_of_group>rosidl_interface_packages</member_of_group><export><build_type>ament_cmake</build_type></export>
</package>

修改CMakeLists.txt

在CMakeLists.txt中找到find_package命令,并确保它包含了rosidl_default_generators:

cmake_minimum_required(VERSION 3.8)
project(robot_nodes)# 查找必要的依赖
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)find_package(rosidl_default_generators REQUIRED)
find_package(geometry_msgs REQUIRED)find_package(example_interfaces REQUIRED) # 假设你使用的是自定义的服务接口# 生成自定义接口
rosidl_generate_interfaces(${PROJECT_NAME}"srv/MyService.srv"DEPENDENCIES # 如果有其他依赖(如 std_msgs)
)# 添加子目录(每个节点)
add_subdirectory(nodes/node1)
add_subdirectory(nodes/node2)ament_package()

编写服务端代码

下面是一个简单的服务端示例,它实现了上述AddTwoInts服务:

#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp" // 引入服务接口class MinimalService : public rclcpp::Node
{
public:MinimalService() : Node("minimal_service"){service_ = this->create_service<example_interfaces::srv::AddTwoInts>("add_two_ints",std::bind(&MinimalService::handle_add_two_ints, this, std::placeholders::_1, std::placeholders::_2));}private:void handle_add_two_ints(const example_interfaces::srv::AddTwoInts::Request::SharedPtr request,const example_interfaces::srv::AddTwoInts::Response::SharedPtr response){response->sum = request->a + request->b;RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Incoming request\na: %ld" " b: %ld", request->a, request->b);RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "sending back response: [%ld]", (long int)response->sum);}rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtr service_;
};int main(int argc, char **argv)
{rclcpp::init(argc, argv);auto node = std::make_shared<MinimalService>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}

编写客户端代码

客户端将调用服务来执行请求:

#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"class MinimalClientAsync : public rclcpp::Node
{
public:MinimalClientAsync() : Node("minimal_client_async"), client_(this->create_client<example_interfaces::srv::AddTwoInts>("add_two_ints")){while (!client_->wait_for_service(std::chrono::seconds(1))){if (!rclcpp::ok()){RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");return;}RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");}send_request();}private:void send_request(){auto request = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();request->a = 1;request->b = 2;using ServiceResponseFuture = rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedFuture;auto response_received_callback = [this](ServiceResponseFuture future){auto result = future.get();RCLCPP_INFO(this->get_logger(), "Result: %ld", result->sum);};auto future_result = client_->async_send_request(request, response_received_callback);}rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr client_;
};int main(int argc, char **argv)
{rclcpp::init(argc, argv);auto node = std::make_shared<MinimalClientAsync>();rclcpp::spin(node);rclcpp::shutdown();return 0;
}

运行结果

分别执行两个节点:

node1:

source install/setup.bash 
ros2 run robot_nodes node1 

node2:

source install/setup.bash 
ros2 run robot_nodes node2

终端输出:

ros2 run robot_nodes node1
[2025-05-21 16:51:15:471][node1][info][node1.cpp:58]:==========main===========
[INFO] [1747817521.071953435] [rclcpp]: Incoming request
a: 1 b: 2
[INFO] [1747817521.071991360] [rclcpp]: sending back response: [3]
ros2 run robot_nodes node2
[2025-05-21 16:52:01:064][node2][info][node2.cpp:76]:==========main===========
[INFO] [1747817521.072052185] [minimal_client_async]: Result: 3
http://www.xdnf.cn/news/7808.html

相关文章:

  • ubuntu 搭建FTP服务,接收部标机历史音视频上报服务器
  • 线性表数据结构-堆栈
  • 网络安全之APP渗透测试总结
  • Vue3 组件之间传值
  • React深度解析:Hooks体系与Redux Toolkit现代状态管理实践
  • linux 学习之位图(bitmap)数据结构
  • 宝塔安装的 MySQL 无法连接的情况及解决方案
  • StepX-Edit:一个通用图像编辑框架——论文阅读笔记
  • 计算机网络相关面试题
  • 安全可控的AI底座:灯塔大模型应用开发平台全面实现国产信创兼容适配认证
  • 数据被泄露了怎么办?
  • 视觉生成新突破!仅0.5B参数,SimpleAR解锁预训练、SFT、RL全能模式
  • 【MC】红石比较器
  • Spring Boot 项目中 Redis 存储 Session 对象序列化处理
  • 面向未来,遨游推出5G-A智能防爆对讲机等系列终端
  • Qt功能区:Ribbon控件
  • BEVDet
  • opencv_version_win32
  • Leetcode-2 最小偶倍数
  • pikachu靶场 暴力破解
  • 服务器安装xfce桌面环境并通过浏览器操控
  • SpringBoot外部化配置
  • NIFI的处理器:ExecuteGroovyScript 2.4.0
  • 第14天-Matplotlib实现数据可视化
  • ollama使用gpu运行大模型
  • Xilinx 7Series\UltraScale 在线升级FLASH STARTUPE2和STARTUPE3使用
  • Java 定时任务中Cron 表达式与固定频率调度的区别及使用场景
  • 唯创安全优化纸业车间安全环境:门口盲区预警报警器的应用与成效
  • STL中的Vector(顺序表)
  • RabbitMQ——消息确认