mainWindow.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. import time
  2. import queue
  3. import tkinter as tk
  4. import numpy as np
  5. from gui.popup import CalibrationPopUp
  6. from gui.graph import Graph
  7. from gui.logScreen import LogScreen
  8. from sensors.opticalSensor import OpticalSensor
  9. import logHandler
  10. class MainWindow(tk.Frame):
  11. def __init__(self, root, conf, ac_sensor, opt_sensor, mag_sensor):
  12. self.root = root
  13. self.conf = conf
  14. self.ac_sensor = ac_sensor
  15. self.opt_sensor = opt_sensor
  16. self.mag_sensor = mag_sensor
  17. self.log_handler = logHandler.get_log_handler()
  18. self.popup_window = None
  19. self.log_window = None
  20. self.mainWindow = None
  21. tk.Frame.__init__(self, root)
  22. # data plot at left side
  23. self.graph = Graph(self)
  24. self.graph.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
  25. # frame at right side
  26. self.controls = tk.Frame(self, borderwidth=4)
  27. self.controls.pack(fill=tk.BOTH, side=tk.RIGHT)
  28. self.controlsUpdateTime = 0
  29. self.ac_dro_val_sums = np.ndarray((4), dtype=np.float)
  30. self.ac_dro_val_count = 0
  31. self.ac_dro_x = tk.StringVar()
  32. self.ac_dro_y = tk.StringVar()
  33. self.ac_dro_t1 = tk.StringVar()
  34. self.ac_dro_t2 = tk.StringVar()
  35. self.ac_label = tk.Label(self.controls, text="Acoustic Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  36. self.ac_label.pack(side="top", fill="both", expand=False)
  37. tk.Label(self.controls, textvariable=self.ac_dro_x, anchor="nw").pack(side="top", fill="both", expand=False)
  38. tk.Label(self.controls, textvariable=self.ac_dro_y, anchor="nw").pack(side="top", fill="both", expand=False)
  39. tk.Label(self.controls, textvariable=self.ac_dro_t1, anchor="nw").pack(side="top", fill="both", expand=False)
  40. tk.Label(self.controls, textvariable=self.ac_dro_t2, anchor="nw").pack(side="top", fill="both", expand=False)
  41. self.opt_dro_val_sums = np.ndarray((4), dtype=np.float)
  42. self.opt_dro_val_count = 0
  43. self.opt_dro_x = tk.StringVar()
  44. self.opt_dro_y = tk.StringVar()
  45. self.opt_dro_offset = tk.StringVar()
  46. self.opt_dro_size = tk.StringVar()
  47. self.opt_label = tk.Label(self.controls, text="Optical Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  48. self.opt_label.pack(side="top", fill="both", expand=False)
  49. tk.Label(self.controls, textvariable=self.opt_dro_x, anchor="nw").pack(side="top", fill="both", expand=False)
  50. tk.Label(self.controls, textvariable=self.opt_dro_y, anchor="nw").pack(side="top", fill="both", expand=False)
  51. tk.Label(self.controls, textvariable=self.opt_dro_offset, anchor="nw").pack(side="top", fill="both", expand=False)
  52. tk.Label(self.controls, textvariable=self.opt_dro_size, anchor="nw").pack(side="top", fill="both", expand=False)
  53. self.mag_dro_val_sums = np.ndarray((4), dtype=np.float)
  54. self.mag_dro_val_count = 0
  55. self.mag_dro_x = tk.StringVar()
  56. self.mag_dro_y = tk.StringVar()
  57. self.mag_label = tk.Label(self.controls, text="Magnetic Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  58. self.mag_label.pack(side="top", fill="both", expand=False)
  59. tk.Label(self.controls, textvariable=self.mag_dro_x, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  60. tk.Label(self.controls, textvariable=self.mag_dro_y, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  61. self.quit_button = tk.Button(self.controls, text="Quit", command=self.root.destroy, height=2, foreground="red")
  62. self.quit_button.pack(side="bottom", fill="both")
  63. self.calibrate_submenu_button = tk.Button(self.controls, text="Calibrate", command=self.calibrate_submenu, height=2)
  64. self.calibrate_submenu_button.pack_forget()
  65. self.calibrate_all_button = tk.Button(self.controls, text="Calibrate All", command=self.calibrate_all, height=2)
  66. self.calibrate_all_button.pack_forget()
  67. self.calibrateac_button = tk.Button(self.controls, text="Calibrate AC", command=self.calibrate_ac, height=2)
  68. self.calibrateac_button.pack_forget()
  69. self.calibrateopt_button = tk.Button(self.controls, text = "Calibrate OPT", command = self.calibrate_opt,height = 2)
  70. self.calibrateopt_button.pack_forget()
  71. self.calibratemag_button = tk.Button(self.controls, text = "Calibrate MAG", command = self.calibrate_mag,height = 2)
  72. self.calibratemag_button.pack_forget()
  73. self.clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=2)
  74. self.clear_button.pack_forget()
  75. self.logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=2)
  76. self.logscreen_button.pack_forget()
  77. self.menu_button = tk.Button(self.controls, text="Menu", command=self.menu, height=2)
  78. self.menu_button.pack(side="bottom", fill="both")
  79. self.menu_back_button = tk.Button(self.controls, text="Back", command=self.back, height=2)
  80. self.menu_back_button.pack_forget()
  81. def update(self):
  82. if not self.root.winfo_exists():
  83. return
  84. ac_positions = []
  85. # aggregate measurements
  86. while self.ac_sensor.queue.qsize() > 0:
  87. name, data = self.ac_sensor.queue.get()
  88. if name == "data":
  89. ac_positions.append(data[0:2])
  90. self.ac_dro_val_sums += data
  91. self.ac_dro_val_count += 1
  92. opt_positions = []
  93. while self.opt_sensor.queue.qsize() > 0:
  94. name, data = self.opt_sensor.queue.get()
  95. if name == "data":
  96. opt_positions.append(data[0:2])
  97. self.opt_dro_val_sums += data
  98. self.opt_dro_val_count += 1
  99. mag_positions = []
  100. while self.mag_sensor.queue.qsize() > 0:
  101. name, data = self.mag_sensor.queue.get()
  102. if name == "data":
  103. mag_positions.append(data[0:2])
  104. self.mag_dro_val_sums += data
  105. self.mag_dro_val_count += 1
  106. # graph shows all values as a line
  107. self.graph.update([ac_positions, opt_positions, mag_positions])
  108. # update status color
  109. if self.ac_sensor.dummyActive:
  110. self.ac_label.config(fg="white", bg="red")
  111. elif len(ac_positions) > 0:
  112. self.ac_label.config(fg="white", bg="green")
  113. else:
  114. self.ac_label.config(fg="black", bg="yellow")
  115. if not self.opt_sensor.success:
  116. self.opt_label.config(fg="white", bg="red")
  117. elif len(opt_positions) > 0:
  118. self.opt_label.config(fg="white", bg="green")
  119. else:
  120. self.opt_label.config(fg="black", bg="yellow")
  121. if not self.mag_sensor.success:
  122. self.mag_label.config(fg="white", bg="red")
  123. elif len(mag_positions) > 0:
  124. self.mag_label.config(fg="white", bg="green")
  125. else:
  126. self.mag_label.config(fg="black", bg="yellow")
  127. # readouts will only be updated so often
  128. if self.controlsUpdateTime + 0.4 < time.time():
  129. self.controlsUpdateTime = time.time()
  130. # they display the average of all values
  131. if self.ac_dro_val_count > 0:
  132. self.ac_dro_val_sums /= self.ac_dro_val_count
  133. else:
  134. self.ac_dro_val_sums.fill(0)
  135. self.ac_dro_x.set("X: {:.1f} mm".format(self.ac_dro_val_sums[0]))
  136. self.ac_dro_y.set("Y: {:.1f} mm".format(self.ac_dro_val_sums[1]))
  137. self.ac_dro_t1.set("t1: {:.3f} ms".format(self.ac_dro_val_sums[2]/1000))
  138. self.ac_dro_t2.set("t2: {:.3f} ms".format(self.ac_dro_val_sums[3]/1000))
  139. self.ac_dro_val_sums.fill(0)
  140. self.ac_dro_val_count = 0
  141. if self.opt_dro_val_count > 0:
  142. self.opt_dro_val_sums /= self.opt_dro_val_count
  143. else:
  144. self.opt_dro_val_sums.fill(0)
  145. self.opt_dro_x.set("X: {:.1f} mm".format(self.opt_dro_val_sums[0]))
  146. self.opt_dro_y.set("Y: {:.1f} mm".format(self.opt_dro_val_sums[1]))
  147. self.opt_dro_offset.set("X Offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100))
  148. self.opt_dro_size.set("Y Offset: {:.1f} %".format(self.opt_dro_val_sums[3]*100))
  149. self.opt_dro_val_sums.fill(0)
  150. self.opt_dro_val_count = 0
  151. if self.mag_dro_val_count > 0:
  152. self.mag_dro_val_sums /= self.mag_dro_val_count
  153. else:
  154. self.mag_dro_val_sums.fill(0)
  155. self.mag_dro_x.set("X: {:.1f} mm".format(self.mag_dro_val_sums[0]))
  156. self.mag_dro_y.set("Y: {:.1f} mm".format(self.mag_dro_val_sums[1]))
  157. #self.mag_dro_offset_x.set("X Offset: {:.1f} %".format(self.mag_dro_val_sums[2]*100))
  158. #self.mag_dro_offset_y.set("Y Offset: {:.1f} %".format(self.mag_dro_val_sums[3]*100))
  159. if self.popup_window: # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~~~~~~~+++*
  160. self.popup_window.update()
  161. if self.log_window:
  162. self.log_window.update()
  163. self.root.after(30, self.update)
  164. def calibrate_submenu(self):
  165. self.calibrate_submenu_button.pack_forget()
  166. self.menu_button.pack_forget()
  167. self.clear_button.pack_forget()
  168. self.logscreen_button.pack_forget()
  169. self.menu_back_button.pack(side="bottom", fill="both")
  170. self.calibratemag_button.pack(side="bottom", fill="both")
  171. self.calibrateopt_button.pack(side="bottom", fill="both")
  172. self.calibrateac_button.pack(side="bottom", fill="both")
  173. self.calibrate_all_button.pack(side="bottom", fill="both")
  174. def calibrate_all(self):
  175. pass
  176. def calibrate_ac(self):
  177. self.ac_sensor.start_calibration()
  178. if not self.popup_window or not self.pu_root.winfo_exists():
  179. # create new window
  180. self.pu_root = tk.Toplevel(self.root)
  181. self.pu_root.wm_transient(self.root)
  182. self.pu_root.wm_title("Acoustic Sensor Calibration")
  183. # make it centered
  184. x = (self.pu_root.winfo_screenwidth() - 500) / 2
  185. y = (self.pu_root.winfo_screenheight() - 200) / 2
  186. self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}')
  187. # deactivate mainWindow
  188. self.pu_root.grab_set()
  189. self.popup_window = CalibrationPopUp(self.pu_root, self.ac_sensor.calibration_state, self.conf)
  190. self.popup_window.pack(side="top", fill="both", expand=True)
  191. def calibrate_opt(self):
  192. pass
  193. def calibrate_mag(self): ###
  194. self.mag_sensor.start_calibration()
  195. if not self.popup_window or not self.pu_root.winfo_exists():
  196. # create new window
  197. self.pu_root = tk.Toplevel(self.root)
  198. self.pu_root.wm_transient(self.root)
  199. self.pu_root.wm_title("Magnetic Sensor Calibration")
  200. # make it centered
  201. x = (self.pu_root.winfo_screenwidth() - 500) / 2
  202. y = (self.pu_root.winfo_screenheight() - 200) / 2
  203. self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}')
  204. # deactivate mainWindow
  205. self.pu_root.grab_set()
  206. self.popup_window = CalibrationPopUp(self.pu_root, self.mag_sensor.calibration_state, self.conf)
  207. self.popup_window.pack(side="top", fill="both", expand=True)
  208. def open_log(self):
  209. #create new window
  210. self.log_root = tk.Toplevel(self.root)
  211. self.log_root.wm_transient(self.root)
  212. self.log_root.wm_title("Logs")
  213. #center
  214. x = (self.log_root.winfo_screenwidth() - 780) / 2
  215. y = (self.log_root.winfo_screenheight() - 400) / 2
  216. self.log_root.geometry(f'780x400+{int(x)}+{int(y)}')
  217. # deactivate mainWindow
  218. self.log_root.grab_set()
  219. self.log_window = LogScreen(self.log_root)
  220. self.log_window.pack(side="top", fill="both", expand=True)
  221. # Menu Button
  222. def menu(self):
  223. self.menu_back_button.pack(side="bottom", fill="both")
  224. self.calibrate_submenu_button.pack(side="bottom", fill="both")
  225. self.clear_button.pack(side="bottom", fill="both")
  226. self.logscreen_button.pack(side="bottom", fill="both")
  227. self.menu_button.pack_forget()
  228. #Back Button
  229. def back(self):
  230. self.calibratemag_button.pack_forget()
  231. self.calibrateopt_button.pack_forget()
  232. self.calibrateac_button.pack_forget()
  233. self.clear_button.pack_forget()
  234. self.logscreen_button.pack_forget()
  235. self.calibrate_submenu_button.pack_forget()
  236. self.menu_button.pack(side="bottom", fill="both")
  237. self.menu_back_button.pack_forget()