radar_interface.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #!/usr/bin/env python3
  2. from math import cos, sin
  3. from cereal import car
  4. from opendbc.can.parser import CANParser
  5. from common.conversions import Conversions as CV
  6. from selfdrive.car.ford.values import CANBUS, DBC, RADAR
  7. from selfdrive.car.interfaces import RadarInterfaceBase
  8. DELPHI_ESR_RADAR_MSGS = list(range(0x500, 0x540))
  9. DELPHI_MRR_RADAR_START_ADDR = 0x120
  10. DELPHI_MRR_RADAR_MSG_COUNT = 64
  11. def _create_delphi_esr_radar_can_parser():
  12. msg_n = len(DELPHI_ESR_RADAR_MSGS)
  13. signals = list(zip(['X_Rel'] * msg_n + ['Angle'] * msg_n + ['V_Rel'] * msg_n,
  14. DELPHI_ESR_RADAR_MSGS * 3))
  15. checks = list(zip(DELPHI_ESR_RADAR_MSGS, [20] * msg_n))
  16. return CANParser(RADAR.DELPHI_ESR, signals, checks, CANBUS.radar)
  17. def _create_delphi_mrr_radar_can_parser():
  18. signals = []
  19. checks = []
  20. for i in range(1, DELPHI_MRR_RADAR_MSG_COUNT + 1):
  21. msg = f"MRR_Detection_{i:03d}"
  22. signals += [
  23. (f"CAN_DET_VALID_LEVEL_{i:02d}", msg),
  24. (f"CAN_DET_AZIMUTH_{i:02d}", msg),
  25. (f"CAN_DET_RANGE_{i:02d}", msg),
  26. (f"CAN_DET_RANGE_RATE_{i:02d}", msg),
  27. (f"CAN_DET_AMPLITUDE_{i:02d}", msg),
  28. (f"CAN_SCAN_INDEX_2LSB_{i:02d}", msg),
  29. ]
  30. checks += [(msg, 20)]
  31. return CANParser(RADAR.DELPHI_MRR, signals, checks, CANBUS.radar)
  32. class RadarInterface(RadarInterfaceBase):
  33. def __init__(self, CP):
  34. super().__init__(CP)
  35. self.updated_messages = set()
  36. self.track_id = 0
  37. self.radar = DBC[CP.carFingerprint]['radar']
  38. if self.radar is None:
  39. self.rcp = None
  40. elif self.radar == RADAR.DELPHI_ESR:
  41. self.rcp = _create_delphi_esr_radar_can_parser()
  42. self.trigger_msg = DELPHI_ESR_RADAR_MSGS[-1]
  43. self.valid_cnt = {key: 0 for key in DELPHI_ESR_RADAR_MSGS}
  44. elif self.radar == RADAR.DELPHI_MRR:
  45. self.rcp = _create_delphi_mrr_radar_can_parser()
  46. self.trigger_msg = DELPHI_MRR_RADAR_START_ADDR + DELPHI_MRR_RADAR_MSG_COUNT - 1
  47. else:
  48. raise ValueError(f"Unsupported radar: {self.radar}")
  49. def update(self, can_strings):
  50. if self.rcp is None:
  51. return super().update(None)
  52. vls = self.rcp.update_strings(can_strings)
  53. self.updated_messages.update(vls)
  54. if self.trigger_msg not in self.updated_messages:
  55. return None
  56. ret = car.RadarData.new_message()
  57. errors = []
  58. if not self.rcp.can_valid:
  59. errors.append("canError")
  60. ret.errors = errors
  61. if self.radar == RADAR.DELPHI_ESR:
  62. self._update_delphi_esr()
  63. elif self.radar == RADAR.DELPHI_MRR:
  64. self._update_delphi_mrr()
  65. ret.points = list(self.pts.values())
  66. self.updated_messages.clear()
  67. return ret
  68. def _update_delphi_esr(self):
  69. for ii in sorted(self.updated_messages):
  70. cpt = self.rcp.vl[ii]
  71. if cpt['X_Rel'] > 0.00001:
  72. self.valid_cnt[ii] = 0 # reset counter
  73. if cpt['X_Rel'] > 0.00001:
  74. self.valid_cnt[ii] += 1
  75. else:
  76. self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0)
  77. #print ii, self.valid_cnt[ii], cpt['VALID'], cpt['X_Rel'], cpt['Angle']
  78. # radar point only valid if there have been enough valid measurements
  79. if self.valid_cnt[ii] > 0:
  80. if ii not in self.pts:
  81. self.pts[ii] = car.RadarData.RadarPoint.new_message()
  82. self.pts[ii].trackId = self.track_id
  83. self.track_id += 1
  84. self.pts[ii].dRel = cpt['X_Rel'] # from front of car
  85. self.pts[ii].yRel = cpt['X_Rel'] * cpt['Angle'] * CV.DEG_TO_RAD # in car frame's y axis, left is positive
  86. self.pts[ii].vRel = cpt['V_Rel']
  87. self.pts[ii].aRel = float('nan')
  88. self.pts[ii].yvRel = float('nan')
  89. self.pts[ii].measured = True
  90. else:
  91. if ii in self.pts:
  92. del self.pts[ii]
  93. def _update_delphi_mrr(self):
  94. for ii in range(1, DELPHI_MRR_RADAR_MSG_COUNT + 1):
  95. msg = self.rcp.vl[f"MRR_Detection_{ii:03d}"]
  96. # SCAN_INDEX rotates through 0..3 on each message
  97. # treat these as separate points
  98. scanIndex = msg[f"CAN_SCAN_INDEX_2LSB_{ii:02d}"]
  99. i = (ii - 1) * 4 + scanIndex
  100. if i not in self.pts:
  101. self.pts[i] = car.RadarData.RadarPoint.new_message()
  102. self.pts[i].trackId = self.track_id
  103. self.pts[i].aRel = float('nan')
  104. self.pts[i].yvRel = float('nan')
  105. self.track_id += 1
  106. valid = bool(msg[f"CAN_DET_VALID_LEVEL_{ii:02d}"])
  107. amplitude = msg[f"CAN_DET_AMPLITUDE_{ii:02d}"] # dBsm [-64|63]
  108. if valid and 0 < amplitude <= 15:
  109. azimuth = msg[f"CAN_DET_AZIMUTH_{ii:02d}"] # rad [-3.1416|3.13964]
  110. dist = msg[f"CAN_DET_RANGE_{ii:02d}"] # m [0|255.984]
  111. distRate = msg[f"CAN_DET_RANGE_RATE_{ii:02d}"] # m/s [-128|127.984]
  112. # *** openpilot radar point ***
  113. self.pts[i].dRel = cos(azimuth) * dist # m from front of car
  114. self.pts[i].yRel = -sin(azimuth) * dist # in car frame's y axis, left is positive
  115. self.pts[i].vRel = distRate # m/s
  116. self.pts[i].measured = True
  117. else:
  118. del self.pts[i]