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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM