当前位置:首页 » 《随便一记》 » 正文

Matlab RRT算法三维轨迹规划及贪心算法轨迹优化

5 人参与  2022年11月08日 12:33  分类 : 《随便一记》  评论

点击全文阅读


RRT算法简单介绍

1. RRT算法定义

RRT(Rapidly-Exploring Random Tree)算法是一种基于采样的路径规划算法,常用于移动机器人路径规划,适合解决高维空间和复杂约束下的路径规划问题。基本思想是以产生随机点的方式通过一个步长向目标点搜索前进,有效躲避障碍物,避免路径陷入局部极小值,收敛速度快。本文通过matlab实现RRT算法,解决二维平面的路径规划问题。
 

2. RRT算法基本步骤

1)确定起点start和终止点goal;

2)在空间中随机生成新的点r(50%为随机点,50%为目标点,目的是增强RRT向goal点生成的导向性);

3)判断点r与轨迹树中哪一个节点的欧氏距离最小,记该点为最近父节点closetNode;

4)沿生长向量方向(最近父节点closetNode指向随机点r的方向)按照步长stepSize生成新的子节点newNode;

5)碰撞检测:检测closetNode到newNode的连线是否会与障碍物发生碰撞。若是,返回步骤2,重新生成随机点;若否,则将newNode添加到轨迹树中。

6)检测是否到达goal附近。若是,结束搜索;若否,返回步骤2继续搜索。

三维轨迹Matlab仿真效果:

障碍物我们只设置了球形障碍物,也可以设置成立方体、圆柱体等等。

实施效果1:

     

 左:RRT随机树                                                 右:贪心算法优化后的随机树

 优化前,RRT树有80个节点,并且路径并不平滑。优化后,随机树只有三个点,路径只有两条直线组成。当然还可以继续对路径进行平滑,本文没有再继续做这些工作了。

 实施效果2:

 

以下为RRT算法的Matlab实现代码:

mian函数:

%created by MW%date: 2022/5/25%func: RRT avoiding obstacleclc;clear;%% 创建并绘制障碍物circleCenter = [100 200 100;                      200 700 100;                      200 500 500;                      700 700 300;                      900 200 100];radius = [100;100;200;200;300];%绘制球形障碍物figure(1);[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;endaxis equal;%% 创建初始位置和目标位置并绘制start = [0 0 0];goal = [700 800 1000];hold on;scatter3(start(1),start(2),start(3),'filled','g');scatter3(goal(1),goal(2),goal(3),'filled','b');%% 图片标注text(start(1),start(2),start(3),'起点');text(goal(1),goal(2),goal(3),'终点');view(3);grid on;axis equal;axis([0 1000 0 1000 0 1000]);xlabel('x');ylabel('y');zlabel('z');%% RRT方法生成避障轨迹path = RRT(start,goal,radius,circleCenter);%% 贪心算法优化RRT轨迹newPath = GreedyOptimize(path,radius,circleCenter);figure(2);%绘制球形障碍物[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;endaxis equal;%绘制原RRT树plot3(path(:,1), path(:,2), path(:,3),'LineWidth',1,'Color','r');%绘制优化后的RRT树for k1 =1: length(newPath)    point = newPath(k1,:);    scatter3(point(1),point(2),point(3),'filled','k');   endplot3(newPath(:,1), newPath(:,2), newPath(:,3),'LineWidth',2,'Color','y');%图片标注text(start(1),start(2),start(3),'起点');text(goal(1),goal(2),goal(3),'终点');view(3);grid on;axis equal;axis([0 1000 0 1000 0 1000]);xlabel('x');ylabel('y');zlabel('z');

RRT算法:

function path = RRT(start,goal,radius,circleCenter)%% 定义RRT参数stepSize = 20;                           %步长maxIterTimes = 5000;                     %最大迭代步数iterTime = 0;                            %当前迭代次数threshold = 20;                          %阈值searchSize = [1000 1000 1000];           %空间尺寸RRTree = double([start -1]);             %创建RRT树,共4列。前3列为节点坐标,第4列为当前节点的父节点的索引。初始点的索引为-1%多个点到某一点欧式距离计算方法calcDis = @(a,b) sqrt((b(:,1)-a(1,1)).^2 + (b(:,2)-a(1,2)).^2 + (b(:,3)-a(1,3)).^2);%% 寻找RRT路径tic                       % tic-toc函数,用于计时,记录完成整个RRT树的运行时间pathFound = false;        %标志物,记录是否正确找到避障路径while iterTime <= maxIterTimes    iterTime = iterTime +1;    %step1 - 生成随机点    %为了提高RRT扩展的导向性,以50%的概率在空间中随机生成生成新的随机点,50%的概率以目标点为新的随机点    if rand < 0.5           sample = rand(1,3) .* searchSize + start;    else        sample = goal;    end        %step2 - 寻找树上最近父节点    [val,nearIndex] = min(calcDis(sample, RRTree(:,1:3)),[],1);       %计算树上每个节点到随机点的欧氏距离,并返回最短距离的值和index    closestNode = RRTree(nearIndex,1:3);        %step3 - 沿生长向量方向按照步长生成新的子节点    growVec = sample - closestNode;    growVec = growVec/sqrt(sum(growVec.^2));    newPoint = closestNode + growVec*stepSize;        %step4 - 碰撞检测    feasible = collisionDetec(newPoint,closestNode,radius,circleCenter);    if ~feasible        continue;         %如果发生碰撞,则重新寻找随机点          end        %为树添加新节点    RRTree = [RRTree;                    newPoint nearIndex];    plot3([closestNode(1) newPoint(1)],[closestNode(2) newPoint(2)],[closestNode(3) newPoint(3)],'LineWidth',1,'Color','b');    pause(0.01);        %检测是否到达goal附近    if sqrt(sum((newPoint - goal).^2)) <= threshold        pathFound = true;        break;           %如果节点已到达goal附近,则结束搜寻    end   end%搜索结束后如果搜索失败,显示错误信息if ~pathFound    disp('no path found. maximum attempts reached');endtoc%% 绘制回溯路径path = goal;lastNode = nearIndex;           %父节点索引,这里的nearIndex是goal的父节点索引while lastNode >= 0    path =[RRTree(lastNode,1:3); path];         %将当前节点的上一个节点添加进回溯路径中    lastNode = RRTree(lastNode, 4);             %更新父节点索引endplot3(path(:,1), path(:,2), path(:,3),'LineWidth',1,'Color','r');end

碰撞检测算法:

线段检测:

%新的生长向量是否发生碰撞function feasible = collisionDetec(newPoint,closestNode,radius,circleCenter)feasible = true;checkVec = newPoint - closestNode;    %检测向量%将检测向量以0.5为步长等比均分为无数个检测点,检测每个检测点是否与球发生碰撞for i = 0:0.5:sqrt(sum(checkVec.^2))    checkPoint = closestNode + i.*(checkVec/sqrt(sum(checkVec.^2)));     %生成检测点    checkPointFeasible = pointCollisionCheck(checkPoint,radius,circleCenter);    if ~checkPointFeasible        feasible = false;        break;    end endend

点检测:

%监测点是否发生碰撞function pointFeasible = pointCollisionCheck(checkPoint,radius,circleCenter)pointFeasible = true;for s = 1:length(radius)    if sqrt(sum((checkPoint - circleCenter(s,:)).^2)) <= radius(s)        pointFeasible = false;        break;    end   endend

贪心算法简单介绍

1. 贪心算法定义:

贪心算法,是指在对问题求解时,总是做出再当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是某种意义上的局部最优解。

贪心算法没有固定算法框架,算法设计的关键是贪心策略的选择。必须注意的是,贪心算法不是对所有问题都能得到整体最优解,选择的贪心策略必须具备无后效性,即某个状态以后的过程不会影响以前的状态,只与当前状态有关。

2. 贪心算法基本步骤:

步骤1:从某个初始解出发;
步骤2:采用迭代的过程,当可以向目标前进一步时,就根据局部最优策略,得到一部分解,缩小问题规模;
步骤3:将所有解综合起来。

本问题下的贪心算法:

1)连接目标点和初始点。

2)检测是否发生碰撞。

3)若是,表明从初始点到该点中间不能被省略,沿目标点往上回溯到上一级父节点(上一级父节点更新为新的目标点),回到步骤1;若否,表明从初始点到该点中间的所有节点均可被省略,将该点添加到新的随机树中,并将该点更新为新的初始点,目标点复位到最后一个节点,回到步骤1.

4)检测直到start更新至goal结束。

function newPath = GreedyOptimize(path,radius,circleCenter)startIndex = 1;goalIndex = length(path(:,1));detectTimes = length(path(:,1)) - 1;          %检测次数newPath = [path(startIndex,:)];               %添加初始位置while detectTimes >0;    detectTimes = detectTimes-1;    start = path(startIndex,:);    goal = path(goalIndex,:);        %碰撞检测    feasible = collisionDetec(goal,start,radius,circleCenter);    if ~feasible        goalIndex = goalIndex - 1;            %若碰撞,index减1,继续向上探索父节点        continue;                                else        newPath = [newPath; goal];            %若未发生碰撞,表示找到一个最优节点,则从该节点往上的所有父节点均可省略,将该节点添加至路径中        detectTimes = length(path(:,1)) - goalIndex;        %检测次数更位        startIndex = goalIndex;               %将当前节点索引更新为新的树的起点        goalIndex = length(path(:,1));        %将终点索引复位    end   endnewPath = [newPath; path(end,:)];             %添加目标位置end


点击全文阅读


本文链接:http://zhangshiyu.com/post/47436.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1