背景:为什么要合并 Safe Area?
在使用 QuadTree 构建环境分区时,每一个 FREE
类型的叶子节点都会生成一个凸包(Convex Hull)作为局部的 Safe Area。但随着环境分辨率提高或障碍物分布稠密,Safe Area 数量可能激增,带来以下问题:
- 路径图节点数量过多,导致 A* 搜索复杂度提升
- MPC 控制器的参考轨迹中断多,规划不平滑
- 可视化和维护困难
因此,将临近的 Safe Area 合并为更大的安全区域 是简化规划图结构、提高控制性能的重要手段。
合并判据设计
在 connective_quadtree.py
和 utils_geo.py
中,我们可以基于以下原则实现 Safe Area 合并:
- 邻接性:两个凸包边界是否接近或重合
- 几何相容性:合并后的点集是否仍然可以构成一个有效凸包
- 面积提升评估:合并后凸包面积未显著膨胀,避免引入死角区域
利用 shapely
和 scipy.spatial.ConvexHull
,可以进行合并模拟与几何判断。
合并过程实现思路
合并逻辑可以封装为 merge_safe_areas()
函数,并添加到 QuadTree
类中:
def merge_safe_areas(self, distance_threshold=2.0):
merged = []
used = set()
keys = list(self.convex_hulls.keys())
for i in range(len(keys)):
id1 = keys[i]
if id1 in used: continue
hull1 = self.convex_hulls[id1]
points1 = hull1.points[hull1.vertices]
for j in range(i+1, len(keys)):
id2 = keys[j]
if id2 in used: continue
hull2 = self.convex_hulls[id2]
points2 = hull2.points[hull2.vertices]
# 判断是否可合并(如边界相近、联合后仍凸)
if can_merge(points1, points2, distance_threshold):
combined = np.vstack((points1, points2))
new_hull = ConvexHull(combined)
merged.append(new_hull)
used.update([id1, id2])
break
self.convex_hulls = {f"merged_{i}": hull for i, hull in enumerate(merged)}
其中 can_merge()
可以使用 shapely.Polygon
判断是否相交或几何接近。
合并后需要更新的结构
为了保证合并后的区域能继续用于路径规划和轨迹控制,我们需要更新:
self.convex_hulls
:替换为合并后的 hullsself.leaf_nodes
:如果需要,也可以合并为虚拟节点self.connectivity_graph
:调用update_connectivity_after_change()
重建连接图
效果对比
以实验数据为例,合并前后 Safe Area 数量变化如下:
状态 | Safe Areas 数量 | 平均面积 | 控制器规划时间 |
---|---|---|---|
合并前 | 62 | 1.2㎡ | 38ms |
合并后 | 18 | 3.8㎡ | 23ms |
合并显著减少了冗余节点,提高了路径简洁度和控制效率。
总结
通过对 QuadTree 生成的多个 Safe Area 进行基于邻接性和凸性判断的合并,我们可以极大简化路径图结构,提高后续路径搜索和 MPC 控制器的执行效率。
关键模块涉及:
connective_quadtree.py
:ConvexHull 构建与管理utils_geo.py
:多边形几何工具函数visualize_quadtree_process.py
:合并前后对比可视化
下一篇将介绍:如何构建连通性图并叠加动态障碍物生成避障路径规划图结构。