ros的插件库 pluginlib 的简介

目录

1 Getting ready

2 Create a Base Class

3 Create the Plugins

4 Registering the Plugins

5 Building the Plugin Library

6 Making the Plugins Available to the ROS Toolchain

6.1 The Plugin XML File

6.2 Exporting Plugins

7 Using a Plugin

8 Running the Code


1 Getting ready

First, install pre-made pluginlib_tutorials pkg by doing the following where %ROS_DISTRO% can be {fuerte, groovy,hydro,indigo,jade} etc.:

$ apt-get install ros-%ROS_DISTRO%-common-tutorials

Then we'll need to create a package to do our work in. It is recommended to create this package inside the catkin_ws/src/ directory.

$ catkin_create_pkg pluginlib_tutorials_ roscpp pluginlib

 

2 Create a Base Class

Ok, now we'll create a base class from which all of our plugins will inherit. For this example, we'll be creating a couple of RegularPolygon objects and using them, so we need to create the RegularPolygon class. Open your favorite editor, edit catkin_ws/src/pluginlib_tutorials_/include/pluginlib_tutorials_/polygon_base.h, and paste the following inside of it:

#ifndef PLUGINLIB_TUTORIALS__POLYGON_BASE_H_
#define PLUGINLIB_TUTORIALS__POLYGON_BASE_H_

namespace polygon_base
{
  class RegularPolygon
  {
    public:
      virtual void initialize(double side_length) = 0;
      virtual double area() = 0;
      virtual ~RegularPolygon(){}

    protected:
      RegularPolygon(){}
  };
};
#endif

上面的代码应该很容易解释...我们正在创建一个名为RegularPolygon的抽象类。 要注意的一件事是initialize方法的存在。

使用pluginlib时,类需要没有参数的构造函数,因此,如果需要任何参数,我们将使用initialize方法来初始化对象。

 

3 Create the Plugins

For this example, we'll create two RegularPolygon plugins, the first will be a Triangle and the second a Square. Open up include/pluginlib_tutorials_/polygon_plugins.h and paste the following into it:

#ifndef PLUGINLIB_TUTORIALS__POLYGON_PLUGINS_H_
#define PLUGINLIB_TUTORIALS__POLYGON_PLUGINS_H_
#include 
#include 

namespace polygon_plugins
{
  class Triangle : public polygon_base::RegularPolygon
  {
    public:
      Triangle(){}

      void initialize(double side_length)
      {
        side_length_ = side_length;
      }

      double area()
      {
        return 0.5 * side_length_ * getHeight();
      }

      double getHeight()
      {
        return sqrt((side_length_ * side_length_) - ((side_length_ / 2) * (side_length_ / 2)));
      }

    private:
      double side_length_;
  };

  class Square : public polygon_base::RegularPolygon
  {
    public:
      Square(){}

      void initialize(double side_length)
      {
        side_length_ = side_length;
      }

      double area()
      {
        return side_length_ * side_length_;
      }

    private:
      double side_length_;

  };
};
#endif

This code should also be pretty clear. We've created two classes that inherit from RegularPolygon that we'll use as our plugins.

4 Registering the Plugins

So far, we've just created some standard C++ classes. Now, we'll start to do the pluginlib specific work as we declare our Triangle and Square classes as plugins. Open up src/polygon_plugins.cpp and paste the following into it:

#include 
#include 
#include 

PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon)
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Square, polygon_base::RegularPolygon)

Let's look at a couple of lines in a bit more detail.

include 

Here, we include the pluginlib macros that allow us to register classes as plugins.

PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon)

Here, we register the Triangle class as a plugin. Let's go through the arguments to the PLUGINLIB_EXPORT_CLASS macro:

  • 1: The fully-qualified type of the plugin class, in this case, polygon_plugins::Triangle.

  • 2: The fully-qualified type of the base class, in this case, polygon_base::RegularPolygon.

5 Building the Plugin Library

To actually build the library, add the following lines to your CMakeLists.txt file:

include_directories(include)
add_library(polygon_plugins src/polygon_plugins.cpp)

You should then be able to compile the code you've written so far by running catkin_make in the top folder of your catkin workspace.

 

6 Making the Plugins Available to the ROS Toolchain

The steps above make it so that instances of our plugins can be created once the library they exist in is loaded, but the plugin loader still needs a way to find that library and to know what to reference within that library. To this end, we'll also create an XML file that, along with a special export line in the package manifest, makes all the necessary information about our plugins available to the ROS toolchain.

6.1 The Plugin XML File

Open up an editor and paste the following into polygon_plugins.xml, which should be in the top level of the package (along with CMakeLists.txt and package.xml):


  
    This is a triangle plugin.
  
  
    This is a square plugin.
  

There are a couple of lines that we'll look at in more detail.


The library tag gives the relative path to a library that contains the plugins that we want to export. In this case, that's lib/libpolygon_plugins

The class tag declares a plugin that we want to export from our library. Let's go through its parameters:

  • type: The fully qualified type of the plugin. For us, that's polygon_plugins::Triangle.

  • base_class: The fully qualified base class type for the plugin. For us, that's polygon_base::RegularPolygon.

  • description: A description of the plugin and what it does.

  • name (not used in the example above): This refers to the name of the plugin that we're exported given as plugin_namespace/PluginName. Since we used the package name as the namespace for our regular_triangle plugin... this results in us using pluginlib_tutorials_/regular_triangle. After the API change, this attribute is no longer required.

6.2 Exporting Plugins

To export the plugins that we created, we'll have to add the following lines to our either manifest.xml with rosbuild pkg or package.xml with catkin package:


  

The name of the tag, pluginlib_tutorials_ above, should correspond to the package where the base_class for the plugin lives. In this case, the base class and the inherited plugin classes live in the same package, but in most real-world situations this will not be the case. From there, the plugin attribute should be set to point to the XML file generated in the step above.

To verify that things are working, first build the workspace and source the resulting setup file, then try running the following rospack command:

rospack plugins --attrib=plugin pluginlib_tutorials_

You should see output giving the full path to the polygon_plugins.xml file. This means that the ROS toolchain is setup properly to work with your plugin.

7 Using a Plugin

Now that we've successfully created and exported some RegularPolygon plugins, let's use them. Open up src/polygon_loader.cpp and paste the following into it:

#include 
#include 

int main(int argc, char** argv)
{
  pluginlib::ClassLoader poly_loader("pluginlib_tutorials_", "polygon_base::RegularPolygon");

  try
  {
    boost::shared_ptr triangle = poly_loader.createInstance("polygon_plugins::Triangle");
    triangle->initialize(10.0);

    boost::shared_ptr square = poly_loader.createInstance("polygon_plugins::Square");
    square->initialize(10.0);

    ROS_INFO("Triangle area: %.2f", triangle->area());
    ROS_INFO("Square area: %.2f", square->area());
  }
  catch(pluginlib::PluginlibException& ex)
  {
    ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
  }

  return 0;
}

Let's look at a few of the key lines:

#include 
#include 

we include the ClassLoader from pluginlib as well as the RegularPolygon interface.

  pluginlib::ClassLoader poly_loader("pluginlib_tutorials_", "polygon_base::RegularPolygon");

we create a ClassLoader that we'll use to load plugins. It takes two arguments. The first, is the name of the package that contains the plugin base class, in our case, pluginlib_tutorials_. The second, is the fully qualified type of the base class, in our case, polygon_base::RegularPolygon.

我们创建了一个用于加载插件的ClassLoader。 它有两个参数。 第一个是包含插件基类的包的名称,在本例中为plugininlib_tutorials_。 第二个是基类的完全限定类型,在本例中为polygon_base :: RegularPolygon。

  try
  {
    boost::shared_ptr triangle = poly_loader.createInstance("polygon_plugins::Triangle");
    triangle->initialize(10.0);

    boost::shared_ptr square = poly_loader.createInstance("polygon_plugins::Square");
    square->initialize(10.0);

    ROS_INFO("Triangle area: %.2f", triangle->area());
    ROS_INFO("Square area: %.2f", square->area());
  }

我们实际上是加载了pluginlib_tutorials_ / regulare_triangle插件。 由于插件的构造函数不能包含参数,因此在构造对象之后立即调用初始化函数

  catch(pluginlib::PluginlibException& ex)
  {
    ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
  }

我们会在加载插件时检查是否出了问题,以便向用户提供有用的反馈。

8 Running the Code

To run the code we just wrote, we'll add the following line to our CMakeLists.txt file:

add_executable(polygon_loader src/polygon_loader.cpp)
target_link_libraries(polygon_loader ${catkin_LIBRARIES})

Next, we'll build everything by running the catkin_make command in the home directory of your catkin workspace.

Finally, run the devel/lib/pluginlib_tutorials_/polygon_loader executable.

You should get output similar to that shown below:

[ INFO] [WallTime: 1279658450.869089666]: Triangle area: 43.30
[ INFO] [WallTime: 1279658450.869138007]: Square area: 100.00

Congratulations! You've just written and used your first plugins.

 

你可能感兴趣的:(ROS)