diff --git a/cereal/log.capnp b/cereal/log.capnp index a5828d61cb..6f137713ef 100644 --- a/cereal/log.capnp +++ b/cereal/log.capnp @@ -58,6 +58,7 @@ struct OnroadEvent @0xc4fa6047f024e718 { controlsMismatch @22; pcmEnable @23; pcmDisable @24; + cancellingCruise @94; radarFault @25; radarTempUnavailable @93; brakeHold @26; diff --git a/selfdrive/selfdrived/alertmanager.py b/selfdrive/selfdrived/alertmanager.py index ac1006ff25..312291e60c 100644 --- a/selfdrive/selfdrived/alertmanager.py +++ b/selfdrive/selfdrived/alertmanager.py @@ -39,6 +39,7 @@ class AlertManager: def __init__(self): self.alerts: dict[str, AlertEntry] = defaultdict(AlertEntry) self.current_alert = EmptyAlert + self.current_audible_alert = EmptyAlert def add_many(self, frame: int, alerts: list[Alert]) -> None: for alert in alerts: @@ -52,6 +53,7 @@ class AlertManager: def process_alerts(self, frame: int, clear_event_types: set): ae = AlertEntry() + ae_audible = AlertEntry() for v in self.alerts.values(): if not v.alert: continue @@ -63,5 +65,19 @@ class AlertManager: greater = ae.alert is None or (v.alert.priority, v.start_frame) > (ae.alert.priority, ae.start_frame) if v.active(frame) and greater: ae = v + ae_audible = v + + for v in self.alerts.values(): + if not v.alert: + continue + + if v.alert.event_type in clear_event_types: + v.end_frame = -1 + + # sort by priority first and then by start_frame + greater = ae_audible.alert is None or (v.alert.priority, v.start_frame) > (ae_audible.alert.priority, ae_audible.start_frame) + if v.active(frame) and v.alert.alert_size == AlertSize.none and greater: + ae_audible = v self.current_alert = ae.alert if ae.alert is not None else EmptyAlert + self.current_alert = ae_audible.alert if ae_audible.alert is not None else EmptyAlert diff --git a/selfdrive/selfdrived/events.py b/selfdrive/selfdrived/events.py index ee2c418b6e..ee55263578 100755 --- a/selfdrive/selfdrived/events.py +++ b/selfdrive/selfdrived/events.py @@ -192,10 +192,11 @@ class NormalPermanentAlert(Alert): class StartupAlert(Alert): - def __init__(self, alert_text_1: str, alert_text_2: str = "Always keep hands on wheel and eyes on road", alert_status=AlertStatus.normal): + def __init__(self, alert_text_1: str, alert_text_2: str = "Always keep hands on wheel and eyes on road", alert_status=AlertStatus.normal, + audible_alert: car.CarControl.HUDControl.AudibleAlert = AudibleAlert.none): super().__init__(alert_text_1, alert_text_2, alert_status, AlertSize.mid, - Priority.LOWER, VisualAlert.none, AudibleAlert.none, 5.), + Priority.LOWER, VisualAlert.none, audible_alert, 5.), # ********** helper functions ********** @@ -229,7 +230,12 @@ def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubM if "REPLAY" in os.environ: branch = "replay" - return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt) + # TODO: also need cb for other startup alerts + audible_alert = AudibleAlert.none + if CS.cruiseState.enabled: + audible_alert = AudibleAlert.disengage + + return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt, audible_alert=audible_alert) def below_engage_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int, personality) -> Alert: return NoEntryAlert(f"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage") @@ -646,6 +652,10 @@ EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), }, + EventName.cancellingCruise: { + ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), + }, + EventName.buttonCancel: { ET.USER_DISABLE: EngagementAlert(AudibleAlert.disengage), ET.NO_ENTRY: NoEntryAlert("Cancel Pressed"), diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index face7dab29..926b845f17 100755 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -163,6 +163,9 @@ class SelfdriveD: if self.CP.passive: return + if CS.cruiseState.enabled and not self.enabled: + self.events.add(EventName.cancellingCruise) + # Block resume if cruise never previously enabled resume_pressed = any(be.type in (ButtonType.accelCruise, ButtonType.resumeCruise) for be in CS.buttonEvents) if not self.CP.pcmCruise and CS.vCruise > 250 and resume_pressed: