From 831a8f27e5503fa78e3cc09f202a21b861587e8c Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Sun, 5 Jul 2026 00:20:55 -0400 Subject: [PATCH] BigUI WIP: Oh lol GM riot prevention --- selfdrive/selfdrived/selfdrived.py | 47 +++++++++++++++++++--- selfdrive/ui/onroad/alert_renderer.py | 5 ++- selfdrive/ui/onroad/augmented_road_view.py | 1 - 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index 284f831d3d..d0159e44c5 100644 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -249,6 +249,12 @@ class SelfdriveD: self.last_steer_saturated_alert_time = -float("inf") self.forcing_stop_chime_played = False + # Once-per-drive latch for belowSteerSpeed — shows the bottom alert once per + # onroad session for the first below-min crossing, suppresses subsequent ones. + self.below_steer_shown_this_drive = False + self.below_steer_has_been_above_min = False + self.below_steer_showing = False + self.starpilot_events_prev = [] self.has_menu = self.CP.brand == "gm" and not (self.CP.flags & GMFlags.NO_CAMERA.value) @@ -290,6 +296,11 @@ class SelfdriveD: switchback_mode_enabled = self.params_memory.get_bool("SwitchbackModeEnabled") switchback_mode_cooldown = max(0.0, float(getattr(self.starpilot_toggles, "switchback_mode_cooldown", 0.0))) + if not self.sm['deviceState'].started: + self.below_steer_shown_this_drive = False + self.below_steer_has_been_above_min = False + self.below_steer_showing = False + if not self.sm['deviceState'].started or not switchback_mode_enabled: self.last_below_steer_speed_alert_time = -float("inf") self.last_steer_saturated_alert_time = -float("inf") @@ -361,14 +372,38 @@ class SelfdriveD: # Add car events, ignore if CAN isn't valid if CS.canValid: car_events = self.car_events.update(CS, self.CS_prev, self.sm['carControl']).to_msg() - has_below_steer_speed_event = any(e.name.raw == EventName.belowSteerSpeed for e in car_events) - if has_below_steer_speed_event: + + # Once-per-drive latch for belowSteerSpeed — match old MinSteerSpeedBanner 1:1. + min_steer_speed = float(self.CP.minSteerSpeed) + under_min = min_steer_speed > 0.0 and float(CS.vEgo) < min_steer_speed + + if not under_min: + self.below_steer_has_been_above_min = True + + was_under_min_prev = min_steer_speed > 0.0 and float(self.CS_prev.vEgo) < min_steer_speed + crossed_below = under_min and not was_under_min_prev + if (not self.below_steer_shown_this_drive) and crossed_below and self.below_steer_has_been_above_min: + self.below_steer_shown_this_drive = True + self.below_steer_showing = True + + if self.below_steer_showing and not under_min: + self.below_steer_showing = False + + # Fully own the event — strip brand emissions, inject our own while active. + car_events = [e for e in car_events if e.name.raw != EventName.belowSteerSpeed] + show_alert = self.below_steer_showing and under_min + + # Switchback cooldown: rate-limits the alert when car sits below min. + if show_alert and switchback_mode_enabled and switchback_mode_cooldown > 0.0: now = time.monotonic() - cooldown_active = switchback_mode_enabled and switchback_mode_cooldown > 0.0 - if cooldown_active and (now - self.last_below_steer_speed_alert_time) < switchback_mode_cooldown: - car_events = [e for e in car_events if e.name.raw != EventName.belowSteerSpeed] - elif switchback_mode_enabled: + if (now - self.last_below_steer_speed_alert_time) < switchback_mode_cooldown: + show_alert = False + else: self.last_below_steer_speed_alert_time = now + + if show_alert: + self.events.add(EventName.belowSteerSpeed) + self.events.add_from_msg(car_events) self.prev_pedal_long_active = add_tesla_preap_starpilot_events( diff --git a/selfdrive/ui/onroad/alert_renderer.py b/selfdrive/ui/onroad/alert_renderer.py index b9e89b9f74..caee27de1a 100644 --- a/selfdrive/ui/onroad/alert_renderer.py +++ b/selfdrive/ui/onroad/alert_renderer.py @@ -84,6 +84,7 @@ class AlertRenderer(Widget): line_height=0.86, letter_spacing=0.025) self._prev_alert: Alert | None = None + self._current_alert: Alert | None = None self._alert_y_filter = BounceFilter(0, 0.1, 1 / gui_app.target_fps, initialized=False) self._alpha_filter = FirstOrderFilter(0, 0.05, 1 / gui_app.target_fps) @@ -127,7 +128,8 @@ class AlertRenderer(Widget): return ret def will_render(self) -> tuple[Alert | None, bool]: - alert = self.get_alert(ui_state.sm) + """Return cached alert state without re-polling get_alert(). Safe to call multiple times per frame.""" + alert = self._current_alert return alert or self._prev_alert, alert is None def _get_alert_rect(self, rect: rl.Rectangle, size: int) -> rl.Rectangle: @@ -138,6 +140,7 @@ class AlertRenderer(Widget): def _render(self, rect: rl.Rectangle) -> bool: alert = self.get_alert(ui_state.sm) + self._current_alert = alert self._alpha_filter.update(0 if alert is None else 1) diff --git a/selfdrive/ui/onroad/augmented_road_view.py b/selfdrive/ui/onroad/augmented_road_view.py index f86b4ed014..6189bd656b 100644 --- a/selfdrive/ui/onroad/augmented_road_view.py +++ b/selfdrive/ui/onroad/augmented_road_view.py @@ -88,7 +88,6 @@ class AugmentedRoadView(CameraView): super()._render(self._content_rect) # Draw all UI overlays - alert_to_render, _not_animating_out = self.alert_renderer.will_render() self.model_renderer.render(self._content_rect) self._hud_renderer.render(self._content_rect) self.alert_renderer.render(self._content_rect)