RRT-基于采样的约束运动规划的引入

本文详细介绍了基于采样的快速随机搜索随机树(RRT)算法,包括算法流程、关键模块如采样器、度量方法和局部规划器。通过MATLAB代码展示了RRT如何在二维路径规划和机器人路径规划场景中应用,以及如何找到从起点到目标点的碰撞避免路径。此外,还提供了参考代码链接和具体实现细节。
摘要由CSDN通过智能技术生成

基于采样的运动规划算法是一种高效的运动规划方法,其放弃了在高维状态中通过网格搜索产生的分辨率上的完整性和最优解,实现高维状态空间中快速找到可行解的能力。在机器人研究和应用中主要有两种基础算法:一个是单次查询的快速探索随机树(Rapidly exploring Random Tree, RRT)和概率路线图(probabilistic roadmap, PRM)。本篇文章主要是为了介绍快速随机搜索随机树的流程和MATLAB代码实现,为基于采样的约束运动规划提供理论和代码基础。

参考:

参考文献:

[1] K. M. Lynch, F. C. Park. Modern robotics. Massachusetts: Cambridge University Press, 2017
[2] Z. Kingston, M. Moll, L. E. Kavraki. Sampling-Based Methods for Motion Planning with Constraints. Annual Review of Control, Robotics, and Autonomous Systems. 2018, 1(1): 159-185

参考代码:

https://github.com/Mesywang/Motion-Planning-Algorithms
https://github.com/Nirucool/Robotics-Motion-Planning
https://petercorke.com/toolboxes/robotics-toolbox/#Downloading_the_Toolbox

RRT

RRT算法的伪代码如下:

Algorithm 1 RRT algorithm.
1: initialize search tree T with qstart
2: while T is less than the maximum tree size do
3:   qsamp ←sample from Q
4:   qnearest ←nearest node in T to qsamp
5:   employ a local planner to find a motion from qnearest to qnew in
the direction of qsamp
6:   if the motion is collision-free then
7:     add qnew to T with an edge from qnearest to qnew
8:     if ||qnew - qgoal||<ε then
9:        return SUCCESS and the motion to qnew
10:    end if
11:  end if
12: end while
13: return FAILURE

RRT的流程

根据伪代码可知对于RRT算法来说,其主要分为如下模块:生成新样本点的采样器,用以确定最近点的距离度量方式;局部规划器用以进行碰撞检测和生成新的节点。

采样器

最常见的采样器是在整个C空间进行随机采样,随着时间的增长,这一采样器理论上能够覆盖整个采样空间,这也为RRT方法提供了概率上的完整性;然而这种随机采样方法,会使得采样效率比较低,搜索产生目标路径所需的节点数量较多。
为了提高采样效率,可以使得采样器以一定的概率采样到目标位形。另一种可行的方案是利用示教学习的方法学习到可行轨迹和最优轨迹所在的采样子空间。如下图,为两种不同采样方法在同一场景和相同参数下的采样点分布和最终路径。

随机采样目标偏向采样

度量方法

度量方法用于确定搜索树中距离采样点中的最近点,通常所采样空间中的欧式距离已经能够解决大部分问题。

局部规划器

局部规划器用于生成新的节点并判断是否存在碰撞,因此往往在不同的应用场景需要使用不同的碰撞算法;而路线插值方法直接使用直线方法。

主要场景和代码

本文以及后续文章主要使用的是参考链接中的场景—二维路径规划和机器人路径规划场景。二维路径规划中的黑色图块为障碍物,搜索空间为整个图像的空间;机器人规划场景中机器人模型采用的是圆柱体模型,由机器人工具包生成,球形物体为障碍,位置和半径均是随机生成。
二维路径规划场景机器人规划场景

代码

ImpRgb = imread('map.png');
Imp = rgb2gray(ImpRgb);
imshow(Imp);
xL = size(Imp,1);   % 地图x轴长度
yL = size(Imp,2);   % 地图y轴长度
space=[0 xL;0 yL;];
规划参数 
x_I = 1; y_I = 1;           % 设置初始点
x_G = 750; y_G = 750;       % 设置目标点
Thr = 30;                   % 设置目标点阈值
Delta = 40;                 % 设置扩展步长
hold on
plot(x_I, y_I, 'mo', 'MarkerSize',10, 'MarkerFaceColor','m');
plot(x_G, y_G, 'go', 'MarkerSize',10, 'MarkerFaceColor','g');   % 绘制起点和目标点
树初始化
tree.v(1).configuration=[x_I;y_I];
tree.v(1).father=1;
tree.v(1).distance=0;
开始构建搜索树
count=1;
for iter=1:3000
    %step1 随机采样
    q_rand=sampler('goal',space,[x_G,y_G],0.1);
    
    %step2 寻找树中的最近点
    for j=1:size(tree.v,2)
       dis(j)=dismetric(q_rand,tree.v(j).configuration) ;
    end
    [minDis,minIndex]=min(dis);
    q_near=tree.v(minIndex).configuration;
    
    %step3 生成新的节点x_new
    q_new=extend_dis(q_near,q_rand,Delta);
        
    %局部规划器与碰撞检测
    if ~collisionChecking(q_near,q_new,Imp)
        continue;   % 有障碍物
    end
    count = count+1;
    
    %将目标点添加到搜索树上
    tree.v(count).configuration=q_new;
    tree.v(count).father=minIndex;
    tree.v(count).distance=Delta+tree.v(minIndex).distance;
    
    %step4 是否到达目标点
    dis2goal=norm([x_G;y_G]-q_new);
    if(dis2goal < Thr)
        count=count+1;
        goalIndex=count;
        tree.v(count).configuration=[x_G;y_G];
        tree.v(count).father=count-1;
        tree.v(count).distance=dis2goal+tree.v(count-1).distance;
        break
    end

    %绘图
    plot([q_near(1), q_new(1)], [q_near(2), q_new(2)], 'b', 'Linewidth', 2);
    plot(q_new(1), q_new(2), 'ko', 'MarkerSize', 4, 'MarkerFaceColor','k');
%     pause(0.02);     % 暂停0.02s,使得RRT扩展过程容易观察
end


路径查询
if iter < 2000
    path=FindTreePath(tree,goalIndex);
    for j = 2:size(path,1)
        plot([path(j,1); path(j-1,1)], [path(j,2); path(j-1,2)], 'g', 'Linewidth', 4);
    end
else
    disp('Error, no path found!');
end

其中寻找可行路径的代码为

configuration=tree.v(goalIndex).configuration;
path(1,:)=configuration(:)';
j=2;
pathIndex=tree.v(goalIndex).father;
while 1
    configuration=tree.v(pathIndex).configuration;
    path(j,:)=configuration(:)';
    pathIndex=tree.v(pathIndex).father;
    if pathIndex == 1
        break
    end
    j=j+1;
end
path(j+1,:)=tree.v(1).configuration;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值