# cpp_custom_interface — C++ 自定义接口(.msg / .srv / .action) > 学会自定义 ROS2 接口,跨包/跨语言共享数据结构。 > > 预计学习时间:2-3 小时。 --- ## 这是什么? ROS2 自带的消息类型(`std_msgs/String`、`geometry_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 ``` 类型:`string`、`int32`、`float64`、`bool`、嵌套其他 `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 ```bash 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" ``` ### 订阅看消息(另开终端) ```bash ros2 topic echo /sensor_reading --once ``` **预期输出**: ``` header: stamp: sec: ... nanosec: ... frame_id: imu_frame sensor_id: imu_0 unit: rad/s value: 0.0 ``` ### 启动标定服务(另开终端) ```bash ros2 run cpp_custom_interface calibration_server_cpp ``` ```bash # 调用服务 ros2 service call /get_calibration cpp_custom_interface/srv/GetCalibration "{sensor_id: 'lidar_front'}" ``` ### 启动机械臂 Action(另开终端) ```bash ros2 run cpp_custom_interface move_arm_server_cpp ``` ```bash # 发 goal ros2 action send_goal --feedback /move_arm cpp_custom_interface/action/MoveArm "{max_velocity_scaling: 0.5}" ``` --- ## 📖 CMakeLists.txt 关键配置 ```cmake # 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) 包必须 rosidl_interface_packages ``` **package.xml 必须加**: ```xml rosidl_interface_packages rosidl_default_generators rosidl_default_runtime ``` --- ## 📖 在自己的代码里使用生成的接口 ### C++ ```cpp #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("topic", 10); ``` ### Python ```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`。 --- ## 🧪 跑测试 ```bash 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.txt` 的 `MSG_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) --- ## 📚 深入学习 - [doc/16-custom-interfaces.md](../../doc/16-custom-interfaces.md) — 自定义接口深度(嵌套 / 数组 / 常量) --- ## ⏭️ 下一个包 继续学 **[py_vision_demo](../py_vision_demo/README.md)** — 图像话题(cv_bridge + OpenCV)。 --- ## 📍 学习路径导航 | ⏮ 上一个 | 🏠 当前位置 | ⏭ 下一个 | |---|---|---| | [py_params — Python Parameter](../py_params/README.md) | **cpp_custom_interface — C++ 自定义接口** | [py_vision_demo — Python 图像](../py_vision_demo/README.md) | 📍 完整 12 包学习顺序见 [主 README](../../README.md#-12-包推荐学习顺序)