mainWindow.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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_label = tk.Label(self.controls, text="Magnetic Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
  56. self.mag_label.pack(side="top", fill="both", expand=False)
  57. self.mag_dro_x = tk.StringVar()
  58. self.mag_dro_y = tk.StringVar()
  59. self.mag_dro_offset_x = tk.StringVar()
  60. self.mag_dro_offset_y = tk.StringVar()
  61. tk.Label(self.controls, textvariable=self.mag_dro_x, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  62. tk.Label(self.controls, textvariable=self.mag_dro_y, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  63. tk.Label(self.controls, textvariable=self.mag_dro_x, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  64. tk.Label(self.controls, textvariable=self.mag_dro_y, anchor = "nw").pack(side = "top", fill = "both", expand = False)
  65. self.quit_button = tk.Button(self.controls, text="Quit", command=self.root.destroy, height=2, foreground="red")
  66. self.quit_button.pack(side="bottom", fill="both")
  67. self.calibrateac_button = tk.Button(self.controls, text="Calibrate AC", command=self.calibrate_ac, height=4)
  68. self.calibrateac_button.pack_forget()
  69. self.calibratemc_button = tk.Button(self.controls, text = "Calibrate MC", command = self.calibrate_mc,height = 4)
  70. self.calibratemc_button.pack_forget()
  71. self.clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=4)
  72. self.clear_button.pack_forget()
  73. self.logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=4)
  74. self.logscreen_button.pack_forget()
  75. self.menu_button = tk.Button(self.controls, text="Menu", command=self.menu, height=4)
  76. self.menu_button.pack(side="bottom", fill="both")
  77. self.menu_back_button = tk.Button(self.controls, text="Back", command=self.back, height=4)
  78. self.menu_back_button.pack_forget()
  79. def update(self):
  80. if not self.root.winfo_exists():
  81. return
  82. ac_positions = []
  83. # aggregate measurements
  84. while self.ac_sensor.queue.qsize() > 0:
  85. name, data = self.ac_sensor.queue.get()
  86. if name == "data":
  87. ac_positions.append(data[0:2])
  88. self.ac_dro_val_sums += data
  89. self.ac_dro_val_count += 1
  90. opt_positions = []
  91. while self.opt_sensor.queue.qsize() > 0:
  92. name, data = self.opt_sensor.queue.get()
  93. if name == "data":
  94. opt_positions.append(data[0:2])
  95. self.opt_dro_val_sums += data
  96. self.opt_dro_val_count += 1
  97. mag_positions = []
  98. while self.mag_sensor.queue.qsize() > 0:
  99. name, data = self.mag_sensor.queue.get()
  100. if name == "data":
  101. mag_positions.append(data[0:2])
  102. self.mag_dro_val_sums += data
  103. self.mag_dro_val_count += 1
  104. # graph shows all values as a line
  105. self.graph.update([ac_positions, opt_positions, mag_positions])
  106. # update status color
  107. if self.ac_sensor.dummyActive:
  108. self.ac_label.config(fg="white", bg="red")
  109. elif len(ac_positions) > 0:
  110. self.ac_label.config(fg="white", bg="green")
  111. else:
  112. self.ac_label.config(fg="black", bg="yellow")
  113. if not self.opt_sensor.success:
  114. self.opt_label.config(fg="white", bg="red")
  115. elif len(opt_positions) > 0:
  116. self.opt_label.config(fg="white", bg="green")
  117. else:
  118. self.opt_label.config(fg="black", bg="yellow")
  119. if not self.mag_sensor.success:
  120. self.mag_label.config(fg="white", bg="red")
  121. elif len(mag_positions) > 0:
  122. self.mag_label.config(fg="white", bg="green")
  123. else:
  124. self.mag_label.config(fg="black", bg="yellow")
  125. # readouts will only be updated so often
  126. if self.controlsUpdateTime + 0.4 < time.time():
  127. self.controlsUpdateTime = time.time()
  128. # they display the average of all values
  129. if self.ac_dro_val_count > 0:
  130. self.ac_dro_val_sums /= self.ac_dro_val_count
  131. else:
  132. self.ac_dro_val_sums.fill(0)
  133. self.ac_dro_x.set("X: {:.1f} mm".format(self.ac_dro_val_sums[0]))
  134. self.ac_dro_y.set("Y: {:.1f} mm".format(self.ac_dro_val_sums[1]))
  135. self.ac_dro_t1.set("t1: {:.3f} ms".format(self.ac_dro_val_sums[2]/1000))
  136. self.ac_dro_t2.set("t2: {:.3f} ms".format(self.ac_dro_val_sums[3]/1000))
  137. self.ac_dro_val_sums.fill(0)
  138. self.ac_dro_val_count = 0
  139. if self.opt_dro_val_count > 0:
  140. self.opt_dro_val_sums /= self.opt_dro_val_count
  141. else:
  142. self.opt_dro_val_sums.fill(0)
  143. self.opt_dro_x.set("X: {:.1f} mm".format(self.opt_dro_val_sums[0]))
  144. self.opt_dro_y.set("Y: {:.1f} mm".format(self.opt_dro_val_sums[1]))
  145. self.opt_dro_offset.set("X Offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100))
  146. self.opt_dro_size.set("Y Offset: {:.1f} %".format(self.opt_dro_val_sums[3]*100))
  147. self.opt_dro_val_sums.fill(0)
  148. self.opt_dro_val_count = 0
  149. if self.mag_dro_val_count > 0:
  150. self.mag_dro_val_sums /= self.mag_dro_val_count
  151. else:
  152. self.mag_dro_val_sums.fill(0)
  153. self.mag_dro_x.set("X: {:.1f} mm".format(self.opt_dro_val_sums[0]))
  154. self.mag_dro_y.set("Y: {:.1f} mm".format(self.opt_dro_val_sums[1]))
  155. self.mag_dro_offset_x.set("offset: {:.1f} %".format(self.opt_dro_val_sums[2]*100))
  156. self.mag_dro_offset_y.set("size: {:.1f} %".format(self.opt_dro_val_sums[3]*100))
  157. if self.popup_window:
  158. self.popup_window.update()
  159. if self.log_window:
  160. self.log_window.update()
  161. self.root.after(30, self.update)
  162. def calibrate_ac(self):
  163. self.ac_sensor.start_calibration()
  164. if not self.popup_window or not self.pu_root.winfo_exists():
  165. # create new window
  166. self.pu_root = tk.Toplevel(self.root)
  167. self.pu_root.wm_transient(self.root)
  168. self.pu_root.wm_title("Acoustic Sensor Calibration")
  169. # make it centered
  170. x = (self.pu_root.winfo_screenwidth() - 500) / 2
  171. y = (self.pu_root.winfo_screenheight() - 200) / 2
  172. self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}')
  173. # deactivate mainWindow
  174. self.pu_root.grab_set()
  175. self.popup_window = CalibrationPopUp(self.pu_root, self.ac_sensor.calibration_state, self.conf)
  176. self.popup_window.pack(side="top", fill="both", expand=True)
  177. def calibrate_mc(self):
  178. pass
  179. def open_log(self):
  180. #create new window
  181. self.log_root = tk.Toplevel(self.root)
  182. self.log_root.wm_transient(self.root)
  183. self.log_root.wm_title("Logs")
  184. #center
  185. x = (self.log_root.winfo_screenwidth() - 780) / 2
  186. y = (self.log_root.winfo_screenheight() - 400) / 2
  187. self.log_root.geometry(f'780x400+{int(x)}+{int(y)}')
  188. # deactivate mainWindow
  189. self.log_root.grab_set()
  190. self.log_window = LogScreen(self.log_root)
  191. self.log_window.pack(side="top", fill="both", expand=True)
  192. # Menu Button
  193. def menu(self):
  194. self.menu_back_button.pack(side="bottom", fill="both")
  195. self.calibrateac_button.pack(side="bottom", fill="both")
  196. self.calibratemc_button.pack(side="bottom", fill="both")
  197. self.clear_button.pack(side="bottom", fill="both")
  198. self.logscreen_button.pack(side="bottom", fill="both")
  199. self.menu_button.pack_forget()
  200. #Back Button
  201. def back(self):
  202. self.calibrateac_button.pack_forget()
  203. self.calibratemc_button.pack_forget()
  204. self.clear_button.pack_forget()
  205. self.logscreen_button.pack_forget()
  206. self.menu_button.pack(side="bottom", fill="both")
  207. self.menu_back_button.pack_forget()