基于Python的RRT算法实现

本文为博主原创内容,未经博主允许不得转载。尊重他人知识成果,共同建立良好学习分享氛围,谢谢!

一、RRT算法原理及实现效果

  关于RRT算法的原理,博主之前看到的RRT算法原理图解这篇文章讲的很好,通俗易懂,所以若不了解RRT算法的原理,推荐各位看这个了解下。

  本文主要是基于Python实现RRT算法,先来看一下RRT算法实现后的效果图。
在这里插入图片描述

图1 RRT算法的实现效果图

二、RRT算法python代码实现

  具体实现代码如下,博主写的可能有些复杂,不过其中大部分代码注释的很详细了,在这里我就不在赘述了。

import matplotlib.pyplot as plt
import random
import math
import time

def main():
    starttime = time.time()#    程序运行时间计时开始
    region1 = region(100,100)#    定义单元区域
    obstacle_area1 = obstacle_area((50,0),(50,80),(60,0),(60,80))#    定义障碍物区域
    tree_point = []  #    存放起点、终点和所有的可用衍生点
    futher = {}  #     存放所有可用衍生点的父节点
    step = 3#    步进系数
    breed_point = 'breed_point is invalid'
    draw_tree_pointx = []#    存放可用衍生点的横坐标
    draw_tree_pointy = []#    存放可用衍生点的纵坐标
    draw_plan_pointx = []#    存放从起点到终点的计划路径点的横坐标
    draw_plan_pointy = []#    存放从起点到终点的计划路径点的纵坐标

    initial_point = point()#    实例化起点对象
    initial_point.set_position(10,10)#    设定起点坐标
    initial_point.set_state(in_obstacle_area(initial_point,obstacle_area1,region1))#    设定起点状态
    if initial_point.state == False:#    若起点在障碍物区域,直接退出
        print("initial point is live in obstacle region , please choose initial point again")
        return

    terminal_point = point()#    实例化终点对象
    terminal_point.set_position(90,50)#    设定终点坐标
    terminal_point.set_state(in_obstacle_area(terminal_point,obstacle_area1,region1))#    设定终点状态
    if terminal_point.state == False:#    若终点在障碍物区域,直接退出
        print("terminal point is live in obstacle region , please choose terminal point again")
        return

    tree_point.append([initial_point.x, initial_point.y])#   把起点加入tree_point集合列表中

    while (breed_point == 'breed_point is invalid') or (math.sqrt((tree_point[-1][0] - terminal_point.x) ** 2 + (tree_point[-1][1] - terminal_point.y) ** 2) > 3):
        radom_point = random_num(region1,obstacle_area1)#   生成有效随机点
        min_point = MinPoint(tree_point, radom_point)#   从tree_point合集列表中选取距离有效随机点最近的点
        breed_point = BreedPoint(min_point, radom_point, step, obstacle_area1,region1)#   在距离有效随机点最近的点的基础上选取有效的衍生点
        if breed_point != 'breed_point is invalid':
            futher[tuple(breed_point.get_position())] = tuple(breed_point.get_futher())#    记录有效衍生点的父节点
            tree_point.append([breed_point.x, breed_point.y])#    将有效衍生点加入到衍生点集合列表
        draw_tree_pointx.append(tree_point[-1][0])#    记录可用衍生点的横坐标
        draw_tree_pointy.append(tree_point[-1][1])#    记录可用衍生点的纵坐标

    futher[tuple(terminal_point.get_position())] = tuple(tree_point[-1])#    将终点的父节点设置为最后加入的tree_point点
    tree_point.append([terminal_point.x, terminal_point.y])#    把终点加入tree_point集合列表中

    current_cheak_point = tuple(terminal_point.get_position())
    while futher[current_cheak_point] != tuple(initial_point.get_position()):#    从终点开始往回寻找父节点,直到找到起点为止
        draw_plan_pointx.append(current_cheak_point[0])#    记录从起点到终点的计划路径点的横坐标
        draw_plan_pointy.append(current_cheak_point[1])#    记录从起点到终点的计划路径点的纵坐标
        current_cheak_point = futher[current_cheak_point]
    draw_plan_pointx.append(current_cheak_point[0])  # 记录父节点为起点的点的横坐标
    draw_plan_pointx.append(initial_point.x)#    记录起点的横坐标
    draw_plan_pointy.append(current_cheak_point[1])  # 记录父节点为终点的点的横坐标
    draw_plan_pointy.append(initial_point.y)#    记录终点的横坐标

    plt.scatter(draw_tree_pointx, draw_tree_pointy, c='green', s=3)#    画出所有的可用衍生点
    plt.plot([obstacle_area1.obstacle_point1[0],obstacle_area1.obstacle_point2[0],obstacle_area1.obstacle_point4[0],obstacle_area1.obstacle_point3[0],obstacle_area1.obstacle_point1[0]],[obstacle_area1.obstacle_point1[1],obstacle_area1.obstacle_point2[1],obstacle_area1.obstacle_point4[1],obstacle_area1.obstacle_point3[1],obstacle_area1.obstacle_point1[1]],color='r', markerfacecolor='blue', marker='o')#    画处障碍物区域
    plt.plot(draw_plan_pointx, draw_plan_pointy, color='r', markerfacecolor='blue', marker='o')#    画出从起点到终点的计划路径点
    plt.axis("equal")
    plt.grid(True)
    plt.title('initial_point' + str(initial_point.get_position()) + ' , terminal_point:' + str(terminal_point.get_position()))
    plt.show()

    endtime = time.time()#    程序运行时间计时结束
    dtime = endtime - starttime#    计算程序运行时长
    print("程序运行时间:%.8s s" % dtime)  #    显示到微秒

def BreedPoint(min_point, radom_point, step,obstacle_area,region):#    在距离有效随机点最近的点的基础上选取有效的衍生点
    New_BreedPoint = point()#    实例化衍生点对象
    if (min_point[0] == radom_point.x):#    若有效随机点和距离其最近的点的横坐标一样
        New_BreedPoint.set_position(min_point[0], step + min_point[1])
    else:
        k = (min_point[1] - radom_point.y) / (min_point[0] - radom_point.x)#    计算有效随机点和距离其最近的点之间的斜率
        New_BreedPoint_x = math.cos(math.atan(k)) * step + min_point[0]
        New_BreedPoint_y = math.sin(math.atan(k)) * step + min_point[1]
        New_BreedPoint.set_position(New_BreedPoint_x, New_BreedPoint_y)
    if in_obstacle_area(New_BreedPoint, obstacle_area,region) is False:#   判断点是否在有效区域内
        return 'breed_point is invalid'
    New_BreedPoint.set_futher(min_point)#   设置衍生点的父节点
    return New_BreedPoint

def random_num(region,obstacle_area):#   生成有效随机点
    radom_point = point()#    实例化随机点对象
    radom_point.set_position(random.randint(0, region.length), random.randint(0, region.width))#   生成随机点坐标
    if in_obstacle_area(radom_point, obstacle_area,region) is False:#   判断随机点是否在无效区域内
        random_num(region,obstacle_area)#   重新生成随机节点
    return radom_point

def in_obstacle_area(check_point,obstacle_area,region):#   判断点是否在有效区域内
    if ((check_point.x >= obstacle_area.obstacle_point1[0]) and (check_point.x <= obstacle_area.obstacle_point3[0]) and (check_point.y <= obstacle_area.obstacle_point2[1]) and (check_point.y >= obstacle_area.obstacle_point1[1])) :#   判断点是否在障碍物区域内
        return False
    elif ((check_point.x >= 0) and (check_point.x <= region.length) and (check_point.y >= 0) and (check_point.y <= region.width)):#   判断点是否在单元区域内
        return True
    else:
        return False

def MinPoint(tree_point, radom_point):#   从tree_point合集列表中选取距离有效随机点最近的点
    Distance = []
    for i in range(0, len(tree_point)):
        Distance.append(math.sqrt((tree_point[i][0] - radom_point.x) ** 2 + (tree_point[i][1] - radom_point.y) ** 2))
    return tree_point[Distance.index(min(Distance))]

class point():
    def set_position(self, x, y):
        self.x = x
        self.y = y

    def set_state(self, state):
        self.state = state

    def set_futher(self, futher):
        self.futher = futher

    def get_position(self):
        return [self.x, self.y]

    def get_state(self):
        return self.state

    def get_futher(self):
        return self.futher

class region():
    def __init__(self,length,width):
        self.length = length
        self.width = width

class obstacle_area():
    def __init__(self,obstacle_point1,obstacle_point2,obstacle_point3,obstacle_point4):
        self.obstacle_point1 = obstacle_point1
        #   左下点
        self.obstacle_point2 = obstacle_point2
        #   左上点
        self.obstacle_point3 = obstacle_point3
        #   右下点
        self.obstacle_point4 = obstacle_point4
        #   右上点

if __name__ == '__main__':
    main()
  • 10
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RRT(Rapidly-exploring Random Tree)算法是一种用于解决路径规划问题的算法。它是一种基于随机采样的树搜索方法,常用于机器人运动规划和自主导航。 在Python中,可以使用以下步骤实现RRT算法: 1. 定义问题空间:确定机器人或车辆的起始点和目标点,并定义障碍物区域。 2. 初始化树:创建一个包含起始点的树,该树将用于存储路径搜索过程中的节点。 3. 扩展树:在每次迭代中,生成一个随机的节点,并在树中找到最近的节点。然后,通过采样和探索的方式将新节点连接到最近节点。 4. 碰撞检测:检查新节点与障碍物是否发生碰撞。如果发生碰撞,则忽略该节点。 5. 判断终止条件:判断新节点是否与目标点足够接近,如果满足终止条件,则路径搜索结束。 6. 反向搜索:从目标点开始,通过连接每个节点的父节点,构建路径。 7. 重复步骤3至6,直到找到一条连接起始点和目标点的路径,或者达到最大迭代次数。 这是一个简单的Python伪代码示例来实现RRT算法: ```python def rrt(start, goal, obstacles, max_iter): tree = {start: None} for _ in range(max_iter): q_rand = random_point() q_near = find_nearest_neighbor(tree, q_rand) q_new = expand_tree(q_near, q_rand) if not collides(q_new, obstacles): tree[q_new] = q_near if distance(q_new, goal) < threshold: path = backtrack(tree, q_new) return path return None ``` 在实际实现中,你需要根据你的问题空间和碰撞检测方法进行适当的修改。此外,还可以通过优化算法参数、引入启发式函数等方式来改进RRT算法的性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值