alerts: escalate soft disable alert near disengagement (#23198)

* alerts: escalate soft disable alert if resulted in disengagement

* show 0.5s before disengagement
pull/20750/head^2
Adeeb Shihadeh 2021-12-11 17:07:37 -08:00 committed by GitHub
parent d28622f8d3
commit 8068df0b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 29 deletions

View File

@ -28,6 +28,7 @@ from selfdrive.locationd.calibrationd import Calibration
from selfdrive.hardware import HARDWARE, TICI, EON from selfdrive.hardware import HARDWARE, TICI, EON
from selfdrive.manager.process_config import managed_processes from selfdrive.manager.process_config import managed_processes
SOFT_DISABLE_TIME = 3 # seconds
LDW_MIN_SPEED = 31 * CV.MPH_TO_MS LDW_MIN_SPEED = 31 * CV.MPH_TO_MS
LANE_DEPARTURE_THRESHOLD = 0.1 LANE_DEPARTURE_THRESHOLD = 0.1
STEER_ANGLE_SATURATION_TIMEOUT = 1.0 / DT_CTRL STEER_ANGLE_SATURATION_TIMEOUT = 1.0 / DT_CTRL
@ -430,7 +431,7 @@ class Controls:
if self.state == State.enabled: if self.state == State.enabled:
if self.events.any(ET.SOFT_DISABLE): if self.events.any(ET.SOFT_DISABLE):
self.state = State.softDisabling self.state = State.softDisabling
self.soft_disable_timer = int(3 / DT_CTRL) self.soft_disable_timer = int(SOFT_DISABLE_TIME / DT_CTRL)
self.current_alert_types.append(ET.SOFT_DISABLE) self.current_alert_types.append(ET.SOFT_DISABLE)
# SOFT DISABLING # SOFT DISABLING
@ -613,7 +614,7 @@ class Controls:
self.events.add(EventName.ldw) self.events.add(EventName.ldw)
clear_event = ET.WARNING if ET.WARNING not in self.current_alert_types else None clear_event = ET.WARNING if ET.WARNING not in self.current_alert_types else None
alerts = self.events.create_alerts(self.current_alert_types, [self.CP, self.sm, self.is_metric]) alerts = self.events.create_alerts(self.current_alert_types, [self.CP, self.sm, self.is_metric, self.soft_disable_timer])
self.AM.add_many(self.sm.frame, alerts) self.AM.add_many(self.sm.frame, alerts)
self.AM.process_alerts(self.sm.frame, clear_event) self.AM.process_alerts(self.sm.frame, clear_event)
CC.hudControl.visualAlert = self.AM.visual_alert CC.hudControl.visualAlert = self.AM.visual_alert

View File

@ -1,5 +1,5 @@
from enum import IntEnum from enum import IntEnum
from typing import Dict, Union, Callable, Any from typing import Dict, Union, Callable
from cereal import log, car from cereal import log, car
import cereal.messaging as messaging import cereal.messaging as messaging
@ -198,11 +198,31 @@ def get_display_speed(speed_ms: float, metric: bool) -> str:
# ********** alert callback functions ********** # ********** alert callback functions **********
def below_engage_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert:
AlertCallbackType = Callable[[car.CarParams, messaging.SubMaster, bool, int], Alert]
def soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
def func(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
if soft_disable_time < int(0.5 / DT_CTRL):
return ImmediateDisableAlert(alert_text_2)
return SoftDisableAlert(alert_text_2)
return func
def user_soft_disable_alert(alert_text_2: str) -> AlertCallbackType:
def func(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
if soft_disable_time < int(0.5 / DT_CTRL):
return ImmediateDisableAlert(alert_text_2)
return UserSoftDisableAlert(alert_text_2)
return func
def below_engage_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
return NoEntryAlert(f"Speed Below {get_display_speed(CP.minEnableSpeed, metric)}") return NoEntryAlert(f"Speed Below {get_display_speed(CP.minEnableSpeed, metric)}")
def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
return Alert( return Alert(
f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}", f"Steer Unavailable Below {get_display_speed(CP.minSteerSpeed, metric)}",
"", "",
@ -210,7 +230,7 @@ def below_steer_speed_alert(CP: car.CarParams, sm: messaging.SubMaster, metric:
Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4) Priority.MID, VisualAlert.steerRequired, AudibleAlert.prompt, 0.4)
def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
return Alert( return Alert(
"Calibration in Progress: %d%%" % sm['liveCalibration'].calPerc, "Calibration in Progress: %d%%" % sm['liveCalibration'].calPerc,
f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}", f"Drive Above {get_display_speed(MIN_SPEED_FILTER, metric)}",
@ -218,7 +238,7 @@ def calibration_incomplete_alert(CP: car.CarParams, sm: messaging.SubMaster, met
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2) Priority.LOWEST, VisualAlert.none, AudibleAlert.none, .2)
def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
gps_integrated = sm['peripheralState'].pandaType in [log.PandaState.PandaType.uno, log.PandaState.PandaType.dos] gps_integrated = sm['peripheralState'].pandaType in [log.PandaState.PandaType.uno, log.PandaState.PandaType.dos]
return Alert( return Alert(
"Poor GPS reception", "Poor GPS reception",
@ -227,21 +247,22 @@ def no_gps_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Al
Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=300.) Priority.LOWER, VisualAlert.none, AudibleAlert.none, .2, creation_delay=300.)
def wrong_car_mode_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def wrong_car_mode_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
text = "Cruise Mode Disabled" text = "Cruise Mode Disabled"
if CP.carName == "honda": if CP.carName == "honda":
text = "Main Switch Off" text = "Main Switch Off"
return NoEntryAlert(text) return NoEntryAlert(text)
def joystick_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool) -> Alert: def joystick_alert(CP: car.CarParams, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert:
axes = sm['testJoystick'].axes axes = sm['testJoystick'].axes
gb, steer = list(axes)[:2] if len(axes) else (0., 0.) gb, steer = list(axes)[:2] if len(axes) else (0., 0.)
vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%" vals = f"Gas: {round(gb * 100.)}%, Steer: {round(steer * 100.)}%"
return NormalPermanentAlert("Joystick Mode", vals) return NormalPermanentAlert("Joystick Mode", vals)
EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, bool], Alert]]]] = {
EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = {
# ********** events with no alerts ********** # ********** events with no alerts **********
EventName.stockFcw: {}, EventName.stockFcw: {},
@ -358,7 +379,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub # bad alignment or bad sensor data. If this happens consistently consider creating an issue on GitHub
EventName.vehicleModelInvalid: { EventName.vehicleModelInvalid: {
ET.NO_ENTRY: NoEntryAlert("Vehicle Parameter Identification Failed"), ET.NO_ENTRY: NoEntryAlert("Vehicle Parameter Identification Failed"),
ET.SOFT_DISABLE: SoftDisableAlert("Vehicle Parameter Identification Failed"), ET.SOFT_DISABLE: soft_disable_alert("Vehicle Parameter Identification Failed"),
}, },
EventName.steerTempUnavailableSilent: { EventName.steerTempUnavailableSilent: {
@ -544,7 +565,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
}, },
EventName.steerTempUnavailable: { EventName.steerTempUnavailable: {
ET.SOFT_DISABLE: SoftDisableAlert("Steering Temporarily Unavailable"), ET.SOFT_DISABLE: soft_disable_alert("Steering Temporarily Unavailable"),
ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"), ET.NO_ENTRY: NoEntryAlert("Steering Temporarily Unavailable"),
}, },
@ -581,12 +602,12 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
EventName.overheat: { EventName.overheat: {
ET.PERMANENT: NormalPermanentAlert("System Overheated"), ET.PERMANENT: NormalPermanentAlert("System Overheated"),
ET.SOFT_DISABLE: SoftDisableAlert("System Overheated"), ET.SOFT_DISABLE: soft_disable_alert("System Overheated"),
ET.NO_ENTRY: NoEntryAlert("System Overheated"), ET.NO_ENTRY: NoEntryAlert("System Overheated"),
}, },
EventName.wrongGear: { EventName.wrongGear: {
ET.SOFT_DISABLE: UserSoftDisableAlert("Gear not D"), ET.SOFT_DISABLE: user_soft_disable_alert("Gear not D"),
ET.NO_ENTRY: NoEntryAlert("Gear not D"), ET.NO_ENTRY: NoEntryAlert("Gear not D"),
}, },
@ -597,33 +618,33 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# See https://comma.ai/setup for more information # See https://comma.ai/setup for more information
EventName.calibrationInvalid: { EventName.calibrationInvalid: {
ET.PERMANENT: NormalPermanentAlert("Calibration Invalid", "Remount Device and Recalibrate"), ET.PERMANENT: NormalPermanentAlert("Calibration Invalid", "Remount Device and Recalibrate"),
ET.SOFT_DISABLE: SoftDisableAlert("Calibration Invalid: Remount Device & Recalibrate"), ET.SOFT_DISABLE: soft_disable_alert("Calibration Invalid: Remount Device & Recalibrate"),
ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"), ET.NO_ENTRY: NoEntryAlert("Calibration Invalid: Remount Device & Recalibrate"),
}, },
EventName.calibrationIncomplete: { EventName.calibrationIncomplete: {
ET.PERMANENT: calibration_incomplete_alert, ET.PERMANENT: calibration_incomplete_alert,
ET.SOFT_DISABLE: SoftDisableAlert("Calibration in Progress"), ET.SOFT_DISABLE: soft_disable_alert("Calibration in Progress"),
ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"), ET.NO_ENTRY: NoEntryAlert("Calibration in Progress"),
}, },
EventName.doorOpen: { EventName.doorOpen: {
ET.SOFT_DISABLE: UserSoftDisableAlert("Door Open"), ET.SOFT_DISABLE: user_soft_disable_alert("Door Open"),
ET.NO_ENTRY: NoEntryAlert("Door Open"), ET.NO_ENTRY: NoEntryAlert("Door Open"),
}, },
EventName.seatbeltNotLatched: { EventName.seatbeltNotLatched: {
ET.SOFT_DISABLE: UserSoftDisableAlert("Seatbelt Unlatched"), ET.SOFT_DISABLE: user_soft_disable_alert("Seatbelt Unlatched"),
ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"), ET.NO_ENTRY: NoEntryAlert("Seatbelt Unlatched"),
}, },
EventName.espDisabled: { EventName.espDisabled: {
ET.SOFT_DISABLE: SoftDisableAlert("ESP Off"), ET.SOFT_DISABLE: soft_disable_alert("ESP Off"),
ET.NO_ENTRY: NoEntryAlert("ESP Off"), ET.NO_ENTRY: NoEntryAlert("ESP Off"),
}, },
EventName.lowBattery: { EventName.lowBattery: {
ET.SOFT_DISABLE: SoftDisableAlert("Low Battery"), ET.SOFT_DISABLE: soft_disable_alert("Low Battery"),
ET.NO_ENTRY: NoEntryAlert("Low Battery"), ET.NO_ENTRY: NoEntryAlert("Low Battery"),
}, },
@ -632,7 +653,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# is thrown. This can mean a service crashed, did not broadcast a message for # is thrown. This can mean a service crashed, did not broadcast a message for
# ten times the regular interval, or the average interval is more than 10% too high. # ten times the regular interval, or the average interval is more than 10% too high.
EventName.commIssue: { EventName.commIssue: {
ET.SOFT_DISABLE: SoftDisableAlert("Communication Issue between Processes"), ET.SOFT_DISABLE: soft_disable_alert("Communication Issue between Processes"),
ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes"), ET.NO_ENTRY: NoEntryAlert("Communication Issue between Processes"),
}, },
@ -642,7 +663,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
}, },
EventName.radarFault: { EventName.radarFault: {
ET.SOFT_DISABLE: SoftDisableAlert("Radar Error: Restart the Car"), ET.SOFT_DISABLE: soft_disable_alert("Radar Error: Restart the Car"),
ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"), ET.NO_ENTRY: NoEntryAlert("Radar Error: Restart the Car"),
}, },
@ -650,7 +671,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# is not processing frames fast enough they have to be dropped. This alert is # is not processing frames fast enough they have to be dropped. This alert is
# thrown when over 20% of frames are dropped. # thrown when over 20% of frames are dropped.
EventName.modeldLagging: { EventName.modeldLagging: {
ET.SOFT_DISABLE: SoftDisableAlert("Driving model lagging"), ET.SOFT_DISABLE: soft_disable_alert("Driving model lagging"),
ET.NO_ENTRY: NoEntryAlert("Driving model lagging"), ET.NO_ENTRY: NoEntryAlert("Driving model lagging"),
}, },
@ -660,25 +681,25 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# usually means the model has trouble understanding the scene. This is used # usually means the model has trouble understanding the scene. This is used
# as a heuristic to warn the driver. # as a heuristic to warn the driver.
EventName.posenetInvalid: { EventName.posenetInvalid: {
ET.SOFT_DISABLE: SoftDisableAlert("Model Output Uncertain"), ET.SOFT_DISABLE: soft_disable_alert("Model Output Uncertain"),
ET.NO_ENTRY: NoEntryAlert("Model Output Uncertain"), ET.NO_ENTRY: NoEntryAlert("Model Output Uncertain"),
}, },
# When the localizer detects an acceleration of more than 40 m/s^2 (~4G) we # When the localizer detects an acceleration of more than 40 m/s^2 (~4G) we
# alert the driver the device might have fallen from the windshield. # alert the driver the device might have fallen from the windshield.
EventName.deviceFalling: { EventName.deviceFalling: {
ET.SOFT_DISABLE: SoftDisableAlert("Device Fell Off Mount"), ET.SOFT_DISABLE: soft_disable_alert("Device Fell Off Mount"),
ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"), ET.NO_ENTRY: NoEntryAlert("Device Fell Off Mount"),
}, },
EventName.lowMemory: { EventName.lowMemory: {
ET.SOFT_DISABLE: SoftDisableAlert("Low Memory: Reboot Your Device"), ET.SOFT_DISABLE: soft_disable_alert("Low Memory: Reboot Your Device"),
ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"), ET.PERMANENT: NormalPermanentAlert("Low Memory", "Reboot your Device"),
ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"), ET.NO_ENTRY: NoEntryAlert("Low Memory: Reboot Your Device"),
}, },
EventName.highCpuUsage: { EventName.highCpuUsage: {
#ET.SOFT_DISABLE: SoftDisableAlert("System Malfunction: Reboot Your Device"), #ET.SOFT_DISABLE: soft_disable_alert("System Malfunction: Reboot Your Device"),
#ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"), #ET.PERMANENT: NormalPermanentAlert("System Malfunction", "Reboot your Device"),
ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"), ET.NO_ENTRY: NoEntryAlert("System Malfunction: Reboot Your Device"),
}, },
@ -714,7 +735,7 @@ EVENTS: Dict[int, Dict[str, Union[Alert, Callable[[Any, messaging.SubMaster, boo
# Sometimes the USB stack on the device can get into a bad state # Sometimes the USB stack on the device can get into a bad state
# causing the connection to the panda to be lost # causing the connection to the panda to be lost
EventName.usbError: { EventName.usbError: {
ET.SOFT_DISABLE: SoftDisableAlert("USB Error: Reboot Your Device"), ET.SOFT_DISABLE: soft_disable_alert("USB Error: Reboot Your Device"),
ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device", ""), ET.PERMANENT: NormalPermanentAlert("USB Error: Reboot Your Device", ""),
ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"), ET.NO_ENTRY: NoEntryAlert("USB Error: Reboot Your Device"),
}, },

View File

@ -52,7 +52,7 @@ def cycle_alerts(duration=200, is_metric=False):
events.clear() events.clear()
events.add(alert) events.add(alert)
a = events.create_alerts([et, ], [CP, sm, is_metric]) a = events.create_alerts([et, ], [CP, sm, is_metric, 0])
AM.add_many(frame, a) AM.add_many(frame, a)
AM.process_alerts(frame) AM.process_alerts(frame)
print(AM.alert) print(AM.alert)