大模型微调实践——Prefix tuning与P-tuning v2的原理、区别与代码解析最终章
大模型微调实践——Prefix tuning与P-tuning v2的原理、区别与代码解析最终章
·
路径规划算法全解析:从原理到代码实现
路径规划的世界
想象一下你在一个陌生城市里使用手机导航,或者看着机器人自动避开障碍物到达目的地,这些场景背后都离不开路径规划算法的支持。今天我们就来深入探讨几种经典的路径规划算法,包括Dijkstra、A和RRT,看看它们是如何工作的,以及如何在代码中实现它们。
路径规划算法可以分为两大类:基于图搜索的算法(如Dijkstra和A)和基于采样的算法(如RRT)。每种算法都有其适用场景和优缺点,了解它们的特点能帮助我们在不同情况下做出合适的选择。
Dijkstra算法:最可靠的老兵
Dijkstra算法是路径规划领域的老兵,由荷兰计算机科学家EdsgerW.Dijkstra在1956年提出。它的核心思想其实很简单:从起点开始,逐步探索周围的节点,每次都选择当前已知的最短路径进行扩展,直到到达目标点。
算法原理详解
1.初始化:将起点放入"待访问"集合,距离设为0,其他所有点距离设为无穷大
2.主循环:
-从"待访问"集合中取出距离最小的节点(当前节点)
-对当前节点的每个邻居:
-计算通过当前节点到达该邻居的新距离
-如果新距离比之前记录的距离小,则更新距离,并将该邻居加入"待访问"集合
3.终止条件:当目标节点被标记为"已访问"时,算法结束
Dijkstra算法之所以能保证找到最短路径,是因为它采用了贪心策略,每次都选择当前最优的路径进行扩展。这种策略确保了当算法首次访问某个节点时,所找到的路径就是到该节点的最短路径。
实际应用案例
Dijkstra算法在计算机网络路由中有着广泛应用。比如当你发送一个网络请求时,路由器需要决定数据包应该走哪条路径才能最快到达目的地。由于网络拓扑可以表示为一个图,Dijkstra算法就能计算出最优路径。
另一个例子是城市交通导航系统。在不太拥堵的情况下,Dijkstra算法可以帮助找到两点之间距离最短的路线。
Python实现与可视化
下面我们用Python实现一个简单的Dijkstra算法,并用matplotlib进行可视化:
```python
importheapq
importmatplotlib.pyplotasplt
importnumpyasnp
defdijkstra(graph,start,end):
初始化距离字典和前驱节点字典
distances={vertex:float('infinity')forvertexingraph}
distances[start]=0
previous_nodes={vertex:Noneforvertexingraph}
使用优先队列
priority_queue=[(0,start)]
whilepriority_queue:
current_distance,current_vertex=heapq.heappop(priority_queue)
如果已经找到更短路径,跳过
ifcurrent_distance>distances[current_vertex]:
continue
forneighbor,weightingraph[current_vertex].items():
distance=current_distance+weight
找到更短路径
ifdistance distances[neighbor]=distance
previous_nodes[neighbor]=current_vertex
heapq.heappush(priority_queue,(distance,neighbor))
重构路径
path=[]
current_vertex=end
whileprevious_nodes[current_vertex]isnotNone:
path.insert(0,current_vertex)
current_vertex=previous_nodes[current_vertex]
ifpath:
path.insert(0,start)
returnpath,distances[end]
示例图
graph={
'A':{'B':6,'D':1},
'B':{'A':6,'D':2,'E':2,'C':5},
'C':{'B':5,'E':5},
'D':{'A':1,'B':2,'E':1},
'E':{'D':1,'B':2,'C':5}
}
计算路径
path,distance=dijkstra(graph,'A','C')
print(f"最短路径:{path},距离:{distance}")
可视化
pos={
'A':(0,0),
'B':(2,2),
'C':(4,0),
'D':(1,1),
'E':(3,1)
}
plt.figure(figsize=(8,6))
绘制边
forvertexingraph:
forneighbor,weightingraph[vertex].items():
plt.plot([pos[vertex][0],pos[neighbor][0]],
[pos[vertex][1],pos[neighbor][1]],
'k-',alpha=0.3,linewidth=weight2)
绘制最短路径
foriinrange(len(path)-1):
plt.plot([pos[path[i]][0],pos[path[i+1]][0]],
[pos[path[i]][1],pos[path[i+1]][1]],
'r-',linewidth=3)
绘制节点
forvertex,(x,y)inpos.items():
plt.plot(x,y,'bo')
plt.text(x,y+0.1,vertex,fontsize=12,ha='center')
plt.title("Dijkstra算法路径规划示例")
plt.axis('equal')
plt.show()
```
这段代码首先定义了一个简单的图结构,然后使用Dijkstra算法计算从A到C的最短路径。可视化部分展示了整个图的结构,并用红色高亮显示找到的最短路径。
A算法:更聪明的搜索者
A算法可以看作是Dijkstra算法的升级版,它在搜索过程中加入了启发式函数,能够更高效地找到最优路径。A算法由PeterHart、NilsNilsson和BertramRaphael在1968年提出。
算法原理与启发式函数
A算法的核心在于它的评估函数:f(n)=g(n)+h(n)
-g(n):从起点到节点n的实际距离
-h(n):从节点n到目标点的估计距离(启发式函数)
启发式函数h(n)的选择对算法性能有很大影响。常用的启发式函数有:
1.曼哈顿距离:适用于只能上下左右移动的网格地图
2.欧几里得距离:适用于可以任意方向移动的连续空间
3.对角线距离:结合了曼哈顿和欧几里得距离的特点
启发式函数必须满足可采纳性(admissible)条件,即它不能高估实际距离,这样才能保证A算法找到最优路径。
实际应用案例
A算法在游戏开发中应用广泛。比如在策略游戏中,单位需要从A点移动到B点,同时避开障碍物。A算法能够高效计算出最优路径。
另一个例子是机器人导航系统。工业机器人在仓库中移动时,需要规划出到达目标位置的最优路径,同时避开货架和其他障碍物。
Python实现与可视化
```python
importheapq
importmath
importmatplotlib.pyplotasplt
defheuristic(a,b):
欧几里得距离作为启发式函数
returnmath.sqrt((a[0]-b[0])2+(a[1]-b[1])2)
defa_star(graph,start,end):
初始化
open_set=[]
heapq.heappush(open_set,(0,start))
came_from={}
g_score={node:float('inf')fornodeingraph}
g_score[start]=0
f_score={node:float('inf')fornodeingraph}
f_score[start]=heuristic(start,end)
whileopen_set:
current=heapq.heappop(open_set)[1]
ifcurrent==end:
重构路径
path=[]
whilecurrentincame_from:
path.append(current)
current=came_from[current]
path.append(start)
path.reverse()
returnpath
forneighbor,weightingraph[current].items():
tentative_g_score=g_score[current]+weight
iftentative_g_score came_from[neighbor]=current
g_score[neighbor]=tentative_g_score
f_score[neighbor]=g_score[neighbor]+heuristic(neighbor,end)
heapq.heappush(open_set,(f_score[neighbor],neighbor))
return[]没有找到路径
示例图(使用坐标作为节点)
graph={
(0,0):{(1,1):1.41,(1,0):1},
(1,0):{(0,0):1,(2,0):1,(1,1):1},
(1,1):{(0,0):1.41,(1,0):1,(2,2):1.41},
(2,0):{(1,0):1,(3,0):1},
(2,2):{(1,1):1.41,(3,3):1.41},
(3,0):{(2,0):1,(3,1):1},
(3,1):{(3,0):1,(3,2):1},
(3,2):{(3,1):1,(3,3):1},
(3,3):{(2,2):1.41,(3,2):1}
}
start=(0,0)
end=(3,3)
path=a_star(graph,start,end)
print("A算法找到的路径:",path)
可视化
plt.figure(figsize=(8,8))
绘制边
fornodeingraph:
forneighbor,weightingraph[node].items():
plt.plot([node[0],neighbor[0]],[node[1],neighbor[1]],'k-',alpha=0.3,linewidth=2)
绘制路径
foriinrange(len(path)-1):
plt.plot([path[i][0],path[i+1][0]],[path[i][1],path[i+1][1]],'r-',linewidth=3)
绘制节点
fornodeingraph:
plt.plot(node[0],node[1],'bo')
plt.text(node[0],node[1]+0.1,str(node),fontsize=10,ha='center')
plt.plot(start[0],start[1],'go',markersize=12,label='起点')
plt.plot(end[0],end[1],'yo',markersize=12,label='终点')
plt.title("A算法路径规划示例")
plt.legend()
plt.axis('equal')
plt.show()
```
这个实现中,我们使用坐标作为节点,欧几里得距离作为启发式函数。可视化展示了A算法如何在网格中找到从起点到终点的最优路径。
RRT算法:处理复杂环境的利器
快速扩展随机树(Rapidly-exploringRandomTree,RRT)算法是一种基于采样的路径规划算法,特别适合高维空间和复杂环境中的路径规划问题。
算法原理与特点
RRT算法的基本思想是通过随机采样扩展一棵树,直到树扩展到目标区域。具体步骤如下:
1.初始化树,只包含起点
2.随机采样一个点
3.找到树上离采样点最近的节点
4.从最近节点向采样点方向扩展一小步,得到新节点
5.如果新节点与障碍物无碰撞,则将其加入树
6.重复上述过程,直到树扩展到目标区域
RRT算法的优点在于:
-能够高效探索高维空间
-不依赖于环境的全局信息
-适用于动态环境
缺点是:
-找到的路径通常不是最优的
-路径可能不够平滑
实际应用案例
RRT算法在自动驾驶领域有广泛应用。自动驾驶汽车需要在复杂的城市环境中规划路径,RRT算法能够快速找到可行的行驶路线。
另一个例子是机械臂运动规划。在狭窄的空间中,机械臂需要规划出无碰撞的运动轨迹,RRT算法能够有效解决这类问题。
Python实现与可视化
```python
importnumpyasnp
importmatplotlib.pyplotasplt
frommatplotlib.patchesimportRectangle
classRRT:
def__init__(self,start,goal,bounds,obstacles,step_size=0.5,max_iter=1000):
self.start=np.array(start)
self.goal=np.array(goal)
self.bounds=bounds[(xmin,xmax),(ymin,ymax)]
self.step_size=step_size
self.max_iter=max_iter
self.obstacles=obstacles每个障碍物表示为(x,y,width,height)
self.tree={tuple(start):None}键:节点,值:父节点
defsample(self):
以一定概率采样目标点,加速收敛
ifnp.random.random()<0.1:
returntuple(self.goal)
x=np.random.uniform(self.bounds[0][0],self.bounds[0][1])
y=np.random.uniform(self.bounds[1][0],self.bounds[1][1])
return(x,y)
defnearest(self,point):
找到树上离point最近的节点
points=np.array(list(self.tree.keys()))
dists=np.linalg.norm(points-np.array(point),axis=1)
nearest_idx=np.argmin(dists)
returntuple(points[nearest_idx])
defsteer(self,from_point,to_point):
从from_point向to_point方向扩展一步
direction=np.array(to_point)-np.array(from_point)
distance=np.linalg.norm(direction)
ifdistance returnto_point
direction=direction/distance
new_point=np.array(from_point)+directionself.step_size
returntuple(new_point)
defcollision_free(self,point1,point2):
检查两点之间的线段是否与障碍物碰撞
forobsinself.obstacles:
ox,oy,ow,oh=obs
简单的矩形碰撞检测
if(ox (ox returnFalse
returnTrue
defbuild_tree(self):
for_inrange(self.max_iter):
sample=self.sample()
nearest=self.nearest(sample)
new_point=self.steer(nearest,sample)
ifself.collision_free(nearest,new_point):
self.tree[new_point]=nearest
检查是否到达目标附近
ifnp.linalg.norm(np.array(new_point)-self.goal) self.tree[tuple(self.goal)]=new_point
returnTrue
returnFalse
defget_path(self):
path=[]
current=tuple(self.goal)
whilecurrentisnotNone:
path.append(current)
current=self.tree.get(current)
path.reverse()
returnpathifpath[0]==tuple(self.start)else[]
defplot(self,path=None):
plt.figure(figsize=(10,8))
绘制边界
plt.xlim(self.bounds[0][0]-1,self.bounds[0][1]+1)
plt.ylim(self.bounds[1][0]-1,self.bounds[1][1]+1)
绘制障碍物
forobsinself.obstacles:
plt.gca().add_patch(Rectangle((obs[0],obs[1]),obs[2],obs[3],
fc='gray',ec='k'))
绘制树
fornode,parentinself.tree.items():
ifparentisnotNone:
plt.plot([node[0],parent[0]],[node[1],parent[1]],'b-',alpha=0.3)
绘制起点和目标点
plt.plot(self.start[0],self.start[1],'go',markersize=10,label='起点')
plt.plot(self.goal[0],self.goal[1],'ro',markersize=10,label='目标点')
绘制路径
ifpath:
plt.plot([p[0]forpinpath],[p[1]forpinpath],'r-',linewidth=2,label='路径')
plt.title("RRT路径规划")
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.show()
示例使用
bounds=[(0,10),(0,10)]边界
obstacles=[(2,2,3,2),(5,5,2,3),(7,1,2,4)]障碍物
start=(1,1)
goal=(9,9)
rrt=RRT(start,goal,bounds,obstacles)
ifrrt.build_tree():
path=rrt.get_path()
print("找到路径,节点数:",len(path))
rrt.plot(path)
else:
print("未找到路径")
rrt.plot()
```
这个RRT实现创建了一个包含障碍物的环境,然后通过随机采样扩展树结构,直到找到从起点到目标的路径。可视化展示了树的扩展过程和最终找到的路径。
算法比较与选择指南
现在我们已经了解了三种主要的路径规划算法,让我们来比较一下它们的特性:
|特性|Dijkstra|A|RRT|
|------|----------|----|-----|
|完备性|是|是|概率完备|
|最优性|最优|最优(启发式可采纳)|非最优|
|适用空间|离散|离散|连续/高维|
|计算效率|中等|高|高|
|内存需求|高|中等|低|
|适用场景|
路径规划的世界
想象一下你在一个陌生城市里使用手机导航,或者看着机器人自动避开障碍物到达目的地,这些场景背后都离不开路径规划算法的支持。今天我们就来深入探讨几种经典的路径规划算法,包括Dijkstra、A和RRT,看看它们是如何工作的,以及如何在代码中实现它们。
路径规划算法可以分为两大类:基于图搜索的算法(如Dijkstra和A)和基于采样的算法(如RRT)。每种算法都有其适用场景和优缺点,了解它们的特点能帮助我们在不同情况下做出合适的选择。
Dijkstra算法:最可靠的老兵
Dijkstra算法是路径规划领域的老兵,由荷兰计算机科学家EdsgerW.Dijkstra在1956年提出。它的核心思想其实很简单:从起点开始,逐步探索周围的节点,每次都选择当前已知的最短路径进行扩展,直到到达目标点。
算法原理详解
1.初始化:将起点放入"待访问"集合,距离设为0,其他所有点距离设为无穷大
2.主循环:
-从"待访问"集合中取出距离最小的节点(当前节点)
-对当前节点的每个邻居:
-计算通过当前节点到达该邻居的新距离
-如果新距离比之前记录的距离小,则更新距离,并将该邻居加入"待访问"集合
3.终止条件:当目标节点被标记为"已访问"时,算法结束
Dijkstra算法之所以能保证找到最短路径,是因为它采用了贪心策略,每次都选择当前最优的路径进行扩展。这种策略确保了当算法首次访问某个节点时,所找到的路径就是到该节点的最短路径。
实际应用案例
Dijkstra算法在计算机网络路由中有着广泛应用。比如当你发送一个网络请求时,路由器需要决定数据包应该走哪条路径才能最快到达目的地。由于网络拓扑可以表示为一个图,Dijkstra算法就能计算出最优路径。
另一个例子是城市交通导航系统。在不太拥堵的情况下,Dijkstra算法可以帮助找到两点之间距离最短的路线。
Python实现与可视化
下面我们用Python实现一个简单的Dijkstra算法,并用matplotlib进行可视化:
```python
importheapq
importmatplotlib.pyplotasplt
importnumpyasnp
defdijkstra(graph,start,end):
初始化距离字典和前驱节点字典
distances={vertex:float('infinity')forvertexingraph}
distances[start]=0
previous_nodes={vertex:Noneforvertexingraph}
使用优先队列
priority_queue=[(0,start)]
whilepriority_queue:
current_distance,current_vertex=heapq.heappop(priority_queue)
如果已经找到更短路径,跳过
ifcurrent_distance>distances[current_vertex]:
continue
forneighbor,weightingraph[current_vertex].items():
distance=current_distance+weight
找到更短路径
ifdistance distances[neighbor]=distance
previous_nodes[neighbor]=current_vertex
heapq.heappush(priority_queue,(distance,neighbor))
重构路径
path=[]
current_vertex=end
whileprevious_nodes[current_vertex]isnotNone:
path.insert(0,current_vertex)
current_vertex=previous_nodes[current_vertex]
ifpath:
path.insert(0,start)
returnpath,distances[end]
示例图
graph={
'A':{'B':6,'D':1},
'B':{'A':6,'D':2,'E':2,'C':5},
'C':{'B':5,'E':5},
'D':{'A':1,'B':2,'E':1},
'E':{'D':1,'B':2,'C':5}
}
计算路径
path,distance=dijkstra(graph,'A','C')
print(f"最短路径:{path},距离:{distance}")
可视化
pos={
'A':(0,0),
'B':(2,2),
'C':(4,0),
'D':(1,1),
'E':(3,1)
}
plt.figure(figsize=(8,6))
绘制边
forvertexingraph:
forneighbor,weightingraph[vertex].items():
plt.plot([pos[vertex][0],pos[neighbor][0]],
[pos[vertex][1],pos[neighbor][1]],
'k-',alpha=0.3,linewidth=weight2)
绘制最短路径
foriinrange(len(path)-1):
plt.plot([pos[path[i]][0],pos[path[i+1]][0]],
[pos[path[i]][1],pos[path[i+1]][1]],
'r-',linewidth=3)
绘制节点
forvertex,(x,y)inpos.items():
plt.plot(x,y,'bo')
plt.text(x,y+0.1,vertex,fontsize=12,ha='center')
plt.title("Dijkstra算法路径规划示例")
plt.axis('equal')
plt.show()
```
这段代码首先定义了一个简单的图结构,然后使用Dijkstra算法计算从A到C的最短路径。可视化部分展示了整个图的结构,并用红色高亮显示找到的最短路径。
A算法:更聪明的搜索者
A算法可以看作是Dijkstra算法的升级版,它在搜索过程中加入了启发式函数,能够更高效地找到最优路径。A算法由PeterHart、NilsNilsson和BertramRaphael在1968年提出。
算法原理与启发式函数
A算法的核心在于它的评估函数:f(n)=g(n)+h(n)
-g(n):从起点到节点n的实际距离
-h(n):从节点n到目标点的估计距离(启发式函数)
启发式函数h(n)的选择对算法性能有很大影响。常用的启发式函数有:
1.曼哈顿距离:适用于只能上下左右移动的网格地图
2.欧几里得距离:适用于可以任意方向移动的连续空间
3.对角线距离:结合了曼哈顿和欧几里得距离的特点
启发式函数必须满足可采纳性(admissible)条件,即它不能高估实际距离,这样才能保证A算法找到最优路径。
实际应用案例
A算法在游戏开发中应用广泛。比如在策略游戏中,单位需要从A点移动到B点,同时避开障碍物。A算法能够高效计算出最优路径。
另一个例子是机器人导航系统。工业机器人在仓库中移动时,需要规划出到达目标位置的最优路径,同时避开货架和其他障碍物。
Python实现与可视化
```python
importheapq
importmath
importmatplotlib.pyplotasplt
defheuristic(a,b):
欧几里得距离作为启发式函数
returnmath.sqrt((a[0]-b[0])2+(a[1]-b[1])2)
defa_star(graph,start,end):
初始化
open_set=[]
heapq.heappush(open_set,(0,start))
came_from={}
g_score={node:float('inf')fornodeingraph}
g_score[start]=0
f_score={node:float('inf')fornodeingraph}
f_score[start]=heuristic(start,end)
whileopen_set:
current=heapq.heappop(open_set)[1]
ifcurrent==end:
重构路径
path=[]
whilecurrentincame_from:
path.append(current)
current=came_from[current]
path.append(start)
path.reverse()
returnpath
forneighbor,weightingraph[current].items():
tentative_g_score=g_score[current]+weight
iftentative_g_score came_from[neighbor]=current
g_score[neighbor]=tentative_g_score
f_score[neighbor]=g_score[neighbor]+heuristic(neighbor,end)
heapq.heappush(open_set,(f_score[neighbor],neighbor))
return[]没有找到路径
示例图(使用坐标作为节点)
graph={
(0,0):{(1,1):1.41,(1,0):1},
(1,0):{(0,0):1,(2,0):1,(1,1):1},
(1,1):{(0,0):1.41,(1,0):1,(2,2):1.41},
(2,0):{(1,0):1,(3,0):1},
(2,2):{(1,1):1.41,(3,3):1.41},
(3,0):{(2,0):1,(3,1):1},
(3,1):{(3,0):1,(3,2):1},
(3,2):{(3,1):1,(3,3):1},
(3,3):{(2,2):1.41,(3,2):1}
}
start=(0,0)
end=(3,3)
path=a_star(graph,start,end)
print("A算法找到的路径:",path)
可视化
plt.figure(figsize=(8,8))
绘制边
fornodeingraph:
forneighbor,weightingraph[node].items():
plt.plot([node[0],neighbor[0]],[node[1],neighbor[1]],'k-',alpha=0.3,linewidth=2)
绘制路径
foriinrange(len(path)-1):
plt.plot([path[i][0],path[i+1][0]],[path[i][1],path[i+1][1]],'r-',linewidth=3)
绘制节点
fornodeingraph:
plt.plot(node[0],node[1],'bo')
plt.text(node[0],node[1]+0.1,str(node),fontsize=10,ha='center')
plt.plot(start[0],start[1],'go',markersize=12,label='起点')
plt.plot(end[0],end[1],'yo',markersize=12,label='终点')
plt.title("A算法路径规划示例")
plt.legend()
plt.axis('equal')
plt.show()
```
这个实现中,我们使用坐标作为节点,欧几里得距离作为启发式函数。可视化展示了A算法如何在网格中找到从起点到终点的最优路径。
RRT算法:处理复杂环境的利器
快速扩展随机树(Rapidly-exploringRandomTree,RRT)算法是一种基于采样的路径规划算法,特别适合高维空间和复杂环境中的路径规划问题。
算法原理与特点
RRT算法的基本思想是通过随机采样扩展一棵树,直到树扩展到目标区域。具体步骤如下:
1.初始化树,只包含起点
2.随机采样一个点
3.找到树上离采样点最近的节点
4.从最近节点向采样点方向扩展一小步,得到新节点
5.如果新节点与障碍物无碰撞,则将其加入树
6.重复上述过程,直到树扩展到目标区域
RRT算法的优点在于:
-能够高效探索高维空间
-不依赖于环境的全局信息
-适用于动态环境
缺点是:
-找到的路径通常不是最优的
-路径可能不够平滑
实际应用案例
RRT算法在自动驾驶领域有广泛应用。自动驾驶汽车需要在复杂的城市环境中规划路径,RRT算法能够快速找到可行的行驶路线。
另一个例子是机械臂运动规划。在狭窄的空间中,机械臂需要规划出无碰撞的运动轨迹,RRT算法能够有效解决这类问题。
Python实现与可视化
```python
importnumpyasnp
importmatplotlib.pyplotasplt
frommatplotlib.patchesimportRectangle
classRRT:
def__init__(self,start,goal,bounds,obstacles,step_size=0.5,max_iter=1000):
self.start=np.array(start)
self.goal=np.array(goal)
self.bounds=bounds[(xmin,xmax),(ymin,ymax)]
self.step_size=step_size
self.max_iter=max_iter
self.obstacles=obstacles每个障碍物表示为(x,y,width,height)
self.tree={tuple(start):None}键:节点,值:父节点
defsample(self):
以一定概率采样目标点,加速收敛
ifnp.random.random()<0.1:
returntuple(self.goal)
x=np.random.uniform(self.bounds[0][0],self.bounds[0][1])
y=np.random.uniform(self.bounds[1][0],self.bounds[1][1])
return(x,y)
defnearest(self,point):
找到树上离point最近的节点
points=np.array(list(self.tree.keys()))
dists=np.linalg.norm(points-np.array(point),axis=1)
nearest_idx=np.argmin(dists)
returntuple(points[nearest_idx])
defsteer(self,from_point,to_point):
从from_point向to_point方向扩展一步
direction=np.array(to_point)-np.array(from_point)
distance=np.linalg.norm(direction)
ifdistance returnto_point
direction=direction/distance
new_point=np.array(from_point)+directionself.step_size
returntuple(new_point)
defcollision_free(self,point1,point2):
检查两点之间的线段是否与障碍物碰撞
forobsinself.obstacles:
ox,oy,ow,oh=obs
简单的矩形碰撞检测
if(ox (ox returnFalse
returnTrue
defbuild_tree(self):
for_inrange(self.max_iter):
sample=self.sample()
nearest=self.nearest(sample)
new_point=self.steer(nearest,sample)
ifself.collision_free(nearest,new_point):
self.tree[new_point]=nearest
检查是否到达目标附近
ifnp.linalg.norm(np.array(new_point)-self.goal) self.tree[tuple(self.goal)]=new_point
returnTrue
returnFalse
defget_path(self):
path=[]
current=tuple(self.goal)
whilecurrentisnotNone:
path.append(current)
current=self.tree.get(current)
path.reverse()
returnpathifpath[0]==tuple(self.start)else[]
defplot(self,path=None):
plt.figure(figsize=(10,8))
绘制边界
plt.xlim(self.bounds[0][0]-1,self.bounds[0][1]+1)
plt.ylim(self.bounds[1][0]-1,self.bounds[1][1]+1)
绘制障碍物
forobsinself.obstacles:
plt.gca().add_patch(Rectangle((obs[0],obs[1]),obs[2],obs[3],
fc='gray',ec='k'))
绘制树
fornode,parentinself.tree.items():
ifparentisnotNone:
plt.plot([node[0],parent[0]],[node[1],parent[1]],'b-',alpha=0.3)
绘制起点和目标点
plt.plot(self.start[0],self.start[1],'go',markersize=10,label='起点')
plt.plot(self.goal[0],self.goal[1],'ro',markersize=10,label='目标点')
绘制路径
ifpath:
plt.plot([p[0]forpinpath],[p[1]forpinpath],'r-',linewidth=2,label='路径')
plt.title("RRT路径规划")
plt.legend()
plt.grid(True)
plt.axis('equal')
plt.show()
示例使用
bounds=[(0,10),(0,10)]边界
obstacles=[(2,2,3,2),(5,5,2,3),(7,1,2,4)]障碍物
start=(1,1)
goal=(9,9)
rrt=RRT(start,goal,bounds,obstacles)
ifrrt.build_tree():
path=rrt.get_path()
print("找到路径,节点数:",len(path))
rrt.plot(path)
else:
print("未找到路径")
rrt.plot()
```
这个RRT实现创建了一个包含障碍物的环境,然后通过随机采样扩展树结构,直到找到从起点到目标的路径。可视化展示了树的扩展过程和最终找到的路径。
算法比较与选择指南
现在我们已经了解了三种主要的路径规划算法,让我们来比较一下它们的特性:
|特性|Dijkstra|A|RRT|
|------|----------|----|-----|
|完备性|是|是|概率完备|
|最优性|最优|最优(启发式可采纳)|非最优|
|适用空间|离散|离散|连续/高维|
|计算效率|中等|高|高|
|内存需求|高|中等|低|
|适用场景|
更多推荐
所有评论(0)