[matlab] 7.快速搜索随机树(RRT---Rapidly-exploring Random Trees) 路径规划

RRT是一种多维空间中有效率的规划方法。它以一个初始点作为根节点,通过随机采样增加叶子节点的方式,生成一个随机扩展树,当随机树中的叶子节点包含了目标点或进入了目标区域,便可以在随机树中找到一条由从初始点到目标点的路径。RRT方法是概率完备且不最优的。

function BuildRRT(qinit, K, Δq)
    T.init(qinit)
    for k = 1 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(0, 1.0)
    if 0 < p < Prob then
        return qgoal
    elseif Prob < p < 1.0 then
        return RandomNode()
RRT 伪代码

  初始化时随机树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 )。可以看到,同样是随机树,但是这棵树并没很好地探索空间。

 

 

下面是具体的代码

%% RRT parameters
map=im2bw(imread('map.bmp')); % input map read from a bmp file. for new maps write the file name here
source=[490 490]; % source position in Y, X format
goal=[10 900]; % 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','r');
line(path(:,2),path(:,1));
rrt_main.m
%% distanceCost.m
function h=distanceCost(a,b)
    h = sqrt(sum((a-b).^2, 2));
distanceCost.m
%% 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
checkPath.m
%% 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
feasiblePoint.m

 

结果如图

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然,我可以为你提供 RRT-Connect 算法的 MATLAB 代码示例。RRT-Connect 是一种基于 Rapidly-exploring Random Trees (RRT) 的路径规划算法,用于在两个给定点之间查找可行路径。以下是一个简单的实现: ```matlab % RRT-Connect Algorithm function path = rrt_connect(start, goal, obstacles, max_iter, step_size) % Initialize trees tree_start = start; tree_goal = goal; for i = 1:max_iter % Randomly sample a point if rand() < 0.5 rand_point = [rand()*100, rand()*100]; % Modify according to your workspace size else rand_point = goal; end % Extend tree_start towards rand_point nearest_start = nearest_neighbor(tree_start, rand_point); new_point_start = steer(nearest_start, rand_point, step_size); if ~collision(new_point_start, nearest_start, obstacles) tree_start = add_node(tree_start, nearest_start, new_point_start); % Connect tree_goal towards new_point_start nearest_goal = nearest_neighbor(tree_goal, new_point_start); new_point_goal = steer(nearest_goal, new_point_start, step_size); if ~collision(new_point_goal, nearest_goal, obstacles) tree_goal = add_node(tree_goal, nearest_goal, new_point_goal); % Check if the trees have met if norm(new_point_start - new_point_goal) <= step_size path = generate_path(tree_start, tree_goal); return; end end end % Swap trees if necessary if rand() < 0.5 temp = tree_start; tree_start = tree_goal; tree_goal = temp; end end % No path found error('No feasible path found'); end % Helper functions function nearest_node = nearest_neighbor(tree, point) distances = vecnorm(tree - point, 2, 2); [~, index] = min(distances); nearest_node = tree(index, :); end function new_point = steer(from, to, step_size) direction = (to - from) / norm(to - from); new_point = from + direction * step_size; end function is_collision = collision(point, from, obstacles) for i = 1:size(obstacles, 1) if norm(point - from) <= norm(obstacles(i, :) - from) is_collision = true; return; end end is_collision = false; end function new_tree = add_node(tree, from, to) new_tree = [tree; to]; end function path = generate_path(tree_start, tree_goal) path_start = trace_path(tree_start); path_goal = flip(trace_path(tree_goal)); path = [path_start; path_goal]; end function path = trace_path(tree) path = tree(end, :); while ~isempty(path) && ~isequal(path(1, :), tree(1, :)) parent_index = find(ismember(tree, path(1, :), 'rows')); path = [tree(parent_index, :); path]; end end ``` 请注意,这只是一个简单的示例代码,你需要根据你的具体场景进行修改和适配。你需要提供起点、终点、障碍物、最大迭代次数和步长等参数来调用 `rrt_connect` 函数。如果找到可行路径,它将返回一系列点构成的路径。如果没有找到可行路径,它将抛出错误。 希望这可以帮助到你!如果你有任何其他问题,请随时问我。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值