RRT*算法的原理简介以及Python实现代码

article/2025/10/4 8:20:21

![RRT算法原理图](https://img-blog.csdnimg.cn/20210420101155956.png?x-oss-p
RRT大致流程
1.初始化随机树tree,以空的随机树开始添加节点,最开始只有Qinit。
2.执行sample函数,在地图中获得一个随机点Qrand。
3.遍历tree中所有节点,找出与Qrand之间代价最小的点Qnearest。
4.执行extend函数,获得Qnearest向Qrand方向上的指定长度的扩展点Qnew。并对Qnew进行碰撞检测,若碰撞检测为真,则结束此次循环,重新选择拓展点。若为假则将Qnearest指定为Qnew的父节点,连接两点之间的连线。
5.判断Qnew是否已经到达指定目标范围,若已经到达,则结束循环,否则继续执行循环知道找到目标范围。
其中sample函数用于,在地图中生成随机点;

    def Sample(self, a, b):Q = [random.randint(0, a), random.randint(0, b)]return Q

extend函数用于找到拓展点,函数中c为步长。

# 获取Q与最近节点之间的拓展点def extend(self, a, b, c = 10):d = [0, 0]d[0] = a[0] + int(c * (b[0] - a[0]) / math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2))d[1] = a[1] + int(c * (b[1] - a[1]) / math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2))return d

整个代码段以输入图片作为地图,以灰度读入作为checkMap,用以碰撞检测;再以正常读入作为drawMap用以画出点与路径。
RRT*原理图
RRT*找Qnew之前的流程与RTT相同,找到Qnew,判断其有效性后。不直接连接Qnew与Qnearest,而是运行函数nearToNew,寻找在指定范围r内的所有节点,遍历所有得到的节点Qnear,判断Qnear中到Qnew与Qnear到Qinit代价和最小的节点,指定其为Qnew的父节点连接两点连线。
再执行函数rewire,遍历剩下的节点Qnear,判断如果以Qnew为父节点,其代价是否会小于原来的代价,若小于,则更改其父节点为Qnew。
其中nearToNew用来寻找距离给定点一定范围内的各个节点返回为一个list;

# 获取指定点周围一定范围内的节点def nearToNew(self, new):nearTonew = []nearCost = []for item in self.tree:costToNew = self.cost(item.loc, new)if costToNew < self.step * 2:# 判断两点之间的连线是否穿过障碍物if self.is_block(item.loc, new):continuenearTonew.append(item)nearCost.append(int(costToNew) + int(item.cost))return nearTonew,nearCost

函数rewire用来重新规划Qnew周围的路径:

 # 重新规划新节点new与其周围节点之间的路径def rewire(self, nearTonew, newPoint):for item2 in nearTonew:costToNew = self.cost(item2.loc, newPoint.loc)if costToNew + newPoint.cost < item2.cost:# 判断两点之间路线是否穿过障碍物if self.is_block(item2.loc, newPoint.loc):continuecv2.line(self.map.drawMap, tuple(item2.loc), tuple(item2.fatherPoint.loc), (255, 255, 255))item2.fatherPoint = newPointitem2.cost = costToNew + newPoint.costcv2.line(self.map.drawMap, tuple(item2.loc), tuple(item2.fatherPoint.loc), (0, 255, 0))cv2.imshow("route", self.map.drawMap)cv2.waitKey(self.speed)

以上代码都是我在整个RRT*代码中截取出来的片段,仅供参考大致思路。
以下是RRT*完整代码,初写代码,可能不太标准,仅供参考,也算是对于自己学习的记录。

# -*- coding = utf-8 -*-
# @Time : 2021/4/14 9:07import random
import cv2
import math
import copy
import time
from numpy import meanclass Point(object):def __init__(self,loc, cost, fatherPoint = None):self.loc = locself.cost = costself.fatherPoint = fatherPointclass Map(object):point = []def __init__(self, img):self.drawMap = cv2.imread(img)self.checkMaps = cv2.imread(img, cv2.IMREAD_GRAYSCALE)self.width = self.checkMaps.shape[1]self.height = self.checkMaps.shape[0]def on_EVENT_LBUTTONDOWN(self,event, x, y, flags, param):# point = []if event == cv2.EVENT_LBUTTONDOWN:xy = '%d,%d' % (x, y)# global pointself.point.append([x,y])# print('x, y = {}, {}'.format(x, y))cv2.circle(self.drawMap, (x, y), 1, (255, 0, 0), thickness=-1)cv2.putText(self.drawMap, xy, (x, y), cv2.FONT_HERSHEY_PLAIN,1.0, (0, 0, 0), thickness=1)cv2.imshow('image', self.drawMap)def start_end(self):cv2.namedWindow('image')cv2.imshow('image', self.checkMaps)cv2.setMouseCallback('image', self.on_EVENT_LBUTTONDOWN)cv2.waitKey(0)cv2.destroyAllWindows()print("起点:", self.point[0], "终点:", self.point[1])return self.pointdef is_block(self,a):if self.checkMaps[a[1], a[0]] == 0:return Trueelse:return Falsedef Route(self,point,v):a = point.locb = point.fatherPoint.loccv2.line(self.drawMap,tuple(a),tuple(b),(0,0,255),3)cv2.imshow('route', self.drawMap)cv2.waitKey(v)return point.fatherPointclass RRTStar(object):tree = []def __init__(self,map,step,speed = 10):self.step = stepself.map = mapself.speed = speedreturn# 获得随机点Q的坐标def Sample(self, a, b):Q = [random.randint(0, a), random.randint(0, b)]return Q# 计算两点之间的代价def cost(self, a, b):c = math.sqrt((a[0] - b[0])**2 + (a[1] - b[1])**2)return c# 找到离随机点Q最近的节点def nearest(self, q, tree):a = []for item in tree:a.append(self.cost(q, item.loc))b = tree[a.index(min(a))]return b# 获取Q与最近节点之间的拓展点def extend(self, a, b, c = 10):d = [0, 0]d[0] = a[0] + int(c * (b[0] - a[0]) / math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2))d[1] = a[1] + int(c * (b[1] - a[1]) / math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2))return d# 取得指定点之间的的碰撞监测点def checkPoint(self, point1, point2):a = copy.deepcopy(point1)b = copy.deepcopy(point2)if a[0] > b[0]:a[0],b[0] = b[0],a[0]a[1],b[1] = b[1],a[1]q = 3c = []if a[0] == b[0]:if a[1] > b[1]:a[1],b[1] = b[1],a[1]for i in range(a[1] - q, b[1] + q):c.append([a[0], i])c.append([a[0] - q, i])c.append([a[0] + q, i])else:for i in range(a[0] - q,b[0] + q):d = (b[1] - a[1])/(b[0] - a[0]) * (i - a[0]) + a[1]e = (b[1] - a[1])/(b[0] - a[0]) * (i - a[0]) + a[1] + qf = (b[1] - a[1])/(b[0] - a[0]) * (i - a[0]) + a[1] - qc.append([i, int(d)])c.append([i, int(e)])c.append([i, int(f)])return c# 利用梯度下降法生对路径进行平滑处理def smoothPoint(self,path, weight_data=0.5, weight_smooth=0.5, tolerance=0.00001):N = len(path)newpath = copy.deepcopy(path)err = 2 * tolerancewhile err > tolerance:err = 0.for i in range(1, N - 1):for j in range(2):delta = weight_data * (path[i][j] - newpath[i][j]) + \weight_smooth * (newpath[(i - 1) % N][j] + newpath[(i + 1) % N][j] - 2.0 * newpath[i][j])newpath[i][j] += deltaerr += abs(delta)return newpath# 碰撞检测def is_block(self, a, b):for i in self.checkPoint(a, b):if 0 < i[0] < self.map.width and 0 < i[1] < self.map.height:if self.map.is_block(i):return Trueelse:return Truereturn False# 获取指定点周围一定范围内的节点def nearToNew(self, new):nearTonew = []nearCost = []for item in self.tree:costToNew = self.cost(item.loc, new)if costToNew < self.step * 2:# 判断两点之间的连线是否穿过障碍物if self.is_block(item.loc, new):continuenearTonew.append(item)nearCost.append(int(costToNew) + int(item.cost))return nearTonew,nearCost# 重新规划新节点new与其周围节点之间的路径def rewire(self, nearTonew, newPoint):for item2 in nearTonew:costToNew = self.cost(item2.loc, newPoint.loc)if costToNew + newPoint.cost < item2.cost:# 判断两点之间路线是否穿过障碍物if self.is_block(item2.loc, newPoint.loc):continuecv2.line(self.map.drawMap, tuple(item2.loc), tuple(item2.fatherPoint.loc), (255, 255, 255))item2.fatherPoint = newPointitem2.cost = costToNew + newPoint.costcv2.line(self.map.drawMap, tuple(item2.loc), tuple(item2.fatherPoint.loc), (0, 255, 0))cv2.imshow("route", self.map.drawMap)cv2.waitKey(self.speed)# 在图上画出路径def drawRoute(self, point):routePoint = []c = pointroutePoint.append(point.loc)while True:c = self.map.Route(c, self.speed)routePoint.append(c.loc)if c.loc == start:breakreturn routePoint# 在图上画出平滑处理后的路径def Smooth(self, routePoint):s = self.smoothPoint(routePoint)for i in range(len(s)):if i == len(s) - 1:breakx = (int(s[i][0]), int(s[i][1]))y = (int(s[i + 1][0]), int(s[i + 1][1]))cv2.line(self.map.drawMap, x, y, (0, 0, 255), 2)cv2.imshow("route", self.map.drawMap)cv2.waitKey(self.speed)cv2.imshow("route", self.map.drawMap)cv2.waitKey(0)def Path(self, start, end):speed = self.speedtree = self.treetree.append(Point(start,0))t = 0while t < 2000:tag = 0# 取得随机点qq = self.Sample(self.map.width, self.map.height)# 取得离随机点最近的点nearest = self.nearest(q, tree)if q == nearest.loc:continue# 获得拓展点newnew = self.extend(nearest.loc, q, self.step)# 获得在拓展点两个步长范围内的所有点,取得其中到拓展点代价最小的点,作为拓展点父节点nearTonew,nearCost = self.nearToNew(new)#如果拓展点附近没有复合要求的点,则结束此次循环,重新选择拓展点if nearCost:passelse:continueminCostPoint = nearTonew[nearCost.index(min(nearCost))]nearTonew.remove(minCostPoint)newPoint = Point(new, min(nearCost), minCostPoint)t += 1# 标出拓展点位置,画出拓展点与其父节点之间的线cv2.circle(self.map.drawMap, tuple(new), 2, (255, 0, 0), thickness=-1)cv2.line(self.map.drawMap, tuple(newPoint.loc), tuple(newPoint.fatherPoint.loc), (0, 255, 0))tree.append(newPoint)cv2.imshow("route", self.map.drawMap)cv2.waitKey(speed)# 浏览拓展点周围的其他点,判断以拓展点为父节点的代价与原本的代价的大小,若小于原本的代价,则将拓展点改为其父节点self.rewire(nearTonew, newPoint)# 判断是否到达终点,画出路径,并进行平滑处理if abs(new[0] - end[0]) < 20 and abs(new[1] - end[1]) < 20:tag = 1routePoint = self.drawRoute(newPoint)# self.Smooth(routePoint)breakif tag == 1:print("RRT*寻路成功")else:print("RRT*寻路失败")if __name__ == "__main__":t0 = 0T = []while t0 < 10:map = Map("../work/testmap.png")time1 = time.time()start = [50, 50]end = [800, 400]cv2.circle(map.drawMap, (start[0], start[1]), 2, (255, 0, 0), thickness=-1)cv2.rectangle(map.drawMap, (end[0] - 20, end[1] - 20), (end[0] + 20, end[1] + 20), (255, 0, 0))a = RRTStar(map, 30, 1)print(len(a.tree))a.Path(start, end)a.tree.clear()time2 = time.time()T.append(time2 - time1)t0 += 1cv2.destroyAllWindows()print(mean(T))print(T)

效果图


http://chatgpt.dhexx.cn/article/oxSBcdVp.shtml

相关文章

RRT 算法研究(附 Python / C++ 实现)

RRT 算法研究 参考 机器人路径规划、轨迹优化课程-第五讲-RRT算法原理和代码讲解 机器人路径规划之RRT算法(附C源码) RRT算法(快速拓展随机树)的Python实现 《基于改进RRT算法的路径规划研究》 《面向室内复杂场景的移动机器人快速路径规划算法研究》 理论基础 RRT&#xff0…

RRT* 算法研究(附 MATLAB 和 Python 实现)

RRT* 算法研究 参考 机器人路径规划、轨迹优化课程-第六讲-RRT*算法原理和代码讲解 路径规划 | 随机采样算法&#xff1a;PRM、RRT、RRT-Connect、RRT* 基于采样的运动规划算法-RRT(Rapidly-exploring Random Trees) 《改进RRT算法在移动机器人路径规划中的应用研究》 理论基础…

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

首先我们得明白算法的原理&#xff0c;然后写出步骤。根据步骤可以写出主函数包括每一步的输入输出&#xff0c;怎么表示&#xff08;基本的伪代码表示&#xff0c;当然如果可以也可以写成汉字形式的&#xff09;&#xff0c;最后一步一步写出代码&#xff0c;调试工作是必须的…

RRT、RRT-connect、RRT*等算法、A*等等路径规划算法

1 原始RRT算法运行结果&#xff1a;python&#xff0c;这里以2D_rrt及其衍生相关算法为例&#xff08;边做边更新&#xff09; CV搬运工们&#xff0c;先上github连接&#xff1a;&#xff08;点个赞呗&#xff09;&#xff08;不想要拿github包的后面有现成代码&#xff09;…

RRT路径规划算法

RRT路径规划算法 地图RRT算法原理路径平滑处理总结 RRT&#xff08;Rapidly-Exploring Random Tree&#xff09;算法是一种基于采样的路径规划算法&#xff0c;常用于移动机器人路径规划&#xff0c;适合解决高维空间和复杂约束下的路径规划问题。基本思想是以产生随机点的方式…

自动驾驶路径规划——基于概率采样的路径规划算法(RRT、RRT*)

目录 1. RRT算法背景1.1 RRT算法核心思想1.2 RRT算法优缺点 2. 经典RRT算法2.1 RRT算法流程2.2 RRT伪代码 3. 基于目标概率采样4. RRT*算法4.1 RRT与RRT*的区别4.2 RRT*算法详解4.2.1 RRT*算法总体伪代码4.2.2 重新选择父节点4.2.3 重新布线4.2.4 RRT*算法Choose Parent过程详解…

基于Python的RRT算法实现

基于Python的RRT算法实现 一、RRT算法原理及实现效果二、RRT算法python代码实现 本文为博主原创内容&#xff0c;未经博主允许不得转载。尊重他人知识成果&#xff0c;共同建立良好学习分享氛围&#xff0c;谢谢&#xff01; 一、RRT算法原理及实现效果 关于RRT算法的原理&…

基于采样的路径规划算法RRT的优化:RRT*,Kinodynamic-RRT*,Anytime-RRT *,Informed RRT *

基于采样的路径规划算法RRT的优化 RRT * 算法Kinodynamic-RRT*Anytime-RRT *Informed RRT *关于搜索树按搜索方向生长的计算方法 基本的基于采样的路径规划算法RRT&#xff0c;在地图中进行采样取点&#xff0c;直到新的节点取到终点的一定阈值范围内&#xff0c;视为查找到路径…

RRT*算法图解

原文链接&#xff1a; https://blog.csdn.net/yuxuan20062007/article/details/88843690 【运动规划RRT*算法图解】 https://blog.csdn.net/weixin_43795921/article/details/88557317 尽管RRT算法是一个相对高效率&#xff0c;同时可以较好的处理带有非完整约束的路径规划问题…

快速扩展随机树(RRT)算法

RRT是Steven M. LaValle和James J. Kuffner Jr.提出的一种通过随机构建Space Filling Tree实现对非凸高维空间快速搜索的算法。该算法可以很容易的处理包含障碍物和差分运动约束的场景&#xff0c;因而广泛的被应用在各种机器人的运动规划场景中。 1. Basic RRT算法 原始的RR…

RRT算法及其部分改进算法介绍

基于采样的运动规划算法-RRT&#xff08;Rapidly-exploring Random Trees&#xff09; RRT&#xff1a;一种通过随机构建Space Filling Tree实现对非凸高维空间快速搜索的算法。该算法可以很容易的处理包含障碍物和差分运动约束的场景&#xff0c;被广泛的应用在各种机器人的运…

RRT*算法

简介 RRT* 和RRTconnect一样&#xff0c;是对RRT算法的优化。RRT算法的一个问题在于&#xff0c;它只是找到了可行的路径&#xff0c;不能保证路径是相对优化的。RRT*算法在每次迭代后&#xff0c;都会在局部更新搜索树&#xff0c;以优化路径。 多了两个过程&#xff0c;为&…

RRT算法介绍

RRT算法介绍 RRT算法原理介绍&#xff1a;RRT搜索树与树的生长相类似&#xff0c;即不断生长的同时又向四周扩散。算法以路径起点Xstart作为随机树T的根节点&#xff0c;树中节点xj用集合V存储&#xff0c;节点间的连接用连接边集E存储&#xff0c;所有节点xj满足属于集合Xfree…

【规划】RRT*算法图解

尽管RRT算法是一个相对高效率&#xff0c;同时可以较好的处理带有非完整约束的路径规划问题的算法&#xff0c;并且在很多方面有很大的优势&#xff0c;但是RRT算法并不能保证所得出的可行路径是相对优化的。因此许多关于RRT算法的改进也致力于解决路径优化的问题&#xff0c;R…

RRT算法简介

声明&#xff1a;本文为转载内容非原创&#xff0c;来源会在文末声明&#xff0c;绝无冒犯之意&#xff0c;只为一时复习之方便&#xff0c;侵权必删&#xff01; 感谢原作者写出如此优秀的博文&#xff0c;让我对RRT算法有个大致的理解。 对RRT算法感兴趣&#xff0c;是因为…

RRT 算法原理以及过程演示

RRT 适用于涉及非完整约束场合下的路径规划问题。 RRT 算法为一种递增式的构造方法&#xff0c;在构造过程中&#xff0c;算法不断在搜索空间中随机生成状态点&#xff0c;如果该点位于无碰撞位置&#xff0c;则寻找搜索树中离该节点最近的结点为基准结点&#xff0c;由基准结点…

【机器人学:运动规划】快速搜索随机树(RRT---Rapidly-exploring Random Trees)入门及在Matlab中演示

快速搜索随机树&#xff08;RRT -Rapidly-ExploringRandom Trees&#xff09;&#xff0c;是一种常见的用于机器人路径&#xff08;运动&#xff09;规划的方法&#xff0c;它本质上是一种随机生成的数据结构—树&#xff0c;这种思想自从LaValle在[1]中提出以后已经得到了极大…

【自动驾驶轨迹规划之RRT算法】

目录 1 RRT算法的简介 2 RRT算法原理 2.1 算法流程 2.2 算法伪代码 2.3 算法流程图 3 RRT算法matlab实现 3.1 测试地图 3.2 distance函数 3.3 RRT算法 3.4 动画效果 4 RRT的缺陷 1 RRT算法的简介 天下武功唯快不破&#xff0c;快是 RRT 的最大优势。RRT 的思想是快…

RRT算法

简介 RRT 算法&#xff08;快速扩展随机树&#xff0c;rapidly exploring random tree&#xff09;是一种随机性算法&#xff0c;它可以直接应用于非完整约束系统的规划&#xff0c;不需进行路径转换&#xff0c;所以它的算法复杂度较小&#xff0c;尤为适用于高维多自由度的系…

RRT(快速随机搜索树)算法原理及代码实践

RRT算法简介 RRT 算法为一种递增式的路径规划算法&#xff0c;算法不断在搜索空间中随机生成采样点&#xff0c;如果该点位于无碰撞位置&#xff0c;则寻找搜索树中离该节点最近的结点为基准结点&#xff0c;由基准结点出发以一定步长朝着该随机结点进行延伸&#xff0c;延伸线…