ROS 接口定义:自定义 msg / srv / action(五)
ROS 接口定义:自定义 msg / srv / action(五)
通用基础优先 · 第五篇|ROS 通识系列|Docker 实战
一图读懂本文:三类接口文件 → 字段类型与嵌套 → 生成机制 → 版本兼容 → 数采 canonical 接口。
前面几篇用的都是 ROS 内置接口(String、JointState…)。但做数采平台,我们要让不同本体"说同一种话",就必须自己定义接口。这一篇讲清楚.msg / .srv / .action怎么写、怎么生成、以及版本兼容的坑。
一、接口文件:声明"数据的长相"
接口就三类,对应三种通信:
| 文件 | 通信 | 结构 | 例子 |
|---|---|---|---|
.msg | Topic | 一行一个字段 | 抓取状态:夹爪开度 + 是否到位 |
.srv | Service | 请求---响应 | 设置力矩阈值 |
.action | Action | goal---result---feedback | 执行一段示教 |
新手视角 · 写接口就是"设计一张表格":动笔前先回答三个问题——①这张表格谁来填、谁来看(发布者/订阅者);②每个格子是什么、什么单位、什么坐标系;③未来会加格子吗(预留兼容空间)。表格设计好了,机器人之间才不会"各说各话";表格设计烂了,后面每个用这张表的人都要来还债。
二、字段类型:基础类型 + 嵌套复用
ROS 接口支持基础类型(int32 / float64 / bool / string / time / duration等)和数组(int32[])、定长数组(float64[6]),还能嵌套其他消息。
# 自定义一个夹爪状态消息:my_robot_interfaces/msg/GripperState.msg float64 opening # 夹爪开度 0~1 bool grasped # 是否抓稳 geometry_msgs/Pose pose # 直接复用标准位姿消息# 自定义一个"执行示教"动作:my_robot_interfaces/action/PlayTrajectory.action string trajectory_id # 目标:哪条轨迹 --- bool success # 结果:成败 float64 elapsed_sec # 结果:耗时 --- float32 progress # 反馈:0~1 进度三、放进包里并生成(Docker 实战)
接口必须放在一个 ROS 包里,并在构建时由rosidl生成对应代码(Python/C++)。最简流程:
# 1) 建一个接口专用包(容器内,已 source) mkdir -p ~/ws/src/my_robot_interfaces && cd ~/ws/src/my_robot_interfacesrosidl_generate_interfaces(${PROJECT_NAME}
“msg/GripperState.msg”
“action/PlayTrajectory.action”)
ros2 interface show my_robot_interfaces/msg/GripperState
ros2 interface show my_robot_interfaces/action/PlayTrajectory
提示:容器里完整走 colcon 构建比较重,本篇重点是"接口怎么定义"。可以先只记文件写法,等第 08 篇(包与构建)再动手编译。先会用
ros2 interface show看别人定义好的接口,也是基本功。老手温故 · 生成机制与零拷贝:
rosidl在编译期把 .msg/.srv/.action 生成目标语言的类型代码(C++/Python),所以接口变更必须重编译依赖它的包。ROS 2 还支持进程内零拷贝(intra-process):两个节点放在同一进程(组件容器)时,大消息如图像可共享内存传递,跳过序列化——这是第 09 篇"组合节点"在机载设备上省 CPU 的底层原因。接口演进建议走语义化版本:加字段=兼容(次版本+1);改类型/改语义=破坏性(主版本+1,旧接口保留过渡期)。四、版本兼容:接口是"契约",改了要小心
接口一旦被别的节点依赖,就是不可随意破坏的契约:
- 加字段:通常安全(老节点忽略新字段);
- 删/改字段类型或顺序:破坏性变更,必须升接口版本或新建接口名;
- 数采平台里,统一动作空间的第一步就是各本体对齐同一套
.msg字段定义(参考 RDT 的 128 维统一动作布局思路)。
老手温故 · 契约里最值钱的三行注释(来自项目实战):①单位——本项目核验过某本体文档"两页分别写 degree 与 radian"的自相矛盾,字段旁必须写死单位;②坐标系——position 是相对谁的(基座还是相机)?;③方向约定——夹爪 0 是"张开"还是"闭合"?这三行没写清,adapter 层迟早要还债,而且往往是在真机联调时才爆出来。
五、接回数采平台
跨品牌适配的本质,是定义一套平台中立的 canonical 接口(如统一的RobotState.msg:关节角/力矩/末端位姿),再让 KUAVO、其他本体的驱动把自家数据映射(retargeting)进这套接口。接口定义权,就是数据主权。
六、小结与下篇
- 三接口文件对应三通信:
.msg→Topic、.srv→Service、.action→Action; - 字段支持基础类型、数组、定长数组,并可嵌套标准消息;
- 接口由
rosidl生成代码,放包里构建; - 接口即契约,破坏性变更要升版本;
- 下一篇:参数与配置——把频率、标定系数等"配置项"从代码里外置出来。
参考资料:ROS 2 官方 Tutorials(Creating custom msg and srv / action);接口规范 docs.ros.org/en/jazzy/Concepts/About-Interfaces。示例包名 my_robot_interfaces 为示意。