window_screen_pyqt.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import datetime
  2. import threading
  3. from PyQt5.QtWidgets import QWidget, QApplication, QMainWindow, QLabel
  4. from PyQt5.QtGui import QPixmap, QPainter, QResizeEvent, QCloseEvent, QPaintEvent, QFont, QColor
  5. from PyQt5.QtCore import QSize, QTimer, QRect, Qt
  6. import async_communication as CM
  7. import message_pb2 as message
  8. import google.protobuf.text_format as tf
  9. import logging
  10. logging.basicConfig(filename='log.txt',
  11. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s-%(funcName)s',
  12. level=logging.ERROR)
  13. MeasureStatu = {"ok": 0, "无数据": 1, "噪声": 2, "超界": 3, "故障": 4, "失去连接": 5}
  14. ArrowType = {message.Range_status.Value('Range_correct'): "正确图片",
  15. message.Range_status.Value('Range_front'): "向后调整",
  16. message.Range_status.Value('Range_back'): "向前调整",
  17. message.Range_status.Value('Range_left'): "向右调整",
  18. message.Range_status.Value('Range_right'): "向左调整",
  19. message.Range_status.Value('Range_car_width'): "超宽车辆",
  20. message.Range_status.Value('Range_car_wheelbase'): "轴距超差",
  21. message.Range_status.Value('Range_angle_anti_clock'): "向右旋转",
  22. message.Range_status.Value('Range_angle_clock'): "向左旋转",
  23. message.Range_status.Value('Range_steering_wheel_nozero'): "回正方向盘",
  24. }
  25. class PicLabel(QLabel):
  26. def __init__(self, parent):
  27. super(PicLabel, self).__init__(parent=parent)
  28. self.image = None
  29. self.Txt = None
  30. self.show = False
  31. self.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150)")
  32. self.timer = QTimer()
  33. self.timer.timeout.connect(self.OnTimer)
  34. def FlashImg(self, pixmap):
  35. self.image = pixmap
  36. if self.timer.isActive() == False:
  37. self.timer.start(500)
  38. def ShowImg(self, pixmap):
  39. self.timer.stop()
  40. self.show = True
  41. self.Txt = None
  42. self.image = pixmap
  43. self.repaint()
  44. def ShowTxt(self, txt):
  45. self.timer.stop()
  46. self.show = True
  47. self.image = None
  48. self.Txt = txt
  49. self.repaint()
  50. def OnTimer(self):
  51. self.show = not self.show
  52. self.repaint()
  53. def paintEvent(self, a0: QPaintEvent) -> None:
  54. if self.show is True:
  55. if self.image is not None:
  56. w, h = self.size().width(), self.size().height()
  57. iw, ih = self.image.width(), self.image.height()
  58. painter = QPainter(self)
  59. painter.drawPixmap(QRect(0, 0, w, h), self.image, QRect(0, 0, iw, ih))
  60. elif self.Txt is not None:
  61. w, h = self.size().width() / len(self.Txt), self.size().height() / 1.5
  62. painter = QPainter(self)
  63. painter.setPen(QColor(255, 0, 0))
  64. painter.setFont(QFont('SimSun', int(min(w, h)),QFont.Bold))
  65. # print(self.Txt)
  66. painter.drawText(a0.rect(), Qt.AlignCenter, self.Txt)
  67. class Frame(QMainWindow):
  68. def __init__(self, import_id, images, prj_parameter, second_screen=False):
  69. super(Frame, self).__init__()
  70. self.flag = None
  71. self.last_back_io = None
  72. self.images = images
  73. self.images = {}
  74. self.import_id = import_id
  75. self.dispatch_statu = CM.TimeStatu(timeout=0.1)
  76. self.measure_statu = CM.TimeStatu(timeout=0.1)
  77. self.terminal_statu = CM.TimeStatu(timeout=0.1)
  78. for key, file in images.items():
  79. self.images[key] = pix = QPixmap(file)
  80. self.InitUI()
  81. # self.last_door_statu=None
  82. self.last_moving_statu = None
  83. # self.last_show = None
  84. # self.last_back_io = "正常"
  85. # self.flag = None
  86. if second_screen == True:
  87. desktop = QApplication.desktop()
  88. screen_count = desktop.screenCount()
  89. displays = [desktop.availableGeometry(i) for i in range(desktop.screenCount())]
  90. second_offx = 0
  91. second_offy = 0
  92. if len(displays) == 2:
  93. second_offx = displays[1].width()
  94. second_offy = displays[1].height()
  95. self.setGeometry(second_offx, second_offy, 200, 500)
  96. self.timer = QTimer()
  97. self.timer.timeout.connect(self.Switch)
  98. self.timer.start(200)
  99. self.lock = threading.Lock()
  100. def InitUI(self):
  101. self.measure_info_txt = QLabel(self)
  102. self.car_number_txt = QLabel(self)
  103. self.car_number_txt.setStyleSheet("border-width:1px;border-style:solid;border-color:rgb(150,150,150)")
  104. self.car_number_txt.setAlignment(Qt.AlignCenter)
  105. self.measure_info_txt.setStyleSheet("color:blue")
  106. self.panel_txt = PicLabel(self)
  107. self.panel_arrow = PicLabel(self)
  108. def receive_dispatch(self, statu):
  109. self.dispatch_statu = statu
  110. def receive_measureInfo(self, statu):
  111. self.measure_statu = statu
  112. def receive_terminal(self, statu):
  113. self.terminal_statu = statu
  114. def receive_entrance_update(self,statu):
  115. with self.lock:
  116. print("---------------刷新投影-----------------")
  117. self.last_moving_statu = None
  118. def resizeEvent(self, a0: QResizeEvent) -> None:
  119. w, h = a0.size().width(), a0.size().height()
  120. w, h = self.size().width(), self.size().height()
  121. top_w, top_h = w, int(h * 0.15)
  122. car_number_w, car_number_h = w, int(h * 0.10)
  123. txt_w, txt_h = w, int(h * 0.20)
  124. arrow_w, arrow_h = w, int(h * 0.55)
  125. font = QFont()
  126. font.setBold(True)
  127. font.setPixelSize(int(w / 40))
  128. self.measure_info_txt.setFont(font)
  129. self.measure_info_txt.setGeometry(0, 0, top_w, top_h)
  130. font.setPixelSize(int(w / 20))
  131. self.car_number_txt.setFont(font)
  132. self.car_number_txt.setGeometry(0, top_h, car_number_w, car_number_h)
  133. self.panel_txt.setGeometry(0, top_h + car_number_h, txt_w, txt_h)
  134. self.panel_arrow.setGeometry(0, top_h + car_number_h + txt_h, arrow_w, arrow_h)
  135. def Switch(self):
  136. try:
  137. if self.terminal_statu.timeout() is False:
  138. terminal_statu = message.terminal_node_statu()
  139. tf.Parse(self.terminal_statu.statu, terminal_statu)
  140. # print(terminal_statu.car_number)
  141. self.car_number_txt.setText(terminal_statu.car_number)
  142. self.car_number_txt.setStyleSheet(
  143. "border-width:1px;border-style:solid;border-color:rgb(150,150,150);color:green")
  144. else:
  145. self.car_number_txt.setText("车牌号为空!")
  146. self.car_number_txt.setStyleSheet(
  147. "border-width:1px;border-style:solid;border-color:rgb(150,150,150);color:red")
  148. # 先判断连接状态
  149. if self.dispatch_statu.timeout():
  150. self.panel_txt.ShowImg(self.images['传感器超时'])
  151. self.panel_arrow.FlashImg(self.images['传感器超时'])
  152. return
  153. if self.measure_statu.timeout():
  154. self.panel_txt.ShowImg(self.images['测绘超时'])
  155. self.panel_arrow.FlashImg(self.images['测绘超时'])
  156. return
  157. # 有车才显示
  158. dispatch_statu = message.dispatch_node_statu()
  159. tf.Parse(self.dispatch_statu.statu, dispatch_statu)
  160. measure_buffer = message.measure_buffer()
  161. measure_info = message.measure_info()
  162. tf.Parse(self.measure_statu.statu, measure_buffer)
  163. measure_info.CopyFrom(measure_buffer.measure_info_to_terminal)
  164. # 测量状态
  165. lidar_statu = measure_info.ground_status # 测量状态(正常,无数据、噪声、超界)
  166. # 传感器状态
  167. dispatch_plc_passway_status = dispatch_statu.dispatch_plc_passway_status_vector[self.import_id - 1]
  168. print(dispatch_plc_passway_status.car_height)
  169. sensor_1 = dispatch_plc_passway_status.sensor_1
  170. if lidar_statu == MeasureStatu['故障']:
  171. self.panel_txt.ShowImg(self.images['测绘超时'])
  172. self.panel_arrow.FlashImg(self.images['测绘超时'])
  173. return
  174. # 获取传感器数据
  175. # print('---------------------------------')
  176. # print('PLC数据:')
  177. # print(dispatch_plc_passway_status)
  178. # print('----------------------------------')
  179. # print('====================================')
  180. # print('雷达数据:')
  181. # print(measure_info)
  182. # print('====================================')
  183. # 关门清除上一帧数据
  184. if dispatch_plc_passway_status.outside_door_status == 2:
  185. with self.lock:
  186. self.last_moving_statu = None
  187. # 判断超界信息
  188. if (sensor_1 >> 3) & 0x01 == 0:
  189. if not self.last_back_io == "超界":
  190. self.last_back_io = "超界"
  191. self.flag = False
  192. else:
  193. if not self.last_back_io == "正常":
  194. self.last_back_io = "正常"
  195. self.flag = True
  196. if dispatch_plc_passway_status.car_height == 0:
  197. self.panel_txt.ShowImg(self.images["空闲"])
  198. self.panel_arrow.ShowImg(self.images["空闲"])
  199. return
  200. if dispatch_plc_passway_status.car_height == 4:
  201. self.panel_txt.ShowImg(self.images["超高车辆"])
  202. self.panel_arrow.ShowImg(self.images["超高车辆"])
  203. return
  204. # 以下是有车的处理
  205. # 1,显示测量数据(实时和静态)
  206. realtime_info_txt = ''
  207. static_info_txt = ''
  208. realtime_info_txt = "(实时) 中心(%.3f,%.3f) 角度:%.2f° 宽:%.3f 轴距:%.3f 前轮角:%.2f°" % \
  209. (measure_info.cx, measure_info.cy, measure_info.theta, measure_info.width,
  210. measure_info.wheelbase, measure_info.front_theta)
  211. if not self.last_moving_statu == None:
  212. static_info_txt = "(静止) 中心(%.3f,%.3f) 角度:%.2f° 宽:%.3f 轴距:%.3f 前轮角:%.2f°" % \
  213. (self.last_moving_statu.cx, self.last_moving_statu.cy,
  214. self.last_moving_statu.theta, self.last_moving_statu.width,
  215. self.last_moving_statu.wheelbase, self.last_moving_statu.front_theta)
  216. self.measure_info_txt.setText(realtime_info_txt + "\n" + static_info_txt)
  217. # 2,获取车辆运动状态(静止or动态)
  218. border_statu = measure_info.border_statu
  219. is_moving = measure_info.motion_statu == 0
  220. # 当前运动
  221. if is_moving:
  222. with self.lock:
  223. self.last_moving_statu = None
  224. else:
  225. # 当前静止
  226. if lidar_statu == MeasureStatu["ok"]:
  227. with self.lock:
  228. self.last_moving_statu = measure_info
  229. elif lidar_statu == MeasureStatu["超界"]:
  230. if not self.last_moving_statu == None:
  231. # 上一刻静止且数据正确,当前静止,不可能出现超界,将超界清除
  232. new_border = border_statu
  233. new_border = (new_border & (~(0x01 << 0)))
  234. new_border = (new_border & (~(0x01 << 1)))
  235. new_border = (new_border & (~(0x01 << 2)))
  236. new_border = (new_border & (~(0x01 << 3)))
  237. new_border = (new_border & (~(0x01 << 6)))
  238. new_border = (new_border & (~(0x01 << 7)))
  239. new_border = (new_border & (~(0x01 << 8)))
  240. new_border = (new_border & (~(0x01 << 9)))
  241. border_statu = new_border
  242. elif lidar_statu == MeasureStatu["无数据"]:
  243. # 当前静止无车,清除上一时刻数据
  244. with self.lock:
  245. self.last_moving_statu = None
  246. elif lidar_statu == MeasureStatu["噪声"]:
  247. if not self.last_moving_statu == None:
  248. # 上一时刻静止且正确,当前噪声,不显示当前数据,显示上一正确数据
  249. measure_info.CopyFrom(self.last_moving_statu)
  250. # print((sensor_1 >> 4) & 0x01)
  251. # 先判断光电
  252. if (sensor_1 >> 3) & 0x01 == 0:
  253. self.panel_txt.ShowImg(self.images["请调整"])
  254. self.panel_arrow.FlashImg(self.images["向前调整"])
  255. self.last_show = "调整"
  256. return
  257. elif (sensor_1 >> 4) & 0x01 == 0:
  258. self.panel_txt.ShowImg(self.images["请调整"])
  259. self.panel_arrow.FlashImg(self.images["向后调整"])
  260. self.last_show = "调整"
  261. # print(111)
  262. return
  263. # elif (sensor_1 >> 5) & 0x01 == 0:
  264. # self.panel_txt.ShowImg(self.images["请调整"])
  265. # self.panel_arrow.FlashImg(self.images["向右调整"])
  266. # self.last_show = "调整"
  267. # return
  268. # elif (sensor_1 >> 6) & 0x01 == 0:
  269. # self.panel_txt.ShowImg(self.images["请调整"])
  270. # self.panel_arrow.FlashImg(self.images["向左调整"])
  271. # self.last_show = "调整"
  272. # return
  273. lidar_statu = measure_info.ground_status # 测量状态(正常,无数据、噪声、超界)
  274. # 光电正常
  275. if lidar_statu == MeasureStatu["无数据"]:
  276. self.panel_txt.ShowImg(self.images["空闲"])
  277. self.panel_arrow.ShowImg(self.images["空闲"])
  278. self.last_show = "空闲"
  279. return
  280. elif lidar_statu == MeasureStatu["失去连接"]:
  281. self.panel_txt.ShowImg(self.images['测绘超时'])
  282. self.panel_arrow.FlashImg(self.images['测绘超时'])
  283. self.last_show = "超时"
  284. return
  285. elif lidar_statu == MeasureStatu["噪声"]:
  286. if self.last_moving_statu is None and self.flag is True:
  287. self.panel_txt.ShowImg(self.images['请调整'])
  288. self.panel_arrow.ShowImg(self.images["请调整"])
  289. self.last_show = "请调整"
  290. return
  291. if self.last_show == "超时":
  292. self.panel_txt.ShowImg(self.images["空闲"])
  293. self.panel_arrow.ShowImg(self.images["空闲"])
  294. self.last_show = "空闲"
  295. return
  296. elif lidar_statu == MeasureStatu["ok"]:
  297. self.panel_txt.ShowImg(self.images['正确文字'])
  298. self.panel_arrow.ShowImg(self.images['正确图片'])
  299. return
  300. # 查看是否超界
  301. elif lidar_statu == MeasureStatu["超界"]:
  302. border = border_statu & 0xf7ff
  303. if (border in ArrowType.keys()) is False:
  304. self.panel_txt.ShowImg(self.images['检查杂物'])
  305. self.panel_arrow.FlashImg(self.images['检查杂物'])
  306. self.last_show = "检查杂物"
  307. else:
  308. if ArrowType[border] == "正确图片":
  309. self.panel_arrow.ShowImg(self.images[ArrowType[border]])
  310. self.panel_txt.ShowImg(self.images['正确文字'])
  311. self.last_show = "正确"
  312. elif ArrowType[border] == "向前调整":
  313. if (measure_info.move_distance is not None):
  314. self.panel_txt.ShowTxt("请向前" + '%.2f'%(measure_info.move_distance * 100) + "厘米")
  315. else:
  316. self.panel_txt.ShowImg(self.images['请调整'])
  317. self.panel_arrow.FlashImg(self.images["向前调整"])
  318. self.last_show = "请调整"
  319. else:
  320. self.panel_arrow.FlashImg(self.images[ArrowType[border]])
  321. self.panel_txt.ShowImg(self.images['请调整'])
  322. self.last_show = "请调整"
  323. except Exception as e:
  324. print(str(e.args))
  325. logging.error(str(e.args))