Map.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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, connect_nodeId):
  22. Node.__init__(self, id, x, y)
  23. self.connect_nodeId_ = connect_nodeId
  24. def singleton(cls):
  25. _instance = {}
  26. def inner():
  27. if cls not in _instance:
  28. _instance[cls] = cls()
  29. return _instance[cls]
  30. return inner
  31. '''
  32. map 采用单例
  33. '''
  34. @singleton
  35. class DijikstraMap(object):
  36. def __init__(self):
  37. self.nodes_ = {}
  38. self.graph_ = Graph()
  39. def AddVertex(self, node):
  40. if isinstance(node, (StreetNode)):
  41. print("add street node :%s " % (node.id_))
  42. self.nodes_[node.id_] = node
  43. if isinstance(node, (SpaceNode)):
  44. if self.nodes_.get(node.connect_nodeId_) == None:
  45. print("add space node failed ,connect street node not exist")
  46. return False
  47. print("add space node :%s connect_id:%s" % (node.id_, node.connect_nodeId_))
  48. self.nodes_[node.id_] = node
  49. self.graph_.AddVertex(node.id_, [node.x_, node.y_])
  50. return True
  51. def AddEdge(self, id1, id2, direct=False):
  52. if self.nodes_.get(id1) == None or self.nodes_.get(id2) == None:
  53. raise ("Add edge failed %s or %s node is not exist" % (id1, id2))
  54. print("Add Edge :%s-%s" % (id1, id2))
  55. self.graph_.AddEdge(id1, id2)
  56. if direct == False:
  57. self.graph_.AddEdge(id2, id1)
  58. def VertexDict(self):
  59. return self.nodes_
  60. def Edges(self):
  61. return self.graph_.graph_edges
  62. def findNeastNode(self, pt):
  63. labels = []
  64. pts = []
  65. for item in self.nodes_.items():
  66. [label, node] = item
  67. labels.append(label)
  68. pts.append([node.x_, node.y_])
  69. points = np.array(pts)
  70. ckt = spt.KDTree(data=points, leafsize=10)
  71. find_pt = np.array(pt)
  72. d, i = ckt.query(find_pt)
  73. if i >= 0 and i < len(pts):
  74. return [labels[i], pts[i]]
  75. def GetShortestPath(self, beg, end):
  76. [pathId, distance] = self.graph_.shortest_path(beg, end)
  77. print("distance:", distance)
  78. print("path:", pathId)
  79. path = []
  80. for nodeId in pathId:
  81. node = self.nodes_[nodeId]
  82. path.append(node)
  83. return path
  84. @staticmethod
  85. def CreatePath(pathNodes, delta):
  86. last_node = None
  87. trajectry = []
  88. for node in pathNodes:
  89. if last_node == None:
  90. last_node = node
  91. continue
  92. dis = last_node.distance(node)
  93. if dis < 0.5:
  94. last_node = node
  95. continue # 同一点
  96. else:
  97. vector = [node.x_ - last_node.x_, node.y_ - last_node.y_]
  98. dx = vector[0]
  99. dy = vector[1]
  100. yaw = math.asin(dy / math.sqrt(dx * dx + dy * dy))
  101. if yaw >= 0:
  102. if dx < 0:
  103. yaw = math.pi - yaw
  104. if yaw < 0:
  105. if dx < 0:
  106. yaw = -math.pi - yaw
  107. len = int(math.sqrt(dx * dx + dy * dy) / delta)
  108. ax = math.cos(yaw) * delta
  109. ay = math.sin(yaw) * delta
  110. poses = []
  111. if isinstance(last_node, (SpaceNode)):
  112. yaw = yaw + math.pi
  113. for i in range(len + 1):
  114. pose = [last_node.x_ + i * ax, last_node.y_ + i * ay, yaw]
  115. poses.append(pose)
  116. trajectry.append(poses)
  117. last_node = node
  118. return trajectry
  119. @staticmethod
  120. def CreateNavCmd(pose, path):
  121. if len(path) <= 1:
  122. return None
  123. cmd = message.NavCmd()
  124. cmd.action = 0 # 新导航
  125. key = str(uuid.uuid4())
  126. cmd.key = (key)
  127. adjustdiff = message.Pose2d()
  128. node_mpcdiff = message.Pose2d()
  129. enddiff = message.Pose2d()
  130. lastAdjustDiff = message.Pose2d()
  131. # 目标点精度设置
  132. adjustdiff.x = (0.1)
  133. adjustdiff.y = (0.05)
  134. adjustdiff.theta = (0.5 * math.pi / 180.0)
  135. node_mpcdiff.x = (0.1)
  136. node_mpcdiff.y = (0.1)
  137. node_mpcdiff.theta = (10 * math.pi / 180.0)
  138. enddiff.x = (0.1)
  139. enddiff.y = (0.1)
  140. enddiff.theta = (5 * math.pi / 180.0)
  141. lastAdjustDiff.x = (0.03)
  142. lastAdjustDiff.y = (0.03)
  143. lastAdjustDiff.theta = (0.3 * math.pi / 180.0)
  144. # 速度限制
  145. v_limit = message.SpeedLimit()
  146. angular_limit = message.SpeedLimit()
  147. horize_limit = message.SpeedLimit()
  148. v_limit.min = (0.1)
  149. v_limit.max = (0.2)
  150. horize_limit.min = (0.05)
  151. horize_limit.max = (0.2)
  152. angular_limit.min = (1)
  153. angular_limit.max = (25.0)
  154. # mpc速度限制
  155. mpc_x_limit = message.SpeedLimit()
  156. mpc_angular_limit = message.SpeedLimit()
  157. mpc_x_limit.min = (0.05)
  158. mpc_x_limit.max = (1.5)
  159. mpc_angular_limit.min = (0 * math.pi / 180.0)
  160. mpc_angular_limit.max = (3 * math.pi / 180.0)
  161. # 创建动作集----------------------
  162. last_node = None
  163. count = 0
  164. for node in path:
  165. if last_node == None:
  166. last_node = node
  167. count += 1
  168. continue
  169. # 运动到上一点
  170. vector = [node.x_ - last_node.x_, node.y_ - last_node.y_]
  171. dx = vector[0]
  172. dy = vector[1]
  173. yaw = math.asin(dy / math.sqrt(dx * dx + dy * dy))
  174. if yaw >= 0:
  175. if dx < 0:
  176. yaw = math.pi - yaw
  177. if yaw < 0:
  178. if dx < 0:
  179. yaw = -math.pi - yaw
  180. if isinstance(last_node, (SpaceNode)):
  181. yaw = yaw + math.pi
  182. # 添加调整动作
  183. act_adjust = message.Action()
  184. act_adjust.type = (1)
  185. act_adjust.target.x = (last_node.x_)
  186. act_adjust.target.y = (last_node.y_)
  187. act_adjust.target.theta = (yaw)
  188. # 最后一个调整点
  189. if count == len(path) - 2:
  190. act_adjust.target_diff.CopyFrom(lastAdjustDiff)
  191. else:
  192. act_adjust.target_diff.CopyFrom(adjustdiff)
  193. act_adjust.velocity_limit.CopyFrom(v_limit)
  194. act_adjust.horize_limit.CopyFrom(horize_limit)
  195. act_adjust.angular_limit.CopyFrom(angular_limit)
  196. cmd.actions.add().CopyFrom(act_adjust)
  197. # 添加mpc动作
  198. act_along = message.Action()
  199. act_along.type = (2)
  200. act_along.begin.x = (last_node.x_)
  201. act_along.begin.y = (last_node.y_)
  202. act_along.begin.theta = (yaw)
  203. act_along.target.x = (node.x_)
  204. act_along.target.y = (node.y_)
  205. act_along.target.theta = (yaw)
  206. if count == len(path) - 1:
  207. act_along.target_diff.CopyFrom(enddiff)
  208. else:
  209. act_along.target_diff.CopyFrom(node_mpcdiff)
  210. act_along.velocity_limit.CopyFrom(mpc_x_limit)
  211. act_along.angular_limit.CopyFrom(mpc_angular_limit)
  212. cmd.actions.add().CopyFrom(act_along)
  213. last_node = node
  214. count += 1
  215. return cmd
  216. # 生成指令的基础信息
  217. @staticmethod
  218. def CreateNavCmd_part_base():
  219. cmd = message.NavCmd()
  220. cmd.action = 0 # 新导航
  221. key = str(uuid.uuid4())
  222. cmd.key = (key)
  223. return cmd
  224. # 生成指令的动作集
  225. @staticmethod
  226. def CreateNavCmd_part_actions(path):
  227. if len(path) <= 1:
  228. return None
  229. adjustdiff = message.Pose2d()
  230. node_mpcdiff = message.Pose2d()
  231. enddiff = message.Pose2d()
  232. lastAdjustDiff = message.Pose2d()
  233. # 目标点精度设置
  234. adjustdiff.x = (0.1)
  235. adjustdiff.y = (0.05)
  236. adjustdiff.theta = (0.5 * math.pi / 180.0)
  237. node_mpcdiff.x = (0.1)
  238. node_mpcdiff.y = (0.1)
  239. node_mpcdiff.theta = (10 * math.pi / 180.0)
  240. enddiff.x = (0.1)
  241. enddiff.y = (0.1)
  242. enddiff.theta = (5 * math.pi / 180.0)
  243. lastAdjustDiff.x = (0.03)
  244. lastAdjustDiff.y = (0.03)
  245. lastAdjustDiff.theta = (0.3 * math.pi / 180.0)
  246. # 速度限制
  247. v_limit = message.SpeedLimit()
  248. angular_limit = message.SpeedLimit()
  249. horize_limit = message.SpeedLimit()
  250. v_limit.min = (0.1)
  251. v_limit.max = (0.2)
  252. horize_limit.min = (0.05)
  253. horize_limit.max = (0.2)
  254. angular_limit.min = (1)
  255. angular_limit.max = (25.0)
  256. # mpc速度限制
  257. mpc_x_limit = message.SpeedLimit()
  258. mpc_angular_limit = message.SpeedLimit()
  259. mpc_x_limit.min = (0.05)
  260. mpc_x_limit.max = (1.5)
  261. mpc_angular_limit.min = (0 * math.pi / 180.0)
  262. mpc_angular_limit.max = (3 * math.pi / 180.0)
  263. # 创建动作集----------------------
  264. actions = list()
  265. last_node = None
  266. count = 0
  267. for node in path:
  268. if last_node == None:
  269. last_node = node
  270. count += 1
  271. continue
  272. # 运动到上一点
  273. vector = [node.x_ - last_node.x_, node.y_ - last_node.y_]
  274. dx = vector[0]
  275. dy = vector[1]
  276. yaw = math.asin(dy / math.sqrt(dx * dx + dy * dy))
  277. if yaw >= 0:
  278. if dx < 0:
  279. yaw = math.pi - yaw
  280. if yaw < 0:
  281. if dx < 0:
  282. yaw = -math.pi - yaw
  283. if isinstance(last_node, (SpaceNode)):
  284. yaw = yaw + math.pi
  285. # 添加调整动作
  286. act_adjust = message.Action()
  287. act_adjust.type = (1)
  288. act_adjust.target.x = (last_node.x_)
  289. act_adjust.target.y = (last_node.y_)
  290. act_adjust.target.theta = (yaw)
  291. # 最后一个调整点
  292. if count == len(path) - 2:
  293. act_adjust.target_diff.CopyFrom(lastAdjustDiff)
  294. else:
  295. act_adjust.target_diff.CopyFrom(adjustdiff)
  296. act_adjust.velocity_limit.CopyFrom(v_limit)
  297. act_adjust.horize_limit.CopyFrom(horize_limit)
  298. act_adjust.angular_limit.CopyFrom(angular_limit)
  299. actions.append(act_adjust)
  300. # 添加mpc动作
  301. act_along = message.Action()
  302. act_along.type = (2)
  303. act_along.begin.x = (last_node.x_)
  304. act_along.begin.y = (last_node.y_)
  305. act_along.begin.theta = (yaw)
  306. act_along.target.x = (node.x_)
  307. act_along.target.y = (node.y_)
  308. act_along.target.theta = (yaw)
  309. if count == len(path) - 1:
  310. act_along.target_diff.CopyFrom(enddiff)
  311. else:
  312. act_along.target_diff.CopyFrom(node_mpcdiff)
  313. act_along.velocity_limit.CopyFrom(mpc_x_limit)
  314. act_along.angular_limit.CopyFrom(mpc_angular_limit)
  315. actions.append(act_along)
  316. last_node = node
  317. count += 1
  318. return actions