acusticSensor.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. from sensors.connection import globalArduinoSlave
  2. import time
  3. import statistics
  4. import math
  5. import threading
  6. import random
  7. import traceback
  8. conn = globalArduinoSlave()
  9. class AcusticSensor:
  10. def __init__(self, conf, ac_queue, calibration_state):
  11. self.ac_queue = ac_queue
  12. self.calibration_state = calibration_state
  13. self.field_height = float(conf["field"]["y"])
  14. self.field_length = float(conf["field"]["x"])
  15. self.sensor_distance = float(conf["ac_sensor"]["sensor_distance"])
  16. self.sensor_y_offset = float(conf["ac_sensor"]["y_offset"])
  17. self.left_sensor_x_offset = float(conf["ac_sensor"]["left_x_offset"])
  18. self.right_sensor_x_offset = float(conf["ac_sensor"]["right_x_offset"])
  19. self.sonic_speed = float(conf["ac_sensor"]["sonicspeed"])
  20. self.overhead_left = float(conf["ac_sensor"]["overhead_left"])
  21. self.overhead_right = float(conf["ac_sensor"]["overhead_right"])
  22. self.time_vals = [[],[]]
  23. self.cal_values = {
  24. "left": [0, 0],
  25. "right": [0, 0]
  26. }
  27. self.n = 0
  28. def start(self):
  29. self.dummyActive = True
  30. if not conn.isConnected():
  31. conn.open()
  32. conn.addRecvCallback(self._readCb)
  33. dummyThread = threading.Thread(target=self._readCb_dummy)
  34. dummyThread.start()
  35. def start_calibration(self):
  36. self.calibration_state.reset_state()
  37. self.time_vals = [[],[]]
  38. self.calibration_state.next_state()
  39. def stop(self):
  40. print("stop acoustic sensor")
  41. self.dummyActive = False
  42. conn.close()
  43. def _readCb_dummy(self):
  44. while self.dummyActive:
  45. value = (900+random.randint(0,300),900+random.randint(0,300))
  46. value = ((math.sin(self.n)+1)*400+900, (math.cos(self.n)+1)*400+900)
  47. self.n += 0.02
  48. if self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_1:
  49. value = (1541+random.randint(-50,50),2076+random.randint(-50,50))
  50. elif self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_2:
  51. value = (2076+random.randint(-50,50),1541+random.randint(-50,50))
  52. self.calibrate(value)
  53. self.pass_to_gui(self.calculate_position(value))
  54. time.sleep(0.01)
  55. def _readCb(self, raw):
  56. value = conn.getAcusticRTTs()
  57. if self.dummyActive:
  58. self.dummyActive = False
  59. if value[0] >= 0 and value[1] >= 0:
  60. self.calibrate(value)
  61. x, y = self.calculate_position(value)
  62. self.pass_to_gui((x, y, *value))
  63. def calibrate(self, value):
  64. if self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_1:
  65. self.time_vals[0].append(value[0])
  66. self.time_vals[1].append(value[1])
  67. if len(self.time_vals[0]) >= 100:
  68. self.cal_values["left"][0] = statistics.mean(self.time_vals[0])
  69. self.cal_values["right"][1] = statistics.mean(self.time_vals[1])
  70. self.time_vals = [[],[]]
  71. self.calibration_state.next_state() # signal gui to get next position
  72. elif self.calibration_state.get_state() == self.calibration_state.ACCUMULATING_2:
  73. self.time_vals[0].append(value[0])
  74. self.time_vals[1].append(value[1])
  75. if len(self.time_vals[0]) >= 100:
  76. self.cal_values["left"][1] = statistics.mean(self.time_vals[0])
  77. self.cal_values["right"][0] = statistics.mean(self.time_vals[1])
  78. # all values have been captured
  79. print(self.cal_values)
  80. # calculate calibration results
  81. timedif = self.cal_values["left"][1] - self.cal_values["left"][0]
  82. distance_1 = math.sqrt(self.left_sensor_x_offset**2 + (self.sensor_y_offset + self.field_height)**2 )
  83. distance_2 = math.sqrt((self.left_sensor_x_offset + self.field_length)**2 + (self.sensor_y_offset + self.field_height)**2 )
  84. distancedif = distance_2 - distance_1
  85. sonicspeed_1 = distancedif / timedif
  86. overhead_1 = statistics.mean((self.cal_values["left"][1] - distance_1/sonicspeed_1, self.cal_values["left"][0] - distance_2/sonicspeed_1))
  87. timedif = self.cal_values["right"][1] - self.cal_values["right"][0]
  88. distance_1 = math.sqrt(self.right_sensor_x_offset**2 + (self.sensor_y_offset + self.field_height)**2 )
  89. distance_2 = math.sqrt((self.right_sensor_x_offset + self.field_length)**2 + (self.sensor_y_offset + self.field_height)**2 )
  90. distancedif = distance_2 - distance_1
  91. sonicspeed_2 = distancedif / timedif
  92. overhead_2 = statistics.mean((self.cal_values["right"][0] - distance_1/sonicspeed_2, self.cal_values["right"][1] - distance_2/sonicspeed_2))
  93. self.sonic_speed = statistics.mean((sonicspeed_1,sonicspeed_2))
  94. self.overhead_left = overhead_1
  95. self.overhead_right = overhead_2
  96. print("calibration results:")
  97. print(" sonicspeed: {:8.6f} mm/us".format(self.sonic_speed))
  98. print(" overhead_left: {:8.3f} us".format(self.overhead_left))
  99. print(" overhead_right: {:8.3f} us".format(self.overhead_right))
  100. self.calibration_state.next_state()
  101. def read(self):
  102. value = conn.getAcusticRTTs()
  103. return value
  104. def calculate_position(self,values):
  105. try:
  106. val1, val2 = values
  107. val1 -= self.overhead_left
  108. val2 -= self.overhead_right
  109. distance_left = val1 * self.sonic_speed
  110. distance_right = val2 * self.sonic_speed
  111. x = (self.sensor_distance**2 - distance_right**2 + distance_left**2) / (2*self.sensor_distance) + self.left_sensor_x_offset
  112. y = math.sqrt(max(distance_left**2 - x**2, 0)) - self.sensor_y_offset
  113. return(x,y)
  114. except Exception as e:
  115. print(values)
  116. traceback.print_exc()
  117. def pass_to_gui(self, data):
  118. self.ac_queue.put(("data", data))