F-RRT*路径规划算法代码 python

路径规划算法的定义是:移动机器人在具有障碍物的环境中按照一定的评价标准,寻找一条从起始状态到目标状态的无碰路径。路径规划算法的其中一种分类方法是分为全局路径规划和局部路径规划。

全局路径规划是根据环境全局的信息,这包括机器人在当前状态下探测不到的信息。全局规划将环境信息存储在一张图中,利用这张图找到可行的路径。全局算法往往需要耗费大量的计算时间,不适于快速变化的动态环境,同时由于全局路径规划需要事先获得全局环境信息,也不适于未知环境下的规划任务。

import numpy as np
from random import random
import matplotlib.pyplot as plt
from matplotlib import collections  as mc
from collections import deque
import math
import time

class Line():
    ''' Define line '''
    def __init__(self, p0, p1):
        self.p = np.array(p0)
        self.dirn = np.array(p1) - np.array(p0)
        self.dist = np.linalg.norm(self.dirn)
        self.dirn /= self.dist # normalize

    def path(self, t):
        return self.p + t * self.dirn


def Intersection(line, center, radius):
    ''' Check line-sphere (circle) intersection '''
    radius=radius+0.1
    a = np.dot(line.dirn, line.dirn)
    b = 2 * np.dot(line.dirn, line.p - center)
    c = np.dot(line.p - center, line.p - center) - radius * radius

    discriminant = b * b - 4 * a * c
    if discriminant < 0:
        return False

    t1 = (-b + np.sqrt(discriminant)) / (2 * a)
    t2 = (-b - np.sqrt(discriminant)) / (2 * a)

    if (t1 < 0 and t2 < 0) or (t1 > line.dist and t2 > line.dist):
        return False

    return True



def distance(x, y):
    return np.linalg.norm(np.array(x) - np.array(y))


def isInObstacle(vex, obstacles, radius):
    for obs in obstacles:
        if distance(obs, vex) < radius+0.01:



            return True
    return False


def isThruObstacle(line, obstacles, radius):
    for obs in obstacles:
        if Intersection(line, obs, radius):
            return True
    return False


def nearest(G, vex, obstacles, radius):
    Nvex = None
    Nidx = None
    minDist = float("inf")

    for idx, v in enumerate(G.vertices):
        line = Line(v, vex)
        if isThruObstacle(line, obstacles, radius):
            continue
        dist = distance(v, vex)
        if dist < minDist:
            minDist = dist
            Nidx = idx
            Nvex = v

    return Nvex, Nidx

def newVertex(randvex, nearvex, stepSize):
    dirn = np.array(randvex) - np.array(nearvex)
    length = np.linalg.norm(dirn)
    dirn = (dirn / length) * min (stepSize, length)

    newvex = (nearvex[0]+dirn[0], nearvex[1]+dirn[1])
    return newvex


def window(startpos, endpos):
    ''' Define seach window - 2 times of start to end rectangle'''
    width = endpos[0] - startpos[0]
    height = endpos[1] - startpos[1]
    winx = startpos[0] - (width / 2.)
    winy = startpos[1] - (height / 2.)
    return winx, winy, width, height


def isInWindow(pos, winx, winy, width, height):
    ''' Restrict new vertex insides search window'''
    if winx < pos[0] < winx+width and \
        winy < pos[1] < winy+height:
        return True
    else:
        return False


class Graph:
    ''' Define graph '''
    def __init__(self, startpos, endpos):
        self.startpos = startpos
        self.endpos = endpos

        self.vertices = [startpos]
        self.edges = []
        self.success = False

        self.vex2idx = {startpos:0}
        self.neighbors = {0:[]}
        self.distances = {0:0.}
        self.parent={0:-1}

        self.sx = endpos[0] - startpos[0]
        self.sy = endpos[1] - startpos[1]
    def add_vex(self, pos):
        try:
            idx = self.vex2idx[pos]
            self.parent[idx]=-1
        except:
            idx = len(self.vertices)
            self.vertices.append(pos)
            self.vex2idx[pos] = idx
            self.neighbors[idx] = []
            self.parent[idx]=-1
        return idx

    def add_edge(self, idx1, idx2, cost):
        self.edges.append((idx1, idx2))
        self.neighbors[idx1].append((idx2, cost))
        self.neighbors[idx2].append((idx1, cost))
        self.parent[idx1]=idx2

    def randomPosition(self):
        rx = random()
        ry = random()

        posx = self.startpos[0] - (self.sx / 2.) + rx * self.sx * 2
        posy = self.startpos[1] - (self.sy / 2.) + ry * self.sy * 2
        return posx, posy
def Parent(G,vex):
    vexidx=G.vex2idx[vex]
    parentidx=G.parent[vexidx]
    if parentidx==-1:
        return startpos
    else:
        return G.vertices[parentidx]
def FindReachest(G,nearvex,newvex):
    reachest=nearvex
    while reachest!=startpos:
        parent=Parent(G,reachest)
        line=Line(newvex,parent)
        if not isThruObstacle(line,obstacles,radius):
            reachest=parent
        else:
            return  reachest
    return reachest
def CreateNode(G,reachestvex,newvex,dichotomy):
    allow=reachestvex
    if reachestvex!=startpos:
        forbid=Parent(G,reachestvex)
        while distance(allow,forbid)>dichotomy:
            mid=((allow[0]+forbid[0])/2,(allow[1]+forbid[1])/2) # 일단 이 부분은 다시 수정
            line=Line(newvex,mid)
            if not isInObstacle(mid,obstacles,radius) and not isThruObstacle(line,obstacles,radius):
                allow=mid
            else:
                forbid=mid
        forbid=newvex
        while distance(allow,forbid)>dichotomy:
            mid=((allow[0]+forbid[0])/2,(allow[1]+forbid[1])/2) #일단 이 부분은 다시 수정
            parent=Parent(G,reachestvex)
            line=Line(parent,mid)
            if not isInObstacle(mid,obstacles,radius) and not isThruObstacle(line,obstacles,radius):
                allow=mid
            else:
                forbid=mid
    if allow!=reachestvex:
        create=allow
    else:
        create=None
    return create
def farfrom(vex1,vex2):
    return math.sqrt(((vex1[0]-vex2[0])**2+(vex1[1]-vex2[1])**2))
def RRT(startpos, endpos, obstacles, n_iter, radius, stepSize):
    ''' RRT algorithm '''
    G = Graph(startpos, endpos)

    for _ in range(n_iter):
        randvex = G.randomPosition()
        if isInObstacle(randvex, obstacles, radius):
            continue

        nearvex, nearidx = nearest(G, randvex, obstacles, radius)
        if nearvex is None:
            continue

        newvex = newVertex(randvex, nearvex, stepSize)

        newidx = G.add_vex(newvex)
        dist = distance(newvex, nearvex)
        G.add_edge(newidx, nearidx, dist)

        dist = distance(newvex, G.endpos)
        if dist < 2 * radius:
            endidx = G.add_vex(G.endpos)
            G.add_edge(newidx, endidx, dist)
            G.success = True
            #print('success')
            # break
    return G


def RRT_star(startpos, endpos, obstacles, n_iter, radius, stepSize,dichotomy):
    ''' RRT star algorithm '''
    G = Graph(startpos, endpos)

    for i in range(n_iter):
        # plot(G, obstacles, radius)
        randvex = G.randomPosition()
        if isInObstacle(randvex, obstacles, radius):
            continue
        nearvex, nearidx = nearest(G, randvex, obstacles, radius)

        if nearvex is None:
            continue

        newvex = newVertex(randvex, nearvex, stepSize)
        if isInObstacle(newvex,obstacles,radius):
            continue
        reachestvex=FindReachest(G,nearvex,newvex)
        # print('reachestvex:',reachestvex)
        createvex=CreateNode(G,reachestvex,newvex,dichotomy)
        # print('createvex',createvex)
        if createvex is not None:
            newidx = G.add_vex(newvex)
            createvexidx=G.add_vex(createvex)
            reachestParent=Parent(G,reachestvex)
            reachestParentidx=G.vex2idx[reachestParent]
            dist = distance(reachestParent,createvex)
            G.add_edge(createvexidx,reachestParentidx,dist)
            G.distances[createvexidx]=G.distances[reachestParentidx]+dist
            dist = distance(newvex,createvex)
            G.add_edge(newidx,createvexidx,dist)
            G.distances[newidx]=G.distances[createvexidx]+dist
        else:
            line = Line(nearvex,newvex)
            if isThruObstacle(line, obstacles, radius):
                continue
            newidx = G.add_vex(newvex)
            dist = distance(newvex, reachestvex)
            reachestidx=G.vex2idx[reachestvex]
            G.add_edge(newidx, reachestidx, dist)
            G.distances[newidx] = G.distances[reachestidx] + dist
        # update nearby vertices distance (if shorter)
        for vex in G.vertices:
            if vex == newvex:
                continue

            dist = distance(vex, newvex)
            if dist > radius:
                continue

            line = Line(vex, newvex)
            if isThruObstacle(line, obstacles, radius):
                continue

            idx = G.vex2idx[vex]
            if G.distances[newidx] + dist < G.distances[idx]:
                G.add_edge(idx, newidx, dist)
                G.distances[idx] = G.distances[newidx] + dist

        dist = distance(newvex, G.endpos)
        if dist < 2 * radius:
            endidx = G.add_vex(G.endpos)
            G.add_edge(newidx, endidx, dist)
            try:
                G.distances[endidx] = min(G.distances[endidx], G.distances[newidx]+dist)
            except:
                G.distances[endidx] = G.distances[newidx]+dist

            G.success = True
            # print('success')
            break
    return G



def dijkstra(G):
    '''
    Dijkstra algorithm for finding shortest path from start position to end.
    '''
    srcIdx = G.vex2idx[G.startpos]
    dstIdx = G.vex2idx[G.endpos]

    # build dijkstra
    nodes = list(G.neighbors.keys())
    dist = {node: float('inf') for node in nodes}
    prev = {node: None for node in nodes}
    dist[srcIdx] = 0

    while nodes:
        curNode = min(nodes, key=lambda node: dist[node])
        nodes.remove(curNode)
        if dist[curNode] == float('inf'):
            break

        for neighbor, cost in G.neighbors[curNode]:
            newCost = dist[curNode] + cost
            if newCost < dist[neighbor]:
                dist[neighbor] = newCost
                prev[neighbor] = curNode

    # retrieve path
    path = deque()
    curNode = dstIdx
    while prev[curNode] is not None:
        path.appendleft(G.vertices[curNode])
        curNode = prev[curNode]
    path.appendleft(G.vertices[curNode])
    return list(path)



def plot(G, obstacles, radius, path=None):
    '''
    Plot RRT, obstacles and shortest path
    '''
    px = [x for x, y in G.vertices]
    py = [y for x, y in G.vertices]
    fig, ax = plt.subplots()

    for obs in obstacles:
        circle = plt.Circle(obs, radius, color='red')
        ax.add_artist(circle)

    ax.scatter(px, py, c='cyan')
    ax.scatter(G.startpos[0], G.startpos[1], c='black')
    ax.scatter(G.endpos[0], G.endpos[1], c='black')

    lines = [(G.vertices[edge[0]], G.vertices[edge[1]]) for edge in G.edges]
    lc = mc.LineCollection(lines, colors='green', linewidths=2)
    ax.add_collection(lc)

    if path is not None:
        paths = [(path[i], path[i+1]) for i in range(len(path)-1)]
        lc2 = mc.LineCollection(paths, colors='blue', linewidths=3)
        ax.add_collection(lc2)

    ax.autoscale()
    ax.margins(0.1)
    plt.show()


def pathSearch(startpos, endpos, obstacles, n_iter, radius, stepSize,dichotomy):
    G = RRT_star(startpos, endpos, obstacles, n_iter, radius, stepSize,dichotomy)
    if G.success:
        path = dijkstra(G)
        # plot(G, obstacles, radius, path)
        return path


if __name__ == '__main__':
    startpos = (0., 0.)
    endpos = (48., 28.)

    obstacles = [(1., 1.), (2., 2.)]

    n_iter = 200
    radius = 0.5
    stepSize = 0.7
    dichotomy= 0.1
    S_time=[]
    S_dist=[]
    for _ in range(100):
        start = time.time()
        G = RRT_star(startpos, endpos, obstacles, n_iter, radius, stepSize,dichotomy)
        # G = RRT(startpos, endpos, obstacles, n_iter, radius, stepSize)

        if G.success:
            path = dijkstra(G)
            print(path)
            plot(G, obstacles, radius, path)
            end = time.time()
            S_time.append(end-start)
            # print(f"{end - start:.5f} sec")
            dist=0
            prevx=startpos[0]
            prevy=startpos[1]
            for x,y in path:
                x_diff=prevx-x
                y_diff=prevy-y
                dist+= math.sqrt(x_diff**2+y_diff**2)
            S_dist.append(dist)
        else:
            pass
            print('yo')
            plot(G, obstacles, radius)
    print('Cost Mean=',np.mean(S_dist))
    print('Cost std=',np.std(S_dist))
    print('Cost Min=', np.min(S_dist))
    print('Cost Max=', np.max(S_dist))
    print('Time Mean=',np.mean(S_time))
    print('Time std=',np.std(S_time))
    print('Time Min=', np.min(S_time))
    print('Time Max=', np.max(S_time))
# Cost Mean= 19.95158009760057
# Cost std= 2.2203056859587984
# Cost Min= 16.286848376528287
# Cost Max= 26.856049490040363
# Time Mean= 0.12551307439804077
# Time std= 0.1737030710498345
# Time Min= 0.019977331161499023
# Time Max= 0.965425968170166

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: rrt*-connect是一种路径规划算法,用于在给定的环境中找到两个已知点之间的最优路径。下面是一个基于Python语言实现的简单示例代码: ```python import numpy as np import matplotlib.pyplot as plt # 初始化rrt*-connect算法的节点类 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 check_obstacle(node1, node2, obstacle_list): for obstacle in obstacle_list: distance_to_obstacle = np.sqrt((obstacle[0] - node1.x)**2 + (obstacle[1] - node1.y)**2) if distance_to_obstacle <= 1.0: return True return False # 使用rrt*-connect算法搜索路径 def rrt_connect(start, goal, obstacle_list): nodes_start = [start] nodes_goal = [goal] while True: # 从起点开始扩展树 random_node = Node(np.random.uniform(0, 10), np.random.uniform(0, 10)) nearest_node = nodes_start[0] for node in nodes_start: if distance(node, random_node) < distance(nearest_node, random_node): nearest_node = node if check_obstacle(nearest_node, random_node, obstacle_list): continue new_node = Node(random_node.x, random_node.y) new_node.parent = nearest_node nodes_start.append(new_node) # 从终点开始扩展树 random_node = Node(np.random.uniform(0, 10), np.random.uniform(0, 10)) nearest_node = nodes_goal[0] for node in nodes_goal: if distance(node, random_node) < distance(nearest_node, random_node): nearest_node = node if check_obstacle(nearest_node, random_node, obstacle_list): continue new_node = Node(random_node.x, random_node.y) new_node.parent = nearest_node nodes_goal.append(new_node) # 检查两颗树是否连接 for node1 in nodes_start: for node2 in nodes_goal: if distance(node1, node2) <= 1.0 and not check_obstacle(node1, node2, obstacle_list): return nodes_start, nodes_goal return None, None # 测试代码 start_node = Node(1, 1) goal_node = Node(9, 9) obstacles = [(5, 5), (6, 6), (7, 7)] path_start, path_goal = rrt_connect(start_node, goal_node, obstacles) if path_start is not None and path_goal is not None: path_start.append(path_goal[-1]) path = [] current_node = path_start[-1] while current_node is not None: path.append((current_node.x, current_node.y)) current_node = current_node.parent path.reverse() print("找到路径:", path) else: print("未找到路径") ``` 这段代码实现了一个简单的rrt*-connect算法,用于寻找起点和终点之间的最优路径。其中通过定义Node类表示路径上的节点,distance函数计算两个节点间的距离,check_obstacle函数用于检查两个节点间是否存在障碍物。主函数rrt_connect则是使用rrt*-connect算法进行路径搜索,并返回两个树的根节点列表。 最后进行测试,通过rrt_connect函数得到的路径点列表,再逆向遍历节点的parent指针,获取完整的路径。如果找到路径,则将其打印输出,否则输出未找到路径的信息。 ### 回答2: rrt*-connect算法是一种针对路径规划问题的改进型Rapidly-Exploring Random Tree (RRT) 算法。以下是一个简单的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 generate_random_node(x_range, y_range): x = np.random.uniform(x_range[0], x_range[1]) y = np.random.uniform(y_range[0], y_range[1]) return Node(x, y) def find_nearest_node(node_list, random_node): distances = [distance(node, random_node) for node in node_list] nearest_index = np.argmin(distances) return node_list[nearest_index] def is_collision_free(node1, node2, obstacles): # 检查路径上是否有碰撞 # 如果有碰撞,返回False;否则返回True # 这里省略碰撞检测的具体实现代码 return not collision_detected def rrt_connect(start, goal, x_range, y_range, obstacles): nodes = [start] while True: random_node = generate_random_node(x_range, y_range) nearest_node = find_nearest_node(nodes, random_node) new_node = Node(nearest_node.x + 0.1 * (random_node.x - nearest_node.x), nearest_node.y + 0.1 * (random_node.y - nearest_node.y)) if is_collision_free(nearest_node, new_node, obstacles): nodes.append(new_node) if distance(new_node, goal) < 0.1: return True, nodes if len(nodes) % 2 == 0: nodes = nodes[::-1] start = Node(1, 1) goal = Node(5, 5) x_range = [0, 10] y_range = [0, 10] obstacles = [[3, 3], [4, 4]] # 障碍物的位置 success, path = rrt_connect(start, goal, x_range, y_range, obstacles) if success: x = [node.x for node in path] y = [node.y for node in path] plt.plot(x, y, '-r') plt.xlim(x_range) plt.ylim(y_range) plt.show() ``` 这段代码描述了rrt*-connect的主要逻辑。它通过生成随机节点,寻找最近邻节点,并尝试从最近邻节点朝随机节点延伸,然后检查路径是否与障碍物相碰撞。如果延伸的路径安全,则将新节点添加到节点列表中。最终,如果找到一条从起始节点到目标节点的路径,则返回路径节点列表。如果找不到路径,则返回False。代码还包含了绘制路径的部分,以便可视化显示结果。请注意,代码中的碰撞检测部分需要根据具体的碰撞检测算法进行实现。 ### 回答3: rrt*-connect是一种改进版的快速随机树(Rapidly-exploring Random Trees,RRT算法,用于路径规划。下面是一个使用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 dist(self, other): return np.sqrt((self.x - other.x)**2 + (self.y - other.y)**2) class RRTConnect: def __init__(self, start, goal, obstacles, step_size=0.5, max_iters=1000): self.start = Node(*start) self.goal = Node(*goal) self.obstacles = obstacles self.step_size = step_size self.max_iters = max_iters def generate_random_point(self): x = np.random.uniform(0, 10) # 计划空间的x范围 y = np.random.uniform(0, 10) # 计划空间的y范围 return Node(x, y) def find_nearest_node(self, tree, point): distances = [node.dist(point) for node in tree] return tree[np.argmin(distances)] def generate_new_node(self, nearest_node, random_node): distance = nearest_node.dist(random_node) if distance <= self.step_size: return random_node else: scale = self.step_size / distance x = nearest_node.x + (random_node.x - nearest_node.x) * scale y = nearest_node.y + (random_node.y - nearest_node.y) * scale return Node(x, y) def is_collision_free(self, node1, node2): for obstacle in self.obstacles: if obstacle[0] < node1.x < obstacle[1] and obstacle[2] < node1.y < obstacle[3]: return False if obstacle[0] < node2.x < obstacle[1] and obstacle[2] < node2.y < obstacle[3]: return False return True def rrt_connect(self): tree1 = [self.start] tree2 = [self.goal] for _ in range(self.max_iters): random_node = self.generate_random_point() nearest_node1 = self.find_nearest_node(tree1, random_node) nearest_node2 = self.find_nearest_node(tree2, random_node) new_node1 = self.generate_new_node(nearest_node1, random_node) new_node2 = self.generate_new_node(nearest_node2, random_node) if self.is_collision_free(nearest_node1, new_node1): tree1.append(new_node1) if self.is_collision_free(nearest_node2, new_node1): path = self.connect_trees(tree1, tree2, nearest_node1, new_node2) if path: return path if self.is_collision_free(nearest_node2, new_node2): tree2.append(new_node2) if self.is_collision_free(nearest_node1, new_node2): path = self.connect_trees(tree1, tree2, nearest_node1, new_node2) if path: return path return None def connect_trees(self, tree1, tree2, node1, node2): path = [] while node1.parent: path.append([node1.x, node1.y]) node1 = node1.parent path.append([self.start.x, self.start.y]) path = path[::-1] while node2.parent: path.append([node2.x, node2.y]) node2 = node2.parent path.append([self.goal.x, self.goal.y]) return path # Usage example: start = [1, 1] # 起点 goal = [9, 9] # 终点 obstacles = [[3, 4, 2, 5], [7, 9, 6, 8]] # 障碍物坐标范围,例如[x1, x2, y1, y2] rrt = RRTConnect(start, goal, obstacles) path = rrt.rrt_connect() print("路径点坐标:", path) # 绘制路径 if path: path = np.array(path) plt.plot(path[:,0], path[:,1], '-o') for obstacle in obstacles: plt.fill([obstacle[0], obstacle[0], obstacle[1], obstacle[1]], [obstacle[2], obstacle[3], obstacle[3], obstacle[2]], 'r') plt.xlim(0, 10) plt.ylim(0, 10) plt.show() ``` 以上是一个简单的RRT*-connect算法Python实现。代码实现了通过随机扩展树的方式来寻找起点到终点的路径,并考虑了障碍物的碰撞检测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值