Map.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. import math
  2. from dijkstra.dijkstra_algorithm import Graph
  3. import numpy as np
  4. import scipy.spatial as spt
  5. import message_pb2 as message
  6. import uuid
  7. class Node(object):
  8. def __init__(self, id, x, y):
  9. self.id_ = id
  10. self.x_ = x
  11. self.y_ = y
  12. def distance(self, other):
  13. if not isinstance(other, (Node, StreetNode, SpaceNode)):
  14. print(" node must be Node,street_node,space_node")
  15. return -1
  16. return math.sqrt(math.pow(other.x_ - self.x_, 2) + math.pow(other.y_ - self.y_, 2))
  17. class StreetNode(Node):
  18. def __init__(self, id, x, y):
  19. Node.__init__(self, id, x, y)
  20. class SpaceNode(Node):
  21. def __init__(self, id, x, y, yaw):
  22. Node.__init__(self, id, x, y)
  23. self.yaw_ = yaw
  24. def frontPoint(self,wheelBase):
  25. x=self.x_+wheelBase/2.0*math.cos(self.yaw_)
  26. y=self.y_+wheelBase/2.0*math.sin(self.yaw_)
  27. return [x,y]
  28. def backPoint(self,wheelBase):
  29. x=self.x_-wheelBase/2.0*math.cos(self.yaw_)
  30. y=self.y_-wheelBase/2.0*math.sin(self.yaw_)
  31. return [x,y]
  32. def singleton(cls):
  33. _instance = {}
  34. def inner():
  35. if cls not in _instance:
  36. _instance[cls] = cls()
  37. return _instance[cls]
  38. return inner
  39. '''
  40. map 采用单例
  41. '''
  42. @singleton
  43. class DijikstraMap(object):
  44. def __init__(self):
  45. self.nodes_ = {}
  46. self.graph_ = Graph()
  47. def GetVertex(self,id):
  48. return self.nodes_.get(id)
  49. def AddVertex(self, node):
  50. if isinstance(node, (StreetNode)):
  51. print("add street node :%s " % (node.id_))
  52. self.nodes_[node.id_] = node
  53. if isinstance(node, (SpaceNode)):
  54. print("add space node :%s " % (node.id_))
  55. self.nodes_[node.id_] = node
  56. self.graph_.AddVertex(node.id_, [node.x_, node.y_])
  57. return True
  58. def AddEdge(self, id1, id2, direct=False):
  59. if self.nodes_.get(id1) == None or self.nodes_.get(id2) == None:
  60. raise ("Add edge failed %s or %s node is not exist" % (id1, id2))
  61. print("Add Edge :%s-%s" % (id1, id2))
  62. self.graph_.AddEdge(id1, id2)
  63. if direct == False:
  64. self.graph_.AddEdge(id2, id1)
  65. def VertexDict(self):
  66. return self.nodes_
  67. def Edges(self):
  68. return self.graph_.graph_edges
  69. def findNeastNode(self,pt):
  70. labels=[]
  71. pts=[]
  72. for item in self.nodes_.items():
  73. [label,node]=item
  74. labels.append(label)
  75. pts.append([node.x_,node.y_])
  76. points=np.array(pts)
  77. ckt=spt.KDTree(data=points,leafsize=10)
  78. find_pt=np.array(pt)
  79. d,i=ckt.query(find_pt)
  80. if i>=0 and i<len(pts):
  81. return [labels[i],pts[i]]
  82. def GetShortestPath(self, beg, end):
  83. [pathId, distance] = self.graph_.shortest_path(beg, end)
  84. print("distance:", distance)
  85. print("path:", pathId)
  86. path = []
  87. for nodeId in pathId:
  88. node = self.nodes_[nodeId]
  89. path.append(node)
  90. return path
  91. @staticmethod
  92. def CreatePath(pathNodes,delta):
  93. last_node=None
  94. trajectry=[]
  95. for node in pathNodes:
  96. if last_node==None:
  97. last_node=node
  98. continue
  99. dis=last_node.distance(node)
  100. if dis<0.5:
  101. last_node=node
  102. continue #同一点
  103. else:
  104. vector=[node.x_-last_node.x_,node.y_-last_node.y_]
  105. dx=vector[0]
  106. dy=vector[1]
  107. yaw=math.asin(dy/math.sqrt(dx*dx+dy*dy))
  108. if yaw>=0:
  109. if dx<0:
  110. yaw=math.pi-yaw
  111. if yaw<0:
  112. if dx<0:
  113. yaw=-math.pi-yaw
  114. len=int(math.sqrt(dx*dx+dy*dy)/delta)
  115. ax=math.cos(yaw)*delta
  116. ay=math.sin(yaw)*delta
  117. poses=[]
  118. if isinstance(last_node,(SpaceNode)):
  119. yaw=yaw+math.pi
  120. for i in range(len+1):
  121. pose=[last_node.x_+i*ax,last_node.y_+i*ay,yaw]
  122. poses.append(pose)
  123. trajectry.append(poses)
  124. last_node=node
  125. return trajectry
  126. @staticmethod
  127. def CreateNavCmd(pose, path):
  128. if len(path) <= 1:
  129. return None
  130. cmd = message.NavCmd()
  131. cmd.action=0 # 新导航
  132. key = str(uuid.uuid4())
  133. cmd.key=(key)
  134. adjustdiff = message.Pose2d()
  135. node_mpcdiff = message.Pose2d()
  136. enddiff = message.Pose2d()
  137. lastAdjustDiff=message.Pose2d()
  138. # 目标点精度设置
  139. # 原地调整精度
  140. adjustdiff.x=(0.1)
  141. adjustdiff.y=(0.1)
  142. adjustdiff.theta=(0.5 * math.pi / 180.0)
  143. #过程点巡线目标精度
  144. node_mpcdiff.x=(0.05)
  145. node_mpcdiff.y=(0.05)
  146. node_mpcdiff.theta=(10 * math.pi / 180.0)
  147. #最后一个巡线目标点精度
  148. enddiff.x=(0.02)
  149. enddiff.y=(0.02)
  150. enddiff.theta=(0.5 * math.pi / 180.0)
  151. #最后一个原地调整精度
  152. lastAdjustDiff.x=(0.03)
  153. lastAdjustDiff.y=(0.01)
  154. lastAdjustDiff.theta=(0.7 * math.pi / 180.0)
  155. # 速度限制
  156. v_limit = message.SpeedLimit()
  157. angular_limit = message.SpeedLimit()
  158. horize_limit = message.SpeedLimit()
  159. v_limit.min=(0.1)
  160. v_limit.max=(0.2)
  161. horize_limit.min=(0.05)
  162. horize_limit.max=(0.2)
  163. angular_limit.min=(2)
  164. angular_limit.max=(40.0)
  165. # mpc速度限制
  166. mpc_x_limit = message.SpeedLimit()
  167. last_MPC_v=message.SpeedLimit()
  168. mpc_angular_limit = message.SpeedLimit()
  169. mpc_x_limit.min=(0.05)
  170. mpc_x_limit.max=(1.2)
  171. last_MPC_v.min=0.03
  172. last_MPC_v.max=0.4
  173. mpc_angular_limit.min=(0 * math.pi / 180.0)
  174. mpc_angular_limit.max=(3 * math.pi / 180.0)
  175. # 创建动作集----------------------
  176. last_node = None
  177. count = 0
  178. for node in path:
  179. if last_node == None:
  180. last_node = node
  181. count+=1
  182. continue
  183. # 运动到上一点
  184. vector = [node.x_ - last_node.x_, node.y_ - last_node.y_]
  185. dx = vector[0]
  186. dy = vector[1]
  187. yaw = math.asin(dy / math.sqrt(dx * dx + dy * dy))
  188. if yaw >= 0:
  189. if dx < 0:
  190. yaw = math.pi - yaw
  191. if yaw < 0:
  192. if dx < 0:
  193. yaw = -math.pi - yaw
  194. if isinstance(last_node, (SpaceNode)):
  195. yaw = yaw + math.pi
  196. # 添加调整动作
  197. act_adjust = message.Action()
  198. act_adjust.type=(1)
  199. act_adjust.target.x=(last_node.x_)
  200. act_adjust.target.y=(last_node.y_)
  201. act_adjust.target.theta=(yaw)
  202. #最后一个调整点
  203. if count==len(path)-2:
  204. act_adjust.target_diff.CopyFrom(lastAdjustDiff)
  205. else:
  206. act_adjust.target_diff.CopyFrom(adjustdiff)
  207. act_adjust.velocity_limit.CopyFrom(v_limit)
  208. act_adjust.horize_limit.CopyFrom(horize_limit)
  209. act_adjust.angular_limit.CopyFrom(angular_limit)
  210. cmd.actions.add().CopyFrom(act_adjust)
  211. # 添加mpc动作
  212. act_along = message.Action()
  213. act_along.type=(2)
  214. act_along.begin.x=(last_node.x_)
  215. act_along.begin.y=(last_node.y_)
  216. act_along.begin.theta=(yaw)
  217. act_along.target.x=(node.x_)
  218. act_along.target.y=(node.y_)
  219. act_along.target.theta=(yaw)
  220. if count==len(path)-1:
  221. act_along.target_diff.CopyFrom(enddiff)
  222. else:
  223. act_along.target_diff.CopyFrom(node_mpcdiff)
  224. if isinstance(node, (SpaceNode)) or isinstance(last_node, (SpaceNode)):
  225. act_along.velocity_limit.CopyFrom(last_MPC_v)
  226. else:
  227. act_along.velocity_limit.CopyFrom(mpc_x_limit)
  228. act_along.angular_limit.CopyFrom(mpc_angular_limit)
  229. cmd.actions.add().CopyFrom(act_along)
  230. last_node = node
  231. count+=1
  232. return cmd