八叉樹地圖的原理與實現

八叉樹與體素圖

八叉樹地圖

八叉樹地圖是可變分辨率的三維柵格地圖,可以自由調整分辨率,如下所示:

根據點云的數量或密度決定每個葉子方塊是否被占據

體素圖

體素就是固定分辨率的三維柵格地圖,如下所示:

根據點云的數量或密度決定每個體素是否被占據

八叉樹地圖與體素圖的區別

最大的區別是八叉樹地圖是可變分辨率,體素圖是固定分辨率,也就是說,在一定大小的三維空間內,體素圖是按照最小的分割體積,將空間完整分割表達,數據結構簡單,不過存儲量更多一些,但是建圖速度更快。

八叉樹地圖使用八叉樹的數據結構來存儲,對于一些沒有點云或點云數量極少的空區域,可以不進行展開分割,只存儲這一大塊體積,而對點云有效,密集的區域進行進一步的分割存儲,也就是所說的可變分辨率,這樣做減少存儲量,但數據結構復雜,通常情況下建圖速度沒有體素圖快

八叉樹地圖適合做大地圖的建模,因為地圖較大的情況下,體素圖會占據大量的空間,不利于存儲,因此八叉樹地圖適合做全局地圖建模,用于做全局規劃

體素圖因為數據結構簡單,建模速度快,因此適合做局部小地圖的建模,用于局部規劃,做動態避障。

八叉樹代碼實現

以下是使用matlab編寫的一個八叉樹的實現

靜態創建八叉樹(點云固定空間大小)

主循環文件:

%*************************************************************************%%使用遞歸的方式根據真實點云數據靜態創建八叉樹(地圖固定,不會越界)
%**********************************************************************%
clc;
clear;
%**********讀取點云數據并進行下采樣**********%
figure
filename = 'cloud.pcd';
pointCloud = pcread(filename);
% 下采樣參數設置
gridSize = 2; % 下采樣網格大小,根據需要進行調整  數值越大,砍掉的點越多
% 執行下采樣
downsampledPtCloud = pcdownsample(pointCloud, 'gridAverage', gridSize);
[p_num, n] = size(downsampledPtCloud.Location);
pcshow(pointCloud);
% %顯示下采樣地圖
% figure
% pcshow(downsampledPtCloud);
%****************建立八叉樹**************%
%計算八叉樹的根節點需要用到的參數
x_min = min(downsampledPtCloud.Location(:, 1));
y_min = min(downsampledPtCloud.Location(:, 2));
z_min = min(downsampledPtCloud.Location(:, 3));
x_max = max(downsampledPtCloud.Location(:, 1));
y_max = max(downsampledPtCloud.Location(:, 2));
z_max = max(downsampledPtCloud.Location(:, 3));
%以xyz點中最大最小值差異最大的作為邊長
x_side = (x_max - x_min);
y_side = (y_max - y_min);
z_side = (z_max - z_min);
side = [x_side y_side z_side];
side_len = max(side) + 1;
%創建八叉樹圖
figure
xlabel('x');
ylabel('y');
zlabel('z');
view(3);  %設定為三維視角
Root = struct();   %創建一個空結構體
Root.isLeaf = false;  %是否是葉子節點 (葉子節點可能是障礙物,也可能不是)
Root.isOccupiedLeaf = false;  %是否是占據葉子
Root.value = 1;  %1表示有點云數據,可以繼續分割
Root.index = 1;  %bitshift表示移位  編號,每一位分為8個節點,每一位的編號代表其位置
Root.x = x_min + x_side / 2;  %此節點方格的中心坐標
Root.y = y_min + y_side / 2;
Root.z = z_min + z_side / 2;
Root.level = 0;  %當前層數 根節點為第0層
Root.side_len = side_len;  %邊長
Root.children = {};  %子節點
%***************根據精度創建八叉樹(靜態創建)********************%
%根據邊長與方塊邊長的要求,計算需要創建多少深度的八叉樹
n = 0;
l = side_len;
while l > 5l = l / 2;n = n + 1;
end
resolution_ratio = n;  %分辨率  向下分n層
obs_leaf = [];
obs_leaf_num = 0;
[Octree, obs_leaf, obs_leaf_num] = create_octree_static(Root, downsampledPtCloud.Location, p_num, resolution_ratio, 1, obs_leaf, obs_leaf_num);
%繪制八叉樹地圖
draw_obs_leaf_node(obs_leaf, obs_leaf_num, Root.x, Root.y, Root.z, side_len, resolution_ratio, z_min, z_max);

遞歸創建八叉樹函數:

%*************************************************************************%%遞歸創建八叉樹函數  任意層%輸出:node--當前節點  p--點云數據%      num--點云數量  level_max--最大層數%      obs_leaf_index--存儲葉子節點的編號%      obs_leaf_num--葉子節點數量
%**********************************************************************%
% 創建八叉樹函數 
function [node, obs_leaf_index, obs_leaf_num] = create_octree_static(node, p, num, level_max, level_current, obs_leaf_index, obs_leaf_num)%若節點為空,則返回失敗,根節點不能為空if isempty(node)return;%當前不是最大層級elseif level_current <= level_max%判斷節點是否未被占據,即沒有數據點在方塊內if isNullPoint(node, p, num)%當前是有數據的葉子節點,并且當前層級為最大層級時,標記節點為占據葉子節點node.isLeaf = true; node.isOccupiedLeaf = false;node.value = 1;  node.children = {};else %非葉子節點  可以繼續往下分割node.isLeaf = false; node.isOccupiedLeaf = false;node.value = 1;node.children = {};  %節點創建八個子節點%創建根節點的八個子節點  此為第一層  根節點為第0層node.children = create_sub_node(node, p, num, level_current, level_max);  %創建8個子節點  層級為1%遞歸創建樹for i = 1:8[node.children{i}, obs_leaf_index, obs_leaf_num] = create_octree_static(node.children{i}, p, num, level_max, level_current+1, obs_leaf_index, obs_leaf_num);endendelseif level_current > level_max%判斷節點是否被占據if isNullPoint(node, p, num)%當前是被占據的葉子節點,并且當前層級為最大層級時,標記節點為障礙物葉子節點node.isLeaf = true; node.isOccupiedLeaf = true;node.value = 1;  node.children = {}; obs_leaf_num = obs_leaf_num + 1;obs_leaf_index(obs_leaf_num) = node.index;elsenode.isLeaf = true; node.isOccupiedLeaf = false;node.value = 0;  node.children = {};             endreturn;end
end

判斷是否是未被占據的節點:

%*************************************************************************%%判斷節點是否未被占據,即空的
%**********************************************************************%
% 判斷是否滿足葉節點條件  node--節點   p--數據點集  num--數據點集數量
function result = isNullPoint(node, p, num)result = true;%檢測節點的方塊內是否有數據點for i = 1:numif (p(i, 1) < (node.x + (node.side_len / 2))) && ...(p(i, 1) >= (node.x - (node.side_len / 2))) && ...(p(i, 2) < (node.y + (node.side_len / 2))) && ...(p(i, 2) >= (node.y - (node.side_len / 2))) && ...(p(i, 3) < (node.z + (node.side_len / 2))) && ...(p(i, 3) >= (node.z - (node.side_len / 2)))result = false;break;  %檢測到有便可以退出endend
end

繪圖函數:

%*************************************************************************%%繪制葉子節點 %輸入:index--葉子節點編號  index_num--葉子節點數量%      root_x,root_y,root_z--根節點坐標  root_side_len--根節點邊長(最大的方塊邊長)%      level--八叉樹深度  min_z--最小高度  max_z--最大高度(用于根據高度漸變顏色)%  注意:畫圖時,需要計算方塊的左下前坐標(即8個頂點中,各坐標值最小的)
%**********************************************************************%
%******************%
%    以最大的方塊為第一層的根
%    編號規則(順時針):
%     底層:  2 3
%            1 4
%     頂層:  6 7
%            5 8
%********************%
function draw_obs_leaf_node(index, index_num, root_x, root_y, root_z, root_side_len, level, z_min, z_max)%計算邊長for i = 1:index_num%根據編號計算坐標;index_current = floor(index(i) / 10);  %第一層為根節點,可以忽略x = root_x;y = root_y;z = root_z;side_len = root_side_len;for j = 1:levelindex_level = mod(index_current, 10); % 取余side_len = side_len/2;switch index_levelcase 1x = x - side_len / 2;y = y - side_len / 2;z = z - side_len / 2;case 2x = x - side_len / 2;y = y + side_len / 2;z = z - side_len / 2;case 3x = x + side_len / 2;y = y + side_len / 2;z = z - side_len / 2;case 4x = x + side_len / 2;y = y - side_len / 2;z = z - side_len / 2;case 5x = x - side_len / 2;y = y - side_len / 2;z = z + side_len / 2;case 6x = x - side_len / 2;y = y + side_len / 2;z = z + side_len / 2;case 7x = x + side_len / 2;y = y + side_len / 2;z = z + side_len / 2;case 8x = x + side_len / 2;y = y - side_len / 2;z = z + side_len / 2;endindex_current = floor(index_current / 10);end%計算最終畫圖的坐標draw_x = x - side_len/2;draw_y = y - side_len/2;draw_z = z - side_len/2;%根據不同的高度繪制不同的顏色cmap = jet; % 使用 jet 色圖,可以根據需要選擇其他色圖z_normalized = (z - z_min) / (z_max - z_min); % 將高度歸一化到 [0, 1] 范圍color = ind2rgb(round(z_normalized * (size(cmap, 1) - 1)) + 1, cmap); % 將歸一化的高度值映射到顏色映射中draw_cube(draw_x, draw_y, draw_z, side_len, color);end
end

之后是采集了一些點云來進行了驗證,因為大小是固定的,因此是靜態創建八叉樹的效果:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72214.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72214.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72214.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

最節省服務器,手搓電子證書查詢系統

用戶預算150元&#xff0c;想要一個最簡單證書查詢系統。前臺能查詢證書、后臺管理員能登錄能修改密碼&#xff0c;證書能夠手動輸入修改刪除、批量導入導出刪除數據、查詢搜索。能夠兼容蘋果、安卓、PC三端瀏覽器&#xff0c;最后幫忙部署到云服務器上。 用戶預算不多&#xf…

什么是全棧?

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點下班 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 &#x1f4c3;文章前言 &#x1f537;文章均為學習工…

作物移栽機器人的結構設計的介紹

作物移栽機器人的結構設計是一個復雜的機械與電子結合的系統工程&#xff0c;單純用代碼來實現整個結構設計是不現實的&#xff0c;因為結構設計更多涉及到機械結構、硬件選型等物理層面的內容。不過&#xff0c;我們可以通過代碼來模擬作物移栽機器人的部分功能&#xff0c;例…

【文獻閱讀】SPRec:用自我博弈打破大語言模型推薦的“同質化”困境

&#x1f4dc;研究背景 在如今的信息洪流中&#xff0c;推薦系統已經成為了我們生活中的“貼心小助手”&#xff0c;無論是看電影、聽音樂還是購物&#xff0c;推薦系統都在努力為我們提供個性化的內容。但這些看似貼心的推薦背后&#xff0c;其實隱藏著一個嚴重的問題——同質…

使用1Panel一鍵搭建WordPress網站的詳細教程(全)

嘿&#xff0c;各位想搭建自己網站的朋友們&#xff01;今天我要跟大家分享我用1Panel搭建WordPress網站的全過程。說實話&#xff0c;我之前對服務器運維一竅不通&#xff0c;但通過這次嘗試&#xff0c;我發現原來建站可以這么簡單&#xff01;下面是我的親身經歷和一些小技巧…

本地fake server,

C# 制作的系統級tcp 重定向&#xff0c;整個系統只要有訪問指定url&#xff0c;返回自定義內容到訪問端。不局限在瀏覽器單一方面。 再者請理解這個圖的含金量&#xff0c;服務器down機都可以模擬。 用途那就太多了&#xff0c;當然很多用途都不正當。嘿嘿 如果你很想要源代…

設計模式之美

UML建模 統一建模語言&#xff08;UML&#xff09;是用來設計軟件的可視化建模語言。它的語言特點是簡單 統一 圖形化 能表達軟件設計中的動態與靜態信息。 UML的分類 動態結構圖&#xff1a; 類圖 對象圖 組件圖 部署圖 動態行為圖&#xff1a; 狀態圖 活動圖 時序圖 協作…

【openGauss】物理備份恢復

文章目錄 1. gs_backup&#xff08;1&#xff09;備份&#xff08;2&#xff09;恢復&#xff08;3&#xff09;手動恢復的辦法 2. gs_basebackup&#xff08;1&#xff09;備份&#xff08;2&#xff09;恢復① 偽造數據目錄丟失② 恢復 3. gs_probackup&#xff08;1&#xf…

一文了解JVM的垃圾回收

Java堆內存結構 java堆內存是垃圾回收器管理的主要區域&#xff0c;也被稱為GC堆。 為了方便垃圾回收&#xff0c;堆內存被分為新生代、老年代和永久代。 新創建的對象的內存會在新生代中分配&#xff0c;達到一定存活時長后會移入老年代&#xff0c;而永久代存儲的是類的元數…

SQL子查詢與MyBatis映射

文章目錄 前言1. 數據庫表結構2. MyBatis Mapper XML3. Java 實體類4. 技術點解析5. 執行效果6. 優化建議 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 以下是一個結合 SQL 別名、子查詢、MyBatis 字段映射和代碼復用的完整案例&#xff0c;以用戶管…

基于SpringBoot的“校園周邊美食探索及分享平臺”的設計與實現(源碼+數據庫+文檔+PPT)

基于SpringBoot的“校園周邊美食探索及分享平臺”的設計與實現&#xff08;源碼數據庫文檔PPT) 開發語言&#xff1a;Java 數據庫&#xff1a;MySQL 技術&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系統展示 校園周邊美食探索及分享平臺結構圖…

時間復雜度(Time Complexity)

時間復雜度 1. 什么是時間復雜度&#xff1f; 時間復雜度&#xff08;Time Complexity&#xff09;是計算算法執行時間隨輸入規模&#xff08;n&#xff09;增長的變化趨勢。它衡量算法的效率&#xff0c;通常使用大 O 記號&#xff08;Big-O notation&#xff09;表示&#…

樹莓派:更新源

發行版本 Debian 一直維護著至少三個發行版本&#xff1a;“穩定版&#xff08;stable&#xff09;”&#xff0c;“測試版&#xff08;testing&#xff09;”和“不穩定版&#xff08;unstable&#xff09;”。 發行版目錄 下一代 Debian 正式發行版的代號為 bullseye — 發布…

K8s 1.27.1 實戰系列(八)Service

一、Service介紹 1、Service 的作用與核心功能 Service 是 Kubernetes 中用于抽象一組 Pod 并提供穩定訪問入口的資源。它解決了以下問題: ?Pod IP 不固定:Pod 可能因故障、擴縮容或更新導致 IP 變化,Service 通過 ClusterIP(虛擬 IP)提供固定訪問地址。?負載均衡:自動…

RocketMQ性能優化篇

在分布式消息系統中&#xff0c;RocketMQ以其高性能、高可靠性和高可擴展性而被廣泛應用。然而&#xff0c;為了充分發揮其性能優勢&#xff0c;需要進行一系列的性能測試和優化。本文將從性能測試方法和優化實踐兩個方面&#xff0c;詳細介紹如何對RocketMQ進行性能優化。通過…

CSS 知識點總結1

CSS 知識點總結&#xff11; 今天寫了兩個頁面,用到的知識點,總結一下 1. Flexbox 布局 display: flex;&#xff1a;啟用 Flexbox 布局&#xff0c;用于創建靈活的容器。flex-direction: column;&#xff1a;將子元素垂直排列。justify-content&#xff1a;控制子元素在主軸…

雙指針算法專題之——復寫零

文章目錄 題目介紹思路分析異地復寫優化為就地復寫 AC代碼 題目介紹 鏈接: 1089. 復寫零 思路分析 那么這道題我們依然可以使用雙指針算法來解決 異地復寫 先不考慮題目的要求&#xff0c;直接就地在原數組上修改&#xff0c;可能不太好想&#xff0c;我們這里可以先在一個…

Python控制語句 ——break和continue

1.以下關于Python循環結構的描述中,錯誤的是() 。 A、break用來結束當前當次語句,但不跳出當前的循環體。 B、遍歷循環中的遍歷結構可以是字符串、文件、組合數據類型和range函數等。 C、Python通過for,while等保留字構建循環結構。 D、continue只結束本次循環。 答案:A。在…

搭建阿里云專有網絡VPC

目錄 一、概述 二、專有網絡vpc 2.1 vpc基本信息 2.2 vpc資源管理 2.3 vpc網段管理 三、交換機 四、NAT網關 4.1 綁定彈性公網IP 4.2 NAT網關信息 4.3 綁定的彈性公網IP 4.4 DNAT 4.5 SNAT 五、彈性公網IP 六、訪問控制ACL&#xff08;綁定交換機&#xff09; 6…

阿里巴巴發布 R1-Omni:首個基于 RLVR 的全模態大語言模型,用于情感識別

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…