ROS从入门到精通2-8:Gazebo仿真之快速生成二维地图真值

news2024/11/27 9:38:37

目录

  • 0 专栏介绍
  • 1 为什么需要地图真值?
  • 2 Gazebo插件实现
    • 2.1 单线扫描碰撞信息
    • 2.2 写入.pgm地图文件
    • 2.3 写入.yaml元文件
  • 3 快速建图测试
  • 4 机器人导航测试

0 专栏介绍

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

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


1 为什么需要地图真值?

栅格地图真值不会受到传感器误差、环境变化等因素的影响,导致地图的不确定性和误差。地图真值可以用作SLAM算法的评估指标,帮助研究人员和开发者了解SLAM算法在不同环境和条件下的性能表现。

通过将SLAM生成的地图与栅格地图真值进行对比,可以识别出SLAM算法的优势、局限性和改进方向,以及进行算法调试和参数优化。在一些对地图精度要求较高的应用中,使用栅格地图真值进行评估和对比可以提供更可靠的结果。同时,栅格地图真值可以用于生成合成数据集,从而扩大数据集的规模和多样性。通过将真实数据与栅格地图真值结合,可以创建具有不同特征、噪声和变化的合成数据集,用于训练和验证SLAM算法的鲁棒性和泛化能力。

如下所示是通过SLAM建立的地图(左)和对应的地图真值(右)

接下来介绍如何基于Gazebo世界场景,快速生成二维地图真值

2 Gazebo插件实现

2.1 单线扫描碰撞信息

原理是基于Gazebo的RayShape引擎,扫描一定高度下世界环境中的障碍物,并把障碍物信息映射到二维地图上。在仿真环境中,这种扫描绝对精准,因此建立的地图是真值地图

核心代码如下所示

gazebo::physics::PhysicsEnginePtr engine = world->Physics();
      engine->InitForThread();
gazebo::physics::RayShapePtr ray =
    boost::dynamic_pointer_cast<gazebo::physics::RayShape>(
        engine->CreateShape("ray", gazebo::physics::CollisionPtr()));

boost::gil::fill_pixels(image._view, blank);
for (int i = 0; i < count_vertical; ++i)
{
  x = i * dX_vertical + msg->lowerleft().x();
  y = i * dY_vertical + msg->lowerleft().y();
  for (int j = 0; j < count_horizontal; ++j)
  {
    x += dX_horizontal;
    y += dY_horizontal;

    start.X(x);
    end.X(x);
    start.Y(y);
    end.Y(y);
    ray->SetPoints(start, end);
    ray->GetIntersection(dist, entityName);
    if (!entityName.empty())
      image._view(i, j) = fill;
  }
}

2.2 写入.pgm地图文件

将扫描的障碍信息保存到.pgm地图文件中

void pgm_write_view(CollisionMapRequestPtr &msg, boost::gil::gray8_view_t &view)
{
  // Write image to pgm file
  std::cout << "running" << std::endl;
  int h = view.height();
  int w = view.width();

  std::ofstream ofs;
  ofs.open(msg->filename() + ".pgm");
  ofs << "P2" << '\n';          // grayscale
  ofs << w << ' ' << h << '\n'; // width and height
  ofs << 255 << '\n';           // max value
  for (int y = 0; y < h; ++y)
  {
    for (int x = 0; x < w; ++x)
      ofs << (int)view(x, y)[0] << ' ';
    ofs << '\n';
  }
  ofs.close();
}

2.3 写入.yaml元文件

保存用于导航的地图元文件

void yaml_write(CollisionMapRequestPtr &msg)
{
  std::string map_meta_file = msg->filename() + ".yaml";
  std::cout << "Writing map occupancy data to " << map_meta_file << std::endl;

  FILE *yaml = fopen(map_meta_file.c_str(), "w");

  // resolution: 0.100000
  // origin: [0.000000, 0.000000, 0.000000]
  // #
  // negate: 0
  // occupied_thresh: 0.65
  // free_thresh: 0.196

  fprintf(yaml,
          "image: %s\nresolution: %f\norigin: [%f, %f, 0.00]\nnegate: 0\noccupied_thresh: 0.65\nfree_thresh: 0.196\n\n",
          (msg->filename() + ".pgm").c_str(), msg->resolution(),
          msg->lowerleft().x(), msg->lowerleft().y());

  fclose(yaml);
}

3 快速建图测试

使用时在需要建图的.world文件中加入世界插件

<plugin filename="libcollision_map_creator.so" name="collision_map_creator"/>

接着启动一个终端打开三维世界

<launch>
  <arg name="world_file" default="$(find pgm_map_creator)/worlds/workshop.world"/>

  <include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="use_sim_time" value="true"/>
    <arg name="debug" value="false"/>
    <arg name="gui" value="true" />
    <arg name="world_name" value="$(arg world_file)"/>
  </include>
</launch>

最后在新终端启动扫描建图功能包,发送建图请求

<launch>
  <arg name="map_name" default="map" />
  <arg name="save_folder" default="$(find pgm_map_creator)/maps" />
  <arg name="xmin" default="-15" />
  <arg name="xmax" default="15" />
  <arg name="ymin" default="-15" />
  <arg name="ymax" default="15" />
  <arg name="scan_height" default="5" />
  <arg name="resolution" default="0.01" />

  <node pkg="pgm_map_creator" type="request_publisher" name="request_publisher" output="screen"
    args="'($(arg xmin),$(arg ymax))($(arg xmax),$(arg ymax))($(arg xmax),$(arg ymin))($(arg xmin),$(arg ymin))'
          $(arg scan_height) $(arg resolution) $(arg save_folder)/$(arg map_name)">
  </node>
</launch>

下面是两个建立地图真值的实例

在这里插入图片描述
在这里插入图片描述

4 机器人导航测试

建立的地图可以很好地应用于机器人导航,在部分运动规划实验中可以实现与建图过程的解耦

在这里插入图片描述

本文完整工程代码请通过下方名片联系博主获取


🔥 更多精彩专栏

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java项目之家用电器销售网站(源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的家用电器销售网站。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风歌&…

防火墙概述及实战

目录 前言 一、概述 &#xff08;一&#xff09;、防火墙分类 &#xff08;二&#xff09;、防火墙性能 &#xff08;三&#xff09;、iptables &#xff08;四&#xff09;、iptables中表的概念 二、iptables规则匹配条件分类 &#xff08;一&#xff09;、基本匹配条…

uniapp如何实现路由守卫、路由拦截,权限引导

因为uniapp路由的实现方式和以往vue开发的router路由时不太一样&#xff0c;故官方这么说&#xff1a; 经过一番网上冲浪发现&#xff0c;有两种方式可以实现&#xff0c; 第一种方式&#xff1a; 在上述代码中&#xff0c;我们通过监听beforeRouterEnter事件来实现路由守卫。…

TypeScript解读TSConfig

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 创建和基本配置 compilerOptions target module outDir strict lib sourceMap paths allowJs esModuleIn…

10_光速学会docker用法:80分钟一口气学完docker+k8s!带你掌握docker+k8s所有核心知识点,全程干货,无废话!

启动第一个docker容器 #1、获取镜像 #2、运行镜像&#xff0c;生成容器&#xff0c;应用就跑在了容器中。 Nginx web服务器&#xff0c;运行处一个80端口的网站 #在宿主机上&#xff0c;运行Nginx 1、开启服务器 2、在服务器上安装好运行Nginx所需的依赖关系 3、安装nginx …

Allegro如何导出带有钻孔数据的dxf文件?

在Allegro软件中&#xff0c;导出带有钻孔数据的DXF文件是一个常见的任务&#xff0c;特别是需要将涉及文件与其他CAD工具或PCB制造商共享时&#xff0c;所以下面将谈谈&#xff0c;如何在Allegro软件中导出带有钻孔数据的dxf文件。 1、打开设计文件 首先&#xff0c;打开Alle…

RISC Zero zkVM 白皮书

1. 引言 RISC Zero提供了开源的虚拟机零知识证明系统&#xff0c;即zero-knowledge virtual machine&#xff08;简称zkVM&#xff09;。当在zkVM中执行某RISC-V二进制文件时&#xff0c;其输出为&#xff1a; 二进制文件执行结果&#xff0b; 一个computational receipt&…

Unity中程序集dll

一&#xff1a;前言 一个程序集由一个或多个文件组成&#xff0c;通常为扩展名.exe和.dll的文件称为程序集&#xff0c;.exe是静态的程序集&#xff0c;可以在.net下直接运行加载&#xff0c;因为exe中有一个main函数(入口函数&#xff09;&#xff0c;.dll是动态链接库&#…

安装配置 zookeeper(单机版)

目录 一 准备并解压安装包 二 修改zoo.cfg文件 三 创建相应两个目录 四 创建文件myid 五 修改环境变量 六 启动 zookeeper 一 准备并解压安装包 这里提供了网盘资源 http://链接: https://pan.baidu.com/s/1BybwSQ_tQUL23OI6AWxwFw?pwdd4cf 提取码: d4cf 这里的安装包是…

市面上的ipad国产触控笔怎么样?开学性价比高的电容笔测评

由于Apple Pencil的问世&#xff0c;成为了iPad的一款便携式的生产力配件&#xff0c;它的优点是&#xff0c;与iPad相结合的电容笔&#xff0c;可以让专业的画师在iPad上画画&#xff0c;并且可以画出不同粗细的线条&#xff0c;这对需要书写的学生来说&#xff0c;是非常有用…

解决 SQLyog 连接 MySQL8.0+ 报错:错误号码2058

文章目录 一、问题现象二、原因分析三、解决方案1. 方案1&#xff1a;更新SQLyog版本2. 方案2&#xff1a;修改用户的授权插件3. 方案3&#xff1a;修复my.cnf 或 my.ini配置文件 四、最后总结 本文将总结如何解决 SQLyog 连接 MySQL8.0 时报错&#xff1a;错误号码2058 一、问…

数据可视化大屏模板 | 保姆级使用教程

近来很多朋友私信咨询怎么下载使用数据可视化大屏模板&#xff0c;在这里就给大家做一个相对简单的教程总结。有需要的朋友记得先收藏保存&#xff0c;以便不时之需。 数据可视化大屏制作软件&#xff1a;奥威BI系统 数据可视化报表模板板块&#xff1a;模板秀 主要操作&…

uni-app:实现条件判断展示图片(函数判定+三目运算)

一、多条件判断&#xff08;通过函数进行图片展示&#xff09; 效果 代码 在data中定义图片信息和要传递的数据信息&#xff0c;在src中写入函数并携带要传递的数据&#xff0c;通过传递的数据在函数中进行判断&#xff0c;并返回对应的图片信息 <template><view&…

vue中转换base64文件数据后通过blob下载

可以看到这里我要转换的数据是content字段&#xff0c;即将base64文件数据转换后下载下来&#xff1a; downloadAttachment({ attachmentId: id }).then(({ data }) > {proxy.$modal.closeLoading();// atob先解码base64数据const raw window.atob(data.content);// 获取解…

亚马逊小类目排名怎么看?亚马逊小类目是什么意思?——站斧浏览器

亚马逊的产品分类结构被分为多个级别&#xff0c;包括大类目、小类目和子类目。本文介绍了亚马逊小类目排名查看方式。 亚马逊小类目排名怎么看&#xff1f; 小类目排名是亚马逊为每个小类目中的商品分配的销售排名。它反映了在该小类目中的销售表现&#xff0c;通常以数字形…

Python编程指南:利用HTTP和HTTPS适配器实现智能路由

嗨&#xff0c;爬虫大佬们&#xff01;今天我要为大家分享一篇关于如何利用HTTP和HTTPS适配器来实现智能路由的Python编程指南。在现代互联网应用中&#xff0c;路由功能起着至关重要的作用&#xff0c;而利用Python编程语言实现智能路由则可以为我们的应用带来更高的灵活性和性…

LeetCode-热题100-笔记-day28

98. 验证二叉搜索树https://leetcode.cn/problems/validate-binary-search-tree/ 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点…

AI绘画:StableDiffusion实操教程-斗罗大陆-朱竹清(附高清图下载)

大家好&#xff0c;我是小梦&#xff0c;最近一直研究AI绘画。 不久前&#xff0c;我与大家分享了StableDiffusion的全面教程 然而&#xff0c;仍有些读者提出&#xff0c;虽然他们已经成功地安装了此工具&#xff0c;但生成的作品与我展示的相差较大。那么&#xff0c;如何缩…

TM1638的8个LED灯和8个数码管的使用

一、模块介绍 上图为使用的模块&#xff0c;顶部8个LED&#xff0c;8个数码管&#xff1b;中间TM1638芯片&#xff0c;右侧是8个二极管&#xff08;非发光二极管&#xff09;&#xff1b;最下方是8个按键。 电路图如下图所示 二、TM1638 1、数据传输格式 在传输数据时&#x…

Java“牵手”快手商品详情数据,快手商品详情接口,快手API接口申请指南

快手商城是快手小店平台和快手进口电商平台的公域导购场景&#xff0c;也是快手的在线购物平台。 用户打开快手APP后点击"商城"即可进入&#xff0c;在商城首页信息流、商城品类频道&#xff08;如女装、百货、家电频道等&#xff0c;其中&#xff0c;部分频道的商品…