掘金 人工智能 06月11日 10:43
ROS2 Jazzy:创建并使用插件(C++)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本教程详细介绍了如何使用pluginlib在ROS2中创建和加载插件。通过创建基类包和插件包,定义多边形类及其具体形状的插件,演示了插件的动态加载和使用方法。文章提供了清晰的步骤和代码示例,帮助读者理解pluginlib的工作原理,并成功运行一个计算多边形面积的节点。教程强调了插件的灵活性,无需显式链接应用程序即可扩展或修改应用程序行为。

💡 首先,创建一个基类包,定义抽象类`RegularPolygon`,包含`initialize`和`area`等虚函数。`initialize`方法用于传递参数,确保pluginlib的无参数构造函数要求得到满足。

🧩 其次,创建插件包,实现`RegularPolygon`的两个具体插件:`Square`和`Triangle`。插件通过`PLUGINLIB_EXPORT_CLASS`宏注册,指定插件类型和基类类型。

📝 然后,创建一个XML文件(`plugins.xml`)来声明插件,包括插件的类型、基类和描述信息。通过`pluginlib_export_plugin_description_file`命令将该XML文件导出。

⚙️ 接着,在基类包中创建一个节点(`area_node`),使用`pluginlib::ClassLoader`动态加载插件。通过`createSharedInstance`方法创建插件实例,并调用其方法。

✅ 最后,编译并运行工作空间。运行`area_node`节点,可以计算出三角形和正方形的面积,验证插件加载和使用的正确性。

目标

学习使用pluginlib创建并加载一个简单的插件。

背景信息

本教程源自 wiki.ros.org/pluginlib 和 编写并使用简单插件教程(wiki.ros.org/pluginlib/T…

pluginlib是一个用于在 ROS 包中加载和卸载插件的 C++ 库。插件是可动态加载的类,它们从运行时库(即共享对象、动态链接库)中加载。使用pluginlib时,你不用将应用程序与包含这些类的库进行显式链接,相反,pluginlib可以在任何时候打开一个包含导出类的库,而应用程序无需事先了解该库或包含类定义的头文件。插件对于在无需应用程序源代码的情况下扩展或修改应用程序行为非常有用。

先决条件

本文假定你具备基本的 C++ 知识,并且已经成功安装了 ROS2。

操作步骤

在本教程中,你将创建两个新的包,一个用于定义基类,另一个用于提供插件。基类将定义一个通用的多边形类,然后我们的插件将定义具体的形状。

1. 创建基类包

在你的ros2_ws/src文件夹中使用以下命令创建一个新的空包:

ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies pluginlib --node-name area_node polygon_base

打开你喜欢的编辑器,新建ros2_ws/src/polygon_base/include/polygon_base/regular_polygon.hpp,并将以下内容粘贴进去:

#ifndef POLYGON_BASE_REGULAR_POLYGON_HPP#define POLYGON_BASE_REGULAR_POLYGON_HPPnamespace polygon_base{  class RegularPolygon  {    public:      virtual void initialize(double side_length) = 0;      virtual double area() = 0;      virtual ~RegularPolygon(){}    protected:      RegularPolygon(){}  };}  // namespace polygon_base#endif  // POLYGON_BASE_REGULAR_POLYGON_HPP

上面的代码创建了一个名为RegularPolygon的抽象类。需要注意的是,这里有一个initialize方法。使用pluginlib时,需要一个无参数的构造函数,所以如果类需要任何参数,我们使用initialize方法将它们传递给对象。

我们需要让其他类能够使用这个头文件,所以打开ros2_ws/src/polygon_base/CMakeLists.txt进行编辑。在ament_target_dependencies命令之后添加以下行:

install(  DIRECTORY include/  DESTINATION include)

并在ament_package命令之前添加这个命令:

ament_export_include_directories(  include)

我们稍后会回到这个包来编写测试节点。

2. 创建插件包

现在我们要为抽象类编写两个非虚实现。在你的ros2_ws/src文件夹中使用以下命令创建第二个空包:

ros2 pkg create --build-type ament_cmake --license Apache-2.0 --dependencies polygon_base pluginlib --library-name polygon_plugins polygon_plugins

2.1 插件的源代码

打开ros2_ws/src/polygon_plugins/src/polygon_plugins.cpp进行编辑,并将以下内容粘贴进去:

#include <polygon_base/regular_polygon.hpp>#include <cmath>namespace polygon_plugins{  class Square : public polygon_base::RegularPolygon  {    public:      void initialize(double side_length) override      {        side_length_ = side_length;      }      double area() override      {        return side_length_ * side_length_;      }    protected:      double side_length_;  };  class Triangle : public polygon_base::RegularPolygon  {    public:      void initialize(double side_length) override      {        side_length_ = side_length;      }      double area() override      {        return 0.5 * side_length_ * getHeight();      }      double getHeight()      {        return sqrt((side_length_ * side_length_) - ((side_length_ / 2) * (side_length_ / 2)));      }    protected:      double side_length_;  };}#include <pluginlib/class_list_macros.hpp>PLUGINLIB_EXPORT_CLASS(polygon_plugins::Square, polygon_base::RegularPolygon)PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon)

SquareTriangle类的实现相当简单:保存边长,然后用它来计算面积。唯一与pluginlib相关的部分是最后三行,它们调用了一些神奇的宏,将这些类注册为实际的插件。下面来看看PLUGINLIB_EXPORT_CLASS宏的参数:

2.2 插件声明 XML 文件

上述步骤使得包含这些插件的库被加载时能够创建插件实例,但插件加载器仍然需要某种方法来找到该库,并知道在该库中引用什么。为此,我们还将创建一个 XML 文件,再结合包清单中的一个特殊导出行,使得 ROS 工具链能够获取插件必要信息。

创建ros2_ws/src/polygon_plugins/plugins.xml,内容如下:

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

需要注意几点:

2.3 CMake 插件声明

最后一步是通过CMakeLists.txt导出你的插件。这与 ROS1 不同,ROS1 中是导出是通过package.xml完成的。在ros2_ws/src/polygon_plugins/CMakeLists.txtfind_package(pluginlib REQUIRED)这一行之后添加以下行:

pluginlib_export_plugin_description_file(polygon_base plugins.xml)

pluginlib_export_plugin_description_file命令的参数如下:

3. 使用插件

现在是使用插件的时候了。这可以在任何包中完成,不过在这里我们将在基类包中进行。新建ros2_ws/src/polygon_base/src/area_node.cpp,使其包含以下内容:

#include <pluginlib/class_loader.hpp>#include <polygon_base/regular_polygon.hpp>int main(int argc, char** argv){  // To avoid unused parameter warnings  (void) argc;  (void) argv;  pluginlib::ClassLoader<polygon_base::RegularPolygon> poly_loader("polygon_base", "polygon_base::RegularPolygon");  try  {    std::shared_ptr<polygon_base::RegularPolygon> triangle = poly_loader.createSharedInstance("polygon_plugins::Triangle");    triangle->initialize(10.0);    std::shared_ptr<polygon_base::RegularPolygon> square = poly_loader.createSharedInstance("polygon_plugins::Square");    square->initialize(10.0);    printf("Triangle area: %.2f\n", triangle->area());    printf("Square area: %.2f\n", square->area());  }  catch(pluginlib::PluginlibException& ex)  {    printf("The plugin failed to load for some reason. Error: %s\n", ex.what());  }  return 0;}

ClassLoader是需要理解的关键类,它在class_loader.hpp头文件中定义:

有多种方法可以实例化这个类的对象。在这个例子中,我们使用智能指针。我们只需要调用createSharedInstance并传入插件类的全限定类型,在这个例子中是polygon_plugins::Square

重要提示:定义这个节点的polygon_base包并不依赖于polygon_plugins类。插件将被动态加载,无需声明任何依赖关系。此外,我们使用硬编码的插件名称来实例化类,但你也可以使用参数等动态地进行实例化。

4. 编译并运行

回到你的工作空间根目录ros2_ws,编译你的新包:

colcon build --packages-select polygon_base polygon_plugins

ros2_ws目录下,确保加载设置文件:

# Linux/macOSsource install/setup.bash

现在运行节点:

ros2 run polygon_base area_node

它应该输出:

Triangle area: 43.30Square area: 100.00

总结

恭喜!你刚刚编写并使用了你的第一个插件。


关注【智践行】,发送 【机器人】 获得机器人经典学习资料

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

ROS2 pluginlib 插件开发 C++
相关文章