InformedRRT¶
src.python_motion_planning.global_planner.sample_search.informed_rrt.InformedRRT
¶
Bases: RRTStar
Class for Informed RRT* motion planning.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
start
|
tuple
|
start point coordinate |
required |
goal
|
tuple
|
goal point coordinate |
required |
env
|
Env
|
environment |
required |
max_dist
|
float
|
Maximum expansion distance one step |
0.5
|
sample_num
|
int
|
Maximum number of sample points |
1500
|
r
|
float
|
optimization radius |
12.0
|
goal_sample_rate
|
float
|
heuristic sample |
0.05
|
Examples:
Python Console Session
>>> import python_motion_planning as pmp
>>> planner = pmp.InformedRRT((5, 5), (45, 25), pmp.Map(51, 31))
>>> cost, path, expand = planner.plan() # planning results only
>>> planner.plot.animation(path, str(planner), cost, expand) # animation
>>> planner.run() # run both planning and animation
References
[1] Optimal Sampling-based Path Planning Focused via Direct Sampling of an Admissible Ellipsoidal heuristic
Source code in src\python_motion_planning\global_planner\sample_search\informed_rrt.py
Python
class InformedRRT(RRTStar):
"""
Class for Informed RRT* motion planning.
Parameters:
start (tuple): start point coordinate
goal (tuple): goal point coordinate
env (Env): environment
max_dist (float): Maximum expansion distance one step
sample_num (int): Maximum number of sample points
r (float): optimization radius
goal_sample_rate (float): heuristic sample
Examples:
>>> import python_motion_planning as pmp
>>> planner = pmp.InformedRRT((5, 5), (45, 25), pmp.Map(51, 31))
>>> cost, path, expand = planner.plan() # planning results only
>>> planner.plot.animation(path, str(planner), cost, expand) # animation
>>> planner.run() # run both planning and animation
References:
[1] Optimal Sampling-based Path Planning Focused via Direct Sampling of an Admissible Ellipsoidal heuristic
"""
def __init__(self, start: tuple, goal: tuple, env: Env, max_dist: float = 0.5,
sample_num: int = 1500, r: float = 12.0, goal_sample_rate: float = 0.05) -> None:
super().__init__(start, goal, env, max_dist, sample_num, goal_sample_rate)
# optimization radius
self.r = r
# best planning cost
self.c_best = float("inf")
# distance between start and goal
self.c_min = self.dist(self.start, self.goal)
# ellipse sampling
self.transform = partial(Ellipse.transform, c=self.c_min / 2, p1=start, p2=goal)
def __str__(self) -> str:
return "Informed RRT*"
def plan(self) -> tuple:
"""
Informed-RRT* motion plan function.
Returns:
cost (float): path cost
path (list): planning path
expand (list): expanded (sampled) nodes list
"""
# Sampled list
sample_list = {self.start.current: self.start}
best_cost, best_path = float("inf"), None
# main loop
for i in range(self.sample_num):
# generate a random node in the map
node_rand = self.generateRandomNode()
# visited
if node_rand.current in sample_list:
continue
# generate new node
node_new = self.getNearest(list(sample_list.values()), node_rand)
if node_new:
sample_list[node_new.current] = node_new
dist = self.dist(node_new, self.goal)
# goal found
if dist <= self.max_dist and not self.isCollision(node_new, self.goal):
self.goal.parent = node_new.current
self.goal.g = node_new.g + self.dist(self.goal, node_new)
sample_list[self.goal.current] = self.goal
cost, path = self.extractPath(sample_list)
if path and cost < best_cost:
best_cost, best_path = cost, path
self.c_best = best_cost
return best_cost, best_path, list(sample_list.values())
def run(self) -> None:
"""
Running both plannig and animation.
"""
cost, path, expand = self.plan()
t = np.arange(0, 2 * np.pi + 0.1, 0.1)
x = [np.cos(it) for it in t]
y = [np.sin(it) for it in t]
z = [1 for _ in t]
fx = self.transform(self.c_best / 2) @ np.array([x, y, z])
fx[0, :] += x
fx[1, :] += y
self.plot.animation(path, str(self), cost, expand, ellipse=fx)
def generateRandomNode(self) -> Node:
"""
Generate a random node to extend exploring tree.
Returns:
node (Node): a random node based on sampling
"""
# ellipse sample
if self.c_best < float("inf"):
while True:
# unit ball sample
p = np.array([.0, .0, 1.])
while True:
x, y = np.random.uniform(-1, 1), np.random.uniform(-1, 1)
if x ** 2 + y ** 2 < 1:
p[0], p[1] = x, y
break
# transform to ellipse
p_star = self.transform(self.c_best / 2) @ p.T
if self.delta <= p_star[0] <= self.env.x_range - self.delta and \
self.delta <= p_star[1] <= self.env.y_range - self.delta:
return Node((p_star[0], p_star[1]), None, 0, 0)
# random sample
else:
return super().generateRandomNode()
generateRandomNode()
¶
Generate a random node to extend exploring tree.
Returns:
Name | Type | Description |
---|---|---|
node |
Node
|
a random node based on sampling |
Source code in src\python_motion_planning\global_planner\sample_search\informed_rrt.py
Python
def generateRandomNode(self) -> Node:
"""
Generate a random node to extend exploring tree.
Returns:
node (Node): a random node based on sampling
"""
# ellipse sample
if self.c_best < float("inf"):
while True:
# unit ball sample
p = np.array([.0, .0, 1.])
while True:
x, y = np.random.uniform(-1, 1), np.random.uniform(-1, 1)
if x ** 2 + y ** 2 < 1:
p[0], p[1] = x, y
break
# transform to ellipse
p_star = self.transform(self.c_best / 2) @ p.T
if self.delta <= p_star[0] <= self.env.x_range - self.delta and \
self.delta <= p_star[1] <= self.env.y_range - self.delta:
return Node((p_star[0], p_star[1]), None, 0, 0)
# random sample
else:
return super().generateRandomNode()
plan()
¶
Informed-RRT* motion plan function.
Returns:
Name | Type | Description |
---|---|---|
cost |
float
|
path cost |
path |
list
|
planning path |
expand |
list
|
expanded (sampled) nodes list |
Source code in src\python_motion_planning\global_planner\sample_search\informed_rrt.py
Python
def plan(self) -> tuple:
"""
Informed-RRT* motion plan function.
Returns:
cost (float): path cost
path (list): planning path
expand (list): expanded (sampled) nodes list
"""
# Sampled list
sample_list = {self.start.current: self.start}
best_cost, best_path = float("inf"), None
# main loop
for i in range(self.sample_num):
# generate a random node in the map
node_rand = self.generateRandomNode()
# visited
if node_rand.current in sample_list:
continue
# generate new node
node_new = self.getNearest(list(sample_list.values()), node_rand)
if node_new:
sample_list[node_new.current] = node_new
dist = self.dist(node_new, self.goal)
# goal found
if dist <= self.max_dist and not self.isCollision(node_new, self.goal):
self.goal.parent = node_new.current
self.goal.g = node_new.g + self.dist(self.goal, node_new)
sample_list[self.goal.current] = self.goal
cost, path = self.extractPath(sample_list)
if path and cost < best_cost:
best_cost, best_path = cost, path
self.c_best = best_cost
return best_cost, best_path, list(sample_list.values())
run()
¶
Running both plannig and animation.
Source code in src\python_motion_planning\global_planner\sample_search\informed_rrt.py
Python
def run(self) -> None:
"""
Running both plannig and animation.
"""
cost, path, expand = self.plan()
t = np.arange(0, 2 * np.pi + 0.1, 0.1)
x = [np.cos(it) for it in t]
y = [np.sin(it) for it in t]
z = [1 for _ in t]
fx = self.transform(self.c_best / 2) @ np.array([x, y, z])
fx[0, :] += x
fx[1, :] += y
self.plot.animation(path, str(self), cost, expand, ellipse=fx)