• ROS知识(18)----Pluginlib原理


     

    目录

    1. Overview
    2. Example
    3. Providing a Plugin
      1. Registering/Exporting a Plugin
      2. The Plugin Description File
      3. Registering Plugin with ROS Package System
      4. Querying ROS Package System For Available Plugins
    4. Using a Plugin
    5. Changes from Pre-Groovy pluginlib
      1. Simplified Export Macro
      2. Legacy "Lookup Name"
    6. Report a Bug


    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系统中所有的插件了,例如这个例子中的矩形和三角形。

    pluginlib/plugin_model.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的实例:

     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 
     8 try
     9 {
    10   boost::shared_ptr<polygon_namespace::Polygon> poly = poly_loader.createInstance("rectangle_namespace::Rectangle");
    11 
    12   //... use the polygon, boost::shared_ptr will automatically delete memory when it goes out of scope
    13 }
    14 catch(pluginlib::PluginlibException& ex)
    15 {
    16   //handle the class failing to load
    17   ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
    18 }

    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.

     

    Report a Bug

  • 相关阅读:
    DTV_SI 汇总 & 兼谈LCN
    Java 泛型 五:泛型与数组
    Java 泛型 四 基本用法与类型擦除
    Java 泛型 三
    Java 泛型 二
    Java 泛型 一
    Java集合类解析 ***
    Java 集合类
    MySQL入门01-MySQL源码安装
    如何彻底杀掉不良用户会话
  • 原文地址:https://www.cnblogs.com/cv-pr/p/6955549.html
Copyright © 2020-2023  润新知