# 7. 插件 Plugin
Plugin 按 **类名** 从动态库或进程内注册表实例化派生类型。对标 ROS `pluginlib`。
| 本文 §7 | 相关文档 |
|---------|----------|
| 可插拔算法 | [§0 指南](00_guide.md) · [§9 启动 Launch](09_launch.md) · [§10 组件 Component](10_component.md) |
与 [Component](10_component.md) 的区别:Component 由 DAG 加载;Plugin 由业务 `CreateInstance` 加载算法实现。
---
## 7.1 加载流程
外部插件
XML 描述文件 + class_loader 动态库
描述
plugin.xml
→
解析
PluginDescription
ParseFromDescriptionFile
加载
LoadPlugin
PluginManager
→
动态库
.so
class_loader 加载
进程内注册
主程序已静态链接,无需拆 .so
注册
RegisterInProcessClass
已链接 · 无需 .so
两路径汇合 · 按类名实例化
↓
实例化
CreateInstance
CreateInstance<Base>
(class_name)
| 路径 | 适用 |
| 外部插件 | XML 描述 + 动态库,规划器等可热插拔算法 |
| 进程内注册 | 主程序已静态链接实现,无需拆 .so |
---
## 7.2 plugin.xml
XML 由 `PluginDescription::ParseFromDescriptionFile` 解析(`plugin_description.cpp`):
```xml
```
| 元素 | 含义 |
|------|------|
| `library@path` | 动态库路径(相对 `AUTOLINK_PLUGIN_LIB_PATH`) |
| `class@type` | 派生类名(`CreateInstance` 参数) |
| `class@base_class` | 基类 RTTI 名 |
环境变量见 [§1.6](01_architecture.md#16-环境与路径变量)(`AUTOLINK_PLUGIN_*`)。
---
## 7.3 CreateInstance
`PluginManager` 单例:加载描述文件或进程内注册后,按类名实例化派生类型。
```cpp
#include "autolink/plugin_manager/plugin_manager.hpp"
auto* pm = autolink::plugin_manager::PluginManager::Instance();
// 加载描述文件
pm->LoadPlugin("/path/to/planner_plugins.xml");
// 进程内注册(无需 XML)
pm->RegisterInProcessClass("NavfnPlanner");
// 按类名创建
auto planner = pm->CreateInstance("NavfnPlanner");
// 列举某基类的所有派生类名
auto names = pm->GetDerivedClassNameByBaseClass();
```
`RegisterInProcessClass` 适用于主程序已静态链接实现、不想拆 `.so` 的场景。
---
## 7.4 Autonomy 集成
`autonomy/planning/planner_server.cpp` 在启动时注册内置规划器并加载外部描述文件:
```cpp
void LoadExternalPlugins(const proto::PlannerOptions& options) {
auto* pm = PluginPm::Instance();
pm->RegisterInProcessClass("NavfnPlanner");
pm->RegisterInProcessClass("DijkstraPlanner");
pm->RegisterInProcessClass("ThetaStarPlanner");
for (const auto& path : options.planner_plugin_libraries()) {
if (!pm->LoadPlugin(path)) {
AWARN << "Failed to load plugin description: " << path;
}
}
pm->LoadInstalledPlugins();
}
common::GlobalPlanner::SharedPtr CreatePlannerInstance(const std::string& type, ...) {
const std::string resolved = ResolvePlannerClass(type);
if (resolved == "NavfnPlanner") {
return std::make_shared(...);
}
// 外部插件
auto instance = PluginPm::Instance()->CreateInstance(resolved);
return common::GlobalPlanner::SharedPtr(std::move(instance));
}
```
配置中通过 `planner_plugin_libraries` 传入 XML 路径列表。
---
## 7.5 Component 对比
| | Component | Plugin |
|---|-----------|--------|
| 注册 | `AUTOLINK_REGISTER_COMPONENT` | XML `` 或 `RegisterInProcessClass` |
| 加载触发 | DAG `class_name` | `LoadPlugin` / `CreateInstance` |
| 生命周期 | `Init` / `Proc` / `Shutdown` | 由业务持有 `shared_ptr` |
| 典型用途 | 通信驱动模块 | 算法策略替换 |
Component 的 `.so` 同样经 `class_loader` 加载;单元测试见 `autolink/autolink/class_loader/class_loader_test.cpp`(`libplugin1.so` / `libplugin2.so`)。
---
## 7.6 mainboard --plugin
```bash
mainboard -d foo.dag --plugin=/path/to/plugins.xml
```
`.launch` XML:
```xml
planning
...
path/to/planner_plugins.xml
```
`autolink_launch` 解析 `` 列表并传给 `mainboard`(`autolink/tools/autolink_launch/main.cpp`)。
---
**导航**:[← §6 参数 Parameter](06_parameter.md) · [§0 指南](00_guide.md) · [§8 日志 Log →](08_log.md)