基于Matlab的改進RRT算法二維/三維路徑規劃
一、引言
在機器人學、自動駕駛等領域,路徑規劃是一個關鍵問題,它旨在為機器人或車輛找到一條從起始點到目標點的安全、高效的路徑。RRT(Rapidly-exploring Random Trees)算法作為一種基于采樣的路徑規劃算法,因其能夠有效處理高維空間和復雜環境下的路徑規劃問題而受到廣泛關注。然而,傳統的RRT算法存在收斂速度慢、路徑質量不高等問題。為了克服這些問題,人們提出了RRT算法以及各種改進的RRT算法。本文將詳細介紹基礎RRT算法、RRT算法和改進RRT算法的原理,并通過Matlab代碼實現這三種算法,對比它們的路徑規劃結果。
二、基礎RRT算法原理
2.1 算法概述
RRT算法是由Steven M. LaValle于1998年提出的一種基于采樣的增量式路徑規劃算法。它的核心思想是通過在狀態空間中隨機采樣,并以當前構建的隨機樹為基礎,逐步向新的采樣點進行擴展,從而快速探索未知區域。RRT算法的優點在于其無需顯式地對整個狀態空間進行離散化,能夠有效地處理高維空間,并且具有概率完備性,即在無限時間內,如果存在解,RRT算法以概率1能夠找到一條路徑。然而,標準的RRT算法通常只能找到一條可行路徑,而不能保證路徑是最優的(例如,最短路徑)。
2.2 算法步驟
RRT算法的主要步驟如下:
- 初始化:在環境中隨機生成一個起始節點,并將其作為樹的根節點。
- 擴展樹:隨機生成一個新的節點,并將其與樹中最近的節點連接起來,形成新的分支。
- 檢查碰撞:檢查新分支是否與障礙物發生碰撞。如果發生碰撞,則放棄該分支。
- 更新目標節點:如果新分支與目標節點的距離小于閾值,則將目標節點與樹連接起來,完成路徑規劃。
- 重復步驟2 - 4:重復步驟2 - 4,直到找到一條連接起點和終點的路徑。
2.3 算法示意圖
三、RRT*算法原理
3.1 算法概述
RRT算法是RRT算法的改進版本,它在標準RRT算法的基礎上引入了兩個關鍵機制:選擇父節點和重布線機制,以實現最優或近似最優的路徑規劃。通過這兩個機制,RRT算法能夠在構建隨機樹的同時,不斷優化已存在的路徑,使得整棵樹趨向于包含最優路徑。RRT*算法具有漸近最優性,即當迭代次數趨近于無窮時,算法以概率1能夠找到最優路徑。
3.2 算法步驟
RRT*算法的主要步驟如下:
- 初始化:設定起始點start和目標點goal,并創建一個只包含start的RRT樹T。
- 重復步驟直到找到路徑或達到最大迭代次數:
a. 隨機采樣:在環境空間中隨機采樣一個點x_rand。
b. 擴展樹:從樹T中找到最近的節點x_near,以x_near為起點,在方向上延伸一定的距離,得到新的節點x_new。
c. 碰撞檢測:檢測路徑x_near到x_new之間是否與障礙物發生碰撞,如果發生碰撞,則返回步驟2繼續下一次迭代。
d. 尋找最優連接:在樹T中找到與x_new最近的節點x_min,并計算從x_min到x_new的代價cost(x_min, x_new)。
e. 重新連接:對于樹T中與x_new距離在一定范圍內的節點x_near_neighbors,計算通過x_near連接到x_new的代價cost(x_near, x_new),選擇代價最小的連接方式。
f. 更新樹:將x_new加入樹T,并更新節點間的連接關系和代價信息。
g. 優化路徑:對樹T中的部分節點,以目標點goal為目標進行優化,通過調整連接關系和代價信息,改善路徑的質量。
h. 判斷終止條件:如果新加入的節點x_new接近目標點goal,則找到了一條可行路徑,算法結束。
四、改進RRT算法原理
4.1 算法概述
為了進一步提高RRT算法的性能,人們提出了多種改進策略。這些改進策略從多個方面對傳統RRT算法進行優化,旨在提升算法的收斂速度、路徑質量以及避障能力等。以下將詳細介紹幾種常見的改進策略。
4.2 多步長策略
4.2.1 原理
在障礙物稀疏區域使用大步長,在障礙物密集區域使用小步長,以提高搜索效率。通過動態調整步長,算法可以在不同環境下更靈活地擴展搜索樹,加速搜索過程,減少無效擴展。
4.2.2 方法
- 計算當前節點附近障礙物的密度(但不直接依賴障礙物密度計算)。
- 根據路徑連續碰撞情況動態調整步長:
- 大步長 step3(自由區域)
- 中步長 step2(一般區域)
- 小步長 step1(障礙物密集區域)
4.2.3 優勢
加速搜索過程,減少無效擴展,提高避障能力。
4.3 目標偏置概率P與權重系數W聯合優化
4.3.1 原理
偏置概率P用于控制隨機點采樣,使算法有一定概率直接朝向目標點,提高收斂速度。權重系數W在生成新節點時,動態調整目標點與隨機點的影響權重,使搜索更加平穩,減少不必要的波動。
4.3.2 計算方式
- 計算隨機點Q1和目標點Q2方向的位移:
- (Q_1=(1 - W)cdot(randNode - nearestNode)+nearestNode)
- (Q_2=Wcdot(goal - nearestNode)+nearestNode)
- 最終采樣點:
- (sample = Q_1+Q_2)
4.4 路徑與障礙物安全距離safe_dis約束
4.4.1 原理
路徑點應始終與障礙物保持安全距離safe_dis以上,避免路徑緊貼障礙物,提高魯棒性。
4.4.2 方法
- 采用dis_fun函數,在路徑點生成時檢查是否滿足安全距離。
- 若不滿足,則重新采樣,避免無效擴展。
4.5 拉伸與剪枝策略
4.5.1 拉伸
若路徑點之間可以直接相連(無碰撞),則移除中間點,提高路徑簡潔性。例如,原路徑點為(P_1→P_2→P_3→P_4→P_5),若(P_1→P_4)直接可行,則移除(P_2),(P_3),得到優化路徑(P_1→P_4→P_5)。
4.5.2 剪枝
從目標點向起點回溯,移除多余拐點,使路徑更順暢。
4.6 碰撞檢測的改進
4.6.1 傳統方法
采用固定分割點數進行路徑檢查,精度受限。
4.6.2 改進方案
- 動態調整采樣點數:(n = round(min(max(baseN-(dist / maxDist), minN), maxN)))
- 逐點檢測:
- 生成插值點:(node_lin = linspace(node1, node2, n))
- 遍歷檢測:若(dis_fun(temp_point, map, row, col, safe_dis)==1),則認為碰撞
4.6.3 優勢
碰撞檢測更加精細,減少漏檢情況,提高路徑安全性。
4.7 終點判斷的優化
4.7.1 方法
在新節點生成時,檢查新節點是否能直接連通目標點(無障礙)。若可直連,則直接連接目標點,結束搜索。
4.7.2 優勢
避免無意義的繼續搜索,提高路徑收斂速度。
4.8 生成新節點時優先選擇“離目標最近的路徑點”
4.8.1 原理
傳統RRT隨機選擇父節點,可能導致路徑較長。本方法確保新節點生成在“當前路徑中最接近目標的點”附近,提高收斂效率。
4.8.2 實現
- 計算所有已生成路徑點到目標點的距離:(nearestToGoal = arg min(dist(path.Nodes, goal)))
- 以該點作為新節點的父節點,提高搜索的導向性。
五、三種算法的路徑規劃結果對比
5.1 對比指標
為了對比基礎RRT算法、RRT*算法和改進RRT算法的性能,我們可以從以下幾個方面進行評估:
- 路徑長度:路徑長度越短,說明算法找到的路徑越優。
- 收斂速度:收斂速度越快,說明算法能夠在更短的時間內找到可行路徑。
- 路徑平滑度:路徑平滑度越高,說明機器人或車輛在行駛過程中越穩定。
- 避障能力:避障能力越強,說明算法在復雜環境下的可靠性越高。
5.2 對比結果
通過Matlab代碼實現這三種算法,并在相同的環境下進行路徑規劃實驗,得到以下對比結果:
算法 | 路徑長度 | 收斂速度 | 路徑平滑度 | 避障能力 |
---|---|---|---|---|
基礎RRT算法 | 較長 | 較慢 | 較差 | 一般 |
RRT*算法 | 較短 | 較快 | 較好 | 較好 |
改進RRT算法 | 最短 | 最快 | 最好 | 最強 |
5.3 結果示意圖
5.3.1 二維結果圖
各個算法性能指標如下:
5.3.2 三維結果圖
六、Matlab代碼實現
6.1 基礎RRT算法代碼示例
% %***************************************
% %RRT
function [trace_coo,dis_yuan]=RRT3D(S_coo,E_coo,radius,circleCenter,mapsize)
tic
x_I=S_coo(1); y_I=S_coo(2); z_I=S_coo(3);
x_G=E_coo(1); y_G=E_coo(2); z_G=E_coo(3);
Thr=100;
Delta= 50; xL=mapsize(1)';
yL=mapsize(2)';
zL=mapsize(3)';
figure;
[x, y, z] = sphere; %創建一個坐標在原點,半徑為1的標準圓,用于繪制自定義的圓
for i = 1: length(radius)mesh(radius(i)*x + circleCenter(i,1), radius(i)*y + circleCenter(i,2), radius(i)*z + circleCenter(i,3));hold on;
end
axis equal;
hold on;
scatter3(S_coo(1),S_coo(2),S_coo(3),'filled','g');
scatter3(E_coo(1),E_coo(2),E_coo(3),'filled','b');
%% 圖片標注
text(S_coo(1),S_coo(2),S_coo(3),'起點');
text(E_coo(1),E_coo(2),E_coo(3),'終點');
view(3);
grid on;
axis equal;
axis([0 xL 0 yL 0 zL]);
xlabel('x');
ylabel('y');
zlabel('z');%%
T.v(1).x = x_I;
T.v(1).y = y_I;
T.v(1).z = z_I; T.v(1).xPrev = x_I;
T.v(1).yPrev = y_I;
T.v(1).zPrev = z_I;T.v(1).dist=0;
T.v(1).indPrev = 0;
%%
count=1;
goal = [x_G,y_G,z_G];
for iter = 1:30000x_rand=[];x_rand(1) = xL*rand; x_rand(2) = yL*rand;x_rand(3) = zL*rand;x_near=[];min_dist = 1000000;near_iter = 1;%%=======尋找x_near===========%%[~,N]=size(T.v);for j = 1:Nx_near(1) = T.v(j).x;x_near(2) = T.v(j).y;x_near(3) = T.v(j).z;dist = norm(x_rand - x_near);if min_dist > distmin_dist = dist;near_iter = j;endendx_near(1) = T.v(near_iter).x;x_near(2) = T.v(near_iter).y;x_near(3) = T.v(near_iter).z;%%========獲取x_new============%%x_new=[];near_to_rand = [x_rand(1)-x_near(1),x_rand(2)-x_near(2),x_rand(3)-x_near(3)];normlized = near_to_rand / norm(near_to_rand) * Delta;x_new = x_near + normlized;%%=======障礙檢測===============%%% if ~collisionChecking(x_near,x_new,Imp) if ~collisionDetec(x_near,x_new,radius,circleCenter,0)continue;endcount=count+1;%%========將X_NEW增加到樹中========%%T.v(count).x = x_new(1);T.v(count).y = x_new(2); T.v(count).z = x_new(3); T.v(count).xPrev = x_near(1); T.v(count).yPrev = x_near(2);T.v(count).zPrev = x_near(3);T.v(count).dist= norm(x_new - x_near); T.v(count).indPrev = near_iter; plot3([x_near(1),x_new(1)],[x_near(2),x_new(2)],[x_near(3),x_new(3)],'-k');hold on;%========判斷是否找到路徑==========%%if norm(x_new - goal) < Thrbreak;end% pause(0.1);
end
%%elsedisp('Error, no path found!');
end%%
trace_coo=[path.pos.x;path.pos.y;path.pos.z]';
toc
time_all=toc;disp(['原始RRT算法采樣點數:',num2str(count)])
disp(['原始RRT算法運行時間:',num2str(time_all)])
disp(['原始RRT算法路徑總距離:',num2str(dis_yuan)])
disp('-----------------------------------------------------------------------' )
6.2 RRT*算法代碼示例
function [trace_coo,dis_yuan]=RRTstar3D(S_coo,E_coo,radius,circleCenter,mapsize)
tic
x_I=S_coo(1); y_I=S_coo(2); z_I=S_coo(3);
x_G=E_coo(1); y_G=E_coo(2); z_G=E_coo(3);
Thr=100;
Delta= 100; xL=mapsize(1)';
yL=mapsize(2)';
zL=mapsize(3)';
figure;
[x, y, z] = sphere; %創建一個坐標在原點,半徑為1的標準圓,用于繪制自定義的圓
for i = 1: length(radius)mesh(radius(i)*x + circleCenter(i,1), radius(i)*y + circleCenter(i,2), radius(i)*z + circleCenter(i,3));hold on;
end
axis equal;
hold on;
scatter3(S_coo(1),S_coo(2),S_coo(3),'filled','g');
scatter3(E_coo(1),E_coo(2),E_coo(3),'filled','b');
%% 圖片標注
text(S_coo(1),S_coo(2),S_coo(3),'起點');
text(E_coo(1),E_coo(2),E_coo(3),'終點');
view(3);
grid on;
axis equal;
axis([0 xL 0 yL 0 zL]);
xlabel('x');
ylabel('y');
zlabel('z');%%
T.v(1).x = x_I;
T.v(1).y = y_I;
T.v(1).z = z_I; T.v(1).xPrev = x_I;
T.v(1).yPrev = y_I;
T.v(1).zPrev = z_I;T.v(1).dist=0;
T.v(1).indPrev = 0;
%%
% figure(1);
% ImpRgb=imread('map6.bmp');
% if size(ImpRgb, 3) == 3
% Imp = rgb2gray(ImpRgb);
% else
% Imp = ImpRgb;
% end
% imshow(Imp)
% xL=size(Imp,1);
% yL=size(Imp,2);
% hold on
% plot(x_I, y_I, 'ro', 'MarkerSize',10, 'MarkerFaceColor','r');
% plot(x_G, y_G, 'go', 'MarkerSize',10, 'MarkerFaceColor','g');
count=1;
goal = [x_G,y_G,z_G];
start_goal_dist = 1000000;
% path.pos(1).x = 700;
% path.pos(1).y = 700;
% path.pos(1).z = 700;
dis_yuan=0;for iter = 1:30000x_rand=[];x_rand(1) = xL*rand;x_rand(2) = yL*rand;x_rand(3) = zL*rand;%%=======尋找x_near===========%%x_near=[];min_dist = 1000000;near_iter = 1;near_iter_tmp = 1;[~,N]=size(T.v);for j = 1:Nx_near(1) = T.v(j).x;x_near(2) = T.v(j).y;x_near(3) = T.v(j).z;dist = norm(x_rand - x_near);if min_dist > distmin_dist = dist;near_iter = j;endendx_near(1) = T.v(near_iter).x;x_near(2) = T.v(near_iter).y;x_near(3) = T.v(near_iter).z;%%========獲取x_new============%%x_new=[];near_to_rand = [x_rand(1)-x_near(1),x_rand(2)-x_near(2),x_rand(3)-x_near(3)];normlized = near_to_rand / norm(near_to_rand) * Delta;x_new = x_near + normlized;%%=======障礙檢測===============%%if ~collisionDetec(x_near,x_new,radius,circleCenter,0)continue;end%%======= nearC && chooseParent =========%%nearptr = [];nearcount = 0;neardist = norm(x_new - x_near) + T.v(near_iter_tmp).dist;for j = 1:Nif j == near_iter_tmpcontinue;endx_neartmp(1) = T.v(j).x;x_neartmp(2) = T.v(j).y;x_neartmp(3) = T.v(j).z;dist = norm(x_new - x_neartmp) + T.v(j).dist;norm_dist = norm(x_new - x_neartmp);if norm_dist < 120%nearCif collisionDetec(x_near,x_new,radius,circleCenter,0)nearcount = nearcount + 1;nearptr(nearcount,1) = j;if neardist > distneardist = dist;near_iter = j;endendendendx_near(1) = T.v(near_iter).x;x_near(2) = T.v(near_iter).y;x_near(3) = T.v(near_iter).z;count=count+1;%%========將X_NEW增加到樹中========%%T.v(count).x = x_new(1);T.v(count).y = x_new(2); T.v(count).z = x_new(3); T.v(count).xPrev = x_near(1); T.v(count).yPrev = x_near(2);T.v(count).zPrev = x_near(3);T.v(count).dist= norm(x_new - x_near) + T.v(near_iter).dist;T.v(count).indPrev = near_iter;%%======== rewirte =========%%[M,~] = size(nearptr);for k = 1:Mx_1(1) = T.v(nearptr(k,1)).x;x_1(2) = T.v(nearptr(k,1)).y;x_1(3) = T.v(nearptr(k,1)).z;x1_prev(1) = T.v(nearptr(k,1)).xPrev;x1_prev(2) = T.v(nearptr(k,1)).yPrev;x1_prev(3) = T.v(nearptr(k,1)).zPrev;if T.v(nearptr(k,1)).dist > (T.v(count).dist + norm(x_1-x_new))T.v(nearptr(k,1)).dist = T.v(count).dist + norm(x_1-x_new);T.v(nearptr(k,1)).xPrev = x_new(1);T.v(nearptr(k,1)).yPrev = x_new(2);T.v(nearptr(k,1)).yPrev = x_new(3);T.v(nearptr(k,1)).indPrev = count;% plot([x_1(1),x1_prev(1)],[x_1(2),x1_prev(2)],'-w');% hold on;plot3([x_1(1),x_new(1)],[x_1(2),x_new(2)],[x_1(3),x_new(3)],'-k');hold on;% drawnowendendplot3([x_near(1),x_new(1)],[x_near(2),x_new(2)],[x_near(3),x_new(3)],'-k');hold on;% plot(x_new(1),x_new(2),'*r');% hold on;% if norm(x_new - goal) < Thrif norm(x_new - goal) < Thrbreak;end
end% if (T.v(count).dist + norm(x_new - goal)) < start_goal_dist
% start_goal_dist = (T.v(count).dist + norm(x_new - goal));
% % if length(path.pos) > 2
% % for j = 2 : length(path.pos)
% % plot([path.pos(j).x; path.pos(j-1).x;], [path.pos(j).y; path.pos(j-1).y], 'w', 'Linewidth', 3);
% % end
% % end
% path.pos = [];
if iter < 30000path.pos(1).x = x_G; path.pos(1).y = y_G;path.pos(1).z = z_G;path.pos(2).x = T.v(end).x; path.pos(2).y = T.v(end).y;path.pos(2).z = T.v(end).z;pathIndex = T.v(end).indPrev; % ??????·??j=0;while 1path.pos(j+3).x = T.v(pathIndex).x;path.pos(j+3).y = T.v(pathIndex).y;path.pos(j+3).z = T.v(pathIndex).z;pathIndex = T.v(pathIndex).indPrev;if pathIndex == 1breakendj=j+1;endpath.pos(end+1).x = x_I; path.pos(end).y = y_I; path.pos(end).z = z_I; for j = 2:length(path.pos)% plot([path.pos(j).x; path.pos(j-1).x;], [path.pos(j).y; path.pos(j-1).y], 'b', 'Linewidth', 3);dis_yuan=dis_yuan+...norm([path.pos(j).x-path.pos(j-1).x,path.pos(j).y- path.pos(j-1).y,path.pos(j).z- path.pos(j-1).z]);end% else% disp('Error, no path found!');% end
end
% continue;
% end
% pause(0.01);
% end%%
trace_coo=[path.pos.x;path.pos.y;path.pos.z]';
toc
time_all=toc;
% dis_yuan=0;
% trace_coo=[tracebackNode.xCoord,tracebackNode.yCoord];
% while tracebackNode.parentNode~=0
% dis_yuan=dis_yuan+norm([tracebackNode.xCoord-nodeArray(tracebackNode.parentNode).xCoord,tracebackNode.yCoord-nodeArray(tracebackNode.parentNode).yCoord]);
% tracebackNode =nodeArray(tracebackNode.parentNode);
% trace_coo=[[tracebackNode.xCoord,tracebackNode.yCoord];trace_coo];
% end% plot(trace_coo(:,1),trace_coo(:,2),'r','LineWidth',2);disp(['RRT*算法采樣點數:',num2str(count)])
disp(['RRT*算法運行時間:',num2str(time_all)])
disp(['RRT*算法路徑總距離:',num2str(dis_yuan)])
disp('-----------------------------------------------------------------------' )
6.3 改進RRT算法代碼示例
function [smoothedPath,dis_smooth]=imRRT3D(S_coo,E_coo,radius,circleCenter,mapsize)
row=mapsize(1);
col=mapsize(2);
height=mapsize(3);figure;
[x, y, z] = sphere; %創建一個坐標在原點,半徑為1的標準圓,用于繪制自定義的圓
for i = 1: length(radius)mesh(radius(i)*x + circleCenter(i,1), radius(i)*y + circleCenter(i,2), radius(i)*z + circleCenter(i,3));hold on;
end
axis equal;
hold on;
scatter3(S_coo(1),S_coo(2),S_coo(3),'filled','g');
scatter3(E_coo(1),E_coo(2),E_coo(3),'filled','b');
%% 圖片標注
text(S_coo(1),S_coo(2),S_coo(3),'起點');
text(E_coo(1),E_coo(2),E_coo(3),'終點');
view(3);
grid on;
axis equal;
axis([0 row 0 col 0 height]);
xlabel('x');
ylabel('y');
zlabel('z');
% title('本文改進RRT算法搜索樹')car_R = 3; % 車的大小
safe_dis1 = 60; % 與障礙物的一類安全距離
safe_dis2 = 110; % 與障礙物的二類安全距離
step1 = 50;% 小步長
step2 = 100; % 正常步長
step3 = 150; % 大步長
P = 0.6; % 概率參數
goalRadius = 100;nodeIndex = 1; % 樹枝節點編號初始值
goalFound = 0;
% 起始節點初始化
initialNode.xCoord = S_coo(1);
initialNode.yCoord = S_coo(2);
initialNode.zCoord = S_coo(3);initialNode.parentNode = 0;
goalNode.xCoord = E_coo(1);
goalNode.yCoord = E_coo(2);
goalNode.zCoord = E_coo(3);nodeArray(nodeIndex).xCoord = initialNode.xCoord;
nodeArray(nodeIndex).yCoord = initialNode.yCoord;
nodeArray(nodeIndex).zCoord = initialNode.zCoord;nodeArray(nodeIndex).parentNode = initialNode.parentNode;
nodeArray(nodeIndex).ind = nodeIndex;
nodeIndex = nodeIndex + 1;%% 主要路徑規劃部分,可以改:隨機生成幾個點,引入代價線,從起點到終點的連線直線,查看離直線最短的點。
tic
while goalFound == 0% === (1) 在已有節點中選擇最接近目標的節點 ===nearestToGoal = findNearestToGoal(nodeArray, goalNode);% === (2) 以該最近節點附近生成新節點 ===randomNode.xCoord = nearestToGoal.xCoord + (rand - 0.5) * 200; % 隨機偏移,范圍 [-50, 50]randomNode.yCoord = nearestToGoal.yCoord + (rand - 0.5) * 200;randomNode.zCoord = nearestToGoal.zCoord + (rand - 0.5) * 200;% if rand < 0.1 % 目標偏置% randomNode.xCoord = E_coo(1);% randomNode.yCoord = E_coo(2);% else% randomNode.xCoord = randi([1, col]);% randomNode.yCoord = randi([1, row]);% end% === (3) 找到最近鄰節點 ===nearestNode = nodeArray(1);for node = nodeArrayif (getDistanceBetween3D(randomNode, node) < getDistanceBetween3D(randomNode, nearestNode))nearestNode = node; % 選擇距離新生成節點最近的已有節點endend% === (4) 目標點偏置 + 權重調整 ===% flag = dis_fun3D(nearestNode, map, row, col, safe_dis1);flag =pointCollisionCheck(nearestNode,radius,circleCenter,safe_dis1);if flag == 0 % 障礙少distToGoal = getDistanceBetween3D(nearestNode, goalNode);w = min(1, distToGoal / (row + col)); % 根據目標距離動態調整權重if rand < P % 目標點方向randomNode.xCoord = goalNode.xCoord;randomNode.yCoord = goalNode.yCoord;randomNode.yCoord = goalNode.zCoord;else % 目標點與隨機點的平衡d1 = getDistanceBetween3D(randomNode, nearestNode);d2 = getDistanceBetween3D(goalNode, nearestNode);Q1(1) = (randomNode.xCoord - nearestNode.xCoord) * (1 - w) / d1 + nearestNode.xCoord;Q1(2) = (randomNode.yCoord - nearestNode.yCoord) * (1 - w) / d1 + nearestNode.yCoord;Q1(3) = (randomNode.zCoord - nearestNode.zCoord) * (1 - w) / d1 + nearestNode.zCoord;Q2(1) = (goalNode.xCoord - nearestNode.xCoord) * w / d2 + nearestNode.xCoord;Q2(2) = (goalNode.yCoord - nearestNode.yCoord) * w / d2 + nearestNode.yCoord;Q2(3) = (goalNode.zCoord - nearestNode.zCoord) * w / d2 + nearestNode.zCoord;Q = Q1 + Q2;randomNode.xCoord = Q(1);randomNode.yCoord = Q(2);randomNode.zCoord = Q(3);endend% === (5) 選擇合適步長 ===flag = pointCollisionCheck(nearestNode,radius,circleCenter,safe_dis2);if flag == 0step = step3;elseflag = pointCollisionCheck(nearestNode,radius,circleCenter,safe_dis2);if flag == 0step = step2;elsestep = step1;endend% === (6) 生成新節點 ===angleAlpha = atan2(randomNode.yCoord - nearestNode.yCoord, randomNode.xCoord - nearestNode.xCoord);newNode.xCoord = nearestNode.xCoord + step * cos(angleAlpha);newNode.yCoord = nearestNode.yCoord + step * sin(angleAlpha);newNode.zCoord = nearestNode.zCoord + step * sin(angleAlpha);growVec = [randomNode.xCoord - nearestNode.xCoord,randomNode.yCoord - nearestNode.yCoord,randomNode.zCoord - nearestNode.zCoord];growVec = growVec/sqrt(sum(growVec.^2));newNode.xCoord = nearestNode.xCoord + step * growVec(1);newNode.yCoord = nearestNode.yCoord + step * growVec(2);newNode.zCoord = nearestNode.zCoord + step * growVec(3);flag1 = ~pointCollisionCheck(newNode,radius,circleCenter,car_R*1.1);% flag2 = checkConstraint(newNode, nearestNode, map, row, col, car_R * 1.1);flag2= ~collisionDetec([newNode.xCoord,newNode.yCoord,newNode.zCoord],...[nearestNode.xCoord,nearestNode.yCoord,nearestNode.zCoord],radius,circleCenter,car_R * 1.1);if flag1||flag2 % 遇到障礙則跳過continue;endif newNode.xCoord <= 0 || newNode.xCoord >= col || newNode.yCoord <= 0 || newNode.yCoord >= row||...newNode.zCoord <= 0 || newNode.zCoord >= heightcontinue;end% === (7) 記錄并繪制路徑 ===plot3([newNode.xCoord nearestNode.xCoord], [newNode.yCoord nearestNode.yCoord], [newNode.zCoord nearestNode.zCoord], 'k-');% drawnow;nodeIndex = nodeIndex + 1;nodeArray(nodeIndex).xCoord = newNode.xCoord; % 記錄新節點nodeArray(nodeIndex).yCoord = newNode.yCoord;nodeArray(nodeIndex).zCoord = newNode.zCoord;nodeArray(nodeIndex).parentNode = nearestNode.ind;nodeArray(nodeIndex).ind = nodeIndex;% === (8) 目標點直連檢測 ===if collisionDetec([newNode.xCoord,newNode.yCoord,newNode.zCoord],...[goalNode.xCoord,goalNode.yCoord,goalNode.zCoord],radius,circleCenter,car_R * 1.1)plot3([newNode.xCoord goalNode.xCoord], [newNode.yCoord goalNode.yCoord], [newNode.zCoord goalNode.zCoord], 'k-');goalFound = 1;break;end% === (9) 判斷是否到達目標點 ===if getDistanceBetween3D(newNode, goalNode) <= goalRadiusgoalFound = 1;break;end
end
toc
time_all=toc;
%%
%判斷最后點是不是終點
if nodeArray(nodeIndex).xCoord~=goalNode.xCoord||nodeArray(nodeIndex).yCoord~=goalNode.yCoord||nodeArray(nodeIndex).zCoord~=goalNode.zCoordnodeIndex=nodeIndex+1;nodeArray(nodeIndex).xCoord=goalNode.xCoord;nodeArray(nodeIndex).yCoord=goalNode.yCoord;nodeArray(nodeIndex).zCoord=goalNode.zCoord;nodeArray(nodeIndex).parentNode=nodeIndex-1;nodeArray(nodeIndex).ind=nodeIndex;plot3([nodeArray(nodeIndex-1).xCoord nodeArray(nodeIndex).xCoord],[nodeArray(nodeIndex-1).yCoord nodeArray(nodeIndex).yCoord],...[nodeArray(nodeIndex-1).zCoord nodeArray(nodeIndex).zCoord],'-k');
end
tracebackNode = nodeArray(nodeIndex);
dis_yuan=0;
trace_coo=[tracebackNode.xCoord,tracebackNode.yCoord,tracebackNode.zCoord];
while tracebackNode.parentNode~=0dis_yuan=dis_yuan+norm([tracebackNode.xCoord-nodeArray(tracebackNode.parentNode).xCoord,...tracebackNode.yCoord-nodeArray(tracebackNode.parentNode).yCoord,...tracebackNode.zCoord-nodeArray(tracebackNode.parentNode).zCoord]);tracebackNode =nodeArray(tracebackNode.parentNode);trace_coo=[[tracebackNode.xCoord,tracebackNode.yCoord,tracebackNode.zCoord];trace_coo];
endbeacon_coo= prunePath3D(trace_coo,radius,circleCenter,1.1*car_R);
% plot3(beacon_coo(:,1),beacon_coo(:,2),beacon_coo(:,3),'b--','LineWidth',1);k = 0.5; % 控制圓弧大小的參數
smoothedPath = smooth_path3D(beacon_coo, k);
dis_smooth=0;
for i=2:size(smoothedPath,1)dis_smooth=dis_smooth+norm(smoothedPath(i,:)-smoothedPath(i-1,:));
end
% plot3(smoothedPath(:,1),smoothedPath(:,2),smoothedPath(:,3),'r-','LineWidth',2);disp(['本文改進RRT算法采樣點數:',num2str(nodeIndex)])
disp(['本文改進RRT算法運行時間:',num2str(time_all)])
disp(['本文改進RRT算法路徑總距離:',num2str(dis_smooth)])
title('本文改進RRT算法路徑圖')
% disp('-----------------------------------------------------------------------' )
七、結論
本文詳細介紹了基礎RRT算法、RRT算法和改進RRT算法的原理,并通過Matlab代碼實現了這三種算法,對比了它們的路徑規劃結果。實驗結果表明,基礎RRT算法雖然能夠快速找到一條可行路徑,但路徑質量不高;RRT算法通過引入選擇父節點和重布線機制,能夠找到漸近最優的路徑,但收斂速度較慢;改進RRT算法通過引入多步長策略、目標偏置概率與權重系數聯合優化等多種改進策略,能夠在提高收斂速度的同時,顯著提升路徑質量和避障能力。在實際應用中,我們可以根據具體的需求選擇合適的算法。
本人擅長各類優化模型的建模和求解,具有近400個優化項目的建模仿真經驗,擅長模型構建,算法設計,算法實現和算法改進。累計指導各類建模/算法比賽和SCI寫作超過100人次。
本人長期提供: ①源碼分享(近1000個本人手寫項目) ②輔導答疑(遠程桌面一對一語音+文檔指導,可以錄屏反復觀看)
③項目定制(根據您的現實問題,針對性建模求解,提供完整方案+代碼實現) 長期在線,歡迎咨詢,一般晚上看消息!!