算法实现1——一步一步实现RRT(算法原理及matlab代码)

  首先我们得明白算法的原理,然后写出步骤。根据步骤可以写出主函数包括每一步的输入输出,怎么表示(基本的伪代码表示,当然如果可以也可以写成汉字形式的),最后一步一步写出代码,调试工作是必须的(建议:子函数尽量分开写,功能分明,便于调试)。好了,差不多就这样,开始做吧^-^

1建立地图,设置起始点,目标点,(障碍带)

2初始化参数:

顶点vertices=起始点q_start;

边edges=空集empty;

设置采样数目k;

初始化启发概率p——>q_goal;

3主循环

For k in range

3.1判断是否到达目标点isGoalOnQNearQNewEdge()

输入:q_new,q_goal,delta_q

输出:返回类型:布尔型。1到达,0未到达

操作内容:判断q_goal与q_new距离在delta_q范围内;

If q_new == q_goal

Break;

End For

 

3.2if rand<p q_rand = q_goal;elseq_rand=p(map_x,map,y),生成随机采样点

3.3在顶点表中寻找离q_rand最近的顶点q_near,根据delta_q距离得到新的子节点——q_new

输入:vertices,delta_q,  q_rand

输出:q_new,q_near

操作内容:根据q_rand与vertices的每个点的欧式距离得出q_near,然后根据方向向量得出q_new

3.4 判断是否加入顶点列表中isAddInVerticesList()

输入:map,q_new,vertices,edges

输出:返回类型:布尔型。1加入0不加入

操作内容:

  将它与父节点连接成边edge1,然后将其分解为10个点,间隔总长/10;

If  1

将新节点加入vertices

将edge1加入edges边集合[q_new,q_parent]

Else

Continue;

EndIf

4根据边集合中,返回顶点索引【行向量】,根据行向量索引在顶点集合中,返回路径

path=Findpathnode(q_goal,q_star vertices);

plot(path)

5 path_smooth = smooth(path,vertices,map)%光滑采用的是贪心策略

此处遇到的问题是由于从目标点向起点进行判断连接成的边是否在障碍区内

所以此时增加插值点个数50个

补充:代码及地图数据地址https://download.csdn.net/download/qinze5857/10901150

——下面是自写代码,用matlab发布形式粘贴的哈

Contents

  • color map
  • rrt tree %行是y坐标,列是x坐标
  • sub function
function My_RRT
 My_RRT
clc
clear
close all
all

color map

load maze.mat map
[map_height,map_width]=size(map); %行是高y,列是宽x
q_start = [206, 198]; %q s t a r t ( 1 ) : x宽 , q s t a r t ( 2 ) : y高
q_goal = [416, 612];
colormap=[1 1 1
          0 0 0
          1 0 0
          0 1 0
          0 0 1];
imshow(uint8(map),colormap)
hold on
maze.mat map
[map_height,map_width]=size(map); %行是高y,列是宽x
q_start = [206, 198]; %q s t a r t ( 1 ) : x宽 , q s t a r t ( 2 ) : y高
q_goal = [416, 612];
colormap=[1 1 1
          0 0 0
          1 0 0
          0 1 0
          0 0 1];
imshow(uint8(map),colormap)
hold on
警告: 图像太大,无法在屏幕上显示;将以
67% 显示 

rrt tree %行是y坐标,列是x坐标

%initial
vertices=q_start;
edges = [];
K=10000;
delta_q=50;
p=0.3;
q_rand=[];
q_near=[];
q_new=[];
%main loop
plot(q_start(2),q_start(1),'*b')
plot(q_goal(2),q_goal(1),'*y')
for k = 1:K
    arrived=is_goal_arrived(vertices,q_goal,delta_q);
    if arrived
        vertices=[vertices;q_goal];
        edges = [edges;[size(vertices,1),size(vertices,1)-1]];
        break;
    end
    if rand <= p
        q_rand = q_goal;%q(1)宽x,q(2)高y
    else
        q_rand = [randi(map_height),randi(map_width)];
    end
    if map( q_rand(1,1),q_rand(1,2) ) == 1 %map(1)height,map(2)width
        continue;
    end
    [q_new,q_near,q_near_ind,vector_dir] = get_qnew_qnear(delta_q,q_rand,vertices);
    add_qnew = is_add_in_veritces(map,q_new,q_near,vector_dir,10);
    if add_qnew
        vertices=[vertices;q_new];
        r_v = size(vertices,1);
        edges = [edges;[r_v,q_near_ind]];
    else
        continue;
    end
%     plot(q_near(1,1),q_near(2,1),'*b');
   plot([q_near(1,2),q_new(1,2)],[q_near(1,1),q_new(1,1)],'-b')
   drawnow
end
path =find_path_node(edges);
%plot base path
plot(vertices(path,2),vertices(path,1),'-r')
%smooth
path_smooth = smooth(path,vertices,map);
%plot smooth path
plot(vertices(path_smooth,2),vertices(path_smooth,1),'-g');

vertices=q_start;
edges = [];
K=10000;
delta_q=50;
p=0.3;
q_rand=[];
q_near=[];
q_new=[];
%main loop
plot(q_start(2),q_start(1),'*b')
plot(q_goal(2),q_goal(1),'*y')
for k = 1:K
    arrived=is_goal_arrived(vertices,q_goal,delta_q);
    if arrived
        vertices=[vertices;q_goal];
        edges = [edges;[size(vertices,1),size(vertices,1)-1]];
        break;
    end
    if rand <= p
        q_rand = q_goal;%q(1)宽x,q(2)高y
    else
        q_rand = [randi(map_height),randi(map_width)];
    end
    if map( q_rand(1,1),q_rand(1,2) ) == 1 %map(1)height,map(2)width
        continue;
    end
    [q_new,q_near,q_near_ind,vector_dir] = get_qnew_qnear(delta_q,q_rand,vertices);
    add_qnew = is_add_in_veritces(map,q_new,q_near,vector_dir,10);
    if add_qnew
        vertices=[vertices;q_new];
        r_v = size(vertices,1);
        edges = [edges;[r_v,q_near_ind]];
    else
        continue;
    end
%     plot(q_near(1,1),q_near(2,1),'*b');
   plot([q_near(1,2),q_new(1,2)],[q_near(1,1),q_new(1,1)],'-b')
   drawnow
end
path =find_path_node(edges);
%plot base path
plot(vertices(path,2),vertices(path,1),'-r')
%smooth
path_smooth = smooth(path,vertices,map);
%plot smooth path
plot(vertices(path_smooth,2),vertices(path_smooth,1),'-g');

<span style="color:#0000ff">end</span>

sub function

function arrived=is_goal_arrived(vertices,q_goal,delta_q)
%判断是否到达终点
dist=pdist2(vertices(end,:),q_goal);
if dist <= delta_q
    arrived=1;
else
    arrived=0;
end
end

function [q_new,q_near,q_near_ind,vector_dir] = get_qnew_qnear(delta_q,q_rand,vertices)
%获得节点中最近的和新节点
dist_rand = pdist2(vertices,q_rand);
[dist_min,q_near_ind]=min(dist_rand);
q_near=vertices(q_near_ind,:);
vector_dir =q_rand-q_near;
vector_dir = vector_dir./dist_min;
if dist_min > delta_q    %随机点到最近点的距离不确定
    q_new = floor( q_near+delta_q*vector_dir );
else
    q_new=q_rand;
end
end

function add_qnew = is_add_in_veritces(map,q_new,q_near,vector_dir,insert_p)
%判断是否加入到列表中,q_new,与edges_new
%输出:add_qnew=1加入 0不加入
%注意:sub2ind,[y高,x宽]=size(map),q_goal=[x宽,y高]
dist_new2near = norm(q_new - q_near);%此处有问题
dist_gap = dist_new2near/insert_p;
ii =1:insert_p;
insert_point = repmat(q_near,insert_p,1)+ii'.*dist_gap* vector_dir;
insert_point =[floor(insert_point);q_new];
insert_num = sub2ind(size(map),insert_point(:,1),insert_point(:,2));
or =find( map(insert_num)==1 );
if ~isempty(or)
    add_qnew=0;
else
    add_qnew=1;
end

end

function path =find_path_node(edges)
%返回路径 ,path代表在顶点中的行数,返回的是行向量
e=edges(end,2);
path = edges(end,:);
while true
   ind= find(edges(:,1)==e);
    tmp_e = edges(ind,:);
    e=tmp_e(2);
    path=[path,e];
    if e==1
        break;
    end
end

end

function path_smooth = smooth(path,vertices,map)
%光滑方法:从起点往前找
% path = fliplr(path);
path_smooth =path(end);
tmp_point = vertices(1,:);
while true
    l_p = length(path);
    for i=1:l_p
        vec = vertices( path(i),:) - tmp_point;
        vec_dir = vec/norm(vec);
        or_reduce = is_add_in_veritces(map ,vertices(path(i),: ),tmp_point,vec_dir,60);
        if or_reduce==1 %可缩减
           path_smooth = [path_smooth, path(i)];
           tmp_point = vertices(path(i),: );
           break;
        else
            continue;
        end
    end
    vec_goal = vertices(end,:) - tmp_point;
    goal_dir = vec_goal/norm(vec_goal);
    or_goal = is_add_in_veritces(map , vertices(end,: ),tmp_point,goal_dir,60);
    if or_goal==1  %可以与目标点连接
        path_smooth = [path_smooth, path(1)];
        break;
    else
        ind_path = find(path==path(i));
        path=path(1:ind_path);
    end
end

end
 arrived=is_goal_arrived(vertices,q_goal,delta_q)
%判断是否到达终点
dist=pdist2(vertices(end,:),q_goal);
if dist <= delta_q
    arrived=1;
else
    arrived=0;
end
end

function [q_new,q_near,q_near_ind,vector_dir] = get_qnew_qnear(delta_q,q_rand,vertices)
%获得节点中最近的和新节点
dist_rand = pdist2(vertices,q_rand);
[dist_min,q_near_ind]=min(dist_rand);
q_near=vertices(q_near_ind,:);
vector_dir =q_rand-q_near;
vector_dir = vector_dir./dist_min;
if dist_min > delta_q    %随机点到最近点的距离不确定
    q_new = floor( q_near+delta_q*vector_dir );
else
    q_new=q_rand;
end
end

function add_qnew = is_add_in_veritces(map,q_new,q_near,vector_dir,insert_p)
%判断是否加入到列表中,q_new,与edges_new
%输出:add_qnew=1加入 0不加入
%注意:sub2ind,[y高,x宽]=size(map),q_goal=[x宽,y高]
dist_new2near = norm(q_new - q_near);%此处有问题
dist_gap = dist_new2near/insert_p;
ii =1:insert_p;
insert_point = repmat(q_near,insert_p,1)+ii'.*dist_gap* vector_dir;
insert_point =[floor(insert_point);q_new];
insert_num = sub2ind(size(map),insert_point(:,1),insert_point(:,2));
or =find( map(insert_num)==1 );
if ~isempty(or)
    add_qnew=0;
else
    add_qnew=1;
end

end

function path =find_path_node(edges)
%返回路径 ,path代表在顶点中的行数,返回的是行向量
e=edges(end,2);
path = edges(end,:);
while true
   ind= find(edges(:,1)==e);
    tmp_e = edges(ind,:);
    e=tmp_e(2);
    path=[path,e];
    if e==1
        break;
    end
end

end

function path_smooth = smooth(path,vertices,map)
%光滑方法:从起点往前找
% path = fliplr(path);
path_smooth =path(end);
tmp_point = vertices(1,:);
while true
    l_p = length(path);
    for i=1:l_p
        vec = vertices( path(i),:) - tmp_point;
        vec_dir = vec/norm(vec);
        or_reduce = is_add_in_veritces(map ,vertices(path(i),: ),tmp_point,vec_dir,60);
        if or_reduce==1 %可缩减
           path_smooth = [path_smooth, path(i)];
           tmp_point = vertices(path(i),: );
           break;
        else
            continue;
        end
    end
    vec_goal = vertices(end,:) - tmp_point;
    goal_dir = vec_goal/norm(vec_goal);
    or_goal = is_add_in_veritces(map , vertices(end,: ),tmp_point,goal_dir,60);
    if or_goal==1  %可以与目标点连接
        path_smooth = [path_smooth, path(1)];
        break;
    else
        ind_path = find(path==path(i));
        path=path(1:ind_path);
    end
end

end


Published with MATLAB® R2015b

  • 42
    点赞
  • 278
    收藏
    觉得还不错? 一键收藏
  • 47
    评论
以下是一个简单的MATLAB实现,包括基于RRT*算法的路径规划和路径可视化: ``` classdef RRTStar < handle properties q_start q_goal obstacle_list step_size max_iter goal_tolerance tree fig_handle axis_handle plot_handle end methods function obj = RRTStar(q_start, q_goal, obstacle_list, step_size, max_iter, goal_tolerance) obj.q_start = q_start; obj.q_goal = q_goal; obj.obstacle_list = obstacle_list; obj.step_size = step_size; obj.max_iter = max_iter; obj.goal_tolerance = goal_tolerance; obj.tree = [q_start, NaN]; obj.fig_handle = figure; obj.axis_handle = gca; obj.plot_handle = plot(q_start(1), q_start(2), 'ro'); axis([0 10 0 10]); hold on; end function [q_new, nearest_node] = extend(obj) q_rand = obj.sample(); nearest_node = obj.nearest(q_rand); q_new = obj.steer(nearest_node, q_rand); if obj.check_collision(nearest_node, q_new) [q_min, c_min] = obj.find_best_parent(q_new, nearest_node); obj.tree = [obj.tree, [q_new; q_min]]; obj.rewire(q_new, c_min); obj.plot(q_new, q_min); end end function q_rand = sample(obj) if rand() < 0.05 q_rand = obj.q_goal; else q_rand = 10 * rand(2, 1); end end function nearest_node = nearest(obj, q_rand) d_min = inf; nearest_node = obj.q_start; for i = 1:size(obj.tree, 2) d = norm(q_rand - obj.tree(1:2, i)); if d < d_min d_min = d; nearest_node = obj.tree(1:2, i); end end end function q_new = steer(obj, nearest_node, q_rand) if norm(q_rand - nearest_node) > obj.step_size q_new = nearest_node + (q_rand - nearest_node) * obj.step_size / norm(q_rand - nearest_node); else q_new = q_rand; end end function collision = check_collision(obj, q1, q2) collision = false; for i = 1:size(obj.obstacle_list, 2) if obj.line_circle_collision(q1, q2, obj.obstacle_list(:, i), 0.5) collision = true; break; end end end function collision = line_circle_collision(obj, q1, q2, c, r) collision = false; d = norm(c - q1); theta = atan2(q2(2) - q1(2), q2(1) - q1(1)); x = c(1) + r * cos(theta); y = c(2) + r * sin(theta); if x < min(q1(1), q2(1)) || x > max(q1(1), q2(1)) || ... y < min(q1(2), q2(2)) || y > max(q1(2), q2(2)) return; end if d < r collision = true; end end function [q_min, c_min] = find_best_parent(obj, q_new, nearest_node) neighbor_nodes = obj.find_near_nodes(q_new); q_min = nearest_node; c_min = obj.cost(q_min) + norm(q_new - q_min); for i = 1:size(neighbor_nodes, 2) if obj.check_collision(neighbor_nodes(:, i), q_new) temp_cost = obj.cost(neighbor_nodes(:, i)) + norm(q_new - neighbor_nodes(:, i)); if temp_cost < c_min q_min = neighbor_nodes(:, i); c_min = temp_cost; end end end end function neighbor_nodes = find_near_nodes(obj, q_new) r = 2 * obj.step_size; neighbor_nodes = []; for i = 1:size(obj.tree, 2) if norm(q_new - obj.tree(1:2, i)) < r neighbor_nodes = [neighbor_nodes, obj.tree(1:2, i)]; end end end function cost = cost(obj, q) cost = 0; for i = 1:size(obj.tree, 2) if all(obj.tree(1:2, i) == q) cost = obj.tree(3, i); return; end end end function rewire(obj, q_new, c_min) r = 2 * obj.step_size; for i = 1:size(obj.tree, 2) if norm(q_new - obj.tree(1:2, i)) < r && obj.tree(3, i) > c_min + norm(q_new - obj.tree(1:2, i)) && obj.check_collision(q_new, obj.tree(1:2, i)) obj.tree(3, i) = c_min + norm(q_new - obj.tree(1:2, i)); obj.tree(4, i) = size(obj.tree, 2); obj.plot(obj.tree(1:2, i), q_new); end end end function plot(obj, q1, q2) obj.plot_handle = plot([q1(1), q2(1)], [q1(2), q2(2)], 'g'); drawnow; end function [path, path_cost] = plan(obj) for i = 1:obj.max_iter [q_new, nearest_node] = obj.extend(); if norm(q_new - obj.q_goal) < obj.goal_tolerance path = obj.get_path(); path_cost = obj.cost(q_new); return; end end path = []; path_cost = inf; end function path = get_path(obj) path = obj.q_goal; node_index = size(obj.tree, 2); while all(obj.tree(1:2, node_index) ~= obj.q_start) path = [obj.tree(1:2, node_index), path]; node_index = obj.tree(4, node_index); end path = [obj.q_start, path]; end end end ``` 这个实现假设环境是一个二维平面,机器人可以在十个单位的空间内自由移动。障碍物是圆形,半径为0.5个单位。`RRTStar`类包括以下方法: - `extend`:根据RRT*算法的过程,从树中选择一个节点并从这个节点向一个新的随机点生长一条新的分支。如果新分支不与环境中的障碍物发生碰撞,则添加到树中。如果添加成功,则调用`rewire`方法以重新连接树,以便最小化从起始位置到新节点的代价。 - `sample`:从随机样本空间中生成一个新的随机点。这个方法有5%的概率生成目标点,有95%的概率生成完全随机的点。 - `nearest`:从树中选择与给定点最接近的节点,并返回该节点。 - `steer`:将机器人从最近的节点移动到给定的新点。如果新点与最近的节点之间的距离大于步长,则机器人只移动到新点的一定距离处。 - `check_collision`:检查机器人从一个节点到另一个节点的路径是否与任何障碍物发生碰撞。 - `line_circle_collision`:检查机器人从一个节点到另一个节点的直线路径是否与一个圆形障碍物发生碰撞。 - `find_best_parent`:从机器人的邻居节点中选择一个最好的父节点,以最小化从起始位置到新节点的代价。 - `find_near_nodes`:返回离给定节点最近的所有邻居节点。 - `cost`:返回树中给定节点的代价。 - `rewire`:重新连接树,以最小化从起始位置到任何节点的代价。 - `plot`:绘制机器人从一个节点到另一个节点的路径。 - `plan`:使用RRT*算法规划机器人的路径,直到找到一条从起始位置到目标位置的路径。 可以使用以下代码测试此实现: ``` obstacle_list = [3, 3, 2; 7, 7, 2; 5, 2, 2]'; rrt_star = RRTStar([1; 1], [9; 9], obstacle_list, 0.5, 500, 0.1); [path, path_cost] = rrt_star.plan(); if ~isempty(path) disp(['Found path with cost ', num2str(path_cost)]); plot(path(1, :), path(2, :), 'r', 'LineWidth', 2); else disp('Failed to find path'); end ``` 这个例子在一个10x10的平面上规划机器人从起始位置到目标位置的路径。环境中有三个障碍物,它们的位置和大小都在`obstacle_list`中指定。机器人的步长为0.5个单位,最大迭代次数为500次,目标容差为0.1个单位。如果路径规划成功,它将显示规划出的路径并输出其代价。否则,它将输出失败消息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值