ROS2 Humble 笔记(七)标准与自定义 Interface 接口
这篇博客是 B 站《古月·ROS2入门21讲》的第十个视频的图文记录,主要介绍了如何自定义 srv 与 msg 接口并将其编译成不同语言可以使用的对象。原始视频链接如下:
- B 站视频链接:10. 通信接口:数据传递的标准结构
1. ROS 自带的标准数据接口
你可以前往 /opt/ros/humble/share 目录下查看 ROS 自带的标准数据接口有哪些:

这里以最常用的 /opt/ros/humble/share/sensor_msgs/msg 为例,进入该文件夹可以看到以下内容:

打开其中的 Image.msg 即可看到官分如何定义标准数据接口,当我们在写自定义接口的时候可以将其作为参考,特别是明确注释的撰写,因为 接口是为了方便沟通 而设计的,如果你的接口只有你自己看的懂,那这个接口将失去作用。

2. ros2 interface 命令
2.1 list
可以通过下面的命令查看 ROS 自带的接口有哪些:
$ ros2 interface list

2.2 show
如果想要查看某个接口的详细信息可以使用 show 命令:
$ ros2 interface show sensor_msgs/msg/PointCloud2

2.3 package
如果想查看某个功能包中定义了哪些接口,可以使用下面的命令:
$ ros2 interface package sensor_msgs

该命令在自己的工作空间中也是生效的,但一定要注意 source 操作,否则无法找到环境变量:
$ cd dev_ws
$ source install/local_setup.sh
$ ros2 interface package learning_interface

3. 自定义 srv 接口
在上一篇博客 《ROS2 Humble 笔记(六)Service 服务 Server & Client 交互》 中提了一句有关自定义服务接口的内容,在此处将详细介绍一下如何定义并实现。
3.1 srv 文件内容
在 learning_interface 功能包中有一个 srv 文件夹,具体位置为 src/ros2_21_tutorials/learning_interface/srv 处,该文件夹下有两个文件:
AddTwoInts.srv:
int64 a # 第一个加数
int64 b # 第二个加数
---
int64 sum # 求和结果
GetObjectPosition.srv:
bool get # 获取目标位置的指令
---
int32 x # 目标的X坐标
int32 y # 目标的Y坐标
自定义服务文件的编写格式如下,请求和响应中间用 三个 - 分割,并且 请求部分是非必须的:
# Request
DataType req_variable_name # 请求中的变量信息
---
# Response
DataType res_variable_name # 相应中的变量信息
3.2 编译 srv 文件
在同级目录下有一个 CMakeLists.txt 文件,具体位置为 src/ros2_21_tutorials/learning_interface/CMakeLists.txt,找到 25 行附近内容如下:
rosidl_generate_interfaces(${PROJECT_NAME}"msg/ObjectPosition.msg""srv/AddTwoInts.srv""srv/GetObjectPosition.srv""action/MoveCircle.action")

这段内容的意思将上面几个 srv、msg 文件编译成不同语言可以使用的通用接口。
3.3 使用自定义接口
打开 learning_services 功能包找到 service_object_server.py 文件,具体位置为 src/ros2_21_tutorials/learning_service/learning_service/service_object_server.py,可以看到在导入库的部分从 learning_interface 包中的 srv 模块直接导入 GetObjectPosition 对象:
import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
from sensor_msgs.msg import Image # 图像消息类型
import numpy as np # Python数值计算库
from cv_bridge import CvBridge # ROS与OpenCV图像转换类
import cv2 # Opencv图像处理库
from learning_interface.srv import GetObjectPosition # 自定义的服务接口

该 GetObjectPosition 对象的具体内容可以从 install/learning_interface/local/lib/python3.10/dist-packages/learning_interface/srv/_get_object_position.py 文件中查看,这个文件就是上面 CMakeLists.txt 文件编译生成的内容:
import builtins # noqa: E402, I100import rosidl_parser.definition # noqa: E402, I100class Metaclass_GetObjectPosition_Request(type):"""Metaclass of message 'GetObjectPosition_Request'."""_CREATE_ROS_MESSAGE = None_CONVERT_FROM_PY = None_CONVERT_TO_PY = None_DESTROY_ROS_MESSAGE = None_TYPE_SUPPORT = None...

如果你想看 C++ 生成的文件内容是什么样的话,可以查看 install/learning_interface/include/learning_interface/learning_interface/srv/get_object_position.h 文件:
// generated from rosidl_generator_c/resource/idl.h.em
// with input from learning_interface:srv/GetObjectPosition.idl
// generated code does not contain a copyright notice#ifndef LEARNING_INTERFACE__SRV__GET_OBJECT_POSITION_H_
#define LEARNING_INTERFACE__SRV__GET_OBJECT_POSITION_H_#include "learning_interface/srv/detail/get_object_position__struct.h"
#include "learning_interface/srv/detail/get_object_position__functions.h"
#include "learning_interface/srv/detail/get_object_position__type_support.h"#endif // LEARNING_INTERFACE__SRV__GET_OBJECT_POSITION_H_

4. 自定义 msg 接口
4.1 使用自定义接口
【Note】:由于我的设备没有相机,因此这里不进行演示,有条件的读者可以自行体验。
- 启动相机节点
usb_cam_node_exe:
$ ros2 run usb_cam usb_cam_node_exe
- 启动相机画面订阅节点
interface_object_pub,在处理后发布出来:
$ ros2 run learning_topic interface_object_pub
- 启动订阅节点
interface_object_sub:
$ ros2 run learning_topic interface_object_sub
4.2 msg 文件内容
这三个节点之间的交互是通过话题实现的,定义的接口的位置为 src/ros2_21_tutorials/learning_interface/msg/ObjectPosition.msg:
ObjectPosition.msg:
int32 x # 表示目标的X坐标
int32 y # 表示目标的Y坐标

4.3 编译 msg 文件
在 learning_interface 功能包下的 CMakeLists.txt 文件可以找到编译该 msg 文件的写法,具体位置在 src/ros2_21_tutorials/learning_interface/CMakeLists.txt:
rosidl_generate_interfaces(${PROJECT_NAME}"msg/ObjectPosition.msg""srv/AddTwoInts.srv""srv/GetObjectPosition.srv""action/MoveCircle.action")

4.4 节点内部使用
打开 interface_object_pub 节点可以看到在导入库的位置处将自定义的 msgs 对象导入,具体位置为 src/ros2_21_tutorials/learning_topic/learning_topic/interface_object_pub.py:
import rclpy # ROS2 Python接口库
from rclpy.node import Node # ROS2 节点类
from sensor_msgs.msg import Image # 图像消息类型
from cv_bridge import CvBridge # ROS与OpenCV图像转换类
import cv2 # Opencv图像处理库
import numpy as np # Python数值计算库
from learning_interface.msg import ObjectPosition # 自定义的目标位置消息

