ROS2服务通信实战
一、前言在机器人系统开发中ROS2 提供多种节点通信方式其中话题通信与服务通信是最核心的两种机制。话题通信发布者持续单向推送数据订阅者被动接收不存在应答机制适合激光雷达、相机等连续流式传感器数据传输服务通信采用客户端 / 服务端C/S一问一答同步交互模型。客户端主动发起请求服务端接收请求、执行业务逻辑并返回处理结果适合单次指令交互场景例如设备启停、参数查询、运算请求、机械臂定点运动。很多初学者学习 ROS2 时容易混淆话题与服务的适用场景同时在自定义.srv接口、客户端服务端交互、编译配置上频繁踩坑。本文严格依照课程实训案例完整还原需求分析→自定义服务接口→功能包创建→服务端开发→客户端开发→编译配置→运行测试全流程附带原理剖析、完整源码、运行效果、易错点总结适合课程作业、实训报告知识点覆盖全面逻辑层次完整。二、案例需求与架构分析2.1 案例需求编写 ROS2 服务通信程序实现整数求和功能客户端在终端传入两个整数作为请求数据发送至服务端服务端持续监听服务请求解析收到的两个数字完成求和运算服务端将求和结果封装为响应消息返回客户端两端打印日志直观展示请求、运算、响应全过程。运行效果客户端输入100 200服务端计算后返回结果300。2.2 服务通信三大核心要素服务通信模型由 3 部分构成缺一不可客户端 Client通信发起方主动创建连接、封装请求数据等待接收服务端反馈服务端 Server通信监听方长期运行等待客户端接入收到请求后触发回调函数处理业务生成响应数据消息载体.srv 服务接口约定客户端与服务端的数据传输格式使用---分隔两段上半段Request请求数据客户端→服务端下半段Response响应数据服务端→客户端2.3 整体开发流程创建并编辑.srv自定义服务文件修改接口包CMakeLists.txt配置消息编译规则创建 C 服务功能包添加对应依赖编写服务端源代码编写客户端源代码修改业务包CMakeLists.txt实现编译安装编译工作空间刷新环境变量多终端启动节点完成功能测试。三、自定义服务通信接口 AddInts.srv3.1 创建.srv 文件在base_interfaces_demo功能包下新建srv文件夹创建AddInts.srv写入内容文件说明int32 num1、int32 num2客户端发送的两个加数---分隔请求区与响应区int32 sum服务端计算完成后返回的求和结果。3.2 配置接口包 CMakeLists.txt想要编译工具识别.srv并自动生成可供 C/Python 调用的接口代码需要配置消息生成器若为全新接口包不能缺少find_package(rosidl_default_generators REQUIRED)已有 msg 消息的包仅需要在rosidl_generate_interfaces内追加srv/AddInts.srv路径。3.3 编译接口包colcon build --packages-select base_interfaces_demo source install/setup.bash3.4 接口校验测试编译完成后执行如下命令查看接口定义是否生效ros2 interface show base_interfaces_demo/srv/AddInts终端输出内容与AddInts.srv完全一致则自定义接口编译成功。四、创建 C 服务功能包进入工作空间src目录执行命令创建 C 功能包ros2 pkg create cpp02_service --build-type ament_cmake --dependencies rclcpp base_interfaces_demo参数解析cpp02_service功能包名称--build-type ament_cmake指定编译框架为 C 使用的 ament_cmakerclcppROS2 C 客户端库提供节点、服务、日志、自旋等基础 APIbase_interfaces_demo依赖自定义服务接口包。五、C 服务端代码实现文件路径cpp02_service/src/demo01_server.cpp重点原理剖析create_service消息类型(服务名, 回调)服务名称为字符串常量属于通信匹配标识客户端服务名字符串必须完全一致否则无法建立连接回调函数参数req为只读请求数据指针读取客户端上传参数res为响应指针开发者填充数据后ROS2 底层自动发送给客户端rclcpp::spin()自旋机制 ROS2 节点所有消息、服务事件依靠自旋循环处理若无 spin节点无法感知客户端请求回调函数永远不会触发。六、C 客户端代码实现文件路径cpp02_service/src/demo02_client.cpp重点原理剖析wait_for_service()持续探测对应名称的服务是否存在解决客户端先行启动而服务端未启动导致通信失败问题async_send_request()异步非阻塞发送请求返回 Future 异步结果对象spin_until_future_complete()阻塞节点直至服务端返回响应防止提前读取空结果。七、配置 CMakeLists.txt打开cpp02_service/CMakeLists.txt在文件末尾追加编译与安装规则这是极易遗漏的扣分点原理ament 编译系统不会自动编译 cpp 源码必须手动声明可执行文件、依赖库以及安装路径缺少 install 指令时ros2 run无法检索到节点程序。八、编译与运行测试8.1 编译功能包colcon build --packages-select cpp02_service8.2 终端 1启动服务端8.3 终端 2启动客户端服务端新增日志运行结果和课程截图完全一致功能验证通过。九、重难点拓展拉高分数核心板块9.1 话题通信与服务通信对比总结对比项话题通信服务通信交互模式单向发布订阅无应答双向一问一答同步应答数据特征连续周期性数据流单次按需交互启动顺序发布订阅无强制先后必须先启动服务端消息文件.msg.srv区分请求 / 响应典型场景传感器数据传输指令控制、数值运算、状态查询9.2 常见问题与故障排查ros2 run 提示找不到可执行文件原因CMakeLists 未添加编译安装代码未执行colcon build新开终端没有source install/setup.bash。头文件找不到 add_ints.hpp原因接口包base_interfaces_demo没有编译功能包缺少对应依赖。客户端长时间无法连接服务端原因客户端、服务端填写的服务名字符串不一致大小写、字符必须完全相同。客户端参数缺失直接退出运行指令格式错误必须传递两个整数参数。十、实验总结本次实验完整实现 ROS2 服务通信 C/S 架构完成从自定义.srv接口、功能包搭建、服务端与客户端编码、编译部署到功能验证整套工程流程。掌握.srv服务接口的语法规则、编译配置与校验方式理解服务通信一问一答交互模型能够区分服务通信与话题通信适用场景掌握 C 服务端创建服务、回调处理请求的标准开发模板掌握 C 客户端连接服务、异步发送请求、接收响应的实现方式熟悉 ROS2 ament 编译体系能够独立编写 CMakeLists.txt 配置并且自主排查编译、节点通信相关故障。服务通信是机器人指令交互不可或缺的通信手段本次两数求和案例的代码框架具备通用性稍加修改即可应用于电机控制、传感器参数读取、任务指令下发等真实机器人工程项目。