在机器人导航、自动驾驶和游戏AI等领域,路径规划一直是个核心问题。今天要聊的RRT(快速探索随机树)算法,正是解决这类问题的利器。不同于传统的A*或Dijkstra算法需要在完整地图上计算,RRT通过随机采样构建搜索树,特别适合处理高维空间和复杂环境下的路径规划。
这个项目的核心目标很明确:给定一张二维图像地图(比如室内平面图或游戏场景),从指定的起点到终点,自动找出一条避开所有障碍物的最优路径。我们会在MATLAB中实现整个算法,让你看到从理论到代码的完整落地过程。
提示:虽然RRT是概率完备的算法(只要存在解就一定能找到),但传统RRT找到的路径往往不够平滑。我们会通过后续优化步骤来提升路径质量。
RRT算法的核心思想可以用"随机撒点+逐步生长"来概括。想象你在一个布满家具的房间里蒙眼找门,最有效的策略可能就是随机伸手探路,碰到障碍就换个方向。RRT正是模拟这个过程:
这个循环会一直执行,直到有节点进入目标区域。最终通过回溯父节点就能得到完整路径。
当使用图像作为输入地图时,我们需要一些特别的处理:
在MATLAB中,这些预处理可以通过im2bw、imdilate等函数高效完成。
基础RRT有几个明显缺点:路径不够平滑、收敛速度不稳定、最终路径不是最优。我们通过以下改进来提升性能:
首先定义几个核心数据结构:
matlab复制% 节点结构体
node = struct('pos',[0 0], 'parent',0, 'cost',0);
% 地图参数
map = struct('image',[], 'resolution',0.1, 'xlim',[0 10], 'ylim',[0 10]);
% 算法参数
params = struct('maxNodes',5000, 'stepSize',0.5, 'goalBias',0.1);
下面是RRT主循环的关键代码:
matlab复制function path = RRTPlanner(start, goal, map, params)
% 初始化树
tree(1) = struct('pos',start, 'parent',0, 'cost',0);
for i = 1:params.maxNodes
% 随机采样(带目标偏向)
if rand < params.goalBias
sample = goal;
else
sample = RandomSample(map);
end
% 寻找最近节点
nearestIdx = FindNearestNode(tree, sample);
nearestNode = tree(nearestIdx);
% 向采样点方向扩展
newNode = Steer(nearestNode, sample, params.stepSize);
% 碰撞检测
if ~CollisionCheck(nearestNode.pos, newNode.pos, map)
% 添加到树中
newNode.parent = nearestIdx;
newNode.cost = nearestNode.cost + ...
norm(newNode.pos - nearestNode.pos);
tree(end+1) = newNode;
% 检查是否到达目标
if norm(newNode.pos - goal) < params.stepSize
path = ExtractPath(tree, goal);
return;
end
end
end
error('未能找到路径');
end
matlab复制function collision = CollisionCheck(p1, p2, map)
% 获取两点间的线段上的所有点
points = GetLinePoints(p1, p2, map.resolution);
% 检查每个点是否在障碍物上
for i = 1:size(points,1)
% 将世界坐标转换为图像像素坐标
px = round((points(i,1)-map.xlim(1))/map.resolution);
py = round((points(i,2)-map.ylim(1))/map.resolution);
% 检查是否超出边界
if px < 1 || px > size(map.image,2) || ...
py < 1 || py > size(map.image,1)
collision = true;
return;
end
% 检查是否为障碍物(黑色像素)
if map.image(py,px) == 0
collision = true;
return;
end
end
collision = false;
end
matlab复制function path = ExtractPath(tree, goal)
path = goal;
nodeIdx = length(tree);
% 从终点回溯到起点
while nodeIdx > 0
node = tree(nodeIdx);
path = [node.pos; path];
nodeIdx = node.parent;
end
end
原始RRT路径通常有很多不必要的转折点。我们采用以下优化策略:
MATLAB实现示例:
matlab复制function smoothPath = SmoothPath(rawPath, map)
% 简化路径
simplePath = SimplifyPath(rawPath);
% B样条平滑
t = linspace(0,1,size(simplePath,1));
tt = linspace(0,1,100);
sx = spline(t,simplePath(:,1),tt);
sy = spline(t,simplePath(:,2),tt);
smoothPath = [sx' sy'];
% 碰撞检查
for i = 2:size(smoothPath,1)
if CollisionCheck(smoothPath(i-1,:), smoothPath(i,:), map)
% 如果平滑后发生碰撞,回退到简化路径
return simplePath;
end
end
end
为了获得更优路径,可以引入RRT算法。与基础RRT不同,RRT会:
虽然计算量更大,但能渐进趋近最优路径。
完整的MATLAB实现包含以下步骤:
示例主程序:
matlab复制% 1. 加载地图
mapImage = imread('office_map.png');
map.image = im2bw(mapImage, 0.5); % 二值化
map.resolution = 0.05; % 每像素代表0.05米
map.xlim = [0 size(map.image,2)*map.resolution];
map.ylim = [0 size(map.image,1)*map.resolution];
% 2. 设置起点和终点
start = [1, 1];
goal = [8, 9];
% 3. 算法参数
params.maxNodes = 3000;
params.stepSize = 0.3;
params.goalBias = 0.1;
% 4. 运行规划器
path = RRTPlanner(start, goal, map, params);
% 5. 路径优化
smoothPath = SmoothPath(path, map);
% 6. 可视化
figure;
imshow(~map.image); % 反色显示
hold on;
plot(path(:,1)/map.resolution, path(:,2)/map.resolution, 'r-', 'LineWidth', 2);
plot(smoothPath(:,1)/map.resolution, smoothPath(:,2)/map.resolution, 'g-', 'LineWidth', 2);
legend('原始路径', '平滑路径');
在20x20米的办公室环境中测试:
注意:实际性能与地图复杂度和参数设置密切相关。步长(stepSize)过大会导致碰撞率上升,过小则增加计算时间。
步长(stepSize):
目标偏向(goalBias):
最大节点数(maxNodes):
找不到路径:
路径不合理绕远:
运行速度慢:
这个算法可以应用于:
动态障碍物处理:
三维扩展:
多机器人协调:
机器学习结合:
在MATLAB中实现这些扩展时,需要注意计算效率问题。对于复杂场景,可以考虑将核心算法用C/C++实现并通过MEX接口调用。