昨天看了ros下的plugin教程,今天整理一下,教程网址如下:http://wiki.ros.org/pluginlib/Tutorials/Writing%20and%20Using%20a%20Simple%20Plugin
所谓插件plugin个人理解就是把一个写好的类按照ros下标准格式封装一下,然后就可以直接按照ros下的标准格式进行调用。这样方便移植和分享给其他人用,相当于一个动态链接库。
1、catkin_ws/src/pluginlib_tutorials_/include/pluginlib_tutorials_/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
上面的代码应该非常自我解释…我们正在创建一个名为RegularPolygon的抽象类。 有一件事要注意的是初始化方法的存在。 使用pluginlib,类不需要参数的构造函数,所以如果需要任何参数,我们使用initialize方法初始化对象。RegularPolygon是一个基类,同时定义了几种纯虚函数,作为一个基类的模板,具体的实现在继承类里面进行实体化。
2、
include/pluginlib_tutorials_/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
这两个继承类将作为我们的插件
3、src/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)
4、
CMakeLists.txt修改功能包的cmakelist这样就可以编译生成库文件
add_library(polygon_plugins src/polygon_plugins.cpp)
然后在功能包的根目录下catkin_make
5、增加一个配置文件说明该插件的功能,
在package.xml的同级目录下新建polygon_plugins.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
然后修改功能包的配置文件package.xml来告诉编译器有了这个插件
<export> <pluginlib_tutorials_ plugin="${prefix}/polygon_plugins.xml" /> </export>
6、验证插件是否正常
rospack plugins --attrib=plugin pluginlib_tutorials_
7、
src/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;
}
CMakeLists.txt添加
:
include_directories(include) add_executable(polygon_loader src/polygon_loader.cpp) target_link_libraries(polygon_loader ${catkin_LIBRARIES})
然后catkin_make
运行生成的可行文件
devel/lib/pluginlib_tutorials_/polygon_loader