ros2 跟着官方教学从零开始 自定义消息数据接口2

张开发
2026/4/5 14:02:09 15 分钟阅读

分享文章

ros2 跟着官方教学从零开始 自定义消息数据接口2
ros2 从零开始12 自定义消息数据2前言回顾上节内容我们介绍了自定义消息数据接口 (.msg和.srv)我们定义在专门的消息包tutorial_interfaces。有时候我们也会直接在业务包中定义消息结构。背景虽然最佳实践是在专用接口包中声明接口但有时声明、创建和使用一个接口包会更方便。实践1.创建一个包进入工作区的src目录用如下指令创建我们的包ros2 pkg create --build-type ament_cmake --license Apache-2.0 more_interfaces mkdir more_interfaces/msgmore_interfaces是我们的本次的接口包名。rootbc2bf85b2e4a:~/ros2_ws# cd ~/ros2_ws/src/ rootbc2bf85b2e4a:~/ros2_ws/src# ros2 pkg create --build-type ament_cmake --license Apache-2.0 more_interfaces going to create a new package package name: more_interfaces destination directory: /root/ros2_ws/src package format: 3 version: 0.0.0 description: TODO: Package description maintainer: [root **********] licenses: [Apache-2.0] build type: ament_cmake dependencies: [] creating folder ./more_interfaces creating ./more_interfaces/package.xml creating source and include folder creating folder ./more_interfaces/src creating folder ./more_interfaces/include/more_interfaces creating ./more_interfaces/CMakeLists.txt rootbc2bf85b2e4a:~/ros2_ws/src# mkdir more_interfaces/msg2. 创建消息结构2.1 创建订阅消息结构AddressBook.msg在msg目录新建文件AddressBook.msg并且内容添加如下uint8 PHONE_TYPE_HOME0 uint8 PHONE_TYPE_WORK1 uint8 PHONE_TYPE_MOBILE2 string first_name string last_name string phone_number uint8 phone_type消息由几部分构成first_name – 类型为字符串类似于中文的名last_name – 类型为字符串类似于中文的姓phone_number – 类型为字符串电话号码phone_type – 类型为无符号整形电话类型可以在类型定义时把默认值也设置上有关细节可以看官方接口一节2.2 修改package.xml在package.xml里面package元素里面添加如下内容buildtool_dependrosidl_default_generators/buildtool_depend exec_dependrosidl_default_runtime/exec_depend member_of_grouprosidl_interface_packages/member_of_group在编译时我们需要rosidl_default_generators而运行时需要rosidl_default_runtime。2.3 修改CMakeLists.txt在CMakeLists.txt中添加如下信息。find_package(rosidl_default_generators REQUIRED) set(msg_files msg/AddressBook.msg ) rosidl_generate_interfaces(${PROJECT_NAME} ${msg_files} ) ament_export_dependencies(rosidl_default_runtime)我们Sphere.msg依赖包geometry_msgs, 这里需要find_package来添加依赖 rosidl_default_generators 是ros2生成自定义消息的组件包而rosidl_generate_interfaces 把我们的自定义消息给传过去第一个参数必须是包名用${PROJECT_NAME}来代替。2.4 增加业务代码我们直接在more_interfaces/src里面增加文件publish_address_book.cpp文件其内容如下#include chrono #include memory #include rclcpp/rclcpp.hpp #include more_interfaces/msg/address_book.hpp using namespace std::chrono_literals; class AddressBookPublisher : public rclcpp::Node { public: AddressBookPublisher() : Node(address_book_publisher) { address_book_publisher_ this-create_publishermore_interfaces::msg::AddressBook(address_book, 10); auto publish_msg [this]() - void { auto message more_interfaces::msg::AddressBook(); message.first_name John; message.last_name Doe; message.phone_number 1234567890; message.phone_type message.PHONE_TYPE_MOBILE; std::cout Publishing Contact\nFirst: message.first_name Last: message.last_name std::endl; this-address_book_publisher_-publish(message); }; timer_ this-create_wall_timer(1s, publish_msg); } private: rclcpp::Publishermore_interfaces::msg::AddressBook::SharedPtr address_book_publisher_; rclcpp::TimerBase::SharedPtr timer_; }; int main(int argc, char * argv[]) { rclcpp::init(argc, argv); rclcpp::spin(std::make_sharedAddressBookPublisher()); rclcpp::shutdown(); return 0; }解析more_interfaces/msg/address_book.hpp是我们刚刚定义的消息的头文件虽然是在同一个包里面最佳实践也要把包名more_interfaces带上。more_interfaces::msg::AddressBook是我们刚刚定义的消息。程序定期1s发布地址信息。2.5 继续修改CMakeLists.txtpublish_address_book.cpp需要参与编译也把它加入CMakeLists.txt中。 如下find_package(rclcpp REQUIRED) rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} rosidl_typesupport_cpp) target_link_libraries(publish_address_book ${cpp_typesupport_target}) add_executable(publish_address_book src/publish_address_book.cpp) ament_target_dependencies(publish_address_book rclcpp) install(TARGETS publish_address_book DESTINATION lib/${PROJECT_NAME})这里有点变化由于消息和业务定义在同一个包。我们需要rosidl_get_typesupport_target命令。完整的CMakeLists.txt如下cmake_minimum_required(VERSION 3.8) project(more_interfaces) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES Clang) add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) # uncomment the following section in order to fill in # further dependencies manually. # find_package(dependency REQUIRED) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) # the following line skips the linter which checks for copyrights # comment the line when a copyright and license is added to all source files set(ament_cmake_copyright_FOUND TRUE) # the following line skips cpplint (only works in a git repo) # comment the line when this package is in a git repo and when # a copyright and license is added to all source files set(ament_cmake_cpplint_FOUND TRUE) ament_lint_auto_find_test_dependencies() endif() find_package(rosidl_default_generators REQUIRED) set(msg_files msg/AddressBook.msg ) rosidl_generate_interfaces(${PROJECT_NAME} ${msg_files} ) ament_export_dependencies(rosidl_default_runtime) find_package(rclcpp REQUIRED) add_executable(publish_address_book src/publish_address_book.cpp) ament_target_dependencies(publish_address_book rclcpp) rosidl_get_typesupport_target(cpp_typesupport_target ${PROJECT_NAME} rosidl_typesupport_cpp) target_link_libraries(publish_address_book ${cpp_typesupport_target}) install(TARGETS publish_address_book DESTINATION lib/${PROJECT_NAME}) ament_package()3. 开始编译进入工作区用colcon build等待编译完成。rootbc2bf85b2e4a:~/ros2_ws# colcon build --packages-up-to more_interfaces Starting more_interfaces Finished more_interfaces [1.12s] Summary: 1 package finished [1.28s]4. 运行查看编译完成后我们需要安装后才能运行使用source install/setup.sh打开一个终端输入如下命令ros2 run more_interfaces publish_address_book运行节点, 如下rootbc2bf85b2e4a:~/ros2_ws# source install/setup.sh rootbc2bf85b2e4a:~/ros2_ws# ros2 run more_interfaces publish_address_book另外打开一个窗口这次我们用命令行查看topic内容source install/setup.bash ros2 topic echo /address_book输出如下rootbc2bf85b2e4a:~/ros2_ws# source install/setup.bash rootbc2bf85b2e4a:~/ros2_ws# ros2 topic echo /address_book first_name: John last_name: Doe phone_number: 1234567890 phone_type: 2 --- first_name: John last_name: Doe phone_number: 1234567890 phone_type: 2 --- first_name: John last_name: Doe phone_number: 1234567890 phone_type: 2 ---可以看到消息发送成功了。我们这里没有创建订阅者但你可以尝试自己写一个来练习。总结在这个教程中你尝试了不同的字段类型来定义接口然后在同一包里构建了一个接口。接下来你要创建一个简单的ROS 2包带有自定义参数你会从启动文件中学习如何设置。

更多文章