传统的路径规划算法有人工势场法、模糊规则法、遗传算法、神经网络、模拟退火算法、蚁群优化算法等。但这些方法都需要在一个确定的空间内对障碍物进行建模,计算复杂度与机器人自由度呈指数关系,不适合解决多自由度机器人在复杂环境中的规划。基于快速扩展随机树(RRT / rapidly exploring random tree)的路径规划算法,通过对状态空间中的采样点进行碰撞检测,避免了对空间的建模,能够有效地解决高维空间和复杂约束的路径规划问题。该方法的特点是能够快速有效地搜索高维空间,通过状态空间的随机采样点,把搜索导向空白区域,从而寻找到一条从起始点到目标点的规划路径,适合解决多自由度机器人在复杂环境下和动态环境中的路径规划。与PRM类似,该方法是概率完备且不最优的。

  

  RRT是一种多维空间中有效率的规划方法。它以一个初始点作为根节点,通过随机采样增加叶子节点的方式,生成一个随机扩展树,当随机树中的叶子节点包含了目标点或进入了目标区域,便可以在随机树中找到一条由从初始点到目标点的路径。基本RRT算法如下面伪代码所示:

 function BuildRRT(qinit, K, Δq)
T.init(qinit)
for k = to K
qrand = Sample() -- chooses a random configuration
qnearest = Nearest(T, qrand) -- selects the node in the RRT tree that is closest to qrand
if Distance(qnearest, qgoal) < Threshold then
return true
qnew = Extend(qnearest, qrand, Δq) -- moving from qnearest an incremental distance in the direction of qrand
if qnew ≠ NULL then
T.AddNode(qnew)
return false function Sample() -- Alternatively,one could replace Sample with SampleFree(by using a collision detection algorithm to reject samples in C_obstacle
p = Random(, 1.0)
if < p < Prob then
return qgoal
elseif Prob < p < 1.0 then
return RandomNode()

  初始化时随机树T只包含一个节点:根节点qinit。首先Sample函数从状态空间中随机选择一个采样点qrand(4行);然后Nearest函数从随机树中选择一个距离qrand最近的节点qnearest(5行);最后Extend函数通过从qnearest向qrand扩展一段距离,得到一个新的节点qnew(8行)。如果qnew与障碍物发生碰撞,则Extend函数返回空,放弃这次生长,否则将qnew加入到随机树中。重复上述步骤直到qnearest和目标点qgaol距离小于一个阈值,则代表随机树到达了目标点,算法返回成功(6~7行)。为了使算法可控,可以设定运行时间上限或搜索次数上限(3行)。如果在限制次数内无法到达目标点,则算法返回失败。
  为了加快随机树到达目标点的速度,简单的改进方法是:在随机树每次的生长过程中,根据随机概率来决定qrand是目标点还是随机点。在Sample函数中设定参数Prob,每次得到一个0到1.0的随机值p,当0<p<Prob的时候,随机树朝目标点生长行;当Prob<p<1.0时,随机树朝一个随机方向生长。

  上述算法的效果是随机采样点会“拉着”树向外生长,这样能更快、更有效地探索空间(The effect is that the nearly uniformly distributed samples “pull” the tree toward them, causing the tree to rapidly explore C-Space)。随机探索也讲究策略,如果我们从树中随机取一个点,然后向着随机的方向生长,那么结果是什么样的呢?见下图(Left: A tree generated by applying a uniformly-distributed random motion from a randomly chosen tree node does not explore very far. Right: A tree generated by the RRT algorithm using samples drawn randomly from a uniform distribution. Both trees have 2000 nodes )。可以看到,同样是随机树,但是这棵树并没很好地探索空间。

  根据上面的伪代码,可以用MATLAB实现一个简单的RRT路径规划(参考这里)。输入一幅像素尺寸为500×500的地图,使用RRT算法搜索出一条无碰撞路径:

%% RRT parameters
map=im2bw(imread('map1.bmp')); % input map read from a bmp file. for new maps write the file name here
source=[10 10]; % source position in Y, X format
goal=[490 490]; % goal position in Y, X format
stepsize = 20; % size of each step of the RRT
threshold = 20; % nodes closer than this threshold are taken as almost the same
maxFailedAttempts = 10000;
display = true; % display of RRT if ~feasiblePoint(source,map), error('source lies on an obstacle or outside map'); end
if ~feasiblePoint(goal,map), error('goal lies on an obstacle or outside map'); end
if display,imshow(map);rectangle('position',[1 1 size(map)-1],'edgecolor','k'); end tic; % tic-toc: Functions for Elapsed Time RRTree = double([source -1]); % RRT rooted at the source, representation node and parent index
failedAttempts = 0;
counter = 0;
pathFound = false; while failedAttempts <= maxFailedAttempts % loop to grow RRTs
  %% chooses a random configuration
if rand < 0.5
sample = rand(1,2) .* size(map); % random sample
else
sample = goal; % sample taken as goal to bias tree generation to goal
end   %% selects the node in the RRT tree that is closest to qrand
[A, I] = min( distanceCost(RRTree(:,1:2),sample) ,[],1); % find the minimum value of each column
closestNode = RRTree(I(1),1:2);   %% moving from qnearest an incremental distance in the direction of qrand
theta = atan2(sample(1)-closestNode(1),sample(2)-closestNode(2)); % direction to extend sample to produce new node
newPoint = double(int32(closestNode(1:2) + stepsize * [sin(theta) cos(theta)]));
if ~checkPath(closestNode(1:2), newPoint, map) % if extension of closest node in tree to the new point is feasible
failedAttempts = failedAttempts + 1;
continue;
end if distanceCost(newPoint,goal) < threshold, pathFound = true; break; end % goal reached [A, I2] = min( distanceCost(RRTree(:,1:2),newPoint) ,[],1); % check if new node is not already pre-existing in the tree
if distanceCost(newPoint,RRTree(I2(1),1:2)) < threshold, failedAttempts = failedAttempts + 1; continue; end RRTree = [RRTree; newPoint I(1)]; % add node
failedAttempts = 0;
if display, line([closestNode(2);newPoint(2)],[closestNode(1);newPoint(1)]);counter = counter + 1; M(counter) = getframe; end % Capture movie frame
end % getframe returns a movie frame, which is a structure having two fields
if display && pathFound, line([closestNode(2);goal(2)],[closestNode(1);goal(1)]); counter = counter+1;M(counter) = getframe; end if display, disp('click/press any key'); waitforbuttonpress; end
if ~pathFound, error('no path found. maximum attempts reached'); end %% retrieve path from parent information
path = [goal];
prev = I(1);
while prev > 0
path = [RRTree(prev,1:2); path];
prev = RRTree(prev,3);
end pathLength = 0;
for i=1:length(path)-1, pathLength = pathLength + distanceCost(path(i,1:2),path(i+1,1:2)); end % calculate path length
fprintf('processing time=%d \nPath Length=%d \n\n', toc, pathLength);
imshow(map);rectangle('position',[1 1 size(map)-1],'edgecolor','k');
line(path(:,2),path(:,1));

  其它M文件:

%% distanceCost.m
function h=distanceCost(a,b)
h = sqrt(sum((a-b).^2, 2)); %% checkPath.m
function feasible=checkPath(n,newPos,map)
feasible=true;
dir=atan2(newPos(1)-n(1),newPos(2)-n(2));
for r=0:0.5:sqrt(sum((n-newPos).^2))
posCheck=n+r.*[sin(dir) cos(dir)];
if ~(feasiblePoint(ceil(posCheck),map) && feasiblePoint(floor(posCheck),map) && ...
feasiblePoint([ceil(posCheck(1)) floor(posCheck(2))],map) && feasiblePoint([floor(posCheck(1)) ceil(posCheck(2))],map))
feasible=false;break;
end
if ~feasiblePoint(newPos,map), feasible=false; end
end %% feasiblePoint.m
function feasible=feasiblePoint(point,map)
feasible=true;
% check if collission-free spot and inside maps
if ~(point(1)>=1 && point(1)<=size(map,1) && point(2)>=1 && point(2)<=size(map,2) && map(point(1),point(2))==1)
feasible=false;
end

  RRT算法也有一些缺点,它是一种纯粹的随机搜索算法对环境类型不敏感,当C-空间中包含大量障碍物或狭窄通道约束时,算法的收敛速度慢,效率会大幅下降:

  RRT 的一个弱点是难以在有狭窄通道的环境找到路径。因为狭窄通道面积小,被碰到的概率低。下图展示的例子是 RRT 应对一个人为制作的很短的狭窄通道,有时RRT很快就找到了出路,有时则一直被困在障碍物里面:

  上述基础RRT算法中有几处可以改进的地方:

  • how to sample from C-Space (line 4). 如何进行随机采样
  • how to define the “nearest” node in T (line 5). 如何定义“最近”点
  • how to plan the motion to make progress toward sample (line 8). 如何进行树的扩展

  Even a small change to the sampling method, for example, can yield a dramatic change in the running time of the planner. A wide variety of planners have been proposed in the literature based on these choices and other variations. 根据以上几个方向,多种RRT改进算法被提出。

  • Defining the Nearest Node

  查找最近点的基础是计算C-Space中两点间的距离。计算距离最直观的方法是使用欧氏距离,但对很多C-Space来说这样做的直观意义并不明显。Finding the “nearest” node depends on a definition of distance. A natural choice for the distance between two points is simply the Euclidean distance. For other spaces, the choice is less obvious. 举个例子,如下图所示,对于一个car-like robot来说其C-space为R2×S1.  虚线框分别代表三种不同的机器人构型:第一个构型绕其旋转了20°,第二个在它后方2米处,最后一个在侧方位1米处。那么哪一种距离灰色的目标“最近”呢?汽车型机器人的运动约束导致其不能直接进行横向运动和原地转动。因此,对于这种机器人来说从第二种构型移动到目标位置“最近”。

  从上面的例子可以看出来,定义一个距离需要考虑以下两点:

  • combining components of different units (e.g., degrees, meters, degrees/s,meters/s) into a single distance measure;
  • taking into account the motion constraints of the robot

  结合不同单位的一个简单办法是使用加权平均计算距离,不同分量的重要程度用权值大小表示(The weights express the relative importance of the different components)。寻找最近点在计算机科学和机器人学等领域中是一个非常普遍的问题,已经有各种用于加速计算的方法,比如K-d树、hash算法等。

  • The Sampler

  The reason that the tree ends up covering the entire search space (in most cases) is because of the combination of the sampling strategy, and always looking to connect from the nearest point in the tree. The choice of where to place the next vertex that you will attempt to connect to is the sampling problem. In simple cases, where search is low dimensional, uniform random placement (or uniform random placement biased toward the goal) works adequately. In high dimensional problems, or when motions are very complex (when joints have positions, velocities and accelerations), or configuration is difficult to control, sampling strategies for RRTs are still an open research area.

  •  The Local Planner

  The job of the local planner is to find a motion from qnearest to some point qnew which is closer to qrand. The planner should be simple and it should run quickly.

  • A straight-line planner. The plan is a straight line to qnew, which may be chosen at qrand or at a fixed distance d from qnearest on the straight line to qrand. This is suitable for kinematic systems with no motion constraints.

Bidirectional RRT / RRT Connect

  基本的RRT每次搜索都只有从初始状态点生长的快速扩展随机树来搜索整个状态空间,如果从初始状态点和目标状态点同时生长两棵快速扩展随机树来搜索状态空间,效率会更高。为此,基于双向扩展平衡的连结型双树RRT算法,即RRT_Connect算法被提出。

  该算法与原始RRT相比,在目标点区域建立第二棵树进行扩展。每一次迭代中,开始步骤与原始的RRT算法一样,都是采样随机点然后进行扩展。然后扩展完第一棵树的新节点

RRT路径规划算法的更多相关文章

  1. RRT路径规划算法(matlab实现)

    基于快速扩展随机树(RRT / rapidly exploring random tree)的路径规划算法,通过对状态空间中的采样点进行碰撞检测,避免了对空间的建模,能够有效地解决高维空间和复杂约束的 ...

  2. ROS(indigo)RRT路径规划

    源码地址:https://github.com/nalin1096/path_planning 路径规划 使用ROS实现了基于RRT路径规划算法. 发行版 - indigo 算法在有一个障碍的环境找到 ...

  3. 路径规划: PRM 路径规划算法 (Probabilistic Roadmaps 随机路标图)

    随机路标图-Probabilistic Roadmaps (路径规划算法) 路径规划作为机器人完成各种任务的基础,一直是研究的热点.研究人员提出了许多规划方法如: 1. A* 2. Djstar 3. ...

  4. 全局路径规划算法Dijkstra(迪杰斯特拉算法)- matlab

    参考博客链接:https://www.cnblogs.com/kex1n/p/4178782.html Dijkstra是常用的全局路径规划算法,其本质上是一个最短路径寻优算法.算法的详细介绍参考上述 ...

  5. DWA局部路径规划算法论文阅读:The Dynamic Window Approach to Collision Avoidance。

    DWA(动态窗口)算法是用于局部路径规划的算法,已经在ROS中实现,在move_base堆栈中:http://wiki.ros.org/dwa_local_planner DWA算法第一次提出应该是1 ...

  6. 基础路径规划算法(Dijikstra、A*、D*)总结

    引言 在一张固定地图上选择一条路径,当存在多条可选的路径之时,需要选择代价最小的那条路径.我们称这类问题为最短路径的选择问题.解决这个问题最经典的算法为Dijikstra算法,其通过贪心选择的步骤从源 ...

  7. PRM路径规划算法

    路径规划作为机器人完成各种任务的基础,一直是研究的热点.研究人员提出了许多规划方法:如人工势场法.单元分解法.随机路标图(PRM)法.快速搜索树(RRT)法等.传统的人工势场.单元分解法需要对空间中的 ...

  8. 路径规划算法之Bellman-Ford算法

    最近由于工作需要一直在研究Bellman-Ford算法,这也是我第一次用C++编写代码. 1.Bellman-Ford算法总结 (1)Bellman-Ford算法计算从源点(起始点)到任意一点的最短路 ...

  9. 机器人路径规划其一 Dijkstra Algorithm【附动态图源码】

    首先要说明的是,机器人路径规划与轨迹规划属于两个不同的概念,一般而言,轨迹规划针对的对象为机器人末端坐标系或者某个关节的位置速度加速度在时域的规划,常用的方法为多项式样条插值,梯形轨迹等等,而路径规划 ...

随机推荐

  1. 使用SpringBoot的关于页面跳转的问题

    示例如下: @Controller public class UserController { @Resource UserService userService; @RequestMapping(& ...

  2. HTML5 浏览器返回按钮/手机返回按钮事件监听

    1.HTML5  History对象 支持使用pushState()方法修改地址栏地址,而不刷新页面. popstate事件 当history实体被改变时,popstate事件将会发生.调用pushS ...

  3. sublime3 安装 Package Control 报错 “There Are No Packages Available For Installation”

    编辑Preferences > Package Settings > Package Control > Settings - User文件 码上 { "channels& ...

  4. Java NIO Pipe

    A Java NIO Pipe is a one-way data connection between two threads. A Pipe has a source channel and a ...

  5. pthread_once重塑singleton模式

    单件模式是非线程安全的: // Single threaded version class Foo { private Helper helper = null; public Helper getH ...

  6. Spring系列:Scheduled注解学习笔记

    一.试验代码 //@Scheduled(fixedRate = 5000) //@Scheduled(fixedDelay = 5000) @Scheduled(cron ="*/5 * * ...

  7. jQuery-append添加元素click无效

    很久没有使用jQuery,做项目的时候遇到一个小问题就是网页加载之后的append的元素是可以执行click事件,网页加载完成之后的,再次append的元素不执行click事件,简单的通过ul模拟一下 ...

  8. 代码提示级别设置 inspection

    配置文件 profile [ˈproʊfaɪl] n.侧面; 外形,轮廓; 人物简介; vt.描-的轮廓; 给-画侧面图; inspection [ɪnˈspɛkʃən] n.检验; 检查; 视察; ...

  9. 老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件

    ios 8 的时间滚轮控件实现了扁平化,带来很好用户体验,android没有现成控件,小弟不才,数学与算法知识不过关,顾十分苦恼,幸好在github上找到sai大神实现代码,甚为欣喜,顾把学习这个控件 ...

  10. scikit-learn的GBDT工具进行特征选取。

    http://blog.csdn.net/w5310335/article/details/48972587 使用GBDT选取特征 2015-03-31 本文介绍如何使用scikit-learn的GB ...