mirror of
https://github.com/zhm-real/PathPlanning.git
synced 2026-08-29 16:40:46 +08:00
update informed rrt*
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 202 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
@@ -6,7 +6,6 @@ Batch Informed Trees (BIT*)
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import math
|
import math
|
||||||
import copy
|
|
||||||
import random
|
import random
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
@@ -66,7 +65,6 @@ class BITStar:
|
|||||||
self.g_T = dict()
|
self.g_T = dict()
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
print("init")
|
|
||||||
self.Tree.V.add(self.x_start)
|
self.Tree.V.add(self.x_start)
|
||||||
self.X_sample.add(self.x_goal)
|
self.X_sample.add(self.x_goal)
|
||||||
|
|
||||||
@@ -141,33 +139,13 @@ class BITStar:
|
|||||||
self.Tree.QV = set()
|
self.Tree.QV = set()
|
||||||
|
|
||||||
if k % 5 == 0:
|
if k % 5 == 0:
|
||||||
self.draw(xCenter, self.g_T[self.x_goal], cMin, theta)
|
self.animation(xCenter, self.g_T[self.x_goal], cMin, theta)
|
||||||
|
|
||||||
path_x, path_y = self.ExtractPath()
|
path_x, path_y = self.ExtractPath()
|
||||||
plt.plot(path_x, path_y, linewidth=2, color='r')
|
plt.plot(path_x, path_y, linewidth=2, color='r')
|
||||||
plt.pause(0.01)
|
plt.pause(0.01)
|
||||||
# test
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
def draw(self, xCenter, cMax, cMin, theta):
|
|
||||||
plt.cla()
|
|
||||||
self.plot_grid("Batch Informed Trees (BIT*)")
|
|
||||||
|
|
||||||
plt.gcf().canvas.mpl_connect(
|
|
||||||
'key_release_event',
|
|
||||||
lambda event: [exit(0) if event.key == 'escape' else None])
|
|
||||||
|
|
||||||
for v in self.X_sample:
|
|
||||||
plt.plot(v.x, v.y, marker='.', color='lightgrey', markersize='2')
|
|
||||||
|
|
||||||
if cMax < np.inf:
|
|
||||||
self.draw_ellipse(xCenter, cMax, cMin, theta)
|
|
||||||
|
|
||||||
for v, w in self.Tree.E:
|
|
||||||
plt.plot([v.x, w.x], [v.y, w.y], '-g')
|
|
||||||
|
|
||||||
plt.pause(0.01)
|
|
||||||
|
|
||||||
def ExtractPath(self):
|
def ExtractPath(self):
|
||||||
node = self.x_goal
|
node = self.x_goal
|
||||||
path_x, path_y = [node.x], [node.y]
|
path_x, path_y = [node.x], [node.y]
|
||||||
@@ -335,9 +313,23 @@ class BITStar:
|
|||||||
dy = node_end.y - node_start.y
|
dy = node_end.y - node_start.y
|
||||||
return math.hypot(dx, dy), math.atan2(dy, dx)
|
return math.hypot(dx, dy), math.atan2(dy, dx)
|
||||||
|
|
||||||
def animation(self, name, cBest):
|
def animation(self, xCenter, cMax, cMin, theta):
|
||||||
theta, cMin, xCenter, C = self.init()
|
plt.cla()
|
||||||
self.draw_ellipse(xCenter, cBest, cMin, theta)
|
self.plot_grid("Batch Informed Trees (BIT*)")
|
||||||
|
|
||||||
|
plt.gcf().canvas.mpl_connect(
|
||||||
|
'key_release_event',
|
||||||
|
lambda event: [exit(0) if event.key == 'escape' else None])
|
||||||
|
|
||||||
|
for v in self.X_sample:
|
||||||
|
plt.plot(v.x, v.y, marker='.', color='lightgrey', markersize='2')
|
||||||
|
|
||||||
|
if cMax < np.inf:
|
||||||
|
self.draw_ellipse(xCenter, cMax, cMin, theta)
|
||||||
|
|
||||||
|
for v, w in self.Tree.E:
|
||||||
|
plt.plot([v.x, w.x], [v.y, w.y], '-g')
|
||||||
|
|
||||||
plt.pause(0.001)
|
plt.pause(0.001)
|
||||||
|
|
||||||
def plot_grid(self, name):
|
def plot_grid(self, name):
|
||||||
|
|||||||
@@ -51,42 +51,55 @@ class IRrtStar:
|
|||||||
self.X_soln = set()
|
self.X_soln = set()
|
||||||
self.path = None
|
self.path = None
|
||||||
|
|
||||||
def planning(self):
|
def init(self):
|
||||||
c_best = np.inf
|
cMin, theta = self.get_distance_and_angle(self.x_start, self.x_goal)
|
||||||
dist, theta = self.get_distance_and_angle(self.x_start, self.x_goal)
|
C = self.RotationToWorldFrame(self.x_start, self.x_goal, cMin)
|
||||||
C = self.RotationToWorldFrame(self.x_start, self.x_goal, dist)
|
xCenter = np.array([[(self.x_start.x + self.x_goal.x) / 2.0],
|
||||||
x_center = np.array([[(self.x_start.x + self.x_goal.x) / 2.0],
|
[(self.x_start.y + self.x_goal.y) / 2.0], [0.0]])
|
||||||
[(self.x_start.y + self.x_goal.y) / 2.0], [0.0]])
|
|
||||||
x_best = self.x_start
|
x_best = self.x_start
|
||||||
|
|
||||||
|
return theta, cMin, xCenter, C, x_best
|
||||||
|
|
||||||
|
def planning(self):
|
||||||
|
theta, dist, x_center, C, x_best = self.init()
|
||||||
|
c_best = np.inf
|
||||||
|
|
||||||
for k in range(self.iter_max):
|
for k in range(self.iter_max):
|
||||||
x_rand = self.Sample(self.x_start, self.x_goal, c_best, x_center, C)
|
if self.X_soln:
|
||||||
|
cost = {node: self.Cost(node) for node in self.X_soln}
|
||||||
|
x_best = min(cost, key=cost.get)
|
||||||
|
c_best = cost[x_best]
|
||||||
|
|
||||||
|
x_rand = self.Sample(c_best, dist, x_center, C)
|
||||||
x_nearest = self.Nearest(self.V, x_rand)
|
x_nearest = self.Nearest(self.V, x_rand)
|
||||||
x_new = self.Steer(x_nearest, x_rand)
|
x_new = self.Steer(x_nearest, x_rand)
|
||||||
|
|
||||||
if x_new and not self.utils.is_collision(x_nearest, x_new):
|
if x_new and not self.utils.is_collision(x_nearest, x_new):
|
||||||
X_near = self.Near(self.V, x_new)
|
X_near = self.Near(self.V, x_new)
|
||||||
c_min = self.Cost(x_new)
|
c_min = self.Cost(x_nearest) + self.Line(x_nearest, x_new)
|
||||||
self.V.append(x_new)
|
self.V.append(x_new)
|
||||||
|
|
||||||
|
# choose parent
|
||||||
for x_near in X_near:
|
for x_near in X_near:
|
||||||
c_new = self.Cost(x_near) + self.Line(x_near, x_new)
|
c_new = self.Cost(x_near) + self.Line(x_near, x_new)
|
||||||
if c_new < c_min:
|
if c_new < c_min:
|
||||||
x_new.parent = x_near
|
x_new.parent = x_near
|
||||||
c_min = c_new
|
c_min = c_new
|
||||||
|
|
||||||
|
# rewire
|
||||||
for x_near in X_near:
|
for x_near in X_near:
|
||||||
c_near = self.Cost(x_near)
|
c_near = self.Cost(x_near)
|
||||||
c_new = c_min + self.Line(x_new, x_near)
|
c_new = self.Cost(x_new) + self.Line(x_new, x_near)
|
||||||
if c_new < c_near:
|
if c_new < c_near:
|
||||||
x_near.parent = x_new
|
x_near.parent = x_new
|
||||||
|
|
||||||
if self.InGoalRegion(x_new):
|
if self.InGoalRegion(x_new):
|
||||||
self.X_soln.add(x_new)
|
if not self.utils.is_collision(x_new, self.x_goal):
|
||||||
new_cost = self.Cost(x_new) + self.Line(x_new, self.x_goal)
|
self.X_soln.add(x_new)
|
||||||
if new_cost < c_best:
|
# new_cost = self.Cost(x_new) + self.Line(x_new, self.x_goal)
|
||||||
c_best = new_cost
|
# if new_cost < c_best:
|
||||||
x_best = x_new
|
# c_best = new_cost
|
||||||
|
# x_best = x_new
|
||||||
|
|
||||||
if k % 20 == 0:
|
if k % 20 == 0:
|
||||||
self.animation(x_center=x_center, c_best=c_best, dist=dist, theta=theta)
|
self.animation(x_center=x_center, c_best=c_best, dist=dist, theta=theta)
|
||||||
@@ -108,34 +121,40 @@ class IRrtStar:
|
|||||||
|
|
||||||
def Near(self, nodelist, node):
|
def Near(self, nodelist, node):
|
||||||
n = len(nodelist) + 1
|
n = len(nodelist) + 1
|
||||||
r = min(self.search_radius * math.sqrt((math.log(n) / n)), self.step_len)
|
r = 50 * math.sqrt((math.log(n) / n))
|
||||||
|
|
||||||
dist_table = [(nd.x - node.x) ** 2 + (nd.y - node.y) ** 2 for nd in nodelist]
|
dist_table = [(nd.x - node.x) ** 2 + (nd.y - node.y) ** 2 for nd in nodelist]
|
||||||
X_near = [nodelist[ind] for ind in range(len(dist_table)) if dist_table[ind] <= r ** 2 and
|
X_near = [nodelist[ind] for ind in range(len(dist_table)) if dist_table[ind] <= r ** 2 and
|
||||||
not self.utils.is_collision(node, nodelist[ind])]
|
not self.utils.is_collision(nodelist[ind], node)]
|
||||||
|
|
||||||
return X_near
|
return X_near
|
||||||
|
|
||||||
def Sample(self, x_start, x_goal, c_max, x_center, C):
|
def Sample(self, c_max, c_min, x_center, C):
|
||||||
if c_max < np.inf:
|
if c_max < np.inf:
|
||||||
c_min = self.Line(x_start, x_goal)
|
|
||||||
r = [c_max / 2.0,
|
r = [c_max / 2.0,
|
||||||
math.sqrt(c_max ** 2 - c_min ** 2) / 2.0,
|
math.sqrt(c_max ** 2 - c_min ** 2) / 2.0,
|
||||||
math.sqrt(c_max ** 2 - c_min ** 2) / 2.0]
|
math.sqrt(c_max ** 2 - c_min ** 2) / 2.0]
|
||||||
L = np.diag(r)
|
L = np.diag(r)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
x_ball = self.SampleUnitNBall()
|
x_ball = self.SampleUnitBall()
|
||||||
x_rand = C @ L @ x_ball + x_center
|
x_rand = np.dot(np.dot(C, L), x_ball) + x_center
|
||||||
if self.x_range[0] + self.delta <= x_rand[0] <= self.x_range[1] - self.delta and \
|
if self.x_range[0] + self.delta <= x_rand[0] <= self.x_range[1] - self.delta and \
|
||||||
self.y_range[0] + self.delta <= x_rand[1] <= self.y_range[1] - self.delta:
|
self.y_range[0] + self.delta <= x_rand[1] <= self.y_range[1] - self.delta:
|
||||||
break
|
break
|
||||||
x_rand = Node((x_rand[0], x_rand[1]))
|
x_rand = Node((x_rand[(0, 0)], x_rand[(1, 0)]))
|
||||||
else:
|
else:
|
||||||
x_rand = self.SampleFreeSpace()
|
x_rand = self.SampleFreeSpace()
|
||||||
|
|
||||||
return x_rand
|
return x_rand
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def SampleUnitBall():
|
||||||
|
while True:
|
||||||
|
x, y = random.uniform(-1, 1), random.uniform(-1, 1)
|
||||||
|
if x ** 2 + y ** 2 < 1:
|
||||||
|
return np.array([[x], [y], [0.0]])
|
||||||
|
|
||||||
def SampleFreeSpace(self):
|
def SampleFreeSpace(self):
|
||||||
delta = self.delta
|
delta = self.delta
|
||||||
|
|
||||||
@@ -173,14 +192,6 @@ class IRrtStar:
|
|||||||
|
|
||||||
return C
|
return C
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def SampleUnitNBall():
|
|
||||||
while True:
|
|
||||||
x, y = random.uniform(-1, 1), random.uniform(-1, 1)
|
|
||||||
|
|
||||||
if x ** 2 + y ** 2 < 1:
|
|
||||||
return np.array([[x], [y], [0.0]])
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def Nearest(nodelist, n):
|
def Nearest(nodelist, n):
|
||||||
return nodelist[int(np.argmin([(nd.x - n.x) ** 2 + (nd.y - n.y) ** 2
|
return nodelist[int(np.argmin([(nd.x - n.x) ** 2 + (nd.y - n.y) ** 2
|
||||||
@@ -190,12 +201,14 @@ class IRrtStar:
|
|||||||
def Line(x_start, x_goal):
|
def Line(x_start, x_goal):
|
||||||
return math.hypot(x_goal.x - x_start.x, x_goal.y - x_start.y)
|
return math.hypot(x_goal.x - x_start.x, x_goal.y - x_start.y)
|
||||||
|
|
||||||
@staticmethod
|
def Cost(self, node):
|
||||||
def Cost(node):
|
if node == self.x_start:
|
||||||
cost = 0.0
|
return 0.0
|
||||||
if node.parent is None:
|
|
||||||
return cost
|
|
||||||
|
|
||||||
|
if node.parent is None:
|
||||||
|
return np.inf
|
||||||
|
|
||||||
|
cost = 0.0
|
||||||
while node.parent:
|
while node.parent:
|
||||||
cost += math.hypot(node.x - node.parent.x, node.y - node.parent.y)
|
cost += math.hypot(node.x - node.parent.x, node.y - node.parent.y)
|
||||||
node = node.parent
|
node = node.parent
|
||||||
@@ -215,13 +228,13 @@ class IRrtStar:
|
|||||||
'key_release_event',
|
'key_release_event',
|
||||||
lambda event: [exit(0) if event.key == 'escape' else None])
|
lambda event: [exit(0) if event.key == 'escape' else None])
|
||||||
|
|
||||||
if c_best != np.inf:
|
|
||||||
self.draw_ellipse(x_center, c_best, dist, theta)
|
|
||||||
|
|
||||||
for node in self.V:
|
for node in self.V:
|
||||||
if node.parent:
|
if node.parent:
|
||||||
plt.plot([node.x, node.parent.x], [node.y, node.parent.y], "-g")
|
plt.plot([node.x, node.parent.x], [node.y, node.parent.y], "-g")
|
||||||
|
|
||||||
|
if c_best != np.inf:
|
||||||
|
self.draw_ellipse(x_center, c_best, dist, theta)
|
||||||
|
|
||||||
plt.pause(0.01)
|
plt.pause(0.01)
|
||||||
|
|
||||||
def plot_grid(self, name):
|
def plot_grid(self, name):
|
||||||
@@ -284,7 +297,7 @@ def main():
|
|||||||
x_start = (18, 8) # Starting node
|
x_start = (18, 8) # Starting node
|
||||||
x_goal = (37, 18) # Goal node
|
x_goal = (37, 18) # Goal node
|
||||||
|
|
||||||
rrt_star = IRrtStar(x_start, x_goal, 10, 0.10, 20, 1000)
|
rrt_star = IRrtStar(x_start, x_goal, 1, 0.10, 12, 1000)
|
||||||
rrt_star.planning()
|
rrt_star.planning()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user