New in Electric: pluginlib is now a separate stack. In previous releases, it was part of common.

Example

To understand how pluginlib works, let's consider a small example. First, suppose that a ROS package exists containing a polygon base class ("polygon_interface_package"). Let's also say that there are two different kinds of polygons supported in the system: a rectangle which lives in the "rectangle_plugin" package and a triangle that lives in the "triangle_plugin" package. The implementers of both the rectangle_plugin and triangle_plugin packages would include special export lines in their manifest.xml file telling the rosbuild system that they intend to provide plugins for the polygon class in the polygon_interface_package package. These export lines, in effect, register the classes with the rosbuild system. This means that someone wishing to see all polygon classes available in the system can run a simple rospack query which will return a list of available classes, in this case, rectangle and triangle.

pluginlib/plugin_model.png

Providing a Plugin

Adding a Plugin to the Plugin List

In order to allow a class to be dynamically loaded, it must be added to a class list for the relevant class type. This list can be defined in any .cpp file that is compiled in the library containing a class. To help with this process, pluginlib defines three macros in the class_list_macros.h file. For the example above, we might create a class_list.cpp file in package 'example_pkg' that looks as follows and compile it into the librectangle library:

   1 #include <pluginlib/class_list_macros.h>
   2 #include <polygon_interface_package/polygon.h>
   3 #include <rectangle_package/rectangle.h>
   4 
   5 //Declare the Rectangle as a Polygon class
   6 PLUGINLIB_DECLARE_CLASS(example_pkg, Rectangle, rectangle_namespace::Rectangle, polygon_namespace::Polygon)

The Plugin Description File

The plugin description file is an XML file that serves to store all the important information about a plugin in a machine readable format. It contains information about the library the plugin is in, the name of the plugin, the type of the plugin, etc. If we consider the rectangle_plugin package discussed above, the plugin description file (e.g. rectangle_plugin.xml), would look something like this:

<library path="lib/librectangle">
  <class name="example_pkg/Rectangle" type="rectangle_namespace::Rectangle" base_class_type="polygon_namespace::Polygon">
  <description>
  This is a rectangle plugin
  </description>
  </class>
</library>

For a detailed description of plugin description files and their associated tags/attributes please see the following documentation.

Why Do We Need This File

We need this file in addition to the code macro to allow the ROS system to automatically discover, load, and reason about plugins. The plugin description file also holds important information, like a description of the plugin, that doesn't fit well in the macro.

Exporting a Plugin

In order to allow plugin users to access information, a plugin provider must point to its plugin description file in its manifest.xml inside the export tag block. Note, if you have other exports they all must go in the same export field.

Considering the rectangle_plugin package again, the relevant lines would look as follows:

<export>
  <polygon_interface_package plugin="${prefix}/rectangle_plugin.xml" />
</export>

For a detailed discussion of exporting a plugin, please see the following documentation.

Important Note: In order for the above export command to work properly, the providing package must depend directly on the package containing the plugin interface. For example, the rectangle_plugin must have the line below in its manifest.xml:

  <depend package="polygon_interface_package" />

Check exports

To check an export has been successfully exported use the following:

rospack plugins --attrib=plugin nav_core

This will return all "plugins" exported into the nav_core package.

Using a Plugin

pluginlib provides a ClassLoader tool available in the class_loader.h header that makes it quick and easy to use provided classes. For detailed documentation of the code-level API for this tool please see pluginlib::ClassLoader documentation. Below, we'll show a simple example of using the ClassLoader to create an instance of a rectangle in some code that uses a polygon:

   1 #include <pluginlib/class_loader.h>
   2 #include <polygon_interface_package/polygon.h>
   3 
   4 //... some code ...
   5 
   6 pluginlib::ClassLoader<polygon_namespace::Polygon> poly_loader("polygon_interface_package", "polygon_namespace::Polygon");
   7 polygon_namespace::Polygon* poly = NULL;
   8 
   9 try{
  10   poly = poly_loader.createClassInstance("example_pkg/Rectangle");
  11 
  12   //... use the polygon
  13 }
  14 catch(pluginlib::PluginlibException& ex){
  15   //handle the class failing to load
  16   ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
  17 }

Important Note: The classloader must not go out scope while you are using the plugin. So, if you are loading a plugin object inside a class, make sure that the class loader is a member variable of that class.

Report a Bug

<<TracLink(ros-pkg common)>>

Wiki: pluginlib/pluginlib_pregroovy (last edited 2015-05-07 00:12:19 by esteve)