ROS2从入门到精通5-1:详解代价地图与costmap插件编写(以距离场ESDF为例)

目录

  • 0 专栏介绍
  • 1 代价地图介绍
    • 1.1 基本概念
    • 1.2 代价定义
  • 2 代价地图配置
    • 2.1 通用配置
    • 2.2 障碍层配置
    • 2.3 静态层配置
    • 2.4 膨胀层配置
  • 3 代价地图插件案例
    • 3.1 构造地图插件类
    • 3.2 注册并导出插件
    • 3.3 编译与使用插件

0 专栏介绍

本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。

🚀详情:《ROS2从入门到精通》


1 代价地图介绍

1.1 基本概念

机器人导航必须依赖于地图,而SLAM构建的地图为静态地图,在导航中一般不可以直接使用,因为导航过程中障碍信息是可变的,因此地图信息需要时时更新。

在这里插入图片描述

代价地图就是ROS定义的用于动态导航的地图数据结构,其在静态地图基础上添加了一些辅助信息,主要分为以下图层:

  • 静态地图层(Static Map Layer):通常是由SLAM建立的静态地图
  • 障碍地图层(Obstacle Map Layer):用于动态记录传感器感知到的障碍信息
  • 膨胀层(Inflation Layer):在以上两层地图基础上进行障碍膨胀,主要目的是防止机器人靠近障碍物边缘时,因惯性、不规则形体等原因与障碍产生碰撞,因此需要让机器人充分远离障碍物
  • 其他图层(Other Layers):可以通过插件形式自定义代价地图层

1.2 代价定义

关于代价地图代价的定义,摘录官方说明:如图所示,横轴是距离机器人中心的距离,纵轴是代价地图中栅格的灰度值,灰度越高代价越大

  • 致命障碍:栅格值254,此时障碍物与机器人中心重叠,必然发生碰撞
  • 内切障碍:栅格值253,此时障碍物处于机器人的内切圆内,必然发生碰撞
  • 外切障碍:栅格值[128,252],此时障碍物处于其机器人的外切圆内,处于碰撞临界,不一定发生碰撞
  • 非自由空间:栅格值(0,127],此时机器人处于障碍物附近,属于危险警戒区,进入此区域,将来可能会发生碰撞
  • 自由区域:栅格值0,此处机器人可以自由通过
  • 未知区域:栅格值255,未探明是否有障碍物

在这里插入图片描述
看一个实例:其中紫色区域为致命障碍;浅蓝色区域为内切障碍;红色区域为外切障碍与非自由障碍空间,颜色越深代价越高;蓝色为自由空间。

在这里插入图片描述

2 代价地图配置

2.1 通用配置

通用配置如下所示:

ros__parameters:
	update_frequency: 1.0
	publish_frequency: 1.0
	global_frame: map
	robot_base_frame: base_link
	use_sim_time: True
	robot_radius: 0.22
	resolution: 0.05
	track_unknown_space: true
	plugins: ["static_layer", "obstacle_layer", "inflation_layer"]
  • global_frame:在全局/局部代价地图中的全局坐标系,一般全局设置为地图坐标系map,局部设置为里程计坐标系odom
  • robot_base_frame:机器人基坐标系通过global_framerobot_base_frame就可以计算两个坐标系间的变换,得知机器人在代价地图位置坐标
  • update_frequency:代价地图的更新频率
  • publish_frequency:代价地图的发布频率
  • robot_radius:机器人等效半径,单位是米

2.2 障碍层配置

obstacle_layer:
  plugin: "nav2_costmap_2d::ObstacleLayer"
  observation_sources: scan
  scan:
    topic: /scan
    max_obstacle_height: 2.0
    clearing: True
    marking: True
    data_type: "LaserScan"
    raytrace_max_range: 3.0
    raytrace_min_range: 0.0
    obstacle_max_range: 2.5
    obstacle_min_range: 0.0
  • observation_sources:设置导航中所使用的传感器,例如激光雷达、碰撞传感器、超声波传感器等。每个传感器需要进行配置:
    • sensor_frame:传感器坐标系名称
    • data_type:传感器数据类型
    • topic:传感器发布的话题名
    • marking:是否可使用该传感器来标记障碍物
    • clearing:是否可使用该传感器来清除障碍物标记
  • obstacle_range:设置机器人检测障碍物的最大范围,只有进入该范围内才把该障碍物当作影响路径规划和移动的障碍物

2.3 静态层配置

static_layer:
  plugin: "nav2_costmap_2d::StaticLayer"
  map_subscribe_transient_local: True

2.4 膨胀层配置

inflation_layer:
  plugin: "nav2_costmap_2d::InflationLayer"
  cost_scaling_factor: 3.0
  inflation_radius: 0.55
  • inflation_radius:膨胀半径,膨胀层会把障碍物代价膨胀直到该半径为止,一般将该值设置为机器人底盘的直径大小。如果机器人经常撞到障碍物就需要增大该值,若经常无法通过狭窄地方就减小该值,代价膨胀公式:

    exp(-1.0 * cost_scaling_factor * (distance_from_obstacle - inscribed_radius)) * (INSCRIBED_INFLATED_OBSTACLE - 1)

    其中,distance_from_obstacle - inscribed_radius是机器人到实际障碍物与内切圆半径之差(且该差值小于膨胀半径),INSCRIBED_INFLATED_OBSTACLE设定为254

  • cost_scaling_factor:膨胀过程代价比例系数,增大比例因子会降低代价

3 代价地图插件案例

然而,这些默认的图层可能并不能满足实际需要。举例而言,社交地图层(Social Costmap Layer)用于机器人在导航过程中考虑与人类之间的社交交互,这个层级允许机器人更加智能地导航,并遵循一些社交规则,以更好地与人类共享空间,避免产生不适或危险的行为;禁区地图层(Prohibition Costmap Layer)用于标记和表示机器人不能进入的区域。这个层级的作用是在机器人的导航过程中限制其进入特定的区域(例如高压区、悬崖边缘、深水区等),从而确保机器人在导航时遵守特定的规则和限制,防止可能的事故和损坏。

3.1 构造地图插件类

所有全局规划插件的基类是nav2_costmap_2d::Layer,该基类提供了7个纯虚方法来实现控制器插件,一个合法的控制插件必须覆盖这7个基本方法:

  • onInitialize()非必须覆盖:在插件初始化结束时调用。通常会在方法里声明ROS参数。任何需要初始化的操作都应该在该方法里完成。
  • updateBounds()必须覆盖:更新costmap层边界
  • updateCosts()必须覆盖:每次需要重新计算costmap时都会调用方法。它仅在其边界窗口内更新costmap层
  • matchSize()非必须覆盖:在每次更改地图大小时调用更新地图尺寸
  • onFootprintChanged()非必须覆盖:在每次更新机器人footprint位置时调用
  • reset()必须覆盖:重置costmap层
  • isClearable()必须覆盖:是否需要在该costmap层执行清除操作

按照上述标准,本文案例中ESDF地图插件的基本成员函数和变量如下所示

class DistanceLayer : public Layer
{
public:
  DistanceLayer() = default;
  virtual ~DistanceLayer() = default;

  void onInitialize() override;
  void updateBounds(double robot_x, double robot_y, double robot_yaw, double* min_x, double* min_y, double* max_x,
                    double* max_y) override;
  void updateCosts(nav2_costmap_2d::Costmap2D& master_grid, int min_i, int min_j, int max_i, int max_j) override;
  void reset() override;
  bool isClearable() override;
};

3.2 注册并导出插件

在创建了自定义地图插件的前提下,需要导出该控制器插件以便地图服务器可以在运行时正确地加载。在ROS2中,插件的导出和加载由pluginlib处理。

  • 源文件配置导出宏

    #include "pluginlib/class_list_macros.hpp"
    PLUGINLIB_EXPORT_CLASS(nav2_costmap_2d::DistanceLayer, nav2_costmap_2d::Layer)
    
  • 配置插件描述文件xxx_costmap_plugin.xml,例如本案例为distance_layer_costmap_plugin.xml文件。此XML文件包含以下信息:

    • library path:插件库名称及其位置;
    • class name:地图算法类的名称;
    • class type:地图算法类的类型;
    • base class:地图层基类的名称,统一为nav2_costmap_2d::Layer
    • description:插件的描述。

    实例如下

    <library path="esdf_plugin">
    	<class name="nav2_costmap_2d/DistanceLayer" type="nav2_costmap_2d::DistanceLayer" base_class_type="nav2_costmap_2d::Layer">
    	  <description>This is a nav2 distance layer plugin.</description>
    	</class>
    </library>
    
  • 配置CMakeLists.txt文件
    使用cmake函数pluginlib_export_plugin_description_file()来导出插件。这个函数会将插件描述文件安装到install/share目录中,并设置ament索引以使其可被发现,实例如下

    pluginlib_export_plugin_description_file(nav2_costmap_2d distance_layer_costmap_plugin.xml)
    
  • 配置package.xml描述文件,实例如下:

    <export>
      <build_type>ament_cmake</build_type>
      <nav2_core plugin="${prefix}/distance_layer_costmap_plugin.xml" />
    </export>
    

3.3 编译与使用插件

编译该插件软件包,接着通过配置文件使用插件。

参数的传递链如下:首先在simulation.launch.py中引用配置文件navigation.yaml

declare_params_file_cmd = DeclareLaunchArgument(
	'params_file',
	default_value=os.path.join(simulation_dir, 'config', 'navigation.yaml'),
	description='Full path to the ROS2 parameters file to use for all launched nodes')

接着在navigation.yaml中修改插件配置,默认如下,是用的是静态层、障碍层和膨胀层插件:

plugins: ["static_layer", "obstacle_layer", "inflation_layer"]
	obstacle_layer:
	  plugin: "nav2_costmap_2d::ObstacleLayer"
	  ...
	static_layer:
	  plugin: "nav2_costmap_2d::StaticLayer"
	  ...
	inflation_layer:
	  plugin: "nav2_costmap_2d::InflationLayer"
	  ...

将上述替换为自己的插件,本案例为:

plugins: ["static_layer", "obstacle_layer", "inflation_layer", "distance_layer"]
	distance_layer:
	  plugin: "nav2_costmap_2d/DistanceLayer"
	  ...
  obstacle_layer:
	  plugin: "nav2_costmap_2d::ObstacleLayer"
	  ...
	static_layer:
	  plugin: "nav2_costmap_2d::StaticLayer"
	  ...
	inflation_layer:
	  plugin: "nav2_costmap_2d::InflationLayer"
	  ...

接着运行即可看到距离层地图被发布

在这里插入图片描述

完整代码通过下方博主名片联系获取


🔥 更多精彩专栏

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【格密码基础】旋转格的性质

目录 一. 回顾ZSVP问题 二. 基于ZSVP问题的密码系统 三. 格基旋转与Gram矩阵 四. 补充矩阵QR分解 4.1 矩阵分解 4.2 举例 前序文章请参考&#xff1a; 【格密码基础】详解ZSVP问题-CSDN博客 一. 回顾ZSVP问题 根据之前的讨论我们知道解决ZSVP问题的计算复杂度为&#x…

链路追踪系列-01.mac m1 安装zipkin

下载地址&#xff1a;https://hub.docker.com/r/openzipkin/zipkin jelexjelexxudeMacBook-Pro zipkin-server % pwd /Users/jelex/Documents/work/zipkin-server 先启动Es: 可能需要先删除 /Users/jelex/dockerV/es/plugins 目录下的.DS_Store 当端口占用时再次启动&#x…

PostgreSQL 中如何处理数据的并发读写和锁等待超时?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何处理数据的并发读写和锁等待超时一、并发读写的基本概念&#xff08;一&#xff09;…

【日常记录】【插件】excel.js 的使用

文章目录 1. 引言2. excel.js2.1 创建工作簿和工作表2.2 excel文件的导出2.3 excel文件的导入2.4 列2.5 行2.6 添加行2.7 单元格2.8 给总价列设置自动计算(除表头行) 3. 总结参考链接 1. 引言 前端导出excel文件常用库一般是 excel.js 和 xlsx.js xlsx.js 导出数据确实方便&…

技术成神之路:设计模式(六)策略模式

1.介绍 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一系列算法&#xff0c;封装每一个算法&#xff0c;并使它们可以相互替换。策略模式使得算法的变化独立于使用算法的客户端。 2.主要作用 策略模式的主要作用是将算法或行为…

大数据基础:Hadoop之Yarn重点架构原理

文章目录 Hadoop之Yarn重点架构原理 一、Yarn介绍 二、Yarn架构 三、Yarn任务运行流程 四、Yarn三种资源调度器特点及使用场景 Hadoop之Yarn重点架构原理 一、Yarn介绍 Apache Hadoop Yarn(Yet Another Reasource Negotiator&#xff0c;另一种资源协调者)是Hadoop2.x版…

优化理论——迭代方法

线性回归建模 训练&#xff0c;预测 { ( x ( i ) , y ( i ) ) } \{(x^{(i)},y^{(i)})\} {(x(i),y(i))} ⼀个训练样本&#xff0c; { ( x ( i ) , y ( i ) ) ; i 1 , ⋯ , N } \{(x^{(i)},y^{(i)});i1,\cdots ,N\} {(x(i),y(i));i1,⋯,N} 训练样本集 { ( x 1 ( i ) , x 2 ( i…

爬虫管理解决方案:让数据收集变得高效且合规

一、为何数据收集的效率与合规性同等重要&#xff1f; 随着大数据技术的飞速发展&#xff0c;数据收集已成为企业决策与市场洞察的核心驱动力。然而&#xff0c;在信息海洋中精准捕捞的同时&#xff0c;如何确保这一过程既高效又不触碰法律的红线&#xff0c;是每个数据实践者…

vue实现动态图片(gif)

目录 1. 背景 2. 分析 3. 代码实现 1. 背景 最近在项目中发现一个有意思的小需求&#xff0c;鼠标移入一个盒子里&#xff0c;然后盒子里的图就开始动起来&#xff0c;就像一个gif一样&#xff0c;然后鼠标移出&#xff0c;再按照原来的变化变回去&#xff0c;就像变形金刚…

YOLOv5和LPRNet的车牌识别系统

车牌识别系统 YOLOv5和LPRNet的车牌识别系统结合了深度学习技术的先进车牌识别解决方案。该系统整合了YOLOv5目标检测框架和LPRNet文本识别模型 1. YOLOv5目标检测框架 YOLO是一种先进的目标检测算法&#xff0c;以其实时性能和高精度闻名。YOLOv5是在前几代基础上进行优化的…

树莓派关机

文件 shutdown.sh #!/usr/bin/bash sudo shutdown -r nowpython 文件开头添加 #!/usr/bin/python3

Apache AGE 从文件导入图

您可以使用以下说明从文件创建图形。本文档介绍了&#xff1a; 包含从文件加载图形的函数的当前分支的信息使图形从文件创建的函数的说明作为输入的加载函数的CSV文件的结构&#xff0c;以及相关的注意事项 以及从文件加载国家和城市的简单源代码示例。 用户可以通过两个步骤…

从课本上面开始学习的51单片机究竟有什么特点,在现在的市场上还有应用吗?

引言 51单片机&#xff0c;作为一种经典的微控制器&#xff0c;被广泛应用于各种嵌入式系统中。尽管如今ARM架构的高性能低成本单片机在市场上占据主导地位&#xff0c;但51单片机凭借其独特的优势依然在某些领域保持着应用价值。本文将深入探讨51单片机的特点、架构、应用以及…

信必优收到著名生命科学前沿客户表扬信

近日&#xff0c;信必优收到著名生命科学前沿客户表扬信&#xff0c;客户表扬信必优员工在岗位上勤奋敬业、积极主动&#xff0c;圆满完成了既定的工作任务&#xff0c;在多个项目上展现出卓越技术能力和团队合作精神&#xff1b;其对工作的热情和对质量的追求给整个团队树立了…

WEB07Vue+Ajax

1. Vue概述 Vue&#xff08;读音 /vjuː/, 类似于 view&#xff09;&#xff0c;是一款用于构建用户界面的渐进式的JavaScript框架&#xff08;官方网站&#xff1a;https://cn.vuejs.org&#xff09;。 在上面的这句话中呢&#xff0c;出现了三个词&#xff0c;分别是&#x…

05:中断

中断 1、定时器T0中断1.1、定时器中断触发1.2、案例&#xff1a;通过定时器T0中断来实现灯间隔1s亮灭 2、外部中断2.1、外部中断的触发2.2、案例&#xff1a;使用外部中断0通过震动传感器控制LED1的亮灭 1、当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求&#xf…

Linux 扩展硬盘容量

根分区的硬盘容量不够了需要添加容量 扩展硬盘容量前提是需要虚拟机关机才能进行以下操作 在虚拟中找到虚拟机设置 >> 点击硬盘 >> 选择扩展 >> 输入自已要扩展的大小 >> 确定 这些设置好之后&#xff0c;启动虚拟机 fdisk /dev/sda n p 三个回车…

数据库作业d8

要求&#xff1a; 一备份 1 mysqldump -u root -p booksDB > booksDB_all_tables.sql 2 mysqldump -u root -p booksDB books > booksDB_books_table.sql 3 mysqldump -u root -p --databases booksDB test > booksDB_and_test_databases.sql 4 mysql -u roo…

在Windows中搭建Docker环境Docker Desktop(保姆级)

在Windows中搭建Docker环境Docker Desktop&#xff08;保姆级&#xff09; 文章目录 在Windows中搭建Docker环境Docker Desktop&#xff08;保姆级&#xff09;一、Docker Desktop是什么&#xff1f;二、Docker Desktop下载与安装①&#xff1a;下载②&#xff1a;安装③&#…

HTTP背后的故事:理解现代网络如何工作的关键(一)

一.HTTP是什么 概念 &#xff1a; 1.HTTP ( 全称为 " 超文本传输协议 ") 是一种应用非常广泛的 应用层协议。 2.HTTP 诞生与1991年. 目前已经发展为最主流使用的一种应用层协议. 3.HTTP 往往是基于传输层的 TCP 协议实现的 . (HTTP1.0, HTTP1.1, HTTP2.0 均为 T…