1.pluginlib是一个C ++库,用于从ROS包中加载和卸载插件。 插件(plug)是可从runtime library下载的类(例如共享对象,动态链接库)。 通过使用pluginlib,永不不必将其应用程序显式链接到包含类的库 ,pluginlib可以在任何时候打开包含导出类的库,而无需应用程序事先了解库或包含类定义的头文件。 插件可用于扩展/修改应用程序行为,而无需应用程序源代码。
2.插件的工作原理
假如一个polygon_interface_package里面包含有一个polygon base class,而且此时系统支持两种polygons,rectangle 类存储在rectangle_plugin package中,triangle 存储在triangle_plugin package中,此时这两个polygons package的.xml文件中会包含一些代码行,他们告诉系统他们打算为polygon_interface_package里面的polygon类提供自己的插件,这些代码实际上将会在ROS 的 build/packaging system中进行自己类的注册,这意味着我们可以通过rospack查询来看到系统中所有可以获得的polygon类。
3.提供一个插件
3.1 使该插件能注册并输出
为了能使类能够动态地下载下来,通过使用特殊宏PLUGINLIB_EXPORT_CLASS将它标记为exported class.该宏可以放在组成插件库的任何.cpp文件中,通常放在文件的末尾。例如我们可以创建一个class_list.cpp文件在example_pkg下面,并把它编译进librectangle library中。
#include <pluginlib/class_list_macros.h>
#include <polygon_interface_package/polygon.h>
#include <rectangle_package/rectangle.h>
//Declare the Rectangle as a Polygon class
PLUGINLIB_EXPORT_CLASS(rectangle_namespace::Rectangle, polygon_namespace::Polygon)
3.2插件package 的.xml文件
.xml文件以机器可读格式存储有关插件的所有信息,例如下面的文件:
<library path="lib/librectangle"> //lplugin所处的library的路径
<class name="FirstPlugin" //在使用pluginlib tool的时候,这将作为class的查找名,作为plugin的标识符。
class type="rectangle_namespace::Rectangle"//插件的类型
base_class_type="polygon_namespace::Polygon">
<description>
This is a rectangle plugin
</description>
</class>
</library>
3.3在ROS系统中注册plugin
为了让pluginlib能够查询到所有ROS package中的plugin,每个package都必须指出他所输出的plugin,以及哪些package library包含这些plugin,提供plugin的文件应该在.xml文件的export标签下面指出所提供的plugin.如下所示:
<export>
<polygon_interface_package plugin="${prefix}/rectangle_plugin.xml" />
</export>
注意,为了能使export命令工作,提供插件的package必须要建立在依赖(包含有插件接口)的package上面,如下所示:
<build_depend>polygon_interface_package</build_depend>
<run_depend>polygon_interface_package</run_depend>
通过以下命令可以查询任意一个package中可以获得的插件有哪些,naz_core是package的名称
rospack plugins --attrib=plugin nav_core
- 使用一个插件
为了更快地使用插件提供的类,我们使用ClassLoader类,它可以通过包含头文件class_loader.h来使用,代码如下所示:
#include <pluginlib/class_loader.h>
#include <polygon_interface_package/polygon.h>
//... some code ...
pluginlib::ClassLoader<polygon_namespace::Polygon> poly_loader("polygon_interface_package", "polygon_namespace::Polygon");
try
{
boost::shared_ptr<polygon_namespace::Polygon> poly = poly_loader.createInstance("rectangle_namespace::Rectangle");
//... use the polygon, boost::shared_ptr will automatically delete memory when it goes out of scope
}
catch(pluginlib::PluginlibException& ex)
{
//handle the class failing to load
ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
}
在使用插件时,ClassLoader不得超出范围。 因此,如果要在类中加载插件对象,请确保类加载器是该类的成员变量。