sensors.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. from connection import ArduinoSlave
  2. import markerDetection
  3. import time
  4. import statistics
  5. import math
  6. import threading
  7. import random
  8. import traceback
  9. import cv2
  10. conn = ArduinoSlave()
  11. class AcusticSensor:
  12. def __init__(self, conf, ac_queue, calibration_state):
  13. self.ac_queue = ac_queue
  14. self.calibration_state = calibration_state
  15. self.field_height = float(conf["field"]["y"])
  16. self.field_length = float(conf["field"]["x"])
  17. self.sensor_distance = float(conf["ac_sensor"]["sensor_distance"])
  18. self.sensor_y_offset = float(conf["ac_sensor"]["y_offset"])
  19. self.left_sensor_x_offset = float(conf["ac_sensor"]["left_x_offset"])
  20. self.right_sensor_x_offset = float(conf["ac_sensor"]["right_x_offset"])
  21. self.sonic_speed = float(conf["ac_sensor"]["sonicspeed"])
  22. self.overhead_left = float(conf["ac_sensor"]["overhead_left"])
  23. self.overhead_right = float(conf["ac_sensor"]["overhead_right"])
  24. self.time_vals = [[],[]]
  25. self.cal_values = {
  26. "left": [0, 0],
  27. "right": [0, 0]
  28. }
  29. self.n = 0
  30. def start(self):
  31. self.dummyActive = True
  32. if not conn.isConnected():
  33. conn.open()
  34. conn.addRecvCallback(self._readCb)
  35. dummyThread = threading.Thread(target=self._readCb_dummy)
  36. dummyThread.start()
  37. def start_calibration(self):
  38. self.calibration_state.reset_state()
  39. self.time_vals = [[],[]]
  40. self.calibration_state.next_state()
  41. def stop(self):
  42. print("stop acoustic sensor")
  43. self.dummyActive = False
  44. conn.close()
  45. def _readCb_dummy(self):
  46. while self.dummyActive:
  47. value = (900+random.randint(0,300),900+random.randint(0,300))
  48. value = ((math.sin(self.n)+1)*400+900, (math.cos(self.n)+1)*400+900)
  49. self.n += 0.02
  50. if self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_1:
  51. value = (1541+random.randint(-50,50),2076+random.randint(-50,50))
  52. elif self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_2:
  53. value = (2076+random.randint(-50,50),1541+random.randint(-50,50))
  54. self.calibrate(value)
  55. self.pass_to_gui(self.calculate_position(value))
  56. time.sleep(0.01)
  57. def _readCb(self, raw):
  58. value = conn.getAcusticRTTs()
  59. if self.dummyActive:
  60. self.dummyActive = False
  61. if value[0] >= 0 and value[1] >= 0:
  62. self.calibrate(value)
  63. x, y = self.calculate_position(value)
  64. self.pass_to_gui((x, y, *value))
  65. def calibrate(self, value):
  66. if self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_1:
  67. self.time_vals[0].append(value[0])
  68. self.time_vals[1].append(value[1])
  69. if len(self.time_vals[0]) >= 100:
  70. self.cal_values["left"][0] = statistics.mean(self.time_vals[0])
  71. self.cal_values["right"][1] = statistics.mean(self.time_vals[1])
  72. self.time_vals = [[],[]]
  73. self.calibration_state.next_state() # signal gui to get next position
  74. elif self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_2:
  75. self.time_vals[0].append(value[0])
  76. self.time_vals[1].append(value[1])
  77. if len(self.time_vals[0]) >= 100:
  78. self.cal_values["left"][1] = statistics.mean(self.time_vals[0])
  79. self.cal_values["right"][0] = statistics.mean(self.time_vals[1])
  80. # all values have been captured
  81. print(self.cal_values)
  82. # calculate calibration results
  83. timedif = self.cal_values["left"][1] - self.cal_values["left"][0]
  84. distance_1 = math.sqrt(self.left_sensor_x_offset**2 + (self.sensor_y_offset + self.field_height)**2 )
  85. distance_2 = math.sqrt((self.left_sensor_x_offset + self.field_length)**2 + (self.sensor_y_offset + self.field_height)**2 )
  86. distancedif = distance_2 - distance_1
  87. sonicspeed_1 = distancedif / timedif
  88. overhead_1 = statistics.mean((self.cal_values["left"][1] - distance_1/sonicspeed_1, self.cal_values["left"][0] - distance_2/sonicspeed_1))
  89. timedif = self.cal_values["right"][1] - self.cal_values["right"][0]
  90. distance_1 = math.sqrt(self.right_sensor_x_offset**2 + (self.sensor_y_offset + self.field_height)**2 )
  91. distance_2 = math.sqrt((self.right_sensor_x_offset + self.field_length)**2 + (self.sensor_y_offset + self.field_height)**2 )
  92. distancedif = distance_2 - distance_1
  93. sonicspeed_2 = distancedif / timedif
  94. overhead_2 = statistics.mean((self.cal_values["right"][0] - distance_1/sonicspeed_2, self.cal_values["right"][1] - distance_2/sonicspeed_2))
  95. self.sonic_speed = statistics.mean((sonicspeed_1,sonicspeed_2))
  96. self.overhead_left = overhead_1
  97. self.overhead_right = overhead_2
  98. print("calibration results:")
  99. print(" sonicspeed: {:8.6f} mm/us".format(self.sonic_speed))
  100. print(" overhead_left: {:8.3f} us".format(self.overhead_left))
  101. print(" overhead_right: {:8.3f} us".format(self.overhead_right))
  102. self.calibration_state.next_state()
  103. def read(self):
  104. value = conn.getAcusticRTTs()
  105. return value
  106. def calculate_position(self,values):
  107. try:
  108. val1, val2 = values
  109. val1 -= self.overhead_left
  110. val2 -= self.overhead_right
  111. distance_left = val1 * self.sonic_speed
  112. distance_right = val2 * self.sonic_speed
  113. x = (self.sensor_distance**2 - distance_right**2 + distance_left**2) / (2*self.sensor_distance) + self.left_sensor_x_offset
  114. y = math.sqrt(max(distance_left**2 - x**2, 0)) - self.sensor_y_offset
  115. return(x,y)
  116. except Exception as e:
  117. print(values)
  118. traceback.print_exc()
  119. def pass_to_gui(self, data):
  120. self.ac_queue.put(("data", data))
  121. class MagneticSensor:
  122. def __init__(self):
  123. pass
  124. def start(self):
  125. if not conn.isConnected():
  126. conn.open()
  127. conn.addRecvCallback(self._readCb)
  128. def _readCb(self, raw):
  129. print("mag: ", conn.getMagneticField())
  130. def calibrate(self, x, y):
  131. pass
  132. def read(self):
  133. return conn.getMagneticField()
  134. class OpticalSensor():
  135. def __init__(self):
  136. self.cap = cv2.VideoCapture(0)
  137. self._t = None
  138. self.values = None
  139. def start(self):
  140. if not self._t:
  141. self._t = threading.Thread(target=self._getFrames, args=())
  142. self._t.daemon = True # thread dies when main thread (only non-daemon thread) exits.
  143. self._t.start()
  144. def _getFrames(self):
  145. while True:
  146. success, image = self.cap.read()
  147. if success:
  148. self.values = markerDetection.measureDistances(image)
  149. print("opt:", self.values)
  150. def calibrate(self, x, y):
  151. pass
  152. def read(self):
  153. return self.values
  154. if __name__ == "__main__":
  155. acc = AcusticSensor()
  156. acc.start()
  157. mag = MagneticSensor()
  158. mag.start()
  159. opt = OpticalSensor()
  160. opt.start()
  161. while True:
  162. time.sleep(1)