当前位置:   article > 正文

Python实现动态窗口避障及路径规划_动态避障 python

动态避障 python

 实现效果

 

实现原理

定义速度空间

速度空间是在下一个时间间隔之内,根据船的实际情况:比如加速度、当前速度等等定义,就是船在下一个时间间隔之内所有可能的速度和加速度的集合,理解起来就是一个二维的矩阵。比如说当前速度为1m/s,偏航角为60°,假设船的最大加速度为0.1m/s^2,最大角加速度为5°/s,时间间隔为0.1s,船的最大允许速度为2m/s,那么当前状态的速度空间中,速度取值为0.9m/s~1.1m/s,偏航角取值为55°~65°。

定义成本函数

因为对于速度空间中的每一个速度与角速度,在一定的时间内都能跑出一条轨迹,成本函数的作用就是筛选出这些轨迹中的最优值。成本函数的定义可以多种多样,在代码中主要考虑的是到达目标点的成本,加速能耗成本和避障成本。对于某一条轨迹,肯定对应着许多个位置,因为我们会预估许多个时间间隔,这些位置距离要航行的终点的距离的一个平均水平肯定是越小越好,因为每走一步我们肯定是希望越来越靠近终点,那么可以根据这个给成本函数中的目标成本赋值一定的权重,如果想要更快到达目标点,这个权重可以给到很大,这样船就能更快到达目标点。同样对于加速能耗成本来说,速度越快,能耗肯定越大;避碰成本也一样,我们肯定希望船航行过程中离障碍点越远越好,在代码中直接用一个幂函数来定义成本函数项。

运动模型

运动模型肯定得根据电机模型来确定,但是这里只是仿真说明,所以尽可能采用平均值的方法定义运动。船下一个时刻的位置和偏航角的定义如下:

代码

  1. import time
  2. import math
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. #定义状态类,用于存储船体航行过程中每一个时刻的状态----------
  6. #time:状态对应的时刻,方便与ROS耦合
  7. #x、y:船体的坐标
  8. #velocity:速度
  9. #yaw:偏航角,仿真只在二维空间,所以只定义一个角
  10. #yawrate:角速度
  11. #dyawrate:角加速度,代码中没有用到,在这里定义只是方便更加靠近真实的船
  12. #cost:每走一步对应的成本
  13. #--------------------------------------------------------
  14. class state(object):
  15. def __init__(self,time,x,y,velocity,yaw,yawrate,dyawrate,cost):
  16. self.time=time
  17. self.x=x
  18. self.y=y
  19. self.velocity=velocity
  20. self.yaw=yaw
  21. self.yawrate=yawrate
  22. self.dyawrate=dyawrate
  23. self.cost=cost
  24. #定义航行过程中存储船所有状态和利用船的状态进行DWM的类-------
  25. #ship:列表,列表的元素是上面定义的state类,用于存储航行过程中的所有时刻的状态
  26. #obstacle:列表,元素是障碍点的坐标,这里的障碍点可以是建图完成之后再传入,或者通过传感器探测实时更新
  27. #obstacle_windows:本意是定义一个船探测障碍物的探测半径,避障只需要考虑船能探测到的范围内进行就可以,本例中没有用到
  28. #dt~saferadius:船的固有参数,比如maxvelocity是船能达到的最大速度。
  29. class ship(object):
  30. def __init__(self):
  31. self.ship=[]
  32. self.obstacle=np.array([[0,0]])
  33. self.obstacle_windows=np.array([[0,0]])
  34. self.dt=0.1
  35. self.maxvelocity=1.4
  36. self.minvelocity=0
  37. self.maxlinearacc=0.2
  38. self.maxdyawrate=40*math.pi/180
  39. self.velocityres=0.01
  40. self.yawrateres=0.5*math.pi/180
  41. self.predicttime=3
  42. self.to_goal_coeff=1.0
  43. self.velocity_coeff=1.0
  44. self.saferadius=0.5
  45. self.goal=np.array([0,0])
  46. self.arrive=False
  47. #初始化函数----------------------------
  48. def initialState(self,state):
  49. self.ship.append(state)
  50. def initialobstacle(self,obstacle):
  51. self.obstacle=obstacle.assemble
  52. def initialgoal(self,goal):
  53. self.goal=goal
  54. #------------------------------------
  55. #运动函数,根据上面说的运动公式---------
  56. def motion(self,velocity,yawrate):
  57. temp_state = state(self.ship[-1].time + self.dt,
  58. self.ship[-1].x + motion_velocity * math.cos(self.ship[-1].yaw) * self.dt,
  59. self.ship[-1].y + motion_velocity * math.sin(self.ship[-1].yaw) * self.dt,
  60. velocity,
  61. self.ship[-1].yaw+yawrate*self.dt,
  62. yawrate,
  63. (yawrate - self.ship[-1].yawrate) / self.dt,
  64. 0)
  65. self.ship.append(temp_state)
  66. return temp_state
  67. #------------------------------------
  68. #动态窗口定义-------------------------
  69. def motion_windows(self):
  70. current_velocity=self.ship[-1].velocity
  71. current_yawrate=self.ship[-1].yawrate
  72. maxvelocity=np.min([self.maxvelocity,current_velocity+self.maxlinearacc*self.dt])
  73. minvelocity=np.max([self.minvelocity,current_velocity-self.maxlinearacc*self.dt])
  74. maxyawrate=current_yawrate+self.maxdyawrate*self.dt
  75. minyawrate=current_yawrate-self.maxdyawrate*self.dt
  76. return np.array([minvelocity,maxvelocity,minyawrate,maxyawrate])
  77. #------------------------------------
  78. #三项成本函数的定义-------------------
  79. def cost_goal(self,locus):
  80. return distance(np.array([locus[-1].x,locus[-1].y]),self.goal)*self.to_goal_coeff
  81. def cost_velocity(self,locus):
  82. return (self.maxvelocity-locus[-1].velocity)*self.velocity_coeff
  83. def cost_obstacle(self,locus):
  84. dis=[]
  85. for i in locus:
  86. for ii in self.obstacle:
  87. dis.append(distance(np.array([i.x,i.y]),ii))
  88. dis_np=np.array(dis)
  89. return 1.0/np.min(dis_np)
  90. def cost_total(self,locus):
  91. return self.cost_goal(locus)+self.cost_velocity(locus)+self.cost_obstacle(locus)
  92. #-----------------------------------
  93. #遍历动态窗口内所有轨迹,调用成本函数计算成本并且择优计算最优速度与加速度----
  94. def search_for_best_uv(self):
  95. windows=self.motion_windows()
  96. best_uv=np.array([0,0])
  97. currentcost=np.inf
  98. # initship=copy.deepcopy(self.ship)
  99. initship = self.ship[:]
  100. best_locus=[]
  101. for i in np.arange(windows[0],windows[1],self.velocityres):
  102. # beginw=time.time()
  103. for ii in np.arange(windows[2],windows[3],self.yawrateres):
  104. locus=[]
  105. # for t in np.arange(0,self.predicttime,self.dt):
  106. # locus.append(self.motion(i,ii))
  107. t=0
  108. while(t<=self.predicttime):
  109. locus.append(self.motion(i, ii))
  110. t=t+self.dt
  111. newcost=self.cost_total(locus)
  112. if currentcost>newcost:
  113. currentcost=newcost
  114. best_uv=[i,ii]
  115. # best_locus=copy.deepcopy(locus)
  116. best_locus=locus[:]
  117. self.ship=initship[:]
  118. self.ship=initship[:]
  119. self.ship=initship[:]
  120. self.show_animation(best_locus)
  121. return best_uv,currentcost
  122. #-----------------------------------------------------------------
  123. #用matplotlib画图,一帧一帧图像交替,展示动态效果--------------------
  124. def show_animation(self,locus):
  125. plt.cla()
  126. plt.scatter(self.obstacle[:,0],self.obstacle[:,1],s=5)
  127. plt.plot(self.goal[0],self.goal[1],"ro")
  128. x=[]
  129. y=[]
  130. for i in locus:
  131. x.append(i.x)
  132. y.append(i.y)
  133. plt.plot(x,y,"g-")
  134. plt.plot(self.ship[-1].x,self.ship[-1].y,"ro")
  135. plt.arrow(self.ship[-1].x,self.ship[-1].y,2*math.cos(self.ship[-1].yaw),2*math.sin(self.ship[-1].yaw),head_length=1.5 * 0.1*6, head_width=0.1*4)
  136. plt.grid(True)
  137. plt.xlim([-10,self.goal[0]*1.3])
  138. plt.ylim([-10,self.goal[1]*1.3])
  139. plt.pause(0.0001)
  140. #-------------------------------------------------------------------
  141. #安全检测,判断船离障碍物是不是撞上了,目前还没有想到什么比较好的重启小船的函数,只能让小船休眠
  142. def safedetect(self):
  143. positionx=self.ship[-1].x
  144. positiony=self.ship[-1].y
  145. position=np.array([positionx,positiony])
  146. for i in self.obstacle:
  147. if distance(position,i)<=self.saferadius:
  148. print("撞上了!")
  149. time.sleep(100000)
  150. #--------------------------------------------------------------------
  151. #障碍物类,实现障碍物随机运动,本来想生成随机数目坐标随机的障碍物,但是想想还是算了---
  152. class obstacle(object):
  153. def __init__(self):
  154. self.assemble=3*np.array([
  155. [-1, -1],
  156. [0, 2],
  157. [4.0, 2.0],
  158. [4.0, 1.0],
  159. [5.0, 4.0],
  160. [2.5, 4.0],
  161. [5.0, 5.0],
  162. [5.0, 2.5],
  163. [5.0, 6.0],
  164. [5.0, 9.0],
  165. [6.0,6.0],
  166. [7.0,6.0],
  167. [10.0,8.0],
  168. [10.0, 4.0],
  169. [8.0, 9.0],
  170. [7.0, 9.0],
  171. [12.0, 12.0]
  172. ])
  173. self.locus=np.vstack(([self.assemble],))
  174. def update(self):
  175. for i in self.assemble:
  176. alpha=2*np.random.random()*np.pi
  177. i[0]=i[0]+0.2*np.cos(alpha)
  178. i[1]=i[1]+0.2*np.sin(alpha)
  179. self.locus = np.vstack((self.locus,[self.assemble]))
  180. def returnlocus(self,index):
  181. lx=[]
  182. ly=[]
  183. for i in self.locus:
  184. lx.append(i[index][0])
  185. ly.append(i[index][1])
  186. return lx,ly
  187. #-----------------------------------------------------------------
  188. def distance(point1,point2):
  189. return np.sqrt((point1[0]-point2[0])**2+(point1[1]-point2[1])**2)
  190. if __name__=='__main__':
  191. state1=state(0,10,0,0.2,math.pi/2,0,0,0)
  192. ship=ship()
  193. obstacle=obstacle()
  194. #初始化
  195. ship.initialState(state1)
  196. ship.initialgoal(np.array([35,35]))
  197. ship.initialobstacle(obstacle)
  198. cost=0
  199. best_uv=np.array([0,0])
  200. #这里的for循环可以改成while循环,在船到达之前都要运动迭代
  201. for i in range(1000):
  202. time_begin=time.time()
  203. best_uv,cost=ship.search_for_best_uv()
  204. newstate=ship.motion(best_uv[0],best_uv[1])
  205. ship.ship[-1].cost = cost
  206. #ship.obstacle_in_windows()
  207. time_end=time.time()
  208. obstacle.update()
  209. ship.initialobstacle(obstacle)
  210. ship.safedetect()
  211. print("第%d次迭代,耗时%.6fs,当前距离终点%.6f"%(i+1,(time_end-time_begin),distance(np.array([ship.ship[-1].x,ship.ship[-1].y]),ship.goal)))
  212. if distance(np.array([ship.ship[-1].x,ship.ship[-1].y]),ship.goal)<ship.saferadius:
  213. print("Done!")
  214. break
  215. # print("当前轨迹值:")
  216. # for i in ship.ship:
  217. # print("(%.2f,%.2f)"%(i.x,i.y))
  218. fig,ax=plt.subplots(nrows=1,ncols=2,figsize=(15,10))
  219. ax[0].scatter(ship.obstacle[:,0],ship.obstacle[:,1],s=5)
  220. ax[0].plot(ship.goal[0],ship.goal[1],"ro")
  221. lx=[]
  222. ly=[]
  223. lt=[]
  224. lc=[]
  225. for i in ship.ship:
  226. lx.append(i.x)
  227. ly.append(i.y)
  228. lt.append(i.time)
  229. lc.append(i.cost)
  230. ax[0].plot(lx,ly)
  231. for i in range(17):
  232. locusx,locusy=obstacle.returnlocus(i)
  233. ax[0].plot(locusx,locusy)
  234. ax[0].grid(True)
  235. ax[0].set_title(label="locus figure")
  236. ax[1].scatter(lt,lc,s=2)
  237. ax[1].grid(True)
  238. ax[1].set_title("cost figure")
  239. plt.show()

动态效果

动态窗口法避障_哔哩哔哩_bilibili

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/875367
推荐阅读
相关标签
  

闽ICP备14008679号