ROS:pluginlib

目录

  • 一、前言
  • 二、概念
  • 三、作用
  • 四实际用例
    • 4.1需求
    • 4.2流程
    • 4.3准备
    • 4.4创建基类
    • 4.5创建插件
    • 4.6注册插件
    • 4.7构建插件库
    • 4.8使插件可用于ROS工具链
      • 4.8.1配置xml
      • 4.8.2导出插件
    • 4.9使用插件
    • 4.10执行

一、前言

pluginlib直译是插件库,所谓插件字面意思就是可插拔的组件,比如:以计算机为例,可以通过USB接口自由插拔的键盘、鼠标、U盘…都可以看作是插件实现,其基本原理就是通过规范化的USB接口协议实现计算机与USB设备的自由组合。同理,在软件编程中,插件是一种遵循一定规范的应用程序接口编写出来的程序,插件程序依赖于某个应用程序,且应用程序可以与不同的插件程序自由组合。在ROS中,也会经常使用到插件,场景如下:
1.导航插件:在导航中,涉及到路径规划模块,路径规划算法有多种,也可以自实现,导航应用时,可能需要测试不同算法的优劣以选择更合适的实现,这种场景下,ROS中就是通过插件的方式来实现不同算法的灵活切换的。

2.rviz插件:在rviz中已经提供了丰富的功能实现,但是即便如此,特定场景下,开发者可能需要实现某些定制化功能并集成到rviz中,这一集成过程也是基于插件的。

二、概念

pluginlib是一个c++库, 用来从一个ROS功能包中加载和卸载插件(plugin)。插件是指从运行时库中动态加载的类。通过使用Pluginlib,不必将某个应用程序显式地链接到包含某个类的库,Pluginlib可以随时打开包含类的库,而不需要应用程序事先知道包含类定义的库或者头文件。

三、作用

结构清晰;
低耦合,易修改,可维护性强;
可移植性强,更具复用性;
结构容易调整,插件可以自由增减;

四实际用例

4.1需求

以插件的方式实现正多边形的相关计算。

4.2流程

1.准备;
2.创建基类;
3.创建插件类;
4.注册插件;
5.构建插件库;
6.使插件可用于ROS工具链;
6.1配置xml
6.2导出插件
7.使用插件;
8.执行

4.3准备

创建功能包xxx导入依赖: roscpp pluginlib。

在 VSCode中需要配置 .vascode/c_cpp_properties.json文件中关于 includepath 选项的设置。

{"configurations": [{"browse": {"databaseFilename": "","limitSymbolsToIncludedHeaders": true},"includePath": ["/opt/ros/noetic/include/**","/usr/include/**","/.../yyy工作空间/功能包/include/**" //配置 head 文件的路径 ],"name": "ROS","intelliSenseMode": "gcc-x64","compilerPath": "/usr/bin/gcc","cStandard": "c11","cppStandard": "c++17"}],"version": 4
}

4.4创建基类

在 xxx/include/xxx下新建C++头文件: polygon_base.h,所有的插件类都需要继承此基类,内容如下:

#ifndef XXX_POLYGON_BASE_H_
#define XXX_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

注:基类必须提供无参构造函数,所以关于多边形的边长没有通过构造函数而是通过单独编写的initialize函数传参。

4.5创建插件

在 xxx/include/xxx下新建C++头文件:polygon_plugins.h,内容如下:

#ifndef XXX_POLYGON_PLUGINS_H_
#define XXX_POLYGON_PLUGINS_H_
#include <xxx/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

该文件中创建了正方形与三角形两个衍生类继承基类。

4.6注册插件

在 src 目录下新建 polygon_plugins.cpp 文件,内容如下:

//pluginlib 宏,可以注册插件类
#include <pluginlib/class_list_macros.h>
#include <xxx/polygon_base.h>
#include <xxx/polygon_plugins.h>//参数1:衍生类 参数2:基类
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon)
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Square, polygon_base::RegularPolygon)

该文件会将两个衍生类注册为插件。

4.7构建插件库

在 CMakeLists.txt 文件中设置内容如下:

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

至此,可以调用 catkin_make 编译,编译完成后,在工作空间/devel/lib目录下,会生成相关的 .so 文件。

4.8使插件可用于ROS工具链

4.8.1配置xml

功能包下新建文件:polygon_plugins.xml,内容如下:

<!-- 插件库的相对路径 -->
<library path="lib/libpolygon_plugins"><!-- type="插件类" base_class_type="基类" --><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>

4.8.2导出插件

package.xml文件中设置内容如下:

<export><xxx plugin="${prefix}/polygon_plugins.xml" />
</export>

标签的名称应与基类所属的功能包名称一致,plugin属性值为上一步中创建的xml文件。

编译后,可以调用rospack plugins --attrib=plugin xxx命令查看配置是否正常,如无异常,会返回 .xml 文件的完整路径,这意味着插件已经正确的集成到了ROS工具链。

4.9使用插件

src 下新建c++文件:polygon_loader.cpp,内容如下:

//类加载器相关的头文件
#include <pluginlib/class_loader.h>
#include <xxx/polygon_base.h>int main(int argc, char** argv)
{//类加载器 -- 参数1:基类功能包名称 参数2:基类全限定名称pluginlib::ClassLoader<polygon_base::RegularPolygon> poly_loader("xxx", "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;
}

4.10执行

修改CMakeLists.txt文件,内容如下:

add_executable(polygon_loader src/polygon_loader.cpp)
target_link_libraries(polygon_loader ${catkin_LIBRARIES})

编译然后执行:polygon_loader,结果如下:

[ INFO] [WallTime: 1279658450.869089666]: Triangle area: 43.30
[ INFO] [WallTime: 1279658450.869138007]: Square area: 100.00

参考视屏:赵虚左ros入门
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/29405.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

极值理论 EVT、POT超阈值、GARCH 模型分析股票指数VaR、条件CVaR:多元化投资组合预测风险测度分析...

全文链接&#xff1a;http://tecdat.cn/?p24182 本文用 R 编程语言极值理论 (EVT) 以确定 10 只股票指数的风险价值&#xff08;和条件 VaR&#xff09;&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 使用 Anderson-Darling 检验对 10 只股票的组合数据进行…

和chatgpt学架构02-环境搭建

目录 1 安装vs code2 vs code功能介绍3 安装nodejs4 安装vue5 在vs code打开工程总结 我们在上一篇 技术选型 里咨询了chatgpt前后端的框架选择和数据库的选择。有了框架之后就需要选择合适的开发工具了&#xff0c;继续咨询一下chatgpt 我现在选型&#xff0c;前端使用vue&am…

JavaScript 判断 null 、undefined、NaN的可靠方法、验证以及注意事项

索引 判断方法判断undefined判断null判断NaN 注意事项undefined和null和比较NaN和自己比较 有些时候需要判断类型是否为null、undefined或者NaN&#xff0c;常用的方法有以下&#xff1a; 判断方法 判断undefined 使用typeof typeof xxx undedfined注意&#xff1a;typeof…

【后端面经-Java】JVM垃圾回收机制

【后端面经-Java】JVM垃圾回收机制 1. Where&#xff1a;回收哪里的东西&#xff1f;——JVM内存分配2. Which&#xff1a;内存对象中谁会被回收&#xff1f;——GC分代思想2.1 年轻代/老年代/永久代2.2 内存细分 3. When&#xff1a;什么时候回收垃圾&#xff1f;——GC触发条…

若依cloud(RuoYi-Cloud)新增业务模块和功能模块增删改查演示

前言 看了几篇文章感觉都不太满意&#xff0c;索性自己来写一篇。 一、后端 后端新建业务模块流程大致如下&#xff1a; 1、后端新建一个&#xff08;在ruoyi-module模块下&#xff09;业务模块&#xff0c;仿照已有的模块将此模块配置好&#xff0c;例如仿照系统模块&…

CodeGeex论文阅读

《CodeGeeX: A Pre-Trained Model for Code Generation with Multilingual Evaluations on HumanEval-X》 论文地址&#xff1a;https://arxiv.org/pdf/2303.17568.pdf 代码地址&#xff1a;https://github.com/THUDM/CodeGe 一、简介 CodeGeeX&#xff0c;是一个具有130亿…

银河麒麟高级服务器操作系统V10安装mysql数据库

一、安装前 1.检查是否已经安装mysql rpm -qa | grep mysql2.将查询出的包卸载掉 rpm -e --nodeps 文件名3.将/usr/lib64/libLLVM-7.so删除 rm -rf /usr/lib64/libLLVM-7.so4.检查删除结果 rpm -qa | grep mysql5.搜索残余文件 whereis mysql6.删除残余文件 rm -rf /usr/b…

【多线程】(六)Java并发编程深度解析:常见锁策略、CAS、synchronized原理、线程安全集合类和死锁详解

文章目录 一、常见锁策略1.1 乐观锁和悲观锁1.2 读写锁1.3 重量级锁和轻量级锁1.4 自旋锁1.5 公平锁和非公平锁1.6 可重入锁和不可重入锁 二、CAS2.1 什么是CAS2.2 CAS的实现原理2.3 CAS应用2.4 ABA问题 三、synchronized原理3.1 synchronized锁的特点3.2 加锁工作过程3.3 锁消…

reggie优化06-项目部署

1、部署架构 2、部署环境 3、部署前端 4、部署后端 修改图片位置&#xff0c;并push至仓库

解决find: ‘/run/user/1000/gvfs’: 权限不够

问题描述 在用find查找对应的文件时&#xff0c;突然报错这个问题 解决办法 其实这个目录是空的&#xff0c;所以删除就好了执行下列操作&#xff1a; umount /run/user/1000/gvfs rm -rf /run/user/1000/gvfs 之后的查找中就没有了报错提示。

uniapp动态获取列表中每个下标的高度赋值给另一个数组(完整代码附效果图)

uniapp实现动态获取列表中每个下标的高度&#xff0c;赋值给另一个数组。 先看效果图&#xff1a; 完整代码&#xff1a; <template><div class""><div class"">我是A列表&#xff0c;我的高度不是固定的</div><div class&qu…

【MySQL】MySQL在Centos7环境下安装

目录 一、卸载不要的环境 1.1、查看是否有安装mysql 1.2、关闭运行的程序 1.3、卸载安装 二、配置yum 源 2.1、下载yum 源 2.2 安装yum源 2.3 查看是否已经生效 三、安装mysql服务 四、启动服务 五、登录方法 方法一&#xff08;不行就下一个&#xff09; 方法二&#xff08;不…