[Documentation] [TitleIndex] [WordIndex

(!) Please ask about problems and questions regarding this tutorial on answers.ros.org. Don't forget to include in your question the link to this page, the versions of your OS & ROS, and also add appropriate tags.

Create and Export new Plugin

Description: This tutorial show how to create and export new plugins to the plugin system.

Keywords: plugins, create, export

Tutorial Level: BEGINNER

Next Tutorial: How to use Dynamic Parameters in Plugins

How to Export Custom Plugins Types

The following subsections give only a brief insight how the system is working. It is just a short introduction how to use the vigir_pluginlib rather provide detailed information how it is working under the hood. If you are interested in details, we refer to the original pluginlib documentation. Although the example is focused how to add a single plugin type, you can also add multiple types in parallel.

Minimal Example of an Interface Plugin

An interface plugin is used to introduce a new plugin type which provides a specific interface such as for example the StepCostEstimator from the vigir_footstep_planning does for step cost estimation. For this purpose it must inherit from the vigir_pluginlib::Plugin class and the constructor should always accept the name as std::string for all concrete implementations. Although the full signature of the vigir_pluginlib::Plugin class constructor allows to take optional arguments for the type_class_package, base_class and base_class_package, those should not be used as the plugin manager can determine them automatically.

Finally, a minimal interface plugin looks as followed:

   1 #include <vigir_pluginlib/plugin.h>
   3 namespace my_interface_plugins_ns
   4 {
   5 class MyInterfacePlugin
   6   : public vigir_pluginlib::Plugin
   7 {
   8 public:
   9   // typedefs
  10   typedef boost::shared_ptr<MyInterfacePlugin> Ptr;
  11   typedef boost::shared_ptr<const MyInterfacePlugin> ConstPtr;
  13   MyInterfacePlugin(const std::string& name)
  14   : vigir_pluginlib::Plugin(name)
  16   // Define your interfaces here!
  17 };
  18 }

Minimal Example of a Concrete Plugin

As the interface plugins are supposed to be (pure) virtual classes, you need concrete plugins that actually implements the given interface. The inheritance is straightforward in this case. As the concrete plugins must be instantiated with default constructor (required by pluginlib), you should forward a default name to the interface plugin class constructor. At the end, the PLUGINLIB_EXPORT_CLASS macro must be called to register the plugin.

   1 #include <my_interface_plugins_ns/my_interface_plugin.h>
   3 namespace my_concrete_plugins_ns
   4 {
   5 public:
   6   MyConcretePlugin::MyConcretePlugin()
   7   : my_interface_plugins_ns::MyInterfacePlugin("my_concrete_plugin")
   9   // Your concrete implementation of the interfaces goes here!
  10 }
  12 // Don't forget to export your plugin!
  13 #include <pluginlib/class_list_macros.h>
  14 PLUGINLIB_EXPORT_CLASS(my_concrete_plugins_ns::MyConcretePlugin, my_interface_plugins_ns::MyInterfacePlugin)

Export Plugin to ROS Package System

Create the plugin description file (e.g. plugin.xml) analogously to following example:

   1 <library path="lib/libmy_concrete_plugins_pkg">
   2   <class name="my_concrete_plugin" type="my_concrete_plugins_ns::MyConcretePlugin" base_class_type="my_interface_plugins_ns::MyInterfacePlugin">
   3   <description>
   4   MyConcretePlugin: My awesome first plugin
   5   </description>
   6   </class>
   7   ...
   8 </library>

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

A plugin provider must point to its plugin description file in its package.xml inside the export tag block. Note, if you have other exports they all must go in the same export field.

   1 <export>
   2   <my_interface_plugins_pkg plugin="${prefix}/plugin.xml" />
   3 </export>

Please take note that each plugin providing package has to depend directly on the packages providing the interface plugins.

Querying ROS Package System for Available Plugins

One can query the ROS package system via rospack to see which plugins are available by any given package. For example:

rospack plugins --attrib=plugin nav_core

This will return all plugins exported from the nav_core package.

Plugin Description Config

The Plugin Description configs aren't required anymore since version >=0.3.0 but can still be used for compatibility reasons. In order to use the new simplified version, just add the name tag in the XML export file for each class.

The plugin manager builds a plugin database based on all plugin descriptions that have been loaded into the rosparam server. For each preconfigured plugin one entry should exists. An example yaml config file could be:

  type_class_package: my_concrete_plugins_pkg
  type_class: my_concrete_plugins_ns::MyConcretePlugin
  base_class_package: my_interface_plugins_pkg
  base_class: my_interface_plugins_ns::MyInterfacePlugin

where the fields are identical to the plugin description.

When starting the ros node running the plugin manager you have to ensure that the config file above (assumed to be located in my_concrete_plugins_pkg/config/plugin_descriptions.yaml) is loaded into the same namespace as well, e.g. via rosparam tag in a launch file:

   1 <rosparam file="$(find my_concrete_plugins_pkg)/config/plugin_descriptions.yaml" command="load" />

2019-12-07 13:16