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

news2024/11/16 13:55:58

目录

  • 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.coloradmin.cn/o/1019009.html

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

相关文章

Web 器学习笔记(基础)

Filter 过滤器 概念&#xff1a;表示过滤器&#xff0c;是 JavaWeb 三大组件&#xff08;Servlet、Filter、Listener&#xff09;之一 作用&#xff1a;顾名思义可以过滤资源的请求&#xff0c;并实现特殊的需求 Filter 接口及它核心的 doFilter() 方法&#xff08;执行前就是…

JVM 第一章:Java运行时数据区

目录 一.了解JVM 1.1什么是JVM 1.2JRE/JDK/JVM 1.3JVM的整体结构 二.Java运行时数据区 2.1程序计数器(PC寄存器) 2.2Java虚拟机栈&#xff08;Java Virtual Machine Stacks&#xff09; 2.2.1栈帧的组成 2.2.2问题辨析 2.2.3逃逸分析 ①栈上分配 ②标量分析 ③同步…

深入探究Spring自动配置原理及SPI机制:实现灵活的插件化开发

文章目录 前言SpringBootApplication 注解AutoConfigurationPackage 注解AutoConfigurationImportSelector SPI 机制和 SpringFactoriesLoaderJDK 中的 SPI 机制SpringFactoriesLoader ConditionalOn 系列条件注解ConditionalOn 系列条件注解的示例ConditionalOn 系列条件注解的…

MySQL中如何识别低效的索引

我是一个目录 前言(可以跳过直接看正文)索引的基本原理索引设计的原则创建索引的原则 正文使用索引查询一定能提高查询的性能吗&#xff1f;怎样查看索引是否有高选择性&#xff1f;用一条SQL查看低效的索引 前言(可以跳过直接看正文) 索引的基本原理 索引用来快速地寻找那些…

学习分布式第一天(分布式系统原理和概念)

目录 分布式系统原理和概念 1.分布式系统&#xff1a; 单体架构&#xff1a; 垂直架构&#xff1a; 分布式架构&#xff1a; 2.分布式计算&#xff1a; 3.CAP 原理&#xff1a; 4.BASE 理论&#xff1a; 5.Paxos 算法&#xff1a; 6.Raft 算法&#xff1a; 分布式系统原…

【Transformer系列】深入浅出理解Transformer网络模型(综合篇)

一、参考资料 The Illustrated Transformer 图解Transformer&#xff08;完整版&#xff09; Attention Is All You Need: The Core Idea of the Transformer transformer 总结(超详细-初版) Transformer各层网络结构详解&#xff01;面试必备&#xff01;(附代码实现) 大语言…

zemax球差与消球差

基础设置&#xff1a; 效果&#xff1a; 光线光扇图&#xff1a; 可见存在球差&#xff08;具体分析看我的另一篇文章&#xff0c;专门介绍光线光扇图&#xff09; 弥散的像&#xff1a; 定量计算赛德尔像差系数&#xff1a; 矫正&#xff1a; 凹凸透镜补偿法、非球面校正球差…

线上论坛之单元测试

对线上论坛进行单元测试的测试报告 源码地址&#xff1a;https://gitee.com/coisini-thirty-three/forum 一、用户部分&#xff08;UserServiceImplTest&#xff09; 1.创建普通用户 测试名称 createNormalUser() 测试源码 Test void createNormalUser() { // 构造用户 User …

Linux 系统目录结构 终端

系统目录结构 Linux 或 Unix 操作系统中&#xff0c;所有文件和目录呈一个以根节点为始的倒置的树状结构。文件系统的最顶层是根目录&#xff0c;用 / 来表示根目录。在根目录之下的既可以是目录&#xff0c;也可以是文件&#xff0c;而每一个目录中又可以包含子目录文件。如此…

什么是函数式编程(functional programming)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 函数式编程⭐ 核心概念⭐ 函数式编程示例⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前…

解决WSL2占用内存过多问题(Docker on WSL2: VmmemWSL)

解决WSL2占用内存过多问题&#xff08;Docker on WSL2: VmmemWSL&#xff09; 一、问题描述二、问题解决2.1 创建.wslconfig文件2.2 重启wsl2 一、问题描述 安装完WSL2后&#xff0c;又安装了Docker&#xff0c;使用了一段时间&#xff0c;发现电脑变卡&#xff0c;进一步查看…

voliate实战:voliate可见性验证有序性非原子性验证

一、可见性验证 下面的程序验证了voliate的可见性。 public class VolatileVisibilityTest {private static volatile boolean inintFlag false;public static void main(String[] args) throws InterruptedException {new Thread(() -> {System.out.println("waiti…

Springboot-mybatis创建项目报错day01

problem01 出现springboot引入mbatis-plus依赖单元测试时出现 Error:(3, 44) java: 程序包com.baomidou.mybatisplus.core.mapper不存在。 Error querying database. Cause: org.springframework.jdbc.CannotGetJdbcConnectionException:异常。 solution 点击右边侧栏Maven的Ge…

在visual studio里安装Python并创建python工程

在2009年&#xff0c;云计算开始发力&#xff0c;Python、R、Go这些天然处理批量计算的语言也迅猛发展。微软在2010年&#xff0c;把Python当成一个语言包插件&#xff0c;集成到了visual studio 2010里。在"云优先&#xff0c;移动优先"的战略下&#xff0c;于2015年…

直方图规定化,计算 SML 映射(数字图像处理大题复习 P3)

文章目录 1. 累计直方图概率2. 累计规定直方图3. 根据累计直方图概率和累计规定直方图 计算 SML 映射4. 计算变化后直方图结果 1. 累计直方图概率 我们最终的目的是从 表 1 变成 表 2 首先我们仍要先求出累计直方图概率 2. 累计规定直方图 把规定直方图抄到下面 然后我们…

Python入门教学——self

1、简介 我们知道在创建类的实例方法时&#xff0c;需要传入一个self&#xff0c;不然就会报错。那么这个self是什么呢&#xff1f;有什么作用呢&#xff1f; def 方法名(self,args): # args为参数pass 在Python类中规定&#xff0c;函数的第一个参数是实例对象本身&#xff…

FreeRTOS进阶-任务管理实践

一、使用接口函数创建任务 1.动态创建 xTaskCreate() 函数原型&#xff1a; BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数 const char * const pcName, // 任务的名字 const configSTACK_DEPTH_T…

渗透测试之漏洞挖掘指南(一)

1.漏洞挖掘中什么漏洞最多&#xff1f; 新手想快速挖掘到漏洞&#xff0c;要专注在业务逻辑与前端漏洞 -- 业务逻辑 &#xff08;弱密码&#xff0c;等等&#xff09; -- 前端漏洞 &#xff08;xss, csrf , cors, jsonp...&#xff09; 2. 常见漏洞提交平台 注册应急响应中…

投资理财基础知识:指数基金定投是什么?

大家好&#xff0c;我是财富智星&#xff0c;今天跟大家分享一下投资理财基础知识&#xff1a;指数基金定投是什么&#xff1f; 首先&#xff0c;你需要进行理财风险偏好测试&#xff0c;以确定自己的类型。风险偏好一般分为保守型、稳健型、平衡型、进取型和激进型。每个人对风…

C# 实现迷宫游戏

智能提示&#xff1a; /// <summary>/// 迷宫/// </summary>internal class Maze : IDisposable{private MazeCell[,] cells;private readonly Stack<MazeCell> stack new Stack<MazeCell>();private readonly Random rand new Random();private int…