Keil工程配置失误导致头文件缺失:操作指南快速修复
2026/1/11 5:51:13
以下是一个完整的ROS2 节点动态组合(Composable Nodes)开发案例,涵盖编译时组合和运行时组合两种方式,并包含参数传递和命名空间重映射等高级功能。
component_container动态加载)。mkdir-p ~/ros2_ws/srccd~/ros2_ws/src ros2 pkg create composition_demo --build-type ament_cmake --dependencies rclcpp rclcpp_componentstalker_component.cpp)#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"std_msgs/msg/string.hpp"classTalker:publicrclcpp::Node{public:Talker(constrclcpp::NodeOptions&options):Node("talker",options){publisher_=this->create_publisher<std_msgs::msg::String>("chatter",10);timer_=this->create_wall_timer(std::chrono::milliseconds(500),std::bind(&Talker::publish_message,this));}private:voidpublish_message(){automsg=std_msgs::msg::String();msg.data="Hello, ROS2 Composition!";publisher_->publish(msg);RCLCPP_INFO(this->get_logger(),"Published: '%s'",msg.data.c_str());}rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;rclcpp::TimerBase::SharedPtr timer_;};RCLCPP_COMPONENTS_REGISTER_NODE(Talker)// 注册为组件listener_component.cpp)#include"rclcpp/rclcpp.hpp"#include"rclcpp_components/register_node_macro.hpp"#include"std_msgs/msg/string.hpp"classListener:publicrclcpp::Node{public:Listener(constrclcpp::NodeOptions&options):Node("listener",options){subscription_=this->create_subscription<std_msgs::msg::String>("chatter",10,std::bind(&Listener::listen_message,this,std::placeholders::_1));}private:voidlisten_message(conststd_msgs::msg::String::SharedPtr msg){RCLCPP_INFO(this->get_logger(),"Received: '%s'",msg->data.c_str());}rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;};RCLCPP_COMPONENTS_REGISTER_NODE(Listener)// 注册为组件manual_composition.cpp#include"rclcpp/rclcpp.hpp"#include"talker_component.hpp"#include"listener_component.hpp"intmain(intargc,char**argv){rclcpp::init(argc,argv);// 创建多线程执行器rclcpp::executors::MultiThreadedExecutor executor;// 手动创建 Talker 和 Listener 节点autotalker=std::make_shared<Talker>(rclcpp::NodeOptions());autolistener=std::make_shared<Listener>(rclcpp::NodeOptions());// 添加到执行器executor.add_node(talker);executor.add_node(listener);// 运行执行器executor.spin();rclcpp::shutdown();return0;}CMakeLists.txtcmake_minimum_required(VERSION 3.8) project(composition_demo) find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(rclcpp_components REQUIRED) find_package(std_msgs REQUIRED) # 组件库 add_library(talker_component SHARED src/talker_component.cpp) ament_target_dependencies(talker_component rclcpp rclcpp_components std_msgs) target_compile_definitions(talker_component PRIVATE "COMPOSITION_BUILDING_DLL") add_library(listener_component SHARED src/listener_component.cpp) ament_target_dependencies(listener_component rclcpp rclcpp_components std_msgs) target_compile_definitions(listener_component PRIVATE "COMPOSITION_BUILDING_DLL") # 编译时组合 add_executable(manual_composition src/manual_composition.cpp) ament_target_dependencies(manual_composition rclcpp rclcpp_components std_msgs) target_link_libraries(manual_composition talker_component listener_component) # 安装 install(TARGETS talker_component listener_component manual_composition DESTINATION lib/${PROJECT_NAME} ) ament_package()cd~/ros2_ws colcon build --packages-select composition_demosourceinstall/setup.bash ros2 run composition_demo manual_composition输出:
[INFO] [talker]: Published: 'Hello, ROS2 Composition!' [INFO] [listener]: Received: 'Hello, ROS2 Composition!'component_containerros2 run rclcpp_components component_container# 加载 Talkerros2 component load /ComponentManager composition_demo composition_demo::Talker# 加载 Listenerros2 component load /ComponentManager composition_demo composition_demo::Listener输出:
[INFO] [talker]: Published: 'Hello, ROS2 Composition!' [INFO] [listener]: Received: 'Hello, ROS2 Composition!'ros2 component list输出:
/ComponentManager 1 /talker 2 /listenerros2 component unload /ComponentManager12输出:
Unloaded component 1 from '/ComponentManager' container Unloaded component 2 from '/ComponentManager' containerros2 component load /ComponentManager composition_demo composition_demo::Talker -p use_sim_time:=trueros2 component load /ComponentManager composition_demo composition_demo::Listener --node-namespace /my_nsdlopen动态加载ros2 run composition_demo dlopen_composition\$(ros2 pkg prefix composition_demo)/lib/libtalker_component.so\$(ros2 pkg prefix composition_demo)/lib/liblistener_component.so| 方式 | 特点 | 适用场景 |
|---|---|---|
| 编译时组合 | 硬编码,所有节点在同一个进程 | 固定节点组合,高性能 |
| 运行时组合 | 动态加载,灵活管理 | 需要动态调整节点 |
dlopen组合 | 直接加载.so文件 | 无 ROS 接口依赖 |
| Launch 文件组合 | 自动化启动 | 复杂系统部署 |
完整代码:GitHub - ROS2 Composition Demo
通过这个案例,你可以: