Map.py 11 KB

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