RRT-Connect算法

简介

RRT-connect算法是基于RRT算法的一种算法,它从起始点和终点同时生长两棵快速扩展随机树来搜索状态空间,效率会更高。

伪代码:
在这里插入图片描述
每一次迭代中,开始步骤与原始的RRT算法一样,都是采样随机点然后进行扩展。然后扩展完第一棵树的新节点𝑞𝑛𝑒𝑤后,以这个新的目标点作为第二棵树扩展的方向。同时第二棵树扩展的方式略有不同(15~22行),首先它会扩展第一步得到𝑞′𝑛𝑒𝑤,如果没有碰撞,继续往相同的方向扩展第二步(贪婪扩展),直到扩展失败或者𝑞′𝑛𝑒𝑤=𝑞𝑛𝑒𝑤表示与第一棵树相连了,即connect了,整个算法结束。

每次选择较小的那棵树进行拓展搜索速度、搜索效率有了显著提高

原始RRTConnect算法,未加入贪婪扩展:

class RRTConnect(object):
    """
    desc:两颗tree交替(其中一颗树的node_new无效时交替)进行sample,每棵树的有效node_new作为另一颗树的goal,
    直到其中一颗树的有效node_new与其goal足够近,即表明两棵树connected"""

    def __init__(self, start, goal, iscollidedfunc, jointlimits, expanddis=.5,
                 starttreesamplerate=10, endtreesamplerate=100, maxiter=5000,
                 robot = None, cdchecker = None):
        """

        :param start: nd point, list
        :param goal: nd point, list
        :param iscollidedfunc: a function returns whether collided or not
        :param jointlimits: [[join0low, joint0high], [joint1low, joint1high], ...]
        :param expandDis: how much to expand along the vector randpoint - nearestnode
        :param starttreesamplerate: bias to set randpoint to be goal
        :param endtreesamplerate: bias to set randpoint to be start
        :param maxIter:

        :param the last three parameters are for robotsim robots

        """

        self.__start = np.asarray(start)
        self.__end = np.asarray(goal)

        self.__iscollidedcallback = iscollidedfunc
        self.__jointlimits = jointlimits
        self.__expanddis = expanddis
        self.__starttreesamplerate = starttreesamplerate
        self.__endtreesamplerate = endtreesamplerate
        self.__maxiter = maxiter

        self.__robot = robot
        self.__cdchecker = cdchecker

        self.__nodeliststart = []
        self.__nodelistend = []  # 两棵树
        self.__obstaclelist = []

    @property
    def start(self):
        # read-only property
        return self.__start

    @property
    def end(self):
        # read-only property
        return self.__end

    @property
    def nodeliststart(self):
        # read-only property
        return self.__nodeliststart

    @property
    def nodelistend(self):
        # read-only property
        return self.__nodelistend

    @property
    def jointlimits(self):
        # read-only property
        return self.__jointlimits

    @property
    def iscollidedcallback(self):
        # read-only property
        return self.__iscollidedcallback

    @property
    def cdchecker(self):
        # read-only property
        return self.__cdchecker

    @property
    def robot(self):
        # read-only property
        return self.__robot

    @property
    def expanddis(self):
        # read-only property
        return self.__expanddis

    @property
    def obstaclelist(self):
        # read-only property
        return self.__obstaclelist

    def planning(self, obstaclelist=[], animation=False):
        """
        Pathplanning

        animation: flag for animation on or off

        :return path [[joint0, joint1, ...], [joint0, joint1, ...], ...]
        """

        self.__obstaclelist = obstaclelist
        itercount = 0

        # one sampled point: [point, iscollided]
        sampledpoints = []

        self.__nodeliststart = [Node(self.__start)]
        self.__nodelistend = [Node(self.__end)]

        starttreegoal = self.__end
        endtreegoal = self.__start
        while True:

            if itercount > self.__maxiter:
                print "failed to find a path"
                break

            # if self.__starttreesamplerate < 80:
            #     self.__starttreesamplerate += itercount/float(self.__maxiter)*10
            # else:
            #     self.__starttreesamplerate = 80
            # print self.__starttreesamplerate

            # Random Sampling
            randpoint = []
            if random.randint(0, 100) > self.__starttreesamplerate:
                for i,jntrng in enumerate(self.__jointlimits):
                    randpoint.append(random.uniform(jntrng[0], jntrng[1]))
                randpoint = np.asarray(randpoint)
            else:
                randpoint = copy.deepcopy(starttreegoal)

            # Find nearest node
            nind = self.getNearestListIndex(self.__nodeliststart, randpoint)
            vec = randpoint-self.__nodeliststart[nind].point
            vec = vec/np.linalg.norm(vec)

            # expand tree
            nearestnode = self.__nodeliststart[nind]
            newnode = copy.deepcopy(nearestnode)
            newnode.point += self.__expanddis * vec
            newnode.parent = nind

            if animation:
                drawwspace(self, obstaclelist, randpoint, newnode.point, '^r')

            if self.__iscollidedcallback(newnode.point, obstaclelist,
                                         self.__robot, self.__cdchecker):
                sampledpoints.append([newnode.point, True])
                bswap = False
                # if collided, try the other tree
                while True:
                    randpoint = []
                    if random.randint(0, 100) > self.__endtreesamplerate:
                        for i,jntrng in enumerate(self.__jointlimits):
                            randpoint.append(random.uniform(jntrng[0], jntrng[1]))
                        randpoint = np.asarray(randpoint)
                    else:
                        randpoint = copy.deepcopy(endtreegoal)

                    # Find nearest node
                    nind = self.getNearestListIndex(self.__nodelistend, randpoint)
                    vec = randpoint-self.__nodelistend[nind].point
                    vec = vec/np.linalg.norm(vec)

                    # expand tree
                    nearestnode = self.__nodelistend[nind]
                    newnode = copy.deepcopy(nearestnode)
                    newnode.point += self.__expanddis * vec
                    newnode.parent = nind

                    if animation:
                        drawwspace(self, obstaclelist, randpoint, newnode.point, '^r')

                    if self.__iscollidedcallback(newnode.point, obstaclelist,
                                                 self.__robot, self.__cdchecker):
                        sampledpoints.append([newnode.point, True])
                        bswap = True
                        break

                    sampledpoints.append([newnode.point, False])
                    self.__nodelistend.append(newnode)
                    starttreegoal = newnode.point  # change end tree goal

                    d = np.linalg.norm(newnode.point - endtreegoal)
                    if d <= self.__expanddis:
                        print("reaching the goal")
                        bswap = False
                        break

                    if animation:
                        drawwspace(self, obstaclelist, randpoint, newnode.point, '^g')

                if bswap:
                    continue
                else:
                    break

            sampledpoints.append([newnode.point, False])
            self.__nodeliststart.append(newnode)
            endtreegoal = newnode.point  # change start tree goal

            # check goal
            d = np.linalg.norm(newnode.point - starttreegoal)
            if d <= self.__expanddis:
                print("reaching the goal")
                break

            if animation:
                drawwspace(self, obstaclelist, randpoint, newnode.point, '^g')

            itercount += 1

        path = []
        lastindex = len(self.__nodelistend) - 1
        # WARNING the first nodelist is a numpyarray
        while self.__nodelistend[lastindex].parent is not None:
            node = self.__nodelistend[lastindex]
            path.append(node.point.tolist())
            lastindex = node.parent
        path.append(self.__end.tolist())
        path = path[::-1]
        lastindex = len(self.__nodeliststart) - 1
        # WARNING the first nodelist is a numpyarray
        while self.__nodeliststart[lastindex].parent is not None:
            node = self.__nodeliststart[lastindex]
            path.append(node.point.tolist())
            lastindex = node.parent
        path.append(self.__start.tolist())
        path = path[::-1]

        return [path, sampledpoints]

    def getNearestListIndex(self, nodelist, randpoint):
        dlist = [np.linalg.norm(randpoint-node.point) for node in nodelist]
        minind = dlist.index(min(dlist))
        return minind

### RRT Connect 算法概述 RRT Connect 是一种基于 Rapidly-exploring Random Tree (RRT) 的路径规划算法,旨在通过双向扩展树结构来提高搜索效率。相比于传统的 RRT 算法RRT Connect 使用两个树结构分别从起点和目标点开始扩展,并尝试将它们连接起来以形成完整路径[^3]。 在实际应用中,RRT Connect 能够显著减少计算复杂度,特别是在高维空间或复杂环境下的路径规划问题中表现出色。该算法的核心思想是利用随机采样技术快速探索自由空间,并通过双向扩展策略加速收敛过程[^4]。 ### RRT Connect 算法实现 以下是一个简单的 RRT Connect 算法Python 实现示例,使用了基本的数据结构和逻辑: ```python import numpy as np import matplotlib.pyplot as plt class Node: def __init__(self, x, y): self.x = x self.y = y self.parent = None def distance(node1, node2): return np.sqrt((node1.x - node2.x)**2 + (node1.y - node2.y)**2) def is_collision_free(node1, node2, obstacles): # 假设 obstacles 是一个包含矩形障碍物的列表 step_size = 0.1 steps = int(distance(node1, node2) / step_size) for i in range(steps): x = node1.x + (node2.x - node1.x) * i / steps y = node1.y + (node2.y - node1.y) * i / steps if any([obstacle.contains(x, y) for obstacle in obstacles]): return False return True def nearest_node(nodes, target_node): distances = [distance(node, target_node) for node in nodes] return nodes[np.argmin(distances)] def extend_tree(tree, target_node, obstacles, max_step=0.5): nearest = nearest_node(tree, target_node) direction = np.array([target_node.x - nearest.x, target_node.y - nearest.y]) direction = direction / np.linalg.norm(direction) new_point = Node(nearest.x + direction[0] * max_step, nearest.y + direction[1] * max_step) if is_collision_free(nearest, new_point, obstacles): new_point.parent = nearest tree.append(new_point) return new_point return None def rrt_connect(start, goal, obstacles, max_iterations=1000): start_tree = [Node(start[0], start[1])] goal_tree = [Node(goal[0], goal[1])] for _ in range(max_iterations): random_point = Node(np.random.uniform(-10, 10), np.random.uniform(-10, 10)) new_node_start = extend_tree(start_tree, random_point, obstacles) if new_node_start: new_node_goal = extend_tree(goal_tree, new_node_start, obstacles) if new_node_goal and distance(new_node_start, new_node_goal) < 0.1: return start_tree, goal_tree, new_node_start, new_node_goal new_node_goal = extend_tree(goal_tree, random_point, obstacles) if new_node_goal: new_node_start = extend_tree(start_tree, new_node_goal, obstacles) if new_node_start and distance(new_node_start, new_node_goal) < 0.1: return start_tree, goal_tree, new_node_start, new_node_goal return None # 示例调用 start = (-8, -8) goal = (8, 8) obstacles = [] # 定义障碍物 result = rrt_connect(start, goal, obstacles) if result: start_tree, goal_tree, connection_start, connection_goal = result print("Path found!") else: print("No path found.") ``` ### 关键点解析 - **双向扩展**:RRT Connect 通过从起点和目标点分别构建两棵树,减少了单向扩展可能带来的低效问题[^5]。 - **碰撞检测**:`is_collision_free` 函数用于判断新生成的节点是否与障碍物发生碰撞,确保路径的可行性。 - **随机采样**:随机点的选择是 RRT算法的核心之一,决定了探索空间的方向和效率[^6]。 ### 性能与局限性 RRT Connect 在复杂环境中表现出色,但其性能受到随机采样质量的影响。此外,在高维空间中,算法可能会面临维度灾难的问题,导致计算成本急剧增加[^7]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值