Map.py 10.0 KB

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