radard: tie radard frequency to modelV2 (#29063)

old-commit-hash: 255f5c13f2
beeps
Kacper Rączy 2 years ago committed by GitHub
parent faa9444a6a
commit 79fa322d4a
  1. 2
      cereal
  2. 2
      selfdrive/car/chrysler/radar_interface.py
  3. 2
      selfdrive/car/ford/radar_interface.py
  4. 2
      selfdrive/car/gm/radar_interface.py
  5. 11
      selfdrive/car/honda/radar_interface.py
  6. 2
      selfdrive/car/hyundai/radar_interface.py
  7. 8
      selfdrive/car/interfaces.py
  8. 2
      selfdrive/car/tesla/radar_interface.py
  9. 13
      selfdrive/car/toyota/radar_interface.py
  10. 64
      selfdrive/controls/radard.py
  11. 4
      selfdrive/test/process_replay/process_replay.py
  12. 2
      selfdrive/test/process_replay/ref_commit

@ -1 +1 @@
Subproject commit 2689300b4aba2a8850a0a8d985f39e2e3954eae9 Subproject commit 774bf79f4da2b72d01c34a2f2d6ac9388293fbdb

@ -52,7 +52,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.rcp is None or self.CP.radarUnavailable: if self.rcp is None or self.CP.radarUnavailable:
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)

@ -62,7 +62,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.rcp is None: if self.rcp is None:
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)

@ -44,7 +44,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.rcp is None: if self.rcp is None:
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)

@ -38,7 +38,7 @@ class RadarInterface(RadarInterfaceBase):
# in Bosch radar and we are only steering for now, so sleep 0.05s to keep # in Bosch radar and we are only steering for now, so sleep 0.05s to keep
# radard at 20Hz and return no points # radard at 20Hz and return no points
if self.radar_off_can: if self.radar_off_can:
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)
@ -54,7 +54,14 @@ class RadarInterface(RadarInterfaceBase):
ret = car.RadarData.new_message() ret = car.RadarData.new_message()
for ii in sorted(updated_messages): for ii in sorted(updated_messages):
cpt = self.rcp.vl[ii] combined_vals = self.rcp.vl_all[ii]
n_vals_per_addr = len(list(combined_vals.values())[0])
cpts = [
{k: v[i] for k, v in combined_vals.items()}
for i in range(n_vals_per_addr)
]
for cpt in cpts:
if ii == 0x400: if ii == 0x400:
# check for radar faults # check for radar faults
self.radar_fault = cpt['RADAR_STATE'] != 0x79 self.radar_fault = cpt['RADAR_STATE'] != 0x79

@ -42,7 +42,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.radar_off_can or (self.rcp is None): if self.radar_off_can or (self.rcp is None):
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)

@ -1,6 +1,5 @@
import yaml import yaml
import os import os
import time
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from typing import Any, Dict, Optional, Tuple, List, Callable from typing import Any, Dict, Optional, Tuple, List, Callable
@ -311,14 +310,9 @@ class RadarInterfaceBase(ABC):
self.rcp = None self.rcp = None
self.pts = {} self.pts = {}
self.delay = 0 self.delay = 0
self.radar_ts = CP.radarTimeStep
self.no_radar_sleep = 'NO_RADAR_SLEEP' in os.environ
def update(self, can_strings): def update(self, can_strings):
ret = car.RadarData.new_message() pass
if not self.no_radar_sleep:
time.sleep(self.radar_ts) # radard runs on RI updates
return ret
class CarStateBase(ABC): class CarStateBase(ABC):

@ -58,7 +58,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.rcp is None: if self.rcp is None:
return super().update(None) return None
values = self.rcp.update_strings(can_strings) values = self.rcp.update_strings(can_strings)
self.updated_messages.update(values) self.updated_messages.update(values)

@ -45,7 +45,7 @@ class RadarInterface(RadarInterfaceBase):
def update(self, can_strings): def update(self, can_strings):
if self.rcp is None: if self.rcp is None:
return super().update(None) return None
vls = self.rcp.update_strings(can_strings) vls = self.rcp.update_strings(can_strings)
self.updated_messages.update(vls) self.updated_messages.update(vls)
@ -67,8 +67,14 @@ class RadarInterface(RadarInterfaceBase):
for ii in sorted(updated_messages): for ii in sorted(updated_messages):
if ii in self.RADAR_A_MSGS: if ii in self.RADAR_A_MSGS:
cpt = self.rcp.vl[ii] combined_vals = self.rcp.vl_all[ii]
n_vals_per_addr = len(list(combined_vals.values())[0])
cpts = [
{k: v[i] for k, v in combined_vals.items()}
for i in range(n_vals_per_addr)
]
for cpt in cpts:
if cpt['LONG_DIST'] >= 255 or cpt['NEW_TRACK']: if cpt['LONG_DIST'] >= 255 or cpt['NEW_TRACK']:
self.valid_cnt[ii] = 0 # reset counter self.valid_cnt[ii] = 0 # reset counter
if cpt['VALID'] and cpt['LONG_DIST'] < 255: if cpt['VALID'] and cpt['LONG_DIST'] < 255:
@ -77,7 +83,6 @@ class RadarInterface(RadarInterfaceBase):
self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0) self.valid_cnt[ii] = max(self.valid_cnt[ii] - 1, 0)
score = self.rcp.vl[ii+16]['SCORE'] score = self.rcp.vl[ii+16]['SCORE']
# print ii, self.valid_cnt[ii], score, cpt['VALID'], cpt['LONG_DIST'], cpt['LAT_DIST']
# radar point only valid if it's a valid measurement and score is above 50 # radar point only valid if it's a valid measurement and score is above 50
if cpt['VALID'] or (score > 50 and cpt['LONG_DIST'] < 255 and self.valid_cnt[ii] > 0): if cpt['VALID'] or (score > 50 and cpt['LONG_DIST'] < 255 and self.valid_cnt[ii] > 0):

@ -8,7 +8,7 @@ import capnp
from cereal import messaging, log, car from cereal import messaging, log, car
from common.numpy_fast import interp from common.numpy_fast import interp
from common.params import Params from common.params import Params
from common.realtime import Ratekeeper, Priority, config_realtime_process from common.realtime import Ratekeeper, Priority, config_realtime_process, DT_MDL
from system.swaglog import cloudlog from system.swaglog import cloudlog
from common.kalman.simple_kalman import KF1D from common.kalman.simple_kalman import KF1D
@ -50,7 +50,8 @@ class KalmanParams:
class Track: class Track:
def __init__(self, v_lead: float, kalman_params: KalmanParams): def __init__(self, identifier: int, v_lead: float, kalman_params: KalmanParams):
self.identifier = identifier
self.cnt = 0 self.cnt = 0
self.aLeadTau = _LEAD_ACCEL_TAU self.aLeadTau = _LEAD_ACCEL_TAU
self.K_A = kalman_params.A self.K_A = kalman_params.A
@ -63,9 +64,13 @@ class Track:
self.dRel = d_rel # LONG_DIST self.dRel = d_rel # LONG_DIST
self.yRel = y_rel # -LAT_DIST self.yRel = y_rel # -LAT_DIST
self.vRel = v_rel # REL_SPEED self.vRel = v_rel # REL_SPEED
self.vLead = v_lead
self.measured = measured # measured or estimate self.measured = measured # measured or estimate
self.update_vlead(v_lead)
def update_vlead(self, v_lead: float):
self.vLead = v_lead
# computed velocity and accelerations # computed velocity and accelerations
if self.cnt > 0: if self.cnt > 0:
self.kf.update(self.vLead) self.kf.update(self.vLead)
@ -98,11 +103,12 @@ class Track:
"vLead": float(self.vLead), "vLead": float(self.vLead),
"vLeadK": float(self.vLeadK), "vLeadK": float(self.vLeadK),
"aLeadK": float(self.aLeadK), "aLeadK": float(self.aLeadK),
"aLeadTau": float(self.aLeadTau),
"status": True, "status": True,
"fcw": self.is_potential_fcw(model_prob), "fcw": self.is_potential_fcw(model_prob),
"modelProb": model_prob, "modelProb": model_prob,
"radar": True, "radar": True,
"aLeadTau": float(self.aLeadTau) "radarTrackId": self.identifier,
} }
def potential_low_speed_lead(self, v_ego: float): def potential_low_speed_lead(self, v_ego: float):
@ -158,14 +164,16 @@ def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: floa
"aLeadTau": 0.3, "aLeadTau": 0.3,
"fcw": False, "fcw": False,
"modelProb": float(lead_msg.prob), "modelProb": float(lead_msg.prob),
"status": True,
"radar": False, "radar": False,
"status": True "radarTrackId": -1,
} }
def get_lead(v_ego: float, ready: bool, tracks: Dict[int, Track], lead_msg: capnp._DynamicStructReader, model_v_ego: float, low_speed_override: bool = True) -> Dict[str, Any]: def get_lead(v_ego: float, ready: bool, tracks: Dict[int, Track], lead_msg: capnp._DynamicStructReader, model_v_ego: float, low_speed_override: bool = True) -> Dict[str, Any]:
# Determine leads, this is where the essential logic happens # Determine leads, this is where the essential logic happens
if len(tracks) > 0 and ready and lead_msg.prob > .5: lead_msg_empty = any([len(c) == 0 for c in [lead_msg.x, lead_msg.y, lead_msg.v]])
if len(tracks) > 0 and ready and not lead_msg_empty and lead_msg.prob > .5:
track = match_vision_to_track(v_ego, lead_msg, tracks) track = match_vision_to_track(v_ego, lead_msg, tracks)
else: else:
track = None track = None
@ -173,7 +181,7 @@ def get_lead(v_ego: float, ready: bool, tracks: Dict[int, Track], lead_msg: capn
lead_dict = {'status': False} lead_dict = {'status': False}
if track is not None: if track is not None:
lead_dict = track.get_RadarState(lead_msg.prob) lead_dict = track.get_RadarState(lead_msg.prob)
elif (track is None) and ready and (lead_msg.prob > .5): elif track is None and ready and not lead_msg_empty and lead_msg.prob > .5:
lead_dict = get_RadarState_from_vision(lead_msg, v_ego, model_v_ego) lead_dict = get_RadarState_from_vision(lead_msg, v_ego, model_v_ego)
if low_speed_override: if low_speed_override:
@ -203,14 +211,14 @@ class RadarD:
self.ready = False self.ready = False
def update(self, sm: messaging.SubMaster, rr: Optional[car.RadarData]): def update(self, sm: messaging.SubMaster, radar_data: Optional[car.RadarData]):
self.current_time = 1e-9*max(sm.logMonoTime.values()) self.current_time = 1e-9*max(sm.logMonoTime.values())
radar_points = [] radar_points = []
radar_errors = [] radar_errors = []
if rr is not None: if radar_data is not None:
radar_points = rr.points radar_points = radar_data.points
radar_errors = rr.errors radar_errors = radar_data.errors
if sm.updated['carState']: if sm.updated['carState']:
self.v_ego = sm['carState'].vEgo self.v_ego = sm['carState'].vEgo
@ -218,6 +226,7 @@ class RadarD:
if sm.updated['modelV2']: if sm.updated['modelV2']:
self.ready = True self.ready = True
if radar_data is not None:
ar_pts = {} ar_pts = {}
for pt in radar_points: for pt in radar_points:
ar_pts[pt.trackId] = [pt.dRel, pt.yRel, pt.vRel, pt.measured] ar_pts[pt.trackId] = [pt.dRel, pt.yRel, pt.vRel, pt.measured]
@ -236,8 +245,13 @@ class RadarD:
# create the track if it doesn't exist or it's a new track # create the track if it doesn't exist or it's a new track
if ids not in self.tracks: if ids not in self.tracks:
self.tracks[ids] = Track(v_lead, self.kalman_params) self.tracks[ids] = Track(ids, v_lead, self.kalman_params)
self.tracks[ids].update(rpt[0], rpt[1], rpt[2], v_lead, rpt[3]) self.tracks[ids].update(rpt[0], rpt[1], rpt[2], v_lead, rpt[3])
else:
# *** no radar points, keep existing tracks, update v_lead
for track in self.tracks.values():
v_lead = track.vRel + self.v_ego_hist[0]
track.update_vlead(v_lead)
# *** publish radarState *** # *** publish radarState ***
self.radar_state_valid = sm.all_checks() and len(radar_errors) == 0 self.radar_state_valid = sm.all_checks() and len(radar_errors) == 0
@ -290,30 +304,28 @@ def radard_thread(sm: Optional[messaging.SubMaster] = None, pm: Optional[messagi
cloudlog.info("radard is importing %s", CP.carName) cloudlog.info("radard is importing %s", CP.carName)
RadarInterface = importlib.import_module(f'selfdrive.car.{CP.carName}.radar_interface').RadarInterface RadarInterface = importlib.import_module(f'selfdrive.car.{CP.carName}.radar_interface').RadarInterface
# *** setup messaging # setup messaging
if can_sock is None: if can_sock is None:
can_sock = messaging.sub_sock('can') can_sock = messaging.sub_sock('can')
if sm is None: if sm is None:
sm = messaging.SubMaster(['modelV2', 'carState'], ignore_avg_freq=['modelV2', 'carState']) # Can't check average frequency, since radar determines timing sm = messaging.SubMaster(['modelV2', 'carState'], poll=["modelV2"])
if pm is None: if pm is None:
pm = messaging.PubMaster(['radarState', 'liveTracks']) pm = messaging.PubMaster(['radarState', 'liveTracks'])
RI = RadarInterface(CP) interface = RadarInterface(CP)
rk = Ratekeeper(1.0 / CP.radarTimeStep, print_delay_threshold=None) rk = Ratekeeper(1 / DT_MDL, print_delay_threshold=None)
RD = RadarD(CP.radarTimeStep, RI.delay) radar = RadarD(DT_MDL, interface.delay)
while 1: while True:
can_strings = messaging.drain_sock_raw(can_sock, wait_for_one=True) sm.update()
rr = RI.update(can_strings)
if rr is None: if sm.updated['modelV2']:
continue can_strings = messaging.drain_sock_raw(can_sock)
radar_data = interface.update(can_strings)
sm.update(0)
RD.update(sm, rr) radar.update(sm, radar_data)
RD.publish(pm, -rk.remaining*1000.0) radar.publish(pm, -rk.remaining*1000.0)
rk.monitor_time() rk.monitor_time()

@ -464,8 +464,8 @@ CONFIGS = [
subs=["radarState", "liveTracks"], subs=["radarState", "liveTracks"],
ignore=["logMonoTime", "valid", "radarState.cumLagMs"], ignore=["logMonoTime", "valid", "radarState.cumLagMs"],
init_callback=get_car_params_callback, init_callback=get_car_params_callback,
should_recv_callback=MessageBasedRcvCallback("can"), should_recv_callback=MessageBasedRcvCallback("modelV2"),
main_pub="can", unlocked_pubs=["can"],
), ),
ProcessConfig( ProcessConfig(
proc_name="plannerd", proc_name="plannerd",

@ -1 +1 @@
8fd42f02d1ecac695327bfc0afd4be1918ab680a 4e55314f3a2502dea71d84e23d4889724c7bd05e
Loading…
Cancel
Save