地图结构 | 详解八叉树Octomap原理与Rviz可视化

目录

  • 0 专栏介绍
  • 1 点云地图的局限性
  • 2 八叉树基本原理
  • 3 Octovis可视化
  • 4 点云转化octomap
  • 5 ROS Rviz可视化

0 专栏介绍

🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。

🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法


1 点云地图的局限性

在这里插入图片描述
在提到八叉树的概念前,先简要介绍点云图在三维导航问题中的局限性

  • 数据量大:三维点云地图通常包含大量的点数据,对存储能力提出了较高的要求;
  • 实时性差:点云地图的构建和更新需要时间,无法实时地反映环境的变化。在动态环境下,实时性差可能导致导航算法无法准确感知障碍物的位置和形状;
  • 处理复杂性高:点云地图的处理和匹配算法相对复杂,需要耗费大量计算资源才能进行高精度的定位和导航;
  • 数据密度不均匀:点云地图中的点分布并不均匀,有些区域可能较为稀疏,而其他区域则可能过于密集。这种不均匀性会导致导航算法在某些区域难以准确感知环境,影响导航的可靠性和精度;

类似于二维平面中栅格地图的概念,我们在三维空间中引入八叉树

2 八叉树基本原理

八叉树(Octree)将三维空间建模为一个立方体,不断将其分成同等大小的八个子立方体直至达到建模的最高精度,在数据结构层面表达为八叉树,如图所示。

在这里插入图片描述

八叉树的叶子节点是对三维空间的最小建模单位,称为体素(Voxel),因此八叉树支持分辨率调节。八叉树的占据概率更新与栅格地图相同,详见地图结构 | 图解占据栅格地图原理(附Matlab建图实验)

八叉树的每个体素亦有三种状态:

  • 占据
  • 空闲
  • 未知

当树结构某个节点的所有子节点都是同一状态时,可以只存储该节点信息而剪去其子节点,实现八叉树压缩以节省内存。此外,八叉树在地图拼接、更新也比点云地图更有优势。

接下来从代码层面更深入地理解八叉树是什么结构。

3 Octovis可视化

首先安装octomap

git clone https://github.com/OctoMap/octomap

并编译安装

cd octomap
mkdir build
cd build
cmake ..
make

接着使用octovis工具进行可视化

bin/octovis octomap/share/data/geb079.bt

在这里插入图片描述

右边的拉条用来调节八叉树分辨率,如下所示(从左往右分别是0.08、0.32、0.64 m m m),这就是八叉树比点云图方便的地方之一

4 点云转化octomap

点云转化为八叉树的原理是,提取点云坐标,接着在八叉树中更新相应位置的节点,核心代码如下

// 从pcd中提取点云
pcl::PointCloud<pcl::PointXYZRGBA> cloud;
pcl::io::loadPCDFile<pcl::PointXYZRGBA> (input_file, cloud);// 创建八叉树对象,参数为分辨率
octomap::OcTree tree(0.05);// 用点云更新八叉树
for (auto p:cloud.points)tree.updateNode( octomap::point3d(p.x, p.y, p.z), true );
tree.updateInnerOccupancy();// 存储八叉树
tree.writeBinary( output_file );

转化结果如下所示

  • 点云
    pcl_viewer data/sample.pcd
    

在这里插入图片描述

  • 八叉树
    bin/pcd2octomap data/sample.pcd data/test.bt
    octovis data/test.bt
    

在这里插入图片描述

如果想保留点云中的色彩信息,就创建带颜色的八叉树

pcl::PointCloud<pcl::PointXYZRGBA> cloud;
pcl::io::loadPCDFile<pcl::PointXYZRGBA> (input_file, cloud);// 创建带颜色的八叉树对象,参数为分辨率
octomap::ColorOcTree tree(0.05);// 用点云更新八叉树
for (auto p:cloud.points)tree.updateNode( octomap::point3d(p.x, p.y, p.z), true );// 设置颜色
for (auto p:cloud.points)tree.integrateNodeColor( p.x, p.y, p.z, p.r, p.g, p.b );tree.updateInnerOccupancy();// 存储octomap, 注意要存成.ot文件而非.bt文件
tree.write(output_file);

在这里插入图片描述

5 ROS Rviz可视化

Rviz可视化八叉树的整体流程很简单:

  • 数据源发布点云数据
  • octomap_server接收点云数据并转化为八叉树
  • Rviz可视化八叉树

发布点云数据采用以下节点

int main(int argc, char **argv)
{std::string pcd_path, frame_id, topic;int hz;ros::init(argc, argv, "publish_point_cloud");ros::NodeHandle nh("~");nh.param<std::string>("pcd_path", pcd_path, "test.pcd");nh.param<std::string>("frame_id", frame_id, "camera");nh.param<std::string>("topic", topic, "/point_cloud/output");nh.param<int>("hz", hz, 5);ros::Publisher pcl_pub = nh.advertise<sensor_msgs::PointCloud2>(topic, 10);pcl::PointCloud<pcl::PointXYZ> cloud;sensor_msgs::PointCloud2 output;pcl::io::loadPCDFile(pcd_path, cloud);pcl::toROSMsg(cloud, output);output.header.stamp = ros::Time::now();output.header.frame_id = frame_id;ros::Rate loop_rate(hz);while (ros::ok()){pcl_pub.publish(output);ros::spinOnce();loop_rate.sleep();}return 0;
}

可以在Rviz中先可视化点云,订阅/point_cloud/output话题即可

在这里插入图片描述

接着将点云数据映射到octomap_server的点云输入接口

<node pkg="octomap_server" type="octomap_server_node" name="octomap_server"><!-- resolution in meters per pixel --><param name="resolution" value="0.05" /><!-- name of the fixed frame, needs to be "/map" for SLAM --><param name="frame_id" type="string" value="camera" /><!-- max range / depth resolution of the kinect in meter --><param name="sensor_model/max_range" value="100.0" /><param name="latch" value="true" /><!-- max/min height for occupancy map, should be in meters --><param name="pointcloud_max_z" value="1000" /><param name="pointcloud_min_z" value="0" /><!-- topic from where pointcloud2 messages are subscribed --><remap from="/cloud_in" to="/point_cloud/output" />
</node>

接着即可在Rviz中可视化八叉树

在这里插入图片描述

八叉树可视化工具用的是官方插件,Rviz插件的使用参考ROS从入门到精通2-4:Rviz插件制作案例(以多点导航插件为例)

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


🔥 更多精彩专栏

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

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

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

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

相关文章

图像处理:双边滤波

1. 双边滤波 公式含义&#xff1a; q&#xff1a;输入的像素点&#xff0c;它代表上图中55的方框中其中的一个像素点 : 空间域核 : 图像像素域核 (两个二维高斯函数&#xff0c;二维高斯函数的公式为:) 进行了一些小的改动&#xff0c;让他们更加符合我们的要求&#xff0…

Java之String类

作者简介&#xff1a; zoro-1&#xff0c;目前大二&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; Java之String类 String的构造String底层String之间…

mysql 密码修改

1、使用mysqladmin修改root密码 使用 mysqladmin 命令修改 MySQL 的 root 用户密码格式为 mysqladmin -u用户名 -p旧密码 password 新密码 注意&#xff1a;下图修改密码的命令中 -uroot 和 -proot 是整体&#xff0c;不要写成 -u root -p root&#xff0c;-u 和 root 间可以加…

大模型赛道如何实现华丽的弯道超车【赠书活动|第十期《分布式统一大数据虚拟文件系统 Alluxio原理、技术与实践》】

文章目录 01 具备对海量小文件的频繁数据访问的 I/O 效率02 提高 GPU 利用率&#xff0c;降低成本并提高投资回报率03 支持各种存储系统的原生接口04 支持单云、混合云和多云部署01 通过数据抽象化统一数据孤岛02 通过分布式缓存实现数据本地性03 优化整个工作流的数据共享04 通…

服务器数据恢复-EVA存储多块硬盘磁头和盘片损坏离线的数据恢复案例

服务器数据恢复环境&#xff1a; HP EVA某型号存储&#xff0c;存储中一共有23块磁盘&#xff0c;上层映射给一台windows server服务器上。 服务器故障&检测&分析&#xff1a; 该EVA存储上三块硬盘指示灯显示黄色&#xff0c;此时存储设备还能正常工作。运维更换显示黄…

Linux日志管理-logrotate(crontab定时任务、Ceph日志转储)

文章目录 一、logrotate概述二、logrotate基本用法三、logrotate运行机制logrotate参数 四、logrotate是怎么做到滚动日志时不影响程序正常的日志输出呢&#xff1f;Linux文件操作机制方案一方案二 五、logrotate实战--Ceph日志转储参考 一、logrotate概述 logrotate是一个用于…

【八大经典排序算法】堆排序

【八大经典排序算法】堆排序 一、概述二、思路解读三、代码实现&#xff08;大堆为例&#xff09; 一、概述 堆排序是J.W.J. Williams于1964年提出的。他提出了一种利用堆的数据结构进行排序的算法&#xff0c;并将其称为堆排序。堆排序是基于选择排序的一种改进&#xff0c;通…

IOTE2023物联网展最新快讯|央企入驻,找物联网平台这一家就够了

IOTE 2023第20届国际物联网展深圳站即将于9月20-22日在深圳国际会展中心&#xff08;宝安&#xff09;启幕&#xff01;航天科技控股集团股份有限公司旗下AIRIOT物联网平台亮相【工业物联网展区9B31-1展位】。 AIRIOT物联网平台定位于通用型物联网技术框架产品&#xff0c;以软…

12306 抢票小助手: 完整易用的抢票解决方案 | 开源日报 0917

testerSunshine/12306 Stars: 31.4k License: MIT 12306 购票小助手是一个使用 Python 编写的项目&#xff0c;主要功能包括自动打码、自动登录、准点预售和捡漏、智能候补以及邮件通知等。该项目具有以下核心优势&#xff1a; 支持多个版本的 Python提供验证码本地识别功能可…

Flutter flutter.minSdkVersion的实际文件位置

Flutter 项目的Android相关版本号配置&#xff1a; flutter.minSdkVersion 的版本号配置文件实际路径&#xff1a; …/flutter_sdk/packages/flutter_tools/gradle/src/main/groovy/flutter.groovy Flutter版本号如下&#xff1a; bzbMacBook-Pro ccsmec % flutter --version …

【iOS】push与present Controller的区别

文章目录 前言一、push方法二、pop方法三、present方法四、dismiss方法五、dismiss多级的方法举例动画 前言 iOS推出与退出界面有两种方式——push与present&#xff0c;接下来笔者分别介绍这两种方式 一、push方法 SecondViewController *second [[SecondViewController all…

JMeter基础 —— 使用Badboy录制JMeter脚本!

1、使用Badboy录制JMeter脚本 打开Badboy工具开始进行脚本录制&#xff1a; &#xff08;1&#xff09;当我们打开Badboy工具时&#xff0c;默认就进入录制状态。 如下图&#xff1a; 当然我们也可以点击录制按钮进行切换。 &#xff08;2&#xff09;在地址栏中输入被测地…