exp c4 ui

This commit is contained in:
firestar5683
2026-05-11 00:36:41 -05:00
parent 8bd080b3e0
commit 3c3969b09d
4 changed files with 86 additions and 51 deletions
+60
View File
@@ -0,0 +1,60 @@
import time
import pyray as rl
from openpilot.selfdrive.ui.lib.starpilot_status import get_border_color, get_mode_transition_banner_text
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import FontWeight
from openpilot.system.ui.widgets.label import UnifiedLabel
class ModeTransitionBanner:
SHOW_TIME_SECONDS = 2.5
def __init__(self, *, font_size: int = 34, width: int = 520, height: int = 72, top_margin: int = 22):
self._last_mode: str | None = None
self._visible_until = 0.0
self._width = width
self._height = height
self._top_margin = top_margin
self._label = UnifiedLabel(
"",
font_size,
FontWeight.BOLD,
text_color=rl.WHITE,
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE,
)
def update(self):
if not ui_state.started:
self._last_mode = None
self._visible_until = 0.0
return
current_mode = get_mode_transition_banner_text(ui_state)
if self._last_mode is None:
self._last_mode = current_mode
return
if current_mode != self._last_mode:
self._last_mode = current_mode
if current_mode is not None:
self._label.set_text(f"{current_mode} MODE")
self._visible_until = time.monotonic() + self.SHOW_TIME_SECONDS
def render(self, rect: rl.Rectangle):
if not ui_state.started or time.monotonic() > self._visible_until:
return
banner_width = min(rect.width - 120, self._width)
banner_rect = rl.Rectangle(
rect.x + (rect.width - banner_width) / 2,
rect.y + self._top_margin,
banner_width,
self._height,
)
rl.draw_rectangle_rounded(banner_rect, 0.3, 12, rl.Color(0, 0, 0, 175))
rl.draw_rectangle_rounded_lines_ex(banner_rect, 0.3, 12, 4, get_border_color(ui_state))
self._label.render(banner_rect)
+16
View File
@@ -74,3 +74,19 @@ def get_experimental_mode_banner_text(state: UIState):
if state.sm["selfdriveState"].experimentalMode:
return "EXPERIMENTAL"
return "CHILL"
def get_mode_transition_banner_text(state: UIState):
enabled = state.sm["selfdriveState"].enabled
lateral_active = enabled or state.always_on_lateral_active
conditional_enabled = state.params.get_bool("ConditionalExperimental")
if state.status == UIStatus.OVERRIDE:
return "OVERRIDE"
if state.switchback_mode_enabled and lateral_active:
return "SWITCHBACK"
if conditional_enabled and enabled and state.conditional_status in CEM_MANUAL_OVERRIDE_STATUSES:
return "OVERRIDDEN"
if enabled and state.sm["selfdriveState"].experimentalMode:
return "EXPERIMENTAL"
return None
@@ -17,8 +17,8 @@ from openpilot.selfdrive.ui.mici.onroad.starpilot_status import (
EXPERIMENTAL_COLOR,
TRAFFIC_COLOR,
get_border_color,
get_experimental_mode_banner_text,
)
from openpilot.selfdrive.ui.lib.starpilot_mode_banner import ModeTransitionBanner
from openpilot.selfdrive.ui.mici.onroad.cameraview import CameraView
from openpilot.selfdrive.ui.lib.starpilot_visuals import get_border_width
from openpilot.system.ui.lib.application import FontWeight, gui_app, MousePos, MouseEvent
@@ -147,54 +147,6 @@ class BookmarkIcon(Widget):
rl.draw_texture(self._icon, int(icon_x), int(icon_y), rl.WHITE)
class ExperimentalModeBanner(Widget):
SHOW_TIME_SECONDS = 2.5
def __init__(self):
super().__init__()
self._last_mode: str | None = None
self._visible_until = 0.0
self._label = UnifiedLabel(
"",
34,
FontWeight.BOLD,
text_color=rl.WHITE,
alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER,
alignment_vertical=rl.GuiTextAlignmentVertical.TEXT_ALIGN_MIDDLE,
)
def _update_state(self):
current_mode = get_experimental_mode_banner_text(ui_state)
if current_mode is None:
return
if self._last_mode is None:
self._last_mode = current_mode
return
if current_mode != self._last_mode:
self._last_mode = current_mode
self._label.set_text(f"{current_mode} MODE")
self._visible_until = time.monotonic() + self.SHOW_TIME_SECONDS
def _render(self, rect):
if not ui_state.started or time.monotonic() > self._visible_until:
return
banner_width = min(rect.width - 120, 520)
banner_height = 72
banner_rect = rl.Rectangle(
rect.x + (rect.width - banner_width) / 2,
rect.y + 22,
banner_width,
banner_height,
)
rl.draw_rectangle_rounded(banner_rect, 0.3, 12, rl.Color(0, 0, 0, 175))
rl.draw_rectangle_rounded_lines_ex(banner_rect, 0.3, 12, 4, get_border_color(ui_state))
self._label.render(banner_rect)
class MinSteerSpeedBanner(Widget):
"""One-shot-per-drive banner shown for the full first below-min-steer interval."""
@@ -420,7 +372,7 @@ class AugmentedRoadView(CameraView):
self._alert_renderer = AlertRenderer()
self._driver_state_renderer = DriverStateRenderer()
self._confidence_ball = ConfidenceBall()
self._experimental_mode_banner = ExperimentalModeBanner()
self._mode_transition_banner = ModeTransitionBanner()
self._min_steer_speed_banner = MinSteerSpeedBanner()
self._standstill_timer = StandstillTimerOverlay()
self._offroad_label = UnifiedLabel("start the car to\nuse openpilot", 54, FontWeight.DISPLAY,
@@ -536,13 +488,14 @@ class AugmentedRoadView(CameraView):
self._hud_renderer.set_can_draw_top_icons((not in_reverse) and (not is_driver_stream) and (alert_to_render is None))
self._hud_renderer.set_wheel_critical_icon((not in_reverse) and (not is_driver_stream) and alert_to_render is not None and not not_animating_out and
alert_to_render.visual_alert == car.CarControl.HUDControl.VisualAlert.steerRequired)
self._mode_transition_banner.update()
# TODO: have alert renderer draw offroad mici label below
if ui_state.started:
self._alert_renderer.render(self._content_rect)
if not in_reverse and not is_driver_stream:
self._hud_renderer.render_foreground()
if (not in_reverse) and (not is_driver_stream) and alert_to_render is None:
self._experimental_mode_banner.render(self._content_rect)
self._mode_transition_banner.render(self._content_rect)
rendered_standstill_timer = False
if not in_reverse and not is_driver_stream:
rendered_standstill_timer = self._standstill_timer.render(self._content_rect, in_reverse)
@@ -12,6 +12,7 @@ from openpilot.selfdrive.ui.onroad.driver_state import DriverStateRenderer
from openpilot.selfdrive.ui.onroad.hud_renderer import HudRenderer
from openpilot.selfdrive.ui.onroad.model_renderer import ModelRenderer
from openpilot.selfdrive.ui.onroad.cameraview import CameraView
from openpilot.selfdrive.ui.lib.starpilot_mode_banner import ModeTransitionBanner
from openpilot.selfdrive.ui.lib.starpilot_status import get_screen_edge_color
from openpilot.system.ui.lib.application import gui_app, FontWeight
from openpilot.common.transformations.camera import DEVICE_CAMERAS, DeviceCameraConfig, view_frame_from_device_frame
@@ -149,6 +150,7 @@ class AugmentedRoadView(CameraView):
self._hud_renderer = HudRenderer()
self.alert_renderer = AlertRenderer()
self.driver_state_renderer = DriverStateRenderer()
self._mode_transition_banner = ModeTransitionBanner()
self._min_steer_speed_banner = MinSteerSpeedBanner()
# debug
@@ -188,10 +190,14 @@ class AugmentedRoadView(CameraView):
super()._render(self._content_rect)
# Draw all UI overlays
current_alert = self.alert_renderer.get_alert(ui_state.sm)
self.model_renderer.render(self._content_rect)
self._hud_renderer.render(self._content_rect)
self._mode_transition_banner.update()
self.alert_renderer.render(self._content_rect)
self.driver_state_renderer.render(self._content_rect)
if current_alert is None:
self._mode_transition_banner.render(self._content_rect)
self._min_steer_speed_banner.render(self._content_rect)
# Custom UI extension point - add custom overlays here