手把手教学RRT*(RRTSTAR)三维算法MATLAB仿真(代码可直接运行,视频手把手教学)

        在我以前的作品里有关于RRT算法的视频和代码,今天主要讲解一下RRT*算法的原理。RRT*算法主要是在RRT算法的基础上加上了重写父节点和随机重连的两个步骤。具体的实现方式我想以视频的方式向大家讲解,个人感觉讲解的十分详细。视频连接在这里,希望大家看完有任何不懂的地方直接指出。

        视频中还讲述了RRT*算法的整套代码实现流程以及代码的手把手教学。代码内容清晰易懂,且低耦合。而且可以通过注释掉相应模块后直接变为传统RRT算法。下面是效果图。

        其中左侧是传统RRT算法,右侧是RRT*算法,通过图片可以看出,RRT*算法相比于传统RRT算法节点收敛性好。下面是全部代码展示,还是挺多的。。。。。

        下面是部分代码,代码获取方式我放在了评论区(不用复制了,指定是运行不成功,我就是单纯凑字数,混个播放量)。

首先是main函数,通过增加路径点可以实现多目标点路径规划。

%% 清空变量
clear;
clc;

%% 变量定义 
axisStart = [0 0 0];                                 %空间起始坐标
axisLWH = [1000 1000 1000];                          %空间长宽高
cubeInfo.exist = 0;                                  %长方体是否存在,若存在则置为1
cylinderInfo.exist = 0;                              %圆柱体是否存在,若存在则置为1
sphereInfo.exist = 0;                                %球是否存在,若存在则置为1
pathPoint = [0     0    0;
            600 200 300;
             600  600  200];                         %一系列的路径点
cubeInfo = CreateCubeObject(cubeInfo);               %创建长方体障碍物信息
cylinderInfo = CreateCylinderObject(cylinderInfo);   %创建圆柱体障碍物信息
sphereInfo = CreateSphereObject(sphereInfo);         %创建圆柱障碍物信息

%% 画图
DrawPicture(cubeInfo,cylinderInfo,sphereInfo,pathPoint,axisStart,axisLWH);

%% 寻找路径
totalPath = [];
for k1 = 1:size(pathPoint,1)-1
    startPoint = pathPoint(k1,:);
    goalPoint = pathPoint(k1+1,:);
    [path,T] = RRTStar(axisStart,axisLWH,startPoint,goalPoint,cubeInfo,cylinderInfo,sphereInfo);
    
    if ~isempty(path)
        for k2 = 1:size(path,1)-1
            line([path(k2,1),path(k2+1,1)],[path(k2,2),path(k2+1,2)],[path(k2,3),path(k2+1,3)],'LineWidth',1,'Color','red');
        end
        totalPath = [totalPath ;path];
    end
    
end

pathLength = 0;
for k1 = 1:size(totalPath,1)-1
    pathLength = pathLength+CalcuDistance([totalPath(k1,1) totalPath(k1,2) totalPath(k1,3)],[totalPath(k1+1,1) totalPath(k1+1,2) totalPath(k1+1,3)]);
end
disp(['路径长度为:',num2str(pathLength)]);

接下来是最核心代码,RRTStar函数,内部可修改一些参数实现不同效果。

function [path,T] = RRTStar(axisStart,axisLWH,startPoint,goalPoint,cubeInfo,cylinderInfo,sphereInfo)
%% 变量定义
iterMax = 5000;                         %最大迭代次数
iter = 0;                               %当前迭代次数
step = 10;                              %步长
count = 1;                              %计数器
Thr = 10;                               %阈值
randProbability = 0.8;                  %随机采样概率,范围0-1之间,越大随机性越大。越小导向性越大,收敛快,但是容易找不到路径
r = 5*step;                             %影响范围,若大一点路径规划效果好,但是迭代慢。若小一点,路径规划效果和rrt算法越贴近
flag = 0;                               %路径规划参数,当规划失败时返回0,规划成功返回1
%%%%%%%%%%%   配置树的信息    %%%%%%%%%%
T.x(1) = startPoint(1);
T.y(1) = startPoint(2);
T.z(1) = startPoint(3);
T.pre(1) = 0;
T.cost(1) = 0;
path = [];

while iter<=iterMax
    %% 迭代次数加1
    iter = iter+1;
    %% 空间中随机采样
    randCoor = RandSample(axisStart,axisLWH,goalPoint,randProbability);    
    %% 寻找树上最近的点
    [nearestCoor,parentIndex] = FindNearstPoint(T,randCoor);  
    %% 根据指定步长扩展新的点
    newCoor = ExpandPoint(nearestCoor,randCoor,step);    
    %% 重写
%     parentIndex = RewriteFunction(T,newCoor,r,parentIndex);        
    %% 碰撞检测
    A = [T.x(parentIndex),T.y(parentIndex),T.z(parentIndex)];
    B = newCoor;
    collisionFlag = CollisionDetection(cubeInfo,cylinderInfo,sphereInfo,A,B,step);    
    if collisionFlag
        continue;
    end   
    %% 将新点插入进来
    count = count + 1;
    T.x(count) = newCoor(1);
    T.y(count) = newCoor(2);
    T.z(count) = newCoor(3);
    T.pre(count) = parentIndex;
    T.cost(count) = CalcuDistance(A,B)+T.cost(parentIndex);    
    line([A(1),B(1)],[A(2),B(2)],[A(3),B(3)],'LineWidth',1);   % 要是想只画最终的路径图,不画扩展图就把这行注释掉
    pause(0.01)  %不想看动画,就把这行注释        
    %% 随机重连
%     T = RandRelink(T,newCoor,cubeInfo,cylinderInfo,sphereInfo,step,r);   
    if CalcuDistance(newCoor,goalPoint)<Thr
        flag = 1;
        break;
    end    
end
%% 路径规划失败直接返回
if ~flag 
    disp('路径规划失败');
    return;
else
    disp('路径规划成功');
end

%% 寻找路径
path = FindPath(T,startPoint,goalPoint);

接下来是RRT*算法核心部分,重写和随机重连部分

function parentIndex = RewriteFunction(T,newCoor,r,parentIndex)
%% 重写函数,将新点newCoor重新连接到代价最小

% 下面是寻找到潜在的父节点,在变量potentialParent里
potentialParent = -ones(1,size(T.x,2));
count = 1;
for k1 = 1:size(T.x,2)
    if CalcuDistance(newCoor,[T.x(k1),T.y(k1),T.z(k1)])<r
        potentialParent(count) = k1;
        count = count+1;
    end
end
potentialParent(potentialParent==-1)=[];

%迭代寻找最小代价,并重新选择新节点newCoor的父节点,并把parentIndex改为新父节点对应的索引
for k2 = 1:size(potentialParent,2)
    % potentialParent(k2)潜在父节点的序号
    pp = [T.x(potentialParent(k2)),T.y(potentialParent(k2)),T.z(potentialParent(k2))];
    p = [T.x(parentIndex),T.y(parentIndex),T.z(parentIndex)];
    if (CalcuDistance(pp,newCoor)+T.cost(potentialParent(k2)))<(CalcuDistance(p,newCoor)+T.cost(parentIndex))
        parentIndex = potentialParent(k2);
    end
end
function T = RandRelink(T,newCoor,cubeInfo,cylinderInfo,sphereInfo,step,r)
%% 随机重连,将新节点newCoor周围节点的父节点尝试改为新节点,若代价小于原来的代价值,则确认更改

% 寻找需要需要修改父节点的节点放入potentialParent里面。
potentialParent = -ones(1,size(T.x,2));
count = 1;
for k1 = 1:size(T.x,2)
    if CalcuDistance(newCoor,[T.x(k1),T.y(k1),T.z(k1)])<r
        potentialParent(count) = k1;
        count = count+1;
    end
end
potentialParent(potentialParent==-1)=[];

% 找到新节点的父节点集合,存在变量Index里
Index = -ones(1,size(T.x,2));
index = T.pre(end);
count = 1;
while T.pre(index)~=0
    Index(count) = index;
    index = T.pre(index);
    count = count+1;  
end
Index(Index==-1) = [];
potentialParent(ismember(potentialParent,Index)==1) = [];  %这行的意思是把需要修改父节点的节点集合,剔除新节点的父节点,以免出现环

% 根据代价决定是否修改父节点
for k2 = 1:size(potentialParent,2)
    pp = [T.x(potentialParent(k2)),T.y(potentialParent(k2)),T.z(potentialParent(k2))];
    if T.cost(potentialParent(k2))>( T.cost(end)+ CalcuDistance(pp,newCoor))
        if ~CollisionDetection(cubeInfo,cylinderInfo,sphereInfo,pp,newCoor,step)
            
            T.pre(potentialParent(k2)) = size(T.x,2)+1;
            T.cost(potentialParent(k2)) = CalcuDistance(newCoor,pp);
        end
    end
end

随机采样函数

function randCoor = RandSample(axisStart,axisLWH,goalPoint,randProbability)
%% 随机采样,当小于某一概率时,采用随机采样,其他情况直接将目标点作为采样点
if rand<randProbability 
    randX = rand*axisLWH(1)+axisStart(1);
    randY = rand*axisLWH(2)+axisStart(2);
    randZ = rand*axisLWH(3)+axisStart(3);
    randCoor = [randX,randY,randZ];
else
    randCoor = goalPoint;
end

 找到最近节点函数

function [nearestCoor,parentIndex] = FindNearstPoint(T,randCoor)
%% 遍历整个树,寻找距离随机点randCoor最近的点,标记为nearestCoor
tempDis = inf;
parentIndex = -1;
for k1 = 1:size(T.x,2)
    dis = CalcuDistance(randCoor,[T.x(k1),T.y(k1),T.z(k1)]);
    if dis<tempDis
        tempDis = dis;
        parentIndex = k1;
    end
end
nearestCoor = [T.x(parentIndex),T.y(parentIndex),T.z(parentIndex)];

 根据步长扩展点

function newCoor = ExpandPoint(nearCoor,randCoor,step)
%% 按照指定步长,随机点方向扩展新的点,命名为newCoor。这里按步长扩展点采用球坐标与直角坐标的转化方式
deltaX = randCoor(1)-nearCoor(1);
deltaY = randCoor(2)-nearCoor(2);
deltaZ = randCoor(3)-nearCoor(3);

r = sqrt(deltaX^2+deltaY^2+deltaZ^2);
fai = atan2(deltaY,deltaX);
theta = acos(deltaZ/r);

x = step*sin(theta)*cos(fai);
y = step*sin(theta)*sin(fai);
z = step*cos(theta);

newCoor = [x+nearCoor(1),y+nearCoor(2),z+nearCoor(3)];

 这些是代码中最核心的部分,因为代码太多,不在这里展示过多,具体获取方式可以看我b站视频(up主名字叫“-不秃头-”)。代码实际上是不免费的,是因为有人拿着我开源代码去卖(很难理解)。但是如果你要是真想学代码,帮我公众号和b站点个关注,我也能免费给你,但你不能拿去赚钱,就当我谢谢你了。

  • 11
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个简单的MATLAB实现RRT*算法代码: ```matlab clc; clear all; close all; start_point = [0, 0]; goal_point = [8, 8]; max_iter = 5000; delta_q = 0.5; goal_radius = 0.5; obstacle_radius = 1; q_start.cost = 0; q_start.parent = 0; q_start.pos = start_point; nodes(1) = q_start; figure(1) hold on plot(start_point(1), start_point(2), 'ro', 'MarkerSize',10,'MarkerFaceColor','r') plot(goal_point(1), goal_point(2), 'go', 'MarkerSize',10,'MarkerFaceColor','g') rectangle('Position',[2,2,2,2],'FaceColor',[0 .5 .5]) rectangle('Position',[5,5,2,2],'FaceColor',[0 .5 .5]) axis([-1 10 -1 10]) axis square grid on for i = 2:max_iter q_rand = [rand(1)*10, rand(1)*10]; % Find nearest node [q_near, q_near_ind] = find_nearest(q_rand, nodes); q_new = steer(q_near, q_rand, delta_q); if obstacle_free(q_near, q_new, obstacle_radius) % Find nearby nodes near_inds = find_near(q_new, nodes, delta_q * 3); % Choose parent q_min = q_near; C_min = q_new.cost + cost(q_near, q_new); for j = 1:length(near_inds) q_near_n = nodes(near_inds(j)); if obstacle_free(q_near_n, q_new, obstacle_radius) && q_near_n.cost + cost(q_near_n, q_new) < C_min q_min = q_near_n; C_min = q_near_n.cost + cost(q_near_n, q_new); end end % Rewire for j = 1:length(near_inds) q_near_n = nodes(near_inds(j)); if obstacle_free(q_new, q_near_n, obstacle_radius) && q_new.cost + cost(q_near_n, q_new) < q_near_n.cost q_near_n.parent = length(nodes); nodes(near_inds(j)) = q_near_n; end end % Add to tree q_new.cost = C_min; q_new.parent = q_min; nodes(end+1) = q_new; % Check if goal reached if norm(q_new.pos - goal_point) < goal_radius goal_node = length(nodes); break; end end % Plotting if mod(i, 100) == 0 plot(q_new.pos(1), q_new.pos(2), 'bo', 'MarkerSize', 5, 'MarkerFaceColor', 'b') plot([q_near.pos(1), q_new.pos(1)], [q_near.pos(2), q_new.pos(2)], 'b') pause(0.01) end end % Find path path = [goal_point]; while true curr_node = nodes(goal_node); path = [curr_node.pos; path]; goal_node = curr_node.parent; if goal_node == 1 path = [start_point; path]; break; end end % Plot path plot(path(:,1), path(:,2), 'r', 'LineWidth', 2) ``` 这段代码实现了RRT*算法来规划机器人在一个二维空间中的路径。请注意,该代码仅用于演示和学习目的,并不是一个完整的路径规划解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值