【Nav2中文网】六、插件教程(一)编写新的二维代价地图(Costmap2D)插件
- 本教程来自:Nav2中文网
- Nav2交流社区:https://fishros.org.cn/forum
- ROS2/Nav2千人交流群:(QQ)139707339
- 更多精彩教程请关注微信公众号:鱼香ROS
- 欢迎添加机器人小伊微信,解锁机器人学习特殊服务
编写新的二维代价地图(Costmap2D)插件
概述
本教程演示如何创建自己的简单的代价地图2D 插件 。 [校准@小鱼]
在开始本教程之前,请参考此 视频 ,其中包含有关代价地图2D层设计和插件基本操作原理的信息。 [校准@小鱼]
必要条件
假如ROS 2、Gazebo 和 TurtleBot3包是在安装或本地构建的。请确保 Nav 2项目也是在本地构建的,构建过程可以参考 编译和安装 。 [校准@小鱼]
教程步骤
1- 写一个新代价地图2D(Costmap2D)插件 [校准@小鱼]
插件类 nav2_gradient_costmap_plugin::GradientLayer
继承于基类 nav2_costmap_2d::Layer
: [校准@小鱼]
namespace nav2_gradient_costmap_plugin
{class GradientLayer : public nav2_costmap_2d::Layer
基类提供了一系列虚函数 API处理costmap层插件。这些函数在运行 LayeredCostmap
时被调用 。函数列表,在插件的代码中的描述和是否必须实现情况见下表: [校准@小鱼]
Virtual method | 方法描述 | 必须重写? |
---|---|---|
onInitialize() | 方法在插件初始化结束时调用。通常会在方法里声明ROS参数。任何需要初始化的操作都应该在该方法里完成。 [校准@小鱼] | 否 [校准@小鱼] |
updateBounds() | 方法问插件: 面积costmap层需要更新。有3输入参数方法: 机器人位置和定位4输出参数: 指针窗口边界。这些边界用于性能原因: 更新区域内窗口是新信息,避免更新整个costmap每次迭代。 [待校准@2056] | 是 [校准@小鱼] |
updateCosts() |
每次需要重新计算costmap时都会调用方法。它仅在其边界窗口内更新costmap层。方法有4个输入参数: 计算窗口边界和1个输出参数: 参考结果costmap master_grid 。 Layer 类为插件提供了一个内部成本图, costmap_ ,用于更新。的 master_grid 应更新值窗口边界使用以下更新方法: updateWithAddition() , updateWithMax() , updateWithOverwrite() 或 updateWithTrueOverwrite() 。 [待校准@2058]
|
是 [校准@小鱼] |
matchSize() | 方法在每次更改地图大小时调用。 [校准@小鱼] | 否 [校准@小鱼] |
onFootprintChanged() | 每次改变足迹(footprint)时都会调用方法。 [校准@小鱼] | 否 [校准@小鱼] |
reset() | 在costmap重置时可能有任何代码被执行。 [校准@小鱼] | 是 [校准@小鱼] |
declareParameter("enabled", rclcpp::ParameterValue(true));
node_->get_parameter(name_ + "." + "enabled", enabled_);
并设置 need_recalculation_
边界重新计算标志: [校准@小鱼]
need_recalculation_ = false;
GradientLayer::updateBounds()
再次计算窗口边界,如果need_recalculation_
值true
并且无视need_recalculation_
值而进行更新。 [校准@小鱼]GradientLayer::updateCosts()
- 在这个方法中,是没有与前一图层合并,而是直接写入梯度到产生的成本地图master_grid
。 这相当于内部工作costmap_
并且调用updateWithTrueOverwrite()
方法。以下是主成本图的梯度制作算法: [校准@小鱼]
int gradient_index;
for (int j = min_j; j < max_j; j++) {// Reset gradient_index each time when reaching the end of re-calculated window// by OY axis.gradient_index = 0;for (int i = min_i; i < max_i; i++) {int index = master_grid.getIndex(i, j);// setting the gradient costunsigned char cost = (LETHAL_OBSTACLE - gradient_index*GRADIENT_FACTOR)%255;if (gradient_index <= GRADIENT_SIZE) {gradient_index++;} else {gradient_index = 0;}master_array[index] = cost;}
}
其中 GRADIENT_SIZE
是地图单元中每个梯度周期的大小, GRADIENT_FACTOR
-每一步的成本图值的递减: [待校准@2070]
GradientLayer::onFootprintChanged()
just resetsneed_recalculation_
value. [待校准@2072]- 参数
GradientLayer::reset()
method is dummy: it is not used in this example plugin. It remaining there since pure virtual functionreset()
in parentLayer
class必须被推翻。 [待校准@2073]
2-Export GradientLayer plugin [待校准@2074]
#include "pluginlib/class_list_macros.hpp"
PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, nav2_costmap_2d::Layer)
这部分通常放在写插件类的cpp文件的末尾 (在我们的例子中是 gradient_layer.cpp
)。最好将这些行放在文件的末尾,但从技术上讲,您也可以放在顶部。 [待校准@2078]
- 参数
path
:路径和名称库插件放置。 [待校准@2080]- 参数
name
: 关于插件类型可以参考plugin_types
parameter (详见下一节)。它可以是你想要的任何东西。 [待校准@2081]- 参数
type
:插件类命名空间从源代码。 [待校准@2082]- 参数
basic_class_type
:基本父类plugin类导出。 [待校准@2083]- 参数
description
:插件描述文本形式。 [待校准@2084]
<library path="nav2_gradient_costmap_plugin_core"><class name="nav2_gradient_costmap_plugin/GradientLayer" type="nav2_gradient_costmap_plugin::GradientLayer" base_class_type="nav2_costmap_2d::Layer"><description>This is an example plugin which puts repeating costs gradients to costmap</description></class>
</library>
插件的导出是通过将 pluginlib_export_plugin_description_file()
cmake函数包含到 CMakeLists.txt
中来执行的。此函数将插件描述文件安装到 share
目录中,并设置插件描述XML的属性索引,以便作为所选类型的插件发现: [待校准@2085]
pluginlib_export_plugin_description_file(nav2_costmap_2d gradient_layer.xml)
插件描述文件也应该添加到 package.xml
。 costmap_2d
是包的接口定义,我们机箱 Layer
,需要路径xml文件: [待校准@2086]
<export><costmap_2d plugin="${prefix}/gradient_layer.xml" />...
</export>
一切完成后把插件封装成 src
目录一定ROS 2-workspace,构建插件包 ( colcon build --packages-select nav2_gradient_costmap_plugin --symlink-install
) 和源 setup.bash
文件有必要。 [待校准@2087]
现在插件可以使用了。 [待校准@2088]
3-在代价地图2D中启用插件 [待校准@2089]
注解:
用Galactic或后,plugin_names
和plugin_types
替换单个plugins
string载体插件名称。类型现在定义在plugin_name
命名空间 ‘‘plugin:field (e.g.
插件: MyPlugin: Plugin’’)。内联注释代码块将帮助您通过这个。 [待校准@2091]
例如: [待校准@2092]
--- a/nav2_bringup/bringup/params/nav2_params.yaml
+++ b/nav2_bringup/bringup/params/nav2_params.yaml
@@ -124,8 +124,8 @@ local_costmap:width: 3height: 3resolution: 0.05
- plugin_names: ["obstacle_layer", "voxel_layer", "inflation_layer"] # For Eloquent and earlier
- plugin_types: ["nav2_costmap_2d::ObstacleLayer", "nav2_costmap_2d::VoxelLayer", "nav2_costmap_2d::InflationLayer"] # For Eloquent and earlier
+ plugin_names: ["obstacle_layer", "voxel_layer", "gradient_layer"] # For Eloquent and earlier
+ plugin_types: ["nav2_costmap_2d::ObstacleLayer", "nav2_costmap_2d::VoxelLayer", "nav2_gradient_costmap_plugin/GradientLayer"] # For Eloquent and earlier
- plugins: ["obstacle_layer", "voxel_layer", "inflation_layer"] # For Foxy and later
+ plugins: ["obstacle_layer", "voxel_layer", "gradient_layer"] # For Foxy and laterrobot_radius: 0.22inflation_layer:cost_scaling_factor: 3.0
@@ -171,8 +171,8 @@ global_costmap:robot_base_frame: base_linkglobal_frame: mapuse_sim_time: True
- plugin_names: ["static_layer", "obstacle_layer", "voxel_layer", "inflation_layer"] # For Eloquent and earlier
- plugin_types: ["nav2_costmap_2d::StaticLayer", "nav2_costmap_2d::ObstacleLayer", "nav2_costmap_2d::VoxelLayer", "nav2_costmap_2d::InflationLayer"] # For Eloquent and earlier
+ plugin_names: ["static_layer", "obstacle_layer", "voxel_layer", "gradient_layer"] # For Eloquent and earlier
+ plugin_types: ["nav2_costmap_2d::StaticLayer", "nav2_costmap_2d::ObstacleLayer", "nav2_costmap_2d::VoxelLayer", "nav2_gradient_costmap_plugin/GradientLayer"] # For Eloquent and earlier
- plugins: ["static_layer", "obstacle_layer", "voxel_layer", "inflation_layer"] # For Foxy and later
+ plugins: ["static_layer", "obstacle_layer", "voxel_layer", "gradient_layer"] # For Foxy and laterrobot_radius: 0.22resolution: 0.05obstacle_layer:
YAML-file还可能包含每个插件的参数列表 (如果有),由插件对象名称标识。 [待校准@2093]
注意: 可能有许多同时加载的一种类型的插件对象。为此, plugin_names
列表应包含不同的插件名称,无论 plugin_types
是否保持相同类型。例如: [待校准@2094]
plugin_names: ["obstacle_layer", "gradient_layer_1", "gradient_layer_2"] # For Eloquent and earlier
plugin_types: ["nav2_costmap_2d::ObstacleLayer", "nav2_gradient_costmap_plugin/GradientLayer", "nav2_gradient_costmap_plugin/GradientLayer"] # For Eloquent and earlier
plugins: ["obstacle_layer", "gradient_layer_1", "gradient_layer_2"] # For Foxy and later
在这种情况下,每个插件对象将由其自己的YAML文件中的参数树处理,例如: [待校准@2095]
gradient_layer_1:plugin: nav2_gradient_costmap_plugin/GradientLayer # For Foxy and laterenabled: True...
gradient_layer_2:plugin: nav2_gradient_costmap_plugin/GradientLayer # For Foxy and laterenabled: False...
4-运行梯度层(GradientLayer )插件 [校准@小鱼]
运行Turtlebot3 仿真启用Nav2。如果你不知道如何仿真,请参考 入门 。下面是一些快捷命令: [校准@小鱼]
$ ros2 launch nav2_bringup tb3_simulation_launch.py
【Nav2中文网】六、插件教程(一)编写新的二维代价地图(Costmap2D)插件相关推荐
- 我的世界服务器修改原版血量,我的世界服务器MythicMobs插件教程技能编写血量限制与触发几率...
小编为大家带来了<我的世界>服务器MythicMobs插件教程技能编写血量限制与触发几率,由于这两个太简单了,又都是用来控制[触发器]的,所以就放在一起讲了. 1)血量限制 故名思议,就是 ...
- 基于Capacitor编写Ionic React二维码扫描应用
在上一篇文章中,我们简要演示了如何使用capacitor-plugin-dynamsoft-barcode-reader构建跨平台二维码扫描应用.在本文中,我们将使用Ionic React来构建一个二 ...
- Ionic二维码扫码插件QR Scanner不能扫描一维码问题
三款扫码插件优劣 在Ionic开发中经常需要用到扫码功能,这个时候就需要用到二维码扫码插件. 目前市面上主要提供了三款扫码的插件,具体的可以参考如下链接: Ionic2入门教程(十三)带你走近3款二维 ...
- Ionic二维码扫码插件QR Scanner不能扫描一维码问题(只解决了android)
三款扫码插件优劣 在Ionic开发中经常需要用到扫码功能,这个时候就需要用到二维码扫码插件. 目前市面上主要提供了三款扫码的插件,具体的可以参考如下链接: Ionic2入门教程(十三)带你走近3款二维 ...
- php 二维数组根据键值合并二维数组_php数组根据某键值,把相同键值的合并最终生成一个新的二维数组...
匿名用户 1级 2013-12-29 回答 php数组根据某一个键值,把相同键值的合并生成一个新的二维数组 源数据: $infos = array( array( 'a' => 36, 'b' ...
- js二维码样式生成插件easy.qrcode.js
下载地址easy.qrcode.js二维码生成插件是一款原生js二维码类库,可以生产成各式各样的二维码样式.支持JavaScript模块化加载.支持点状风格,Logo,背景图片,规则色彩控制,标题等设 ...
- PHP将一个二维数组按照某个键的键值做出重组一个新的二维数组
如下一个二维数组,将一个二维数组按照apname的 键值来排序组合成一个新的二维数组 apname 键值不变,其中其他几个红色划线部分进行组合. 构建好之后展现效果如下 使用了两种方式进行构建 方法 ...
- Spring Boot电商项目57:订单模块六:【前台:生成支付二维码】接口;(支付url的拼凑;利用zxing生成二维码;二维码图片的存储;真实地址与可访问地址的转换;)
说明: (1)本篇博客主要内容是:开发[前台:生成支付二维码]接口: (2)本篇博客需要注意的点有: ● 支付url的拼凑: ● 利用zxing生成二维码: ● 二维码图片的存储:真实地址与可访问地址 ...
- eclipse 插件教程_编写Eclipse插件教程–第1部分
eclipse 插件教程 Eclipse是三个最受欢迎的Java开发IDE之一. 其成功的原因之一是其可扩展性. 对于任何知道该怎么做并且已经做到的人来说,编写eclipse插件都可以非常轻松快捷. ...
最新文章
- 使用R构建随机森林回归模型(Random Forest Regressor)
- linux 卡在grub_安装Linux系统,Ubuntu时卡在这个界面不动了,有3个小时了。。显示:“正在运行update_grub”......
- 十万浙企上云 阿里云崛起的最大征候?
- 使用jstack 发现死锁
- angular 字符串转换成数字_Python | 一文看懂Python列表、元组和字符串操作
- 【直播预告 | 今天10:30】多媒体技术PI第三期:网络传输
- 33. 深入解析互联网协议的原理
- tomcat修改端口号后无法访问
- u2 接口 服务器硬盘,M.2、U.2谁更好?主流硬盘接口都有哪些?
- this command with --force, or --legacy-peer-deps
- 由浅入深的了解Groovy的基本使用
- 中考计算机易错知识点,中考语文常见的易错考点23个
- re- 正则表达操作
- 微信小程序播放背景音乐
- 我国亟待建立全国危化品安全监管大数据平台
- 【NLP】将机器学习应用于情感分析
- Logstash~filter.kv插件使用教程(附带示例)
- html 水平分割,HTML设置水平分割线
- gitee 从 拉取新分支到本地_git fetch 的简单用法:更新远程代码到本地仓库
- VB6播放MP3小程序