首页 资讯 应用 高压 设计 行业 低压 电路图 关于

机器人

旗下栏目: 物联网 机器人 新技术 仪器仪表

ROS-Pluginlib原理

机器人 | 发布时间:2017-10-22 | 人气: | #评论# |本文关键字:ROS,Pluginlib,原理
摘要:Overview pluginlib 是一个C++ 类库,用于从一个ROS包中加载和卸载插件 plugins . 插件 plugins 是一种能从运行库(例如:共享对象,动态链接库)中动态导入的类. 使用 pluginlib , 我们就不必在程

Overview

pluginlib 是一个C++ 类库,用于从一个ROS包中加载和卸载插件 plugins. 插件plugins是一种能从运行库(例如:共享对象,动态链接库)中动态导入的类. 使用 pluginlib, 我们就不必在程序中显式地声明或定义类库,而是可以在代码中的任何位置动态的导入外部的类,甚至我们不需要知道类库或头文件或类定义。Plugins在扩展和修改应用程序(这汇总程序不需要修改应用程序的源码)的时候是非常有用的。例如代价地图层中需要添加一层新的代价地图,用于表示车辆或行人,就需要用到pluginlib导入这一层心的代价地图(一个已经被导出的类,这个类称为插件)。

Example

为了更好的理解plugin是如何工作的,我们来看一个小例子。首先,假设已经有了一个多边形接口包“polygon_interface_package”的ROS包,它包含有一个多边形生成的ploygen基类。在假定我们的系统支持两种多边形,一种是矩形,包含在“rectangle_plugin”中;另一种是三角形,,包含在“triangle_plugin”中。rectangle_plugin 和 triangle_plugin必须在package.xml中声明注册,以便于rosbuild系统能够从polygon_interface_package包里索引到这些多边形插件。这样就可以通过rospack命令来查看ros系统中所有的插件了,例如这个例子中的矩形和三角形。

2codes.png

Providing a Plugin

 Registering/Exporting a Plugin

为了能够让一个类能够被动态的导入,它必须被标记为一个导出类。这可以通过特定的宏PLUGINLIB_EXPORT_CLASS来实现。该宏可以放到任何源文件(.cpp)中,这样该源文件定义的类就能变成一个插件库了,注意这个宏一般放在源文件的最后来导出类。对于该例子,我们可以在“example_pkg"中创建class_list.cpp文件,这样就可以把矩形rectangle类编译到librectangle库中。

#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)

The Plugin Description File

 plugin 描述文件是一个XML文件,用于存储了plugin所有重要信息,这种信息格式是可读的。主要包含了插件的名字,插件的类型等等。以rectangle_plugin包为例,该包的插件描述文件(rectangle_plugin.xml)看起来像下面的样子:

<library path="lib/librectangle">

  <class type="rectangle_namespace::Rectangle" base_class_type="polygon_namespace::Polygon">

  <description>

  This is a rectangle plugin

  </description>

  </class>

</library>


 插件描述文件及其关联的tags/attributes的详细介绍请参考documentation.

 

Why Do We Need This File

除了代码宏,我们需要这个文件以便于让ROS系统自动发现,加载和推理插件。插件描述文件也包含重要信息,如插件的描述,这是宏所不能做到的

Registering Plugin with ROS Package System

为了让pluginlib在ROS包中查询到所有有效的插件,每个包都必须显式地声明导出了哪些插件,这就是通过package.xml来实现了,以rectangle_plugin为例子,只需要在文件中添加一下的代码即可:

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

关于插件导出的详细讨论,请参考documentation。

 重要提示:为了能够正确导出类,必须要提供该包的接口依赖,例如rectangle_plugin插件必须在package.xml添加以下的依赖:

  <build_depend>polygon_interface_package</build_depend>   <run_depend>polygon_interface_package</run_depend>

  

Querying ROS Package System For Available Plugins

我们可以使用rospack查询ROS系统包(包括自行开发的插件包)中的所有有效的插件,例如:

rospack plugins --attrib=plugin nav_core

这将会返回 nav_core导出的所有插件。结果如下:

global_planner /opt/ros/indigo/share/global_planner/bgp_plugin.xml

dwa_local_planner /opt/ros/indigo/share/dwa_local_planner/blp_plugin.xml

rotate_recovery /opt/ros/indigo/share/rotate_recovery/rotate_plugin.xml

move_slow_and_clear /opt/ros/indigo/share/move_slow_and_clear/recovery_plugin.xml

clear_costmap_recovery /opt/ros/indigo/share/clear_costmap_recovery/ccr_plugin.xml

carrot_planner /opt/ros/indigo/share/carrot_planner/bgp_plugin.xml

base_local_planner /opt/ros/indigo/share/base_local_planner/blp_plugin.xml

navfn /opt/ros/indigo/share/navfn/bgp_plugin.xml


Using a Plugin

pluginlib在class_loader.h中提供了一个ClassLoader类,用于导入外部的插件。更详细的API文档,请参见。下面我们展示一个简单的例子,实现ClassLoader创建一个rectangle的实例:

#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());

}

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.

注意 在使用的插件的时候,ClassLoader必须在域范围内。因此,如果在类中加载插件对象,请确保ClassLoader是该类的成员变量。

Changes from Pre-Groovy pluginlib(过时不做翻译) 

Simplified Export Macro

Prior to pluginlib 1.9 (Groovy), the macros PLUGINLIB_REGISTER_CLASS and PLUGINLIB_DECLARE_CLASS were used to register exported classes. These have been deprecated in favor of the new PLUGINLIB_EXPORT_CLASS. The new macro is simpler as it only takes two arguments.

A script has been provided with pluginlib which can be run in the root of your source folder to automatically update the legacy macros to utilize the new one:

plugin_macro_update

Legacy "Lookup Name"

Pre-Groovy versions of pluginlib required specifying a "lookup name" for exported classes in both the plugin description file and export macro. This lookup name acted as an alias for the true class name -- the true class name was not used in the user facing interface. The reason why this lookup alias was used instead of the real name was due to a technical limitation in older versions.

One can now use the real name of a class instead of the lookup name. However, if users want to still use the lookup name, they can add it in their plugin description file. For example: 

<library path="lib/librectangle">

  <class name="rviz/Rectangle" type="rectangle_namespace::Rectangle" base_class_type="polygon_namespace::Polygon">

  <description>

  This is a rectangle plugin

  </description>

  </class>

</library>

pluginlib will now utilize "rviz/Rectangle" instead of "rectangle_namespace::Rectangle" to refer to the class. The real class name cannot be used to refer to the class if a lookup name alias is used. If no lookup name is provided, the lookup name and true class name are equivalent.


责任编辑:电气自动化网

热门文章

首页 | 资讯 | 应用 | 高压 | 设计 | 行业 | 低压 | 电路图 | 关于

Copyright 2017-2018 电气自动化网 版权所有 辽ICP备17010593号-1

电脑版 | 移动版

Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。