iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 25
0
Software Development

ROS進階學習筆記系列 第 25

Day 25 - ROS pluginlib

連假終於來啦~~~今天筆者久違的回了一趟公館,吃到好多學生時代的回憶感覺非常懷念d(`・∀・)b
今天來稍微寫個小品系列,就是pluginlib,這個package是用來動態載入plugin的工具,不過這些plugin需要在package.xml中列出來才有效。plugin感覺起來是用來做多型的處理,原本package內定義的class,經過他人接手後需要新增別的實作的class,就可以用plugin來插入一個新的class,因此不會影響到原本的package功能這樣。

https://ithelp.ithome.com.tw/upload/images/20201009/20112348WYuIO1DvCq.png

以官網的圖片為例,原本的polygon_interface這個package內只是一個虛擬的class,沒有任何實作,但因為加入兩個plugin: rectangle_plugin和triangle_plugin,讓polygon_interface有了實作的class可供使用這樣。

自己建一個plugin

以上述的polygon為例,先建立一個虛擬的class:
in polygon_base.h:

#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

在建立plugin的時候就需要去include該class,並且新增兩個class做實作,分別是triangle和square:
in polygon_plugins.h:

#ifndef PLUGINLIB_TUTORIALS__POLYGON_PLUGINS_H_
#define PLUGINLIB_TUTORIALS__POLYGON_PLUGINS_H_
#include <pluginlib_tutorials_/polygon_base.h>
#include <cmath>

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

接著在cpp實作的部分加入plugin的設定:
in polygon_plugins.cpp:

#include <pluginlib/class_list_macros.h>
#include <pluginlib_tutorials_/polygon_base.h>
#include <pluginlib_tutorials_/polygon_plugins.h>

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

並且在CMakeList.txt和package.xml進行編譯的規則:
in CMakeList.txt:

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

in package.xml:

<library path="lib/libpolygon_plugins">
  <class type="polygon_plugins::Triangle" base_class_type="polygon_base::RegularPolygon">
    <description>This is a triangle plugin.</description>
  </class>
  <class type="polygon_plugins::Square" base_class_type="polygon_base::RegularPolygon">
    <description>This is a square plugin.</description>
  </class>
</library>

使用plugin

建立好一個plugin以後,要使用就很簡單啦,就新增include以後就可以使用了:
in polygon_loader.cpp :

#include <pluginlib/class_loader.h>
#include <pluginlib_tutorials_/polygon_base.h>

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

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

    boost::shared_ptr<polygon_base::RegularPolygon> 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;
}

plugin筆者在看的時候一直覺得跟package很像,後來想想,package就是不同的套件,內有完整的專案功能,而plugin就比較像是新增的一些小功能,需要依附在特定的package底下才能進行實作,因為跟原本的package內的一些class有相同的特性,卻需要抽換不同的實作方法,因此可以用到plugin這個功能。以上述範例為例,三角形和長方形都具有多邊形的特性,但是卻有不同的實作例如計算周長等,基本上就是利用plugin做到多型的處理。

Reference

http://wiki.ros.org/pluginlib
http://wiki.ros.org/pluginlib/Tutorials/Writing%20and%20Using%20a%20Simple%20Plugin


上一篇
Day24 - ROS TF Time
下一篇
Day 26 - ROS nodelet
系列文
ROS進階學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言