Files
ROS2_learn/src/cpp_custom_interface/README.md
T

6.1 KiB

cpp_custom_interface — C++ 自定义接口(.msg / .srv / .action)

学会自定义 ROS2 接口,跨包/跨语言共享数据结构。

预计学习时间:2-3 小时。


这是什么?

ROS2 自带的消息类型(std_msgs/Stringgeometry_msgs/Twist...)够用吗?不够。

做项目一定要自定义接口,比如:

  • 机器人: /robot_status.msg (含电量、位置、状态)
  • 机械臂: /MoveArm.action (含目标位姿 + 反馈进度 + 结果)
  • 相机: /CameraCalibration.srv (含内外参矩阵)

本包演示:

  • .msg (消息,Topic 用): SensorReading(传感器读数)
  • .srv (服务): GetCalibration(获取标定数据)
  • .action (动作): MoveArm(机械臂运动)

🎯 学完之后你能做什么?

  1. 定义 .msg / .srv / .action 文件
  2. rosidl_generate_interfaces 生成 C++ / Python 代码
  3. 在自己的包里 include 生成的 C++ 头文件
  4. 跨包/跨语言用自定义类型通信

📁 文件结构

src/cpp_custom_interface/
├── msg/SensorReading.msg               # 消息定义
├── srv/GetCalibration.srv              # 服务定义
├── action/MoveArm.action               # 动作定义
├── include/cpp_custom_interface/       # 生成的头文件会被装到这里
├── src/
│   ├── sensor_publisher.cpp/hpp        # 发布自定义 msg 的 Publisher
│   ├── calibration_server.cpp/hpp      # 自定义 srv 的 Server
│   └── move_arm_server.cpp/hpp         # 自定义 action 的 Server
├── test/test_custom_interfaces.cpp     # 测试生成的接口
├── CMakeLists.txt                      # ⭐ 关键:rosidl_generate_interfaces
└── package.xml

📖 接口定义文件格式

.msg(SensorReading.msg)

std_msgs/Header header    # 用其他包的消息类型
string sensor_id
string unit
float64 value

类型:stringint32float64bool、嵌套其他 msg/...

.srv(GetCalibration.srv)

string sensor_id          # 请求字段
---
float64[9] intrinsic_matrix  # 响应字段
float64[3] bias
string calibration_date
bool valid

--- 上是请求,下面是响应。

.action(MoveArm.action)

# Goal
float64 max_velocity_scaling
---
# Result
bool success
string error_message
float64 total_time_sec
---
# Feedback
float32 progress
string current_state

三段分别是 Goal / Result / Feedback


🚀 跑起来

启动自定义 Publisher

source /opt/ros/humble/setup.bash
source /root/ros2_ws/install/setup.bash

ros2 run cpp_custom_interface sensor_publisher_cpp

预期输出:

[INFO] [sensor_publisher]: SensorPublisher started: topic="/sensor_reading"

订阅看消息(另开终端)

ros2 topic echo /sensor_reading --once

预期输出:

header:
  stamp:
    sec: ...
    nanosec: ...
  frame_id: imu_frame
sensor_id: imu_0
unit: rad/s
value: 0.0

启动标定服务(另开终端)

ros2 run cpp_custom_interface calibration_server_cpp
# 调用服务
ros2 service call /get_calibration cpp_custom_interface/srv/GetCalibration "{sensor_id: 'lidar_front'}"

启动机械臂 Action(另开终端)

ros2 run cpp_custom_interface move_arm_server_cpp
# 发 goal
ros2 action send_goal --feedback /move_arm cpp_custom_interface/action/MoveArm "{max_velocity_scaling: 0.5}"

📖 CMakeLists.txt 关键配置

# 1) 定义接口文件
set(MSG_FILES "msg/SensorReading.msg")
set(SRV_FILES "srv/GetCalibration.srv")
set(ACTION_FILES "action/MoveArm.action")

# 2) 生成 C++ + Python 代码(关键!)
rosidl_generate_interfaces(${PROJECT_NAME}
  ${MSG_FILES} ${SRV_FILES} ${ACTION_FILES}
  DEPENDENCIES std_msgs geometry_msgs
)

# 3) 链接生成的 typesupport 库
rosidl_get_typesupport_target(cpp_typesupport
  ${PROJECT_NAME} "rosidl_typesupport_cpp")
target_link_libraries(${LIBRARY_NAME} ${cpp_typesupport})

# 4) 包必须 <member_of_group>rosidl_interface_packages</member_of_group>

package.xml 必须加:

<member_of_group>rosidl_interface_packages</member_of_group>
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>

📖 在自己的代码里使用生成的接口

C++

#include "cpp_custom_interface/msg/sensor_reading.hpp"
#include "cpp_custom_interface/srv/get_calibration.hpp"
#include "cpp_custom_interface/action/move_arm.hpp"

// 使用消息类型
auto msg = cpp_custom_interface::msg::SensorReading();
msg.sensor_id = "imu_0";
msg.value = 1.23;

// Publisher
auto pub = create_publisher<cpp_custom_interface::msg::SensorReading>("topic", 10);

Python

from cpp_custom_interface.msg import SensorReading
from cpp_custom_interface.srv import GetCalibration
from cpp_custom_interface.action import MoveArm

msg = SensorReading()
msg.sensor_id = 'imu_0'

注意:Python 包名是 cpp_custom_interface.msg 而不是 cpp_custom_interface/msg


🧪 跑测试

colcon test --packages-select cpp_custom_interface
colcon test-result --all --verbose

预期:cpp_custom_interface: gtest 3/3 ✓ 全部通过。


🔧 自己定义接口

  1. msg/srv/action/ 下新建 .msg/.srv/.action 文件
  2. CMakeLists.txtMSG_FILES/SRV_FILES/ACTION_FILES 列表
  3. colcon build
  4. 生成的代码在 install/cpp_custom_interface/include/(C++)或 install/cpp_custom_interface/lib/python3.10/site-packages/(Python)

📚 深入学习


⏭️ 下一个包

继续学 py_vision_demo — 图像话题(cv_bridge + OpenCV)。


📍 学习路径导航

⏮ 上一个 🏠 当前位置 ⏭ 下一个
py_params — Python Parameter cpp_custom_interface — C++ 自定义接口 py_vision_demo — Python 图像

📍 完整 12 包学习顺序见 主 README