radar_interface.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #!/usr/bin/env python3
  2. from cereal import car
  3. from opendbc.can.parser import CANParser
  4. from selfdrive.car.tesla.values import DBC, CANBUS
  5. from selfdrive.car.interfaces import RadarInterfaceBase
  6. RADAR_MSGS_A = list(range(0x310, 0x36E, 3))
  7. RADAR_MSGS_B = list(range(0x311, 0x36F, 3))
  8. NUM_POINTS = len(RADAR_MSGS_A)
  9. def get_radar_can_parser(CP):
  10. # Status messages
  11. signals = [
  12. ('RADC_HWFail', 'TeslaRadarSguInfo'),
  13. ('RADC_SGUFail', 'TeslaRadarSguInfo'),
  14. ('RADC_SensorDirty', 'TeslaRadarSguInfo'),
  15. ]
  16. checks = [
  17. ('TeslaRadarSguInfo', 10),
  18. ]
  19. # Radar tracks. There are also raw point clouds available,
  20. # we don't use those.
  21. for i in range(NUM_POINTS):
  22. msg_id_a = RADAR_MSGS_A[i]
  23. msg_id_b = RADAR_MSGS_B[i]
  24. # There is a bunch more info in the messages,
  25. # but these are the only things actually used in openpilot
  26. signals.extend([
  27. ('LongDist', msg_id_a),
  28. ('LongSpeed', msg_id_a),
  29. ('LatDist', msg_id_a),
  30. ('LongAccel', msg_id_a),
  31. ('Meas', msg_id_a),
  32. ('Tracked', msg_id_a),
  33. ('Index', msg_id_a),
  34. ('LatSpeed', msg_id_b),
  35. ('Index2', msg_id_b),
  36. ])
  37. checks.extend([
  38. (msg_id_a, 8),
  39. (msg_id_b, 8),
  40. ])
  41. return CANParser(DBC[CP.carFingerprint]['radar'], signals, checks, CANBUS.radar)
  42. class RadarInterface(RadarInterfaceBase):
  43. def __init__(self, CP):
  44. super().__init__(CP)
  45. self.rcp = get_radar_can_parser(CP)
  46. self.updated_messages = set()
  47. self.track_id = 0
  48. self.trigger_msg = RADAR_MSGS_B[-1]
  49. def update(self, can_strings):
  50. if self.rcp is None:
  51. return super().update(None)
  52. values = self.rcp.update_strings(can_strings)
  53. self.updated_messages.update(values)
  54. if self.trigger_msg not in self.updated_messages:
  55. return None
  56. ret = car.RadarData.new_message()
  57. # Errors
  58. errors = []
  59. sgu_info = self.rcp.vl['TeslaRadarSguInfo']
  60. if not self.rcp.can_valid:
  61. errors.append('canError')
  62. if sgu_info['RADC_HWFail'] or sgu_info['RADC_SGUFail'] or sgu_info['RADC_SensorDirty']:
  63. errors.append('fault')
  64. ret.errors = errors
  65. # Radar tracks
  66. for i in range(NUM_POINTS):
  67. msg_a = self.rcp.vl[RADAR_MSGS_A[i]]
  68. msg_b = self.rcp.vl[RADAR_MSGS_B[i]]
  69. # Make sure msg A and B are together
  70. if msg_a['Index'] != msg_b['Index2']:
  71. continue
  72. # Check if it's a valid track
  73. if not msg_a['Tracked']:
  74. if i in self.pts:
  75. del self.pts[i]
  76. continue
  77. # New track!
  78. if i not in self.pts:
  79. self.pts[i] = car.RadarData.RadarPoint.new_message()
  80. self.pts[i].trackId = self.track_id
  81. self.track_id += 1
  82. # Parse track data
  83. self.pts[i].dRel = msg_a['LongDist']
  84. self.pts[i].yRel = msg_a['LatDist']
  85. self.pts[i].vRel = msg_a['LongSpeed']
  86. self.pts[i].aRel = msg_a['LongAccel']
  87. self.pts[i].yvRel = msg_b['LatSpeed']
  88. self.pts[i].measured = bool(msg_a['Meas'])
  89. ret.points = list(self.pts.values())
  90. self.updated_messages.clear()
  91. return ret