From 5a0c06434609b762b4d84da594ff567f0910df07 Mon Sep 17 00:00:00 2001 From: Jason Wen Date: Sat, 28 Feb 2026 20:06:38 -0500 Subject: [PATCH] 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 --- selfdrive/ui/sunnypilot/onroad/speed_limit.py | 65 ++++++++++++++----- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/selfdrive/ui/sunnypilot/onroad/speed_limit.py b/selfdrive/ui/sunnypilot/onroad/speed_limit.py index 962c96e17..02df292cd 100644 --- a/selfdrive/ui/sunnypilot/onroad/speed_limit.py +++ b/selfdrive/ui/sunnypilot/onroad/speed_limit.py @@ -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)