mirror of https://github.com/commaai/openpilot.git
add alert for CAN bus timeout (#24162)
* add alert for CAN bus timeout * add alert * set in interface * cleanup * cleanup * add event * fix mock * bump * bump opendbc * update refs * return reader
This commit is contained in:
parent
3ff14adbd6
commit
49c2164814
2
cereal
2
cereal
|
@ -1 +1 @@
|
|||
Subproject commit d6c3cf6b33e699f82e5d78ae22c74cad978830b6
|
||||
Subproject commit 932c44c6bda17d7e19e1f58cd26442560a562696
|
2
opendbc
2
opendbc
|
@ -1 +1 @@
|
|||
Subproject commit eb56fff37a4a2738df7add08779db51a0a6f38e2
|
||||
Subproject commit 004db342a825155f7bd03e7d08f3861e18b23795
|
|
@ -37,13 +37,9 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp)
|
||||
|
||||
ret.canValid = self.cp.can_valid
|
||||
|
||||
# wait for everything to init first
|
||||
if self.frame > int(5. / DT_CTRL):
|
||||
# body always wants to enable
|
||||
|
@ -52,8 +48,7 @@ class CarInterface(CarInterfaceBase):
|
|||
ret.events[0].enable = True
|
||||
self.frame += 1
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
return self.CC.update(c, self.CS)
|
||||
|
|
|
@ -47,16 +47,9 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
|
||||
# speeds
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
# events
|
||||
|
@ -67,10 +60,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
# copy back carState packet to CS
|
||||
self.CS.out = ret.as_reader()
|
||||
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
|
|
|
@ -41,15 +41,9 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp)
|
||||
|
||||
ret.canValid = self.cp.can_valid
|
||||
|
||||
# events
|
||||
events = self.create_common_events(ret)
|
||||
|
||||
|
@ -58,8 +52,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
|
|
|
@ -155,13 +155,9 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_loopback.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_loopback)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_loopback.can_valid
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
buttonEvents = []
|
||||
|
@ -210,10 +206,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
# copy back carState packet to CS
|
||||
self.CS.out = ret.as_reader()
|
||||
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
ret = self.CC.update(c, self.CS)
|
||||
|
|
|
@ -328,17 +328,9 @@ class CarInterface(CarInterfaceBase):
|
|||
disable_ecu(logcan, sendcan, bus=1, addr=0x18DAB0F1, com_cont_req=b'\x28\x83\x03')
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
if self.cp_body:
|
||||
self.cp_body.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_body)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid and (self.cp_body is None or self.cp_body.can_valid)
|
||||
|
||||
buttonEvents = []
|
||||
|
||||
if self.CS.cruise_buttons != self.CS.prev_cruise_buttons:
|
||||
|
@ -412,11 +404,9 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
def apply(self, c):
|
||||
ret = self.CC.update(c, self.CS)
|
||||
return ret
|
||||
return self.CC.update(c, self.CS)
|
||||
|
|
|
@ -297,12 +297,8 @@ class CarInterface(CarInterfaceBase):
|
|||
if CP.openpilotLongitudinalControl:
|
||||
disable_ecu(logcan, sendcan, addr=0x7d0, com_cont_req=b'\x28\x83\x01')
|
||||
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
events = self.create_common_events(ret, pcm_enable=self.CS.CP.pcmCruise)
|
||||
|
@ -352,8 +348,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
ret = self.CC.update(c, self.CS)
|
||||
|
|
|
@ -33,12 +33,17 @@ class CarInterfaceBase(ABC):
|
|||
self.low_speed_alert = False
|
||||
self.silent_steer_warning = True
|
||||
|
||||
self.CS = None
|
||||
self.can_parsers = []
|
||||
if CarState is not None:
|
||||
self.CS = CarState(CP)
|
||||
|
||||
self.cp = self.CS.get_can_parser(CP)
|
||||
self.cp_cam = self.CS.get_cam_can_parser(CP)
|
||||
self.cp_adas = self.CS.get_adas_can_parser(CP)
|
||||
self.cp_body = self.CS.get_body_can_parser(CP)
|
||||
self.cp_loopback = self.CS.get_loopback_can_parser(CP)
|
||||
self.can_parsers = [self.cp, self.cp_cam, self.cp_adas, self.cp_body, self.cp_loopback]
|
||||
|
||||
self.CC = None
|
||||
if CarController is not None:
|
||||
|
@ -100,9 +105,28 @@ class CarInterfaceBase(ABC):
|
|||
return ret
|
||||
|
||||
@abstractmethod
|
||||
def update(self, c: car.CarControl, can_strings: List[bytes]) -> car.CarState:
|
||||
def _update(self, c: car.CarControl) -> car.CarState:
|
||||
pass
|
||||
|
||||
def update(self, c: car.CarControl, can_strings: List[bytes]) -> car.CarState:
|
||||
# parse can
|
||||
for cp in self.can_parsers:
|
||||
if cp is not None:
|
||||
cp.update_strings(can_strings)
|
||||
|
||||
# get CarState
|
||||
ret = self._update(c)
|
||||
|
||||
ret.canValid = all(cp.can_valid for cp in self.can_parsers if cp is not None)
|
||||
ret.canTimeout = any(cp.bus_timeout for cp in self.can_parsers if cp is not None)
|
||||
|
||||
# copy back for next iteration
|
||||
reader = ret.as_reader()
|
||||
if self.CS is not None:
|
||||
self.CS.out = reader
|
||||
|
||||
return reader
|
||||
|
||||
@abstractmethod
|
||||
def apply(self, c: car.CarControl) -> Tuple[car.CarControl.Actuators, List[bytes]]:
|
||||
pass
|
||||
|
@ -254,6 +278,10 @@ class CarStateBase(ABC):
|
|||
def get_cam_can_parser(CP):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_adas_can_parser(CP):
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_body_can_parser(CP):
|
||||
return None
|
||||
|
|
|
@ -75,13 +75,8 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
|
||||
# events
|
||||
events = self.create_common_events(ret)
|
||||
|
@ -93,8 +88,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
ret = self.CC.update(c, self.CS, self.frame)
|
||||
|
|
|
@ -48,7 +48,7 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
def _update(self, c):
|
||||
# get basic data from phone and gps since CAN isn't connected
|
||||
sensors = messaging.recv_sock(self.sensor)
|
||||
if sensors is not None:
|
||||
|
@ -63,7 +63,6 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
# create message
|
||||
ret = car.CarState.new_message()
|
||||
ret.canValid = True
|
||||
|
||||
# speeds
|
||||
ret.vEgo = self.speed
|
||||
|
@ -83,7 +82,7 @@ class CarInterface(CarInterfaceBase):
|
|||
curvature = self.yaw_rate / max(self.speed, 1.)
|
||||
ret.steeringAngleDeg = curvature * self.CP.steerRatio * self.CP.wheelbase * CV.RAD_TO_DEG
|
||||
|
||||
return ret.as_reader()
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
# in mock no carcontrols
|
||||
|
|
|
@ -5,9 +5,6 @@ from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness,
|
|||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
|
||||
class CarInterface(CarInterfaceBase):
|
||||
def __init__(self, CP, CarController, CarState):
|
||||
super().__init__(CP, CarController, CarState)
|
||||
self.cp_adas = self.CS.get_adas_can_parser(CP)
|
||||
|
||||
@staticmethod
|
||||
def get_params(candidate, fingerprint=gen_empty_fingerprint(), car_fw=None, disable_radar=False):
|
||||
|
@ -53,15 +50,9 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
self.cp_adas.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_adas, self.cp_cam)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_adas.can_valid and self.cp_cam.can_valid
|
||||
|
||||
buttonEvents = []
|
||||
be = car.CarState.ButtonEvent.new_message()
|
||||
be.type = car.CarState.ButtonEvent.Type.accelCruise
|
||||
|
@ -74,8 +65,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
hud_control = c.hudControl
|
||||
|
|
|
@ -107,19 +107,15 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
def _update(self, c):
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
ret.events = self.create_common_events(ret).to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
hud_control = c.hudControl
|
||||
|
|
|
@ -57,18 +57,12 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
return ret
|
||||
|
||||
def update(self, c, can_strings):
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
|
||||
events = self.create_common_events(ret)
|
||||
ret.events = self.create_common_events(ret).to_msg()
|
||||
|
||||
ret.events = events.to_msg()
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
ret = self.CC.update(c, self.CS)
|
||||
|
|
|
@ -240,14 +240,9 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
def _update(self, c):
|
||||
ret = self.CS.update(self.cp, self.cp_cam)
|
||||
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
# events
|
||||
|
@ -266,8 +261,7 @@ class CarInterface(CarInterfaceBase):
|
|||
|
||||
ret.events = events.to_msg()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
# pass in a car.CarControl
|
||||
# to be called @ 100hz
|
||||
|
|
|
@ -161,17 +161,10 @@ class CarInterface(CarInterfaceBase):
|
|||
return ret
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
def _update(self, c):
|
||||
buttonEvents = []
|
||||
|
||||
# Process the most recent CAN message traffic, and check for validity
|
||||
# The camera CAN has no signals we use at this time, but we process it
|
||||
# anyway so we can test connectivity with can_valid
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
|
||||
ret = self.CS.update(self.cp, self.cp_cam, self.cp_ext, self.CP.transmissionType)
|
||||
ret.canValid = self.cp.can_valid and self.cp_cam.can_valid
|
||||
ret.steeringRateLimited = self.CC.steer_rate_limited if self.CC is not None else False
|
||||
|
||||
# Check for and process state-change events (button press or release) from
|
||||
|
@ -204,8 +197,7 @@ class CarInterface(CarInterfaceBase):
|
|||
self.displayMetricUnitsPrev = self.CS.displayMetricUnits
|
||||
self.buttonStatesPrev = self.CS.buttonStates.copy()
|
||||
|
||||
self.CS.out = ret.as_reader()
|
||||
return self.CS.out
|
||||
return ret
|
||||
|
||||
def apply(self, c):
|
||||
hud_control = c.hudControl
|
||||
|
|
|
@ -270,7 +270,9 @@ class Controls:
|
|||
LaneChangeState.laneChangeFinishing):
|
||||
self.events.add(EventName.laneChange)
|
||||
|
||||
if not CS.canValid:
|
||||
if CS.canTimeout:
|
||||
self.events.add(EventName.canBusMissing)
|
||||
elif not CS.canValid:
|
||||
self.events.add(EventName.canError)
|
||||
|
||||
for i, pandaState in enumerate(self.sm['pandaStates']):
|
||||
|
|
|
@ -757,7 +757,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
|
|||
# - CAN data is received, but some message are not received at the right frequency
|
||||
# If you're not writing a new car port, this is usually cause by faulty wiring
|
||||
EventName.canError: {
|
||||
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Error: Check Connections"),
|
||||
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Error"),
|
||||
ET.PERMANENT: Alert(
|
||||
"CAN Error: Check Connections",
|
||||
"",
|
||||
|
@ -766,7 +766,15 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
|
|||
ET.NO_ENTRY: NoEntryAlert("CAN Error: Check Connections"),
|
||||
},
|
||||
|
||||
EventName.canBusMissing: {},
|
||||
EventName.canBusMissing: {
|
||||
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("CAN Bus Disconnected"),
|
||||
ET.PERMANENT: Alert(
|
||||
"CAN Bus Disconnected: Likely Faulty Cable",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, 1., creation_delay=1.),
|
||||
ET.NO_ENTRY: NoEntryAlert("CAN Bus Disconnected: Check Connections"),
|
||||
},
|
||||
|
||||
EventName.steerUnavailable: {
|
||||
ET.IMMEDIATE_DISABLE: ImmediateDisableAlert("LKAS Fault: Restart the Car"),
|
||||
|
|
|
@ -1 +1 @@
|
|||
de01f1544a1441f89c24c5ea587f3f99632f2b5a
|
||||
dea753b12032ad2c50b4a163a3077a8530267800
|
Loading…
Reference in New Issue