当前位置:首页 > 技术 > 正文内容

ROS2服务通信机制详解与实践

访客 技术 2026年6月18日 1

服务在ROS2中的角色与重要性

作为机器人系统中关键的同步通信方式,ROS2的服务(Service)机制为请求-响应型交互提供了高效支持。相较于话题的异步数据流,服务适用于需要即时反馈的操作场景,如状态查询、指令执行确认等。随着ROS2 Jazzy Jalisco长期支持版本的普及,其对服务数据记录和回放功能的支持显著增强了系统的可调试性。

最新发布的Kilted Kaiju版本引入了Eclipse Zenoh作为一级中间件选项,进一步优化了服务通信的网络适应性和传输效率,特别是在边缘计算和分布式部署环境中表现出更强的灵活性。

服务通信的基本原理

ROS2服务采用典型的客户端-服务器架构:

  • 服务端:监听特定名称的服务请求,处理逻辑后返回结果
  • 客户端:发起请求并等待响应,期间通常处于阻塞状态

这种模式特别适合短时、确定性的任务,例如触发传感器校准、获取设备当前运行参数等操作。

接口定义与数据结构

服务的数据格式通过.srv文件进行声明,文件内容分为上下两部分,使用---分隔:

int64 operand_a
int64 operand_b
---
int64 result

前半部分为请求字段,后半部分为响应字段。编译时ROS2会自动生成对应语言的代码结构体。

核心特性说明

  • 同步调用:客户端必须收到响应或超时才能继续执行
  • 唯一性约束:同一节点命名空间下不允许存在同名服务提供者
  • 时效建议:推荐处理时间控制在1秒以内,长时间任务应改用Action机制

创建C++服务示例

以下步骤演示如何构建一个整数相加服务。

初始化开发环境

确保已安装ROS2 Jazzy桌面版:

sudo apt install ros-jazzy-desktop

建立功能包

mkdir -p ~/ros_workspace/src && cd ~/ros_workspace/src
ros2 pkg create --build-type ament_cmake math_service_pkg --dependencies rclcpp example_interfaces

实现服务端逻辑

编写src/integer_sum_server.cpp

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

void compute_sum(
    const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> req,
    std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> res)
{
    res->sum = req->a + req->b;
    RCLCPP_INFO(rclcpp::get_logger("sum_server"), 
               "Received request: %ld + %ld = %ld", 
               req->a, req->b, res->sum);
}

int main(int argc, char* argv[])
{
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("sum_calculator");
    
    auto service = node->create_service<example_interfaces::srv::AddTwoInts>(
        "calculate_sum", compute_sum);

    RCLCPP_INFO(node->get_logger(), "Sum service is ready.");
    rclcpp::spin(node);
    rclcpp::shutdown();
    return 0;
}

实现客户端逻辑

创建src/integer_sum_client.cpp

#include "rclcpp/rclcpp.hpp"
#include "example_interfaces/srv/add_two_ints.hpp"
#include <chrono>

using namespace std::chrono_literals;

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

    if (argc != 3) {
        fprintf(stderr, "Usage: sum_client X Y\n");
        return 1;
    }

    auto client_node = rclcpp::Node::make_shared("sum_requester");
    auto client = client_node->create_client<example_interfaces::srv::AddTwoInts>("calculate_sum");

    while (!client->wait_for_service(2s)) {
        if (!rclcpp::ok()) {
            RCLCPP_ERROR(client_node->get_logger(), "Interrupted before connection.");
            return -1;
        }
        RCLCPP_INFO(client_node->get_logger(), "Waiting for service to appear...");
    }

    auto request_msg = std::make_shared<example_interfaces::srv::AddTwoInts::Request>();
    request_msg->a = atoll(argv[1]);
    request_msg->b = atoll(argv[2]);

    auto future = client->async_send_request(request_msg);
    if (rclcpp::spin_until_future_complete(client_node, future) == rclcpp::FutureReturnCode::SUCCESS)
    {
        RCLCPP_INFO(client_node->get_logger(), "Result: %ld", future.get()->sum);
    } else {
        RCLCPP_ERROR(client_node->get_logger(), "Service call failed.");
    }

    rclcpp::shutdown();
    return 0;
}

配置构建系统

修改CMakeLists.txt以包含新目标:

cmake_minimum_required(VERSION 3.8)
project(math_service_pkg)

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(example_interfaces REQUIRED)

add_executable(sum_server src/integer_sum_server.cpp)
ament_target_dependencies(sum_server rclcpp example_interfaces)

add_executable(sum_client src/integer_sum_client.cpp)
ament_target_dependencies(sum_client rclcpp example_interfaces)

install(TARGETS sum_server sum_client DESTINATION lib/${PROJECT_NAME})

ament_package()

编译与测试流程

# 构建项目
cd ~/ros_workspace
colcon build --packages-select math_service_pkg

# 启动服务端(新开终端)
source install/setup.bash
ros2 run math_service_pkg sum_server

# 发送请求(另开终端)
source install/setup.bash
ros2 run math_service_pkg sum_client 7 8

实际应用场景分析

服务机制广泛应用于各类机器人系统:

机械臂控制系统

在xArm系列机械臂驱动中,服务用于精确控制末端执行器:

ros2 service call /arm/gripper_ctrl xarm_msgs/srv/GripperCtrl "{pos: 800, vel: 300}"

无人机飞行管理

PX4平台利用服务实现关键动作确认:

  • arming:发送解锁命令并等待飞控确认
  • return_to_home:请求返航并接收执行状态

自动导引车导航

矿山AGV使用服务进行路径查询与紧急制动:

  • check_path_validity:验证规划路径是否安全
  • trigger_emergency_stop:立即停止所有运动并反馈系统状态

进阶技巧与最佳实践

数据记录与重演

Jazzy版本支持服务通信的数据捕获:

# 记录服务交互
ros2 bag record /calculate_sum

# 回放历史数据
ros2 bag play recorded_session_01

性能调优建议

  • 优先使用异步请求避免主线程阻塞
  • 合理设置连接等待超时时间
  • 将复杂服务拆解为多个轻量级接口

安全通信配置

借助SROS2框架实现服务加密:

ros2 security create_key store /sum_server
# 配置权限策略以保护敏感服务

总结

ROS2服务为机器人系统提供了可靠的同步通信能力,在工业自动化、智能移动平台等领域具有不可替代的作用。结合新型中间件Zenoh的支持,未来将在跨域协同和低延迟控制方面展现更大潜力。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。