ROS2高级教程使用pluginlib自定义插件
引言
很多小伙伴学完导航后可能想用自己的路径规划算法或者控制算法在机器人试一试身手,Nav2文档中提供了详细的操作教程:
但是这些教程无一例外都使用了pluginlib即插件机制进行组织,包括Nav2的源码在内,都大量使用了它,那什么是pluginlib呢?
大家知道在C++中使用一个动态库,需要包含动态库的头文件,并链接动态库文件。但这样会降低代码的灵活性,后来的新库文件能不能直接加载和使用,不包含头文件和进行链接呢?
pluginlib就提供了这样一个解决方案,实现了对库的动态加载和调用,只说不做不是小鱼的风格,上代码,带你从头学习如何使用它。
当你在ROS 2中开发功能包并使用pluginlib
创建动态加载的插件时,下面的步骤将帮助你更好地理解整个过程。我们将以一个简单的运动控制系统为例,展示如何创建一个ROS 2功能包,包含了插件的定义、配置、编译和使用。
使用pluginlib动态加载库
灵魂就是main.cpp没有对libsimple_motion_controller.so进行link就直接使用了。
步骤 1:创建功能包
首先,在你的ROS 2工作空间中创建一个功能包。我们将使用motion_control_system
作为功能包的名称:
cd ~/ros2_ws/src
ros2 pkg create motion_control_system
步骤 2:定义插件接口
在ROS 2功能包中,我们首先定义一个插件接口,即一个纯虚基类,用于规定插件的基本方法。在motion_control_system/include/motion_control_system
文件夹中创建一个名为motion_control_interface.hpp
的文件,并添加以下内容:
#ifndef MOTION_CONTROL_INTERFACE_HPP
#define MOTION_CONTROL_INTERFACE_HPP
namespace motion_control_system {
class MotionController {
public:
virtual void start() = 0;
virtual void stop() = 0;
virtual ~MotionController() {}
};
} // namespace motion_control_system
#endif // MOTION_CONTROL_INTERFACE_HPP
步骤 3:创建插件类
接下来,我们创建一个实现了插件接口的具体插件类。在motion_control_system/include/motion_control_system
文件夹中创建一个名为simple_motion_controller.hpp
的文件,并添加以下内容:
#ifndef SIMPLE_MOTION_CONTROLLER_HPP
#define SIMPLE_MOTION_CONTROLLER_HPP
#include "motion_control_system/motion_control_interface.hpp"
namespace motion_control_system {
class SimpleMotionController : public MotionController {
public:
void start() override;
void stop() override;
};
} // namespace motion_control_system
#endif // SIMPLE_MOTION_CONTROLLER_HPP
然后,在motion_control_system/src
文件夹中创建一个名为simple_motion_controller.cpp
的文件,并添加以下内容:
#include <iostream>
#include "motion_control_system/simple_motion_controller.hpp"
namespace motion_control_system {
void SimpleMotionController::start() {
// 实现简单的运动控制逻辑
std::cout << "SimpleMotionController::start" << std::endl;
}
void SimpleMotionController::stop() {
// 停止运动控制
std::cout << "SimpleMotionController::stop" << std::endl;
}
} // namespace motion_control_system
#include "pluginlib/class_list_macros.hpp"
PLUGINLIB_EXPORT_CLASS(motion_control_system::SimpleMotionController, motion_control_system::MotionController)
步骤 4:配置插件描述文件
在motion_control_system
文件夹中创建一个名为simple_motion_plugins.xml
的文件,并添加以下内容:
<library path="simple_motion_controller">
<class name="motion_control_system/SimpleMotionController" type="motion_control_system::SimpleMotionController" base_class_type="motion_control_system::MotionController">
<description>简单运动控制器</description>
</class>
</library>
步骤 5:配置CMakeLists.txt
打开motion_control_system/CMakeLists.txt
文件,并确保以下内容已添加:
# ...
ament_target_dependencies(${library_name}
pluginlib
)
# ...
pluginlib_export_plugin_description_file(motion_control_system simple_motion_plugins.xml)
ament_package()
步骤 6:创建主程序
在motion_control_system/src
文件夹中创建一个名为main.cpp
的文件,并添加以下内容:
#include <rclcpp/rclcpp.hpp>
#include <pluginlib/class_loader.hpp>
#include "motion_control_system/motion_control_interface.hpp"
int main(int argc, char **argv) {
rclcpp::init(argc, argv);
// 创建插件加载器
pluginlib::ClassLoader<motion_control_system::MotionController> controller_loader("motion_control_system", "motion_control_system::MotionController");
// 选择要加载的插件
std::string controller_name = "motion_control_system/SimpleMotionController";
// 加载插件
auto controller = controller_loader.createClassInstance(controller_name);
// 启动运动控制
controller->start();
// 做一些其他操作
// 停止运动控制
controller->stop();
rclcpp::shutdown();
return 0;
}
步骤 7:编译和运行
在你的ROS 2工作空间中,执行以下命令编译功能包:
cd ~/ros2_ws
colcon build --packages-select motion_control_system
运行编译后的可执行文件:
source install/setup.bash
ros2 run motion_control_system test_plugin
通过上述步骤,你已经成功创建了一个ROS 2功能包,其中包含一个简单的运动控制插件。这个插件可以在运行时被动态加载和运行,从而使你的ROS 2应用程序更加灵活和可扩展。