文章目录
前言
ROS中的插件就是可以动态加载的扩展功能类。
ROS中的pluginlib功能包提供了加载喝卸载plugin的C++库,开发者在使用插件时,不需要考虑plugin类的链接位置,只需要将插件注册到pluginlib中,即可直接动态加载。
一、工作原理
如图所示:
实现一个插件需要如下几个步骤:
- 创建基类,定义统一接口(如果基于现有基类实现插件,跳过该步)
- 创建plugin类,继承基类,实现统一的接口
- 注册插件(使用pluginlib的宏完成注册)
- 编译生成插件的动态链接库(修改CMakefile.txt文件)
- 将插件加入到ROS中(创建喝修改相应xml文件)
二、具体实现
按照上述步骤,下面利用pluginlib实现一个插件。创建名为pluginlib_tutorials的功能包,命令如下:
catkin_create_pkg pluginlib_tutorials roscpp pluginlib
注意,创建时添加pluginlib依赖。
1、创建基类
在include/pluginlib_tutorials/polygon_bash.h文件中,创建polygon基类,定义一些接口,注意initialize()接口的使用。文件内容如下:
#ifndef PLUGINLIB_TUTORIALS_POLYGON_BASE_H_
#define PLUGINLIB_TUTORIALS_POLYGON_BASE_H_
namespace polygon_base
{
class RegularPolygon
{
public:
//pluginlib要求构造函数不能带有参数,所以定义initialize来完成需要初始化的工作
virtual void initialize(double side_length) = 0;
//计算面积的接口函数
virtual double area() = 0;
virtual ~RegularPolygon(){}
protected:
RegularPolygon(){}
};
};
#endif
2、创建plugin类
在include/pluginlib_tutorials/polygon_plugins.h文件中,定义rectangle_plugin和triangle_plugin类,实现基类的接口,也可以添加plugin自身需要的接口。文件内容如下:
#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() : side_length_() {}
// 初始化边长
void initialize(double side_length)
{
side_length_ = side_length;
}
double area()
{
return 0.5 * side_length_ * getHeight();
}
// Triangle类自己的接口
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() : side_length_() {}
// 初始化边长
void initialize(double side_length)
{
side_length_ = side_length;
}
double area()
{
return side_length_ * side_length_;
}
private:
double side_length_;
};
};
#endif
3、注册插件
在src/pluginlib_tutorials/polygon_plugins.cpp文件中,注册创建好的插件。文件内容如下:
//包含pluginlib的头文件,使用pluginlib的宏来注册插件
#include <pluginlib/class_list_macros.h>
#include <pluginlib_tutorials/polygon_base.h>
#include <pluginlib_tutorials/polygon_plugins.h>
//注册插件,宏参数:plugin的实现类,plugin的基类
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon);
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Square, polygon_base::RegularPolygon);
4、编译插件的动态链接库
修改CMakefile.txt文件,如下:
add_library(pluginlib_tutorials src/polygon_plugins.cpp)
target_link_libraries(pluginlib_tutorials ${catkin_LIBRARIES})
5、将插件加入ROS
- 创建src/pluginlib_tutorials/polygon_plugins.xml文件,内容如下:
<library path="lib/libpluginlib_tutorials">
<class name="pluginlib_tutorials/regular_triangle" type="polygon_plugins::Triangle" base_class_type="polygon_base::RegularPolygon">
<description>This is a triangle plugin.</description>
</class>
<class name="pluginlib_tutorials/regular_square" type="polygon_plugins::Square" base_class_type="polygon_base::RegularPolygon">
<description>This is a square plugin.</description>
</class>
</library>
这个XML主要描述了plugin的动态库路径、实现类、基类、功能描述等信息。
- 修改src/pluginlib_tutorials/package.xml文件,内容如下:
<?xml version="1.0"?>
<package>
<name>pluginlib_tutorials</name>
<version>0.1.10</version>
<description>The pluginlib_tutorials package</description>
<maintainer email="d.stonier@gmail.com">Daniel Stonier</maintainer>
<license>BSD</license>
<url type="website">http://www.ros.org/wiki/pluginlib/Tutorials</url>
<url type="bugtracker">https://github.com/ros/common_tutorials/issues</url>
<url type="repository">https://github.com/ros/common_tutorials/</url>
<author>Eitan Marder-Eppstein</author>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>pluginlib</build_depend>
<build_depend>roscpp</build_depend>
<run_depend>pluginlib</run_depend>
<run_depend>roscpp</run_depend>
<export>
<pluginlib_tutorials plugin="${prefix}/polygon_plugins.xml" />
</export>
</package>
可以使用如下命令,查看功能包的插件路径:
rospack plugins --attrib=plugin pluginlib_tutorials
如果配置正确,效果如下:
6、调用插件
上面已经实现了该插件的所有代码,现在开始调用该插件,创建src/pluginlib_tutorials/polygon_loader.cpp文件,内容如下:
#include <boost/shared_ptr.hpp>
#include <pluginlib/class_loader.h>
#include <pluginlib_tutorials/polygon_base.h>
int main(int argc, char** argv)
{
// 创建一个ClassLoader,用来加载plugin
pluginlib::ClassLoader<polygon_base::RegularPolygon> poly_loader("pluginlib_tutorials", "polygon_base::RegularPolygon");
try
{
// 加载Triangle插件类,路径在polygon_plugins.xml中定义
boost::shared_ptr<polygon_base::RegularPolygon> triangle = poly_loader.createInstance("pluginlib_tutorials/regular_triangle");
// 初始化边长
triangle->initialize(10.0);
ROS_INFO("Triangle area: %.2f", triangle->area());
}
catch(pluginlib::PluginlibException& ex)
{
ROS_ERROR("The plugin failed to load for some reason. Error: %s", ex.what());
}
try
{
boost::shared_ptr<polygon_base::RegularPolygon> square = poly_loader.createInstance("pluginlib_tutorials/regular_square");
square->initialize(10.0);
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;
}
修改CMakefile.txt文件,如下:
add_executable(polygon_loader src/polygon_loader.cpp)
target_link_libraries(polygon_loader ${catkin_LIBRARIES})
7、运行效果
编译成功后,运行该插件,命令如下:
rosrun pluginlib_tutorials polygon_loader
效果如下:
评论(0)
您还未登录,请登录后发表或查看评论