Lazy loaded image
🤖 ROS 理论与实践
ROS 1 入门 02|Topic 与 Service 通信实战(C++)
Words 1318Read Time≈ 4 min
2024-9-9
2026-9-6
💡
本文通过两个最小示例,介绍 ROS 1 中最常用的两种通信方式:
  • Topic(话题):发布者持续发送消息,订阅者异步接收消息。
  • Service(服务):客户端发送一次请求,服务端处理后返回响应。

一、准备工作

本文假设已经完成以下准备:
  • 安装 ROS 1,并创建 Catkin 工作空间 ~/catkin_ws。
  • 创建功能包 beginner_tutorials。
  • 功能包已依赖 roscpp、std_msgs 和 message_generation。
  • 已创建服务定义文件 srv/AddTwoInts.srv。
进入功能包源码目录:

二、Topic:发布者与订阅者

Topic 适合持续、异步的数据传输。例如,传感器不断发布数据,其他节点按需订阅。

2.1 编写发布者节点

创建 src/talker.cpp:
这段代码完成了四件事:
  1. 初始化 ROS 节点 talker。
  1. 创建 chatter 话题的发布者。
  1. 以 10 Hz 的频率生成字符串消息。
  1. 调用 publish() 将消息发送给订阅者。

2.2 编写订阅者节点

创建 src/listener.cpp:
这段代码的执行过程是:
  1. 初始化 ROS 节点 listener。
  1. 订阅 chatter 话题。
  1. 调用 ros::spin() 进入事件循环。
  1. 收到消息后,由 ROS 调用 chatterCallback()。

2.3 配置 CMakeLists.txt

确认 CMakeLists.txt 包含以下配置:

2.4 编译并运行

先编译工作空间:
打开三个终端,并分别执行:
订阅者终端将持续输出类似结果:

三、Service:服务端与客户端

Service 采用同步的请求/响应模型:客户端发送请求,服务端处理后返回结果。它适合偶发、需要明确返回值的操作,不适合持续传输数据。
本例实现一个整数加法服务:客户端发送两个整数,服务端返回它们的和。

3.1 定义服务接口

创建 srv/AddTwoInts.srv:
分隔线 --- 上方是请求字段,下方是响应字段。

3.2 编写服务端节点

创建 src/add_two_ints_server.cpp:
服务端收到请求后,会执行 add(),计算两个整数之和并写入响应。

3.3 编写客户端节点

创建 src/add_two_ints_client.cpp:

3.4 添加构建配置

在 CMakeLists.txt 末尾添加:
重新编译:

3.5 运行并验证

确保 roscore 正在运行,然后分别启动服务端和客户端:
客户端输出:
服务端输出:

四、Topic 与 Service 的区别

对比项
Topic
Service
通信方式
发布/订阅
请求/响应
是否持续通信
通常持续
通常单次
是否等待结果
发布者不等待
客户端等待响应
节点关系
多对多
通常一对一调用
典型场景
传感器数据、状态广播、控制指令
参数查询、触发动作、一次性计算
✅
选择原则
持续产生、允许异步处理的数据使用 Topic;需要发起一次操作并获得明确结果时使用 Service。

五、常见问题

找不到功能包或节点

确认当前终端已加载工作空间环境:

找不到 AddTwoInts.h

通常是服务代码尚未生成。检查 add_service_files()、generate_messages() 和 add_dependencies() 配置,然后重新执行 catkin_make。

客户端调用失败

依次检查:
  1. roscore 是否正在运行。
  1. 服务端节点是否已经启动。
  1. 服务名是否为 /add_two_ints。
可使用以下命令查看当前服务:
上一篇
ROS 1 入门 01|Noetic 环境、Catkin 工作空间与核心概念
下一篇
ROS 学习导航|架构、环境、通信与工具链

Comments
Loading...