ui: consolidate Speed Limit Assist preActive status rendering (#1745)

* mici init

* obv

* hybrid

* adapt

* less

* consolidate

* oops

Refactor speed limit alert function to use car state directly.

* no event border for tizi/tici

* abstract it

* too soon junior

* refactor
This commit is contained in:
Jason Wen
2026-02-28 20:06:38 -05:00
committed by GitHub
parent fd1937c6d4
commit 5a0c064346
+47 -18
View File
@@ -6,6 +6,7 @@ See the LICENSE.md file in the root directory for more details.
"""
from dataclasses import dataclass
from enum import StrEnum
import pyray as rl
from cereal import custom
@@ -14,6 +15,7 @@ from openpilot.common.filter_simple import FirstOrderFilter
from openpilot.selfdrive.ui.onroad.hud_renderer import UI_CONFIG
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode as SpeedLimitMode
from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.text_measure import measure_text_cached
@@ -40,11 +42,21 @@ class Colors:
MUTCD_LINES = rl.Color(255, 255, 255, 100)
class IconSide(StrEnum):
left = 'left'
right = 'right'
class SpeedLimitAlertRenderer:
ARROW_SIZE = 90 if HARDWARE.get_device_type() == 'mici' else 200
def __init__(self):
arrow_size = 200
self.arrow_up = gui_app.texture("../../sunnypilot/selfdrive/assets/img_plus_arrow_up.png", arrow_size, arrow_size)
self.arrow_down = gui_app.texture("../../sunnypilot/selfdrive/assets/img_minus_arrow_down.png", arrow_size, arrow_size)
self.arrow_up = gui_app.texture("../../sunnypilot/selfdrive/assets/img_plus_arrow_up.png", self.ARROW_SIZE, self.ARROW_SIZE)
self.arrow_down = gui_app.texture("../../sunnypilot/selfdrive/assets/img_minus_arrow_down.png", self.ARROW_SIZE, self.ARROW_SIZE)
blank_image = rl.gen_image_color(self.ARROW_SIZE, self.ARROW_SIZE, rl.Color(0, 0, 0, 0))
self.arrow_blank = rl.load_texture_from_image(blank_image)
rl.unload_image(blank_image)
self._pre_active_alpha_filter = FirstOrderFilter(1.0, 0.05, 1 / gui_app.target_fps)
self._pre_active_alert_frame = 0
@@ -61,6 +73,31 @@ class SpeedLimitAlertRenderer:
self._pre_active_alert_frame = 0
self._pre_active_alpha_filter.update(1.0)
def speed_limit_pre_active_icon_helper(self):
icon_alpha = max(0.0, min(self._pre_active_alpha_filter.x * 255.0, 255.0))
txt_icon = self.arrow_blank
icon_margin_x = 10
icon_margin_y = 18
if icon_alpha > 0:
speed_conv = CV.MS_TO_KPH if ui_state.is_metric else CV.MS_TO_MPH
speed_limit_final_last = ui_state.sm['longitudinalPlanSP'].speedLimit.resolver.speedLimitFinalLast
v_cruise_cluster = ui_state.sm['carState'].vCruiseCluster
set_speed = ui_state.sm['controlsState'].vCruiseDEPRECATED if v_cruise_cluster == 0.0 else v_cruise_cluster
if not ui_state.is_metric:
set_speed *= KM_TO_MILE
set_speed_round = round(set_speed)
speed_limit_round = round(speed_limit_final_last * speed_conv)
if set_speed_round < speed_limit_round:
txt_icon = self.arrow_up
elif set_speed_round > speed_limit_round:
txt_icon = self.arrow_down
return IconSide.right, txt_icon, icon_alpha, icon_margin_x, icon_margin_y
class SpeedLimitRenderer(Widget, SpeedLimitAlertRenderer):
def __init__(self):
@@ -192,22 +229,14 @@ class SpeedLimitRenderer(Widget, SpeedLimitAlertRenderer):
self._render_mutcd(rect, limit_str, sub_text, txt_color, has_limit, alpha)
def _draw_pre_active_arrow(self, sign_rect):
set_speed_rounded = round(self.set_speed)
limit_rounded = round(self.speed_limit_final_last)
sign_margin = 12
arrow_spacing = int(sign_margin * 1.4)
arrow_x = sign_rect.x + sign_rect.width + arrow_spacing
icon_alpha = max(0.0, min(self._pre_active_alpha_filter.x * 255.0, 255.0))
if icon_alpha > 0:
_, txt_icon, icon_alpha, _, _ = SpeedLimitAlertRenderer.speed_limit_pre_active_icon_helper(self)
if icon_alpha > 0 and txt_icon != self.arrow_blank:
sign_margin = 12
arrow_spacing = int(sign_margin * 1.4)
arrow_x = sign_rect.x + sign_rect.width + arrow_spacing
arrow_y = sign_rect.y + (sign_rect.height - txt_icon.height) / 2
color = rl.Color(255, 255, 255, int(icon_alpha))
if set_speed_rounded < limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self.arrow_up.height) / 2
rl.draw_texture(self.arrow_up, int(arrow_x), int(arrow_y), color)
elif set_speed_rounded > limit_rounded:
arrow_y = sign_rect.y + (sign_rect.height - self.arrow_down.height) / 2
rl.draw_texture(self.arrow_down, int(arrow_x), int(arrow_y), color)
rl.draw_texture(txt_icon, int(arrow_x), int(arrow_y), color)
def _render_vienna(self, rect, val, sub, color, has_limit, alpha=1.0):
center = rl.Vector2(rect.x + rect.width / 2, rect.y + rect.height / 2)