欢迎光临
我们一直在努力

【启发式算法】RRT*算法详细介绍(Python)

RRT* 算法原理

RRT*(Rapidly-exploring Random Tree Star)是RRT算法的优化版本,通过渐进最优的方式改进路径质量。核心思想是在扩展树的过程中重新选择父节点和重布线,以降低路径成本。

  • 采样:在配置空间中随机采样点。
  • 最近邻搜索:找到树上距离采样点最近的节点。
  • 扩展:从最近节点向采样点方向扩展新节点。
  • 父节点优化:在新节点附近半径内寻找成本更低的父节点。
  • 重布线:优化附近节点的父节点以降低整体路径成本。

Python 实现步骤

初始化环境

定义二维空间、起点、终点和障碍物:

import numpy as np
import matplotlib.pyplot as plt

class RRTStar:
def __init__(self, start, goal, obstacles, bounds, max_iter=1000, step_size=0.5, radius=1.0):
self.start = np.array(start)
self.goal = np.array(goal)
self.obstacles = obstacles # List of (center, radius)
self.bounds = bounds # (x_min, x_max, y_min, y_max)
self.max_iter = max_iter
self.step_size = step_size
self.radius = radius
self.nodes = [{'point': start, 'parent': None, 'cost': 0}]

采样与扩展

随机采样并扩展树:

def sample(self):
if np.random.rand() < 0.1: # 10%概率采样目标点
return self.goal
return np.random.uniform(low=[self.bounds[0], self.bounds[2]],
high=[self.bounds[1], self.bounds[3]])

def nearest(self, point):
distances = [np.linalg.norm(point – node['point']) for node in self.nodes]
return np.argmin(distances)

def steer(self, from_point, to_point):
direction = to_point – from_point
distance = np.linalg.norm(direction)
if distance <= self.step_size:
return to_point
return from_point + direction * (self.step_size / distance)

碰撞检测

检查路径是否与障碍物相交:

def is_collision_free(self, point1, point2):
for (center, radius) in self.obstacles:
if self.line_circle_intersection(point1, point2, center, radius):
return False
return True

def line_circle_intersection(self, p1, p2, center, r):
# 线段与圆的相交检测
d = p2 – p1
f = p1 – center
a = np.dot(d, d)
b = 2 * np.dot(f, d)
c = np.dot(f, f) – r**2
discriminant = b**2 – 4 * a * c
if discriminant < 0:
return False
t1 = (-b – np.sqrt(discriminant)) / (2 * a)
t2 = (-b + np.sqrt(discriminant)) / (2 * a)
return 0 <= t1 <= 1 or 0 <= t2 <= 1

父节点优化与重布线

def find_best_parent(self, new_point, near_indices):
min_cost = float('inf')
best_parent = None
for idx in near_indices:
node = self.nodes[idx]
if self.is_collision_free(node['point'], new_point):
cost = node['cost'] + np.linalg.norm(new_point – node['point'])
if cost < min_cost:
min_cost = cost
best_parent = idx
return best_parent, min_cost

def rewire(self, new_node_idx, near_indices):
new_node = self.nodes[new_node_idx]
for idx in near_indices:
node = self.nodes[idx]
if self.is_collision_free(new_node['point'], node['point']):
new_cost = new_node['cost'] + np.linalg.norm(node['point'] – new_node['point'])
if new_cost < node['cost']:
node['parent'] = new_node_idx
node['cost'] = new_cost

主算法流程

def plan(self):
for _ in range(self.max_iter):
rand_point = self.sample()
nearest_idx = self.nearest(rand_point)
nearest_point = self.nodes[nearest_idx]['point']
new_point = self.steer(nearest_point, rand_point)

if self.is_collision_free(nearest_point, new_point):
near_indices = self.find_near_indices(new_point)
best_parent, cost = self.find_best_parent(new_point, near_indices)
if best_parent is not None:
self.nodes.append({'point': new_point, 'parent': best_parent, 'cost': cost})
self.rewire(len(self.nodes)-1, near_indices)

if np.linalg.norm(new_point – self.goal) <= self.step_size:
if self.is_collision_free(new_point, self.goal):
self.nodes.append({'point': self.goal, 'parent': len(self.nodes)-1,
'cost': self.nodes[-1]['cost'] + np.linalg.norm(self.goal – new_point)})
return self.extract_path()
return None

可视化与路径提取

def extract_path(self):
path = []
node = self.nodes[-1]
while node['parent'] is not None:
path.append(node['point'])
node = self.nodes[node['parent']]
path.append(self.start)
return np.array(path[::-1])

def plot(self, path=None):
plt.figure(figsize=(10, 8))
for (center, radius) in self.obstacles:
circle = plt.Circle(center, radius, color='r', alpha=0.5)
plt.gca().add_patch(circle)

for node in self.nodes[1:]:
parent = self.nodes[node['parent']]
plt.plot([node['point'][0], parent['point'][0]],
[node['point'][1], parent['point'][1]], 'b-', alpha=0.3)

if path is not None:
plt.plot(path[:,0], path[:,1], 'g-', linewidth=2)

plt.scatter(*self.start, color='g', s=100, label='Start')
plt.scatter(*self.goal, color='y', s=100, label='Goal')
plt.xlim(self.bounds[0], self.bounds[1])
plt.ylim(self.bounds[2], self.bounds[3])
plt.legend()
plt.show()

示例用法

# 定义障碍物和边界
obstacles = [((3, 3), 1.5), ((6, 7), 2), ((8, 2), 1)]
bounds = (0, 10, 0, 10)

# 运行RRT*
rrt = RRTStar(start=(1, 1), goal=(9, 9), obstacles=obstacles, bounds=bounds)
path = rrt.plan()
rrt.plot(path)

关键参数说明

  • max_iter:最大迭代次数,影响路径优化程度。
  • step_size:扩展步长,平衡探索速度与精度。
  • radius:重布线半径,决定局部优化的范围。

通过调整参数和增加迭代次数,RRT*能够逐渐逼近最优路径。算法复杂度高于RRT,但路径质量显著提升。

赞(0)
未经允许不得转载:171主机测评 » 【启发式算法】RRT*算法详细介绍(Python)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址