1. ROS服务通信基础概念
在机器人操作系统(ROS)中,服务(Service)是一种重要的进程间通信机制。与话题(Topic)的发布/订阅模式不同,服务采用请求/响应模型,更适合需要即时反馈的交互场景。想象一下你去餐厅点餐:话题通信就像餐厅广播今日特价,所有顾客都能听到;而服务通信则像是你向服务员点单,必须得到明确的确认回复。
服务由两部分组成:服务端(Server)和客户端(Client)。服务端负责处理请求并返回响应,客户端则发送请求并等待响应。这种同步通信方式特别适合需要确认结果的场景,比如让机器人移动到指定位置后返回是否成功。
提示:服务通信是阻塞式的,客户端在收到响应前会一直等待。对于耗时较长的操作,建议考虑使用动作(Action)。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 服务数据定义详解
2.1 创建srv文件
服务数据类型定义存储在.srv文件中,通常放在功能包的srv目录下。一个完整的srv文件由三部分组成,用---分隔:
code复制# 请求部分(客户端发送)
string name
int32 age
---
# 响应部分(服务端返回)
bool success
string message
---
# 下方可以添加注释说明
这个例子定义了一个简单的个人信息查询服务:客户端发送姓名和年龄,服务端返回操作是否成功及附加消息。
2.2 数据类型支持
ROS服务支持多种基本数据类型,包括:
- 基本类型:bool, int8/16/32/64, float32/64, string, time, duration
- 数组:固定长度(如int32[5])和可变长度(如int32[])
- 特殊类型:Header(常用于时间戳和坐标系信息)
- 嵌套类型:可以包含其他msg定义
2.3 编译系统配置
在定义好srv文件后,需要修改package.xml和CMakeLists.txt以确保编译系统能正确处理:
xml复制<!-- package.xml -->
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
cmake复制# CMakeLists.txt
find_package(catkin REQUIRED COMPONENTS
message_generation
# 其他依赖...
)
add_service_files(
FILES
YourService.srv
)
generate_messages(
DEPENDENCIES
std_msgs # 如果有使用标准消息类型
)
catkin_package(
CATKIN_DEPENDS message_runtime
# 其他配置...
)
编译后会生成对应的Python或C++代码文件,存放在devel/include和devel/lib相应目录中。
3. 服务端实现全解析
3.1 Python服务端示例
下面是一个完整的Python服务端实现,提供加法计算服务:
python复制#!/usr/bin/env python
import rospy
from beginner_tutorials.srv import AddTwoInts, AddTwoIntsResponse
def handle_add_two_ints(req):
print(f"收到请求: {req.a} + {req.b}")
sum = req.a + req.b
return AddTwoIntsResponse(sum) # 也可以直接返回sum
def add_two_ints_server():
rospy.init_node('add_two_ints_server')
s = rospy.Service('add_two_ints', AddTwoInts, handle_add_two_ints)
print("准备就绪,等待加法请求...")
rospy.spin()
if __name__ == "__main__":
add_two_ints_server()
关键点说明:
rospy.Service第一个参数是服务名称,建议使用package_name/srv_name格式避免冲突- 回调函数接收请求对象,返回响应对象
- 服务端需要保持运行,通常使用
rospy.spin()
3.2 C++服务端实现
对应的C++版本实现如下:
cpp复制#include "ros/ros.h"
#include "beginner_tutorials/AddTwoInts.h"
bool add(beginner_tutorials::AddTwoInts::Request &req,
beginner_tutorials::AddTwoInts::Response &res)
{
res.sum = req.a + req.b;
ROS_INFO("请求: %ld + %ld", (long int)req.a, (long int)req.b);
return true;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "add_two_ints_server");
