• 本教程来自:Nav2中文网
  • Nav2交流社区:https://fishros.org.cn/forum
  • ROS2/Nav2千人交流群:(QQ)139707339
  • 更多精彩教程请关注微信公众号:鱼香ROS
  • 欢迎添加机器人小伊微信,解锁机器人学习特殊服务

编写新的二维代价地图(Costmap2D)插件

概述

本教程演示如何创建自己的简单的代价地图2D 插件 。 [校准@小鱼]

在开始本教程之前,请参考此 视频 ,其中包含有关代价地图2D层设计和插件基本操作原理的信息。 [校准@小鱼]

必要条件

假如ROS 2、Gazebo 和 TurtleBot3包是在安装或本地构建的。请确保 Nav 2项目也是在本地构建的,构建过程可以参考 编译和安装 。 [校准@小鱼]

教程步骤

1- 写一个新代价地图2D(Costmap2D)插件 [校准@小鱼]

为了方便演示,下面这个例子将创建代价地图(costmap)插件,然后放置重复代价梯度到costmap中。有注解代码可以找到本教程在 navigation2_tutorials 库的 nav2_gradient_costmap_plugin ROS 2d的包。当你自己想要创建2D代价地图插件时请参考它。 [校准@小鱼]

插件类 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_gridLayer 类为插件提供了一个内部成本图, costmap_ ,用于更新。的 master_grid 应更新值窗口边界使用以下更新方法: updateWithAddition()updateWithMax()updateWithOverwrite()updateWithTrueOverwrite() 。 [待校准@2058] 是 [校准@小鱼]
matchSize() 方法在每次更改地图大小时调用。 [校准@小鱼] 否 [校准@小鱼]
onFootprintChanged() 每次改变足迹(footprint)时都会调用方法。 [校准@小鱼] 否 [校准@小鱼]
reset() 在costmap重置时可能有任何代码被执行。 [校准@小鱼] 是 [校准@小鱼]

在我们的示例中,这些方法具有以下功能: [校准@小鱼]

  1. 参数 GradientLayer::onInitialize() 包含声明ROS参数的默认值: [校准@小鱼]
declareParameter("enabled", rclcpp::ParameterValue(true));
node_->get_parameter(name_ + "." + "enabled", enabled_);

并设置 need_recalculation_ 边界重新计算标志: [校准@小鱼]

need_recalculation_ = false;
  1. GradientLayer::updateBounds() 再次计算窗口边界,如果 need_recalculation_true 并且无视 need_recalculation_ 值而进行更新。 [校准@小鱼]
  2. 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]

这些参数在插件的头文件中定义。 [待校准@2071]

  1. GradientLayer::onFootprintChanged() just resets need_recalculation_ value. [待校准@2072]
  2. 参数GradientLayer::reset() method is dummy: it is not used in this example plugin. It remaining there since pure virtual function reset() in parent Layer class必须被推翻。 [待校准@2073]

2-Export GradientLayer plugin [待校准@2074]

书面插件将加载运行时基本父类然后将调用插件处理模块 (costmap2d的 LayeredCostmap )。Pluginlib打开给定插件在运行时提供方法导出类调用。机制类导出告诉pluginlib基本类中使用这些调用。这允许扩展应用插件不知道应用源代码或重新编译它。 [待校准@2075]

在我们的示例中,“nav2_gradent_costmap_plugin:: gradentlayer” 插件的类应作为“ nav2_costmap_2d:: layer” 基础类动态加载。为此,插件应按如下方式注册: [待校准@2076]

  1. 插件的类应该用加载类的基本类型注册。为此,应该将一个特殊的宏 PLUGINLIB_EXPORT_CLASS 添加到组成插件库的任何源文件中: [待校准@2077]
#include "pluginlib/class_list_macros.hpp"
PLUGINLIB_EXPORT_CLASS(nav2_gradient_costmap_plugin::GradientLayer, nav2_costmap_2d::Layer)

这部分通常放在写插件类的cpp文件的末尾 (在我们的例子中是 gradient_layer.cpp )。最好将这些行放在文件的末尾,但从技术上讲,您也可以放在顶部。 [待校准@2078]

  1. 插件的信息应该存储到插件描述文件中。这是通过在插件包中使用单独的XML (在我们的示例中是 gradient_plugins.xml ) 来完成的。此文件包含以下信息: [待校准@2079]
  • 参数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.xmlcostmap_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]

下一步,需要告知代价地图2D有关新插件的信息。的插件应添加到 plugin_namesplugin_types 列表 nav2_params.yaml 可选用 local_costmap / global_costmap 为了启用在运行时间控制器/规划器服务器。 plugin_names 列表包含插件对象的名称。这些名字可以是你想要的任何东西。 plugin_types 包含列在 plugin_names 对象中的类型。这些类型应对应于插件描述XML文件中指定的插件类的 name 字段。 [待校准@2090]

注解:
用Galactic或后, plugin_namesplugin_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

然后转到RViz,点击顶部的 “2D Pose Estimate” 按钮,指出地图上的位置,就像 入门 中描述的那样。机器人将被定位在地图上,结果应如下图所示。可以看到梯度成本图。还有两件值得注意的事情: 由 “梯度层::updateCosts()” 在其边界内的成本图和按梯度弯曲的全局路径动态更新: [待校准@2098]

【Nav2中文网】六、插件教程(一)编写新的二维代价地图(Costmap2D)插件相关推荐

  1. 我的世界服务器修改原版血量,我的世界服务器MythicMobs插件教程技能编写血量限制与触发几率...

    小编为大家带来了<我的世界>服务器MythicMobs插件教程技能编写血量限制与触发几率,由于这两个太简单了,又都是用来控制[触发器]的,所以就放在一起讲了. 1)血量限制 故名思议,就是 ...

  2. 基于Capacitor编写Ionic React二维码扫描应用

    在上一篇文章中,我们简要演示了如何使用capacitor-plugin-dynamsoft-barcode-reader构建跨平台二维码扫描应用.在本文中,我们将使用Ionic React来构建一个二 ...

  3. Ionic二维码扫码插件QR Scanner不能扫描一维码问题

    三款扫码插件优劣 在Ionic开发中经常需要用到扫码功能,这个时候就需要用到二维码扫码插件. 目前市面上主要提供了三款扫码的插件,具体的可以参考如下链接: Ionic2入门教程(十三)带你走近3款二维 ...

  4. Ionic二维码扫码插件QR Scanner不能扫描一维码问题(只解决了android)

    三款扫码插件优劣 在Ionic开发中经常需要用到扫码功能,这个时候就需要用到二维码扫码插件. 目前市面上主要提供了三款扫码的插件,具体的可以参考如下链接: Ionic2入门教程(十三)带你走近3款二维 ...

  5. php 二维数组根据键值合并二维数组_php数组根据某键值,把相同键值的合并最终生成一个新的二维数组...

    匿名用户 1级 2013-12-29 回答 php数组根据某一个键值,把相同键值的合并生成一个新的二维数组 源数据: $infos = array( array( 'a' => 36, 'b' ...

  6. js二维码样式生成插件easy.qrcode.js

    下载地址easy.qrcode.js二维码生成插件是一款原生js二维码类库,可以生产成各式各样的二维码样式.支持JavaScript模块化加载.支持点状风格,Logo,背景图片,规则色彩控制,标题等设 ...

  7. PHP将一个二维数组按照某个键的键值做出重组一个新的二维数组

    如下一个二维数组,将一个二维数组按照apname的 键值来排序组合成一个新的二维数组  apname 键值不变,其中其他几个红色划线部分进行组合. 构建好之后展现效果如下 使用了两种方式进行构建 方法 ...

  8. Spring Boot电商项目57:订单模块六:【前台:生成支付二维码】接口;(支付url的拼凑;利用zxing生成二维码;二维码图片的存储;真实地址与可访问地址的转换;)

    说明: (1)本篇博客主要内容是:开发[前台:生成支付二维码]接口: (2)本篇博客需要注意的点有: ● 支付url的拼凑: ● 利用zxing生成二维码: ● 二维码图片的存储:真实地址与可访问地址 ...

  9. eclipse 插件教程_编写Eclipse插件教程–第1部分

    eclipse 插件教程 Eclipse是三个最受欢迎的Java开发IDE之一. 其成功的原因之一是其可扩展性. 对于任何知道该怎么做并且已经做到的人来说,编写eclipse插件都可以非常轻松快捷. ...

最新文章

  1. 使用R构建随机森林回归模型(Random Forest Regressor)
  2. linux 卡在grub_安装Linux系统,Ubuntu时卡在这个界面不动了,有3个小时了。。显示:“正在运行update_grub”......
  3. 十万浙企上云 阿里云崛起的最大征候?
  4. 使用jstack 发现死锁
  5. angular 字符串转换成数字_Python | 一文看懂Python列表、元组和字符串操作
  6. 【直播预告 | 今天10:30】多媒体技术PI第三期:网络传输
  7. 33. 深入解析互联网协议的原理
  8. tomcat修改端口号后无法访问
  9. u2 接口 服务器硬盘,M.2、U.2谁更好?主流硬盘接口都有哪些?
  10. this command with --force, or --legacy-peer-deps
  11. 由浅入深的了解Groovy的基本使用
  12. 中考计算机易错知识点,中考语文常见的易错考点23个
  13. re- 正则表达操作
  14. 微信小程序播放背景音乐
  15. 我国亟待建立全国危化品安全监管大数据平台
  16. 【NLP】将机器学习应用于情感分析
  17. Logstash~filter.kv插件使用教程(附带示例)
  18. html 水平分割,HTML设置水平分割线
  19. gitee 从 拉取新分支到本地_git fetch 的简单用法:更新远程代码到本地仓库
  20. VB6播放MP3小程序

热门文章

  1. 零基础搭建属于自己的网站--网页设计【学习笔记8】
  2. windows p12(pfx)个人证书安装过程
  3. 一张图展示被动学习与主动学习的效率差距
  4. 05年大纲新增词汇(含中文释义)
  5. ls路由算法_路由算法详解
  6. CentOS VI命令自动显示行号
  7. 白斩鸡大佬指点的一些关键信息点
  8. swt/jface控件的隐藏与显示
  9. 使用OpenGL实现视频录制
  10. 惊!!!某地区,研究生公务员年薪80万!