test.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #===============================================================================
  4. #
  5. # test.py
  6. #
  7. # Test program for the simple GL Viewer.
  8. #
  9. # Copyright (c) 2011, Arne Schmitz <arne.schmitz@gmx.net>
  10. # All rights reserved.
  11. #
  12. # Redistribution and use in source and binary forms, with or without
  13. # modification, are permitted provided that the following conditions are met:
  14. # * Redistributions of source code must retain the above copyright
  15. # notice, this list of conditions and the following disclaimer.
  16. # * Redistributions in binary form must reproduce the above copyright
  17. # notice, this list of conditions and the following disclaimer in the
  18. # documentation and/or other materials provided with the distribution.
  19. # * Neither the name of the <organization> nor the
  20. # names of its contributors may be used to endorse or promote products
  21. # derived from this software without specific prior written permission.
  22. #
  23. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. # DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  27. # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  30. # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #
  34. #===============================================================================
  35. import math
  36. import time
  37. import sys
  38. from PyQt5.QtGui import *
  39. from PyQt5.QtWidgets import *
  40. from PyQt5.QtCore import *
  41. from MapGLWidget import MapGLWidget,TimeStatu
  42. import json
  43. import dijkstra.Map as mp
  44. import ControllWidget
  45. import mqtt_async as mqtt
  46. import message_pb2 as message
  47. import google.protobuf.json_format as jtf
  48. #===============================================================================
  49. class MainWindow(QMainWindow):
  50. """docstring for Mainwindow"""
  51. def __init__(self, parent = None):
  52. super(MainWindow,self).__init__(parent)
  53. self.basic()
  54. splitter_main = self.split_()
  55. self.setCentralWidget(splitter_main)
  56. self.path=None
  57. self.agv1_statu=TimeStatu(None,0.1)
  58. self.agv2_statu=TimeStatu(None,0.1)
  59. self.mqtt_=mqtt.MqttAsync("UI")
  60. self.mqtt_.connect("127.0.0.1",1883,"admin","zx123456")
  61. self.mqtt_.subscribe("agv1_child/agv_statu",self.agv_statu_arrived)
  62. self.mqtt_.loop_start()
  63. def agv_statu_arrived(self,client,user_data,msg):
  64. statu=message.AGVStatu()
  65. jtf.Parse(msg.payload.decode(),statu)
  66. self.gl.ResetAgv1(statu)
  67. self.agv1_statu=TimeStatu(statu,0.3)
  68. def load_map(self,file):
  69. with open(file,'r',encoding='utf-8') as fp:
  70. map=json.load(fp)
  71. return map
  72. #窗口基础属性
  73. def basic(self):
  74. #设置标题,大小,图标
  75. self.setWindowTitle("GT")
  76. self.resize(1100,650)
  77. self.setWindowIcon(QIcon("./image/Gt.png"))
  78. #居中显示
  79. screen = QDesktopWidget().geometry()
  80. self_size = self.geometry()
  81. self.move(int((screen.width() - self_size.width())/2),int((screen.height() - self_size.height())/2))
  82. def closeEvent(self, QCloseEvent):
  83. self.gl.close()
  84. @staticmethod
  85. def Create_traj(path,delta):
  86. last_node=None
  87. trajectry=[]
  88. for node in path:
  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,(mp.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. def generater_path(self,beg,end):
  120. self.path=self.djks_map_.GetShortestPath(beg,end)
  121. self.traj=self.Create_traj(self.path,0.5)
  122. self.gl.AddTraj("agv1",self.traj)
  123. self.gl.update()
  124. def send_cmd(self):
  125. if self.path is not None and self.agv1_statu.timeout()==False:
  126. statu=self.agv1_statu.statu
  127. if statu is not None:
  128. cmd=self.djks_map_.CreateNavCmd([statu.x,statu.y,statu.theta],self.path)
  129. if cmd is not None:
  130. self.mqtt_.publish("agv1_child/nav_cmd",jtf.MessageToJson(cmd))
  131. else:
  132. print(" NavCmd is None")
  133. def Cancel_cmd(self):
  134. cmd=message.NavCmd()
  135. cmd.action=3
  136. self.mqtt_.publish("agv1_child/nav_cmd",jtf.MessageToJson(cmd))
  137. #分割窗口
  138. def split_(self):
  139. splitter = QSplitter(Qt.Vertical)
  140. self.gl = MapGLWidget() #将opengl例子嵌入GUI
  141. map=self.load_map("./map.json")
  142. UI_data={}
  143. UI_data["nodes"]=[]
  144. self.djks_map_=mp.Map()
  145. for node in map['street_nodes'].items():
  146. [id,point]=node
  147. street_node=mp.StreetNode(id,point[0],point[1])
  148. self.djks_map_.AddVertex(street_node)
  149. self.gl.AddNode([id,"street_node",point])
  150. UI_data["nodes"].append(id)
  151. for node in map['space_nodes'].items():
  152. [id,point]=node
  153. [x,y,connectId]=point
  154. space_node=mp.SpaceNode(id,point[0],point[1],connectId)
  155. self.djks_map_.AddVertex(space_node)
  156. self.djks_map_.AddEdge(id,connectId)
  157. glNode=[id,"space_node",[x,y]]
  158. self.gl.AddNode(glNode)
  159. self.gl.AddRoad(["conn%s-%s"%(id,connectId),[id,connectId]])
  160. UI_data["nodes"].append(id)
  161. for road in map['roads'].items():
  162. self.gl.AddRoad(road)
  163. [_,points]=road
  164. for pt1 in points:
  165. for pt2 in points:
  166. if not pt1==pt2:
  167. self.djks_map_.AddEdge(pt1,pt2)
  168. splitter.addWidget(self.gl)
  169. testedit = QTextEdit()
  170. splitter.addWidget(testedit)
  171. splitter.setStretchFactor(0,3)
  172. splitter.setStretchFactor(1,2)
  173. splitter_main = QSplitter(Qt.Horizontal)
  174. Controller = ControllWidget.Frame(UI_data)
  175. callbacks={}
  176. callbacks["CreateTraj"]=self.generater_path
  177. callbacks["SendCmd"]=self.send_cmd
  178. callbacks["CancelCmd"]=self.Cancel_cmd
  179. Controller.SetBtnFunc(callbacks)
  180. splitter_main.addWidget(Controller)
  181. splitter_main.addWidget(splitter)
  182. splitter_main.setStretchFactor(0,1)
  183. splitter_main.setStretchFactor(1,4)
  184. return splitter_main
  185. if __name__ == "__main__":
  186. app = QApplication(sys.argv)
  187. win = MainWindow()
  188. win.show()
  189. sys.exit(app.exec_())
  190. #===============================================================================
  191. # Main
  192. #===============================================================================
  193. '''app = QApplication(sys.argv)
  194. mainWindow = MapGLWidget()
  195. mainWindow.show()
  196. mainWindow.raise_() # Need this at least on OS X, otherwise the window ends up in background
  197. sys.exit(app.exec_())'''
  198. #===============================================================================
  199. #
  200. # Local Variables:
  201. # mode: Python
  202. # indent-tabs-mode: nil
  203. # End:
  204. #
  205. #===============================================================================