在 ROS 2 系统中,pluginlib 是一个支持运行时动态加载 C++ 插件的框架,广泛用于控制器、导航模块、传感器驱动等模块化场景。相比传统的静态类继承方式,pluginlib 允许开发者在不修改主程序的前提下,通过字符串指定并加载不同的功能模块,实现高度解耦与可扩展设计。
本篇文档系统地梳理了 ROS 2 插件开发的完整流程,包括:
.so 共享库;最终目标是实现这样一种能力:
在运行时仅通过字符串名称,即可加载并调用任意插件类,无需修改或重新编译主程序。
本流程结合实际 CMake 与 pluginlib 的接口调用,详细解释了插件的“构建 → 导出 → 注册 → 加载 → 调用”全周期流程。
ROS 2 中的 pluginlib 提供了运行时插件加载机制,广泛应用于控制器、导航、硬件驱动等场景。整个插件的开发流程包括以下六个步骤:
class MotionController {
public:
virtual void start() = 0;
virtual void stop() = 0;
virtual ~MotionController() {}
};
override 明确重写。class SpinMotionController : public MotionController {
public:
void start() override;
void stop() override;
};
.cppvoid SpinMotionController::start() {
std::cout << "SpinMotionController::start" << std::endl;
}
void SpinMotionController::stop() {
std::cout << "SpinMotionController::stop" << std::endl;
}
PLUGINLIB_EXPORT_CLASS 宏注册类,便于 pluginlib 在运行时创建其实例。#include
PLUGINLIB_EXPORT_CLASS(motion_control_system::SpinMotionController, motion_control_system::MotionController)
<library path="spin_motion_controller">
<class
name="motion_control_system/SpinMotionController"
type="motion_control_system::SpinMotionController"
base_class_type="motion_control_system::MotionController">
<description>Spin Motion Controllerdescription>
class>
library>
path: 动态库文件名,不含lib前缀和.so后缀,即对应libspin_motion_controller.so库,这个库的创建设置在CMakeLists中有描述,后面会提到。
name: 插件的唯一标识符,用于加载时传入。
type: 实际 C++ 实现类名。
base_class_type: 必须与ClassLoader的基类一致。
pluginlib::ClassLoader<motion_control_system::MotionController> loader("motion_control_system", "motion_control_system::MotionController");
auto controller = loader.createSharedInstance("motion_control_system/SpinMotionController");
controller->start();
controller->stop();
在 CMakeLists.txt 中配置如下:
find_package(pluginlib REQUIRED)
# 创建动态库目标
add_library(spin_motion_controller SHARED src/spin_motion_controller.cpp)
# 指定依赖项,自动添加头文件路径和链接信息
ament_target_dependencies(spin_motion_controller pluginlib)
# 安装插件库(仅 .so 有效)
install(TARGETS spin_motion_controller
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
)
# 安装插件描述文件(用于 pluginlib 运行时查找)
pluginlib_export_plugin_description_file(
motion_control_system spin_motion_plugins.xml
)
加载器通过包名 motion_control_system 找到安装路径:
install/share/motion_control_system/spin_motion_plugins.xml
解析 XML:
找到 name 对应的类;
映射到 .so 动态库路径;
使用 dlopen 动态加载 .so 文件;
使用 dlsym 获取构造函数;
创建类实例并调用接口。
| 项目 | 含义 |
|---|---|
.so |
共享库,支持运行时加载(pluginlib 的必要前提) |
pluginlib_export_plugin_description_file(...) |
安装 XML 到 share/包名/,供运行时读取 |
ament_target_dependencies(...) |
为目标添加头文件路径、链接库、编译选项 |
createSharedInstance() |
基于插件唯一标识符(字符串)动态构造类实例 |
ClassLoader |
插件加载核心类,内部使用 dlopen + dlsym |
# 编译
colcon build --packages-select motion_control_system
source install/setup.bash
# 运行
./install/motion_control_system/lib/motion_control_system/test_plugin motion_control_system/SpinMotionController
motion_control_system/
├── CMakeLists.txt
├── package.xml
├── spin_motion_plugins.xml
├── include/
│ └── motion_control_system/
│ ├── motion_control_interface.hpp
│ └── spin_motion_controller.hpp
└── src/
├── spin_motion_controller.cpp
└── test_plugin.cpp
插件加载流程图:
ClassLoader→ 查找包路径 → 读取 XML → 找到插件类 →dlopen(.so)→dlsym获取构造函数 → 创建对象
ROS2机器人开发:从入门到实践 (桑欣)
Chatgpt
Claude