From 7d53bd5af73daf748a34e9bee44fcf0d54efdd64 Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Tue, 9 Jun 2026 21:30:52 -0400 Subject: [PATCH] BigUI WIP: LED --- .../layouts/settings/starpilot/aethergrid.py | 79 +++++++++++++++---- .../ui/layouts/settings/starpilot/lateral.py | 37 ++++----- .../settings/starpilot/system_settings.py | 6 +- 3 files changed, 85 insertions(+), 37 deletions(-) diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index e1c78fa15..b30b2c956 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -636,13 +636,21 @@ class PanelManagerView(AetherInteractiveMixin, Widget): # active drag if self._page_drag_active: - self._page_scissor_push(clip_rect) - grid.render(rl.Rectangle(rect.x + self._page_drag_offset, rect.y, rect.width, rect.height)) + drag_off = self._page_drag_offset + drag_clip = rl.Rectangle( + clip_rect.x + min(0, drag_off), + clip_rect.y, + clip_rect.width + abs(drag_off), + clip_rect.height, + ) + self._page_scissor_push(drag_clip) + grid.render(rl.Rectangle(rect.x + drag_off, rect.y, rect.width, rect.height)) self._page_scissor_pop() return # no animation if not self._page_animating: + grid.set_parent_rect(self._scroll_rect) grid.render(rect) return @@ -652,6 +660,7 @@ class PanelManagerView(AetherInteractiveMixin, Widget): if elapsed >= duration: self._page_animating = False self._page_anim_prev_tiles.clear() + grid.set_parent_rect(self._scroll_rect) grid.render(rect) return @@ -665,8 +674,8 @@ class PanelManagerView(AetherInteractiveMixin, Widget): old_target = -direction * rect.width prev_offset = self._page_anim_from + (old_target - self._page_anim_from) * t - self._page_scissor_push(rl.Rectangle(clip_rect.x, clip_rect.y, - clip_rect.width + rect.width, clip_rect.height)) + self._page_scissor_push(rl.Rectangle(clip_rect.x - rect.width, clip_rect.y, + clip_rect.width + rect.width * 2, clip_rect.height)) if self._page_anim_prev_tiles: old_grid = TileGrid(columns=grid.get_column_count(), padding=grid.gap) old_grid.tiles.extend(self._page_anim_prev_tiles) @@ -686,7 +695,10 @@ class PanelManagerView(AetherInteractiveMixin, Widget): def _handle_mouse_press(self, mouse_pos: MousePos) -> None: super()._handle_mouse_press(mouse_pos) - if self._has_pagination and not self._page_animating: + if self._has_pagination: + if self._page_animating: + self._page_animating = False + self._page_anim_prev_tiles.clear() self._page_drag_start_x = mouse_pos.x self._page_drag_start_y = mouse_pos.y self._page_drag_active = True @@ -719,11 +731,13 @@ class PanelManagerView(AetherInteractiveMixin, Widget): self._start_drag_commit(offset) self._current_page = new_page self._on_page_changed() + return elif abs(offset) > 8: self._start_drag_snap(offset) + return elif abs(offset) > 8: self._start_drag_snap(offset) - return + return super()._handle_mouse_release(mouse_pos) # ── page indicator ───────────────────────────────────────── @@ -2787,6 +2801,8 @@ class AetherTile(Widget): color=AetherListColors.MUTED, ) + return layout + def _render(self, rect: rl.Rectangle): pass @@ -2906,6 +2922,7 @@ class ToggleTile(AetherTile): desc: str = "", is_enabled: Callable[[], bool] | None = None, disabled_label: str = "", + show_led: bool = False, ): if bg_color: super().__init__(surface_color=bg_color) @@ -2922,6 +2939,7 @@ class ToggleTile(AetherTile): self._inactive_color = rl.Color(120, 120, 120, 255) self._disabled_color = rl.Color(75, 75, 75, 255) self._disabled_label = disabled_label + self._show_led = show_led def _handle_mouse_release(self, mouse_pos: MousePos): if self._is_pressed: @@ -2947,17 +2965,44 @@ class ToggleTile(AetherTile): else: state_text = tr(self._disabled_label) if self._disabled_label else tr("LOCKED") self._draw_signal_edge(face, self._active_color if enabled and active else self.surface_color, width=TILE_SIGNAL_WIDTH, alpha=62 if enabled and active else 28) - self._render_tile_stack( - face, - title=self.title, - primary=state_text, - desc=self.desc, - title_font=self._font, - primary_font=self._font, - desc_font=self._font_desc, - title_size=28, - primary_size=30, - ) + + if self._show_led and enabled: + layout = self._render_tile_stack( + face, + title=self.title, + primary="", + desc=self.desc, + title_font=self._font, + primary_font=self._font, + desc_font=self._font_desc, + title_size=28, + primary_size=30, + ) + primary_y = layout["primary_y"] + content_pad = SPACING.tile_content + scale = max(0.82, min(1.12, min(face.width / 360.0, face.height / 205.0))) + ps = max(18, int(round(30 * scale))) + cx = face.x + face.width - content_pad - 10 + cy = primary_y + ps / 2 + if active: + glow_color = _with_alpha(self._active_color, 24) + rl.draw_circle(int(cx), int(cy), 10, glow_color) + rl.draw_circle(int(cx), int(cy), 6, self._active_color) + else: + rl.draw_circle(int(cx), int(cy), 7, rl.Color(14, 16, 22, 255)) + rl.draw_ring(rl.Vector2(cx, cy), 5, 6, 0, 360, 24, rl.Color(70, 78, 95, 140)) + else: + self._render_tile_stack( + face, + title=self.title, + primary=state_text, + desc=self.desc, + title_font=self._font, + primary_font=self._font, + desc_font=self._font_desc, + title_size=28, + primary_size=30, + ) class ValueTile(AetherTile): diff --git a/selfdrive/ui/layouts/settings/starpilot/lateral.py b/selfdrive/ui/layouts/settings/starpilot/lateral.py index 6fe1265f8..897a37d3b 100644 --- a/selfdrive/ui/layouts/settings/starpilot/lateral.py +++ b/selfdrive/ui/layouts/settings/starpilot/lateral.py @@ -115,7 +115,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "AdvancedLateralTune", "title": tr("Advanced Lateral Tuning"), - "subtitle": tr("Advanced steering control changes to fine-tune how openpilot drives."), + "subtitle": tr("Fine-tune steering response and auto-tuning."), "get": lambda: p.get_bool("AdvancedLateralTune"), "set": lambda s: p.put_bool("AdvancedLateralTune", s), }) @@ -123,7 +123,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "AlwaysOnLateral", "title": tr("Always On Lateral"), - "subtitle": tr("Keep lateral control active even without openpilot engaged."), + "subtitle": tr("Steering stays active when ACC is off."), "get": lambda: p.get_bool("AlwaysOnLateral"), "set": lambda s: (_confirm_reboot_toggle(p, "AlwaysOnLateral", s) if s else p.put_bool("AlwaysOnLateral", False)), @@ -140,7 +140,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "PauseLateralOnSignal", "title": tr("Turn Signal Only"), - "subtitle": tr("Only pause steering below the set speed when the turn signal is active."), + "subtitle": tr("Only pause steering when turn signal is active."), "get": lambda: p.get_bool("PauseLateralOnSignal"), "set": lambda s: p.put_bool("PauseLateralOnSignal", s), }) @@ -148,7 +148,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "NudgelessLaneChange", "title": tr("Auto Lane Changes"), - "subtitle": tr("When the turn signal is on, openpilot will automatically change lanes without a nudge."), + "subtitle": tr("Signal triggers automatic lane change."), "get": lambda: p.get_bool("NudgelessLaneChange"), "set": lambda s: p.put_bool("NudgelessLaneChange", s), }) @@ -156,7 +156,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "OneLaneChange", "title": tr("One Per Signal"), - "subtitle": tr("Limit automatic lane changes to one per turn-signal activation."), + "subtitle": tr("One lane change per signal activation."), "get": lambda: p.get_bool("OneLaneChange"), "set": lambda s: p.put_bool("OneLaneChange", s), }) @@ -164,7 +164,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "TurnDesires", "title": tr("Force Turn Desires"), - "subtitle": tr("While driving below the minimum lane change speed with an active turn signal, instruct openpilot to turn."), + "subtitle": tr("Follow turn intent below min lane change speed."), "get": lambda: p.get_bool("TurnDesires"), "set": lambda s: (p.put_bool("TurnDesires", s), _sync_parent(p, "LateralTune", _LATERAL_TUNE_KEYS)), @@ -173,7 +173,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "NavDesiresAllowed", "title": tr("Use Route Desires"), - "subtitle": tr("Allow an active navigation route to request keep-left, keep-right, and low-speed turn desires."), + "subtitle": tr("Allow navigation to request lane keep and turns."), "get": lambda: p.get_bool("NavDesiresAllowed"), "set": lambda s: p.put_bool("NavDesiresAllowed", s), }) @@ -181,7 +181,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "NNFF", "title": tr("NNFF"), - "subtitle": tr("Neural Network FeedForward controller — uses a trained model to predict steering torque."), + "subtitle": tr("Neural net feedforward steering controller."), "get": lambda: p.get_bool("NNFF"), "set": lambda s: (p.put_bool("NNFF", s), s and p.put_bool("NNFFLite", False), @@ -193,7 +193,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "NNFFLite", "title": tr("NNFF Lite"), - "subtitle": tr("Lightweight NNFF steering logic when the full model is off."), + "subtitle": tr("Lightweight NNFF when full model is off."), "get": lambda: p.get_bool("NNFFLite"), "set": lambda s: (p.put_bool("NNFFLite", s), _sync_parent(p, "LateralTune", _LATERAL_TUNE_KEYS)), @@ -204,7 +204,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "ForceAutoTune", "title": tr("Force Auto-Tune On"), - "subtitle": tr("Force-enable live auto-tuning for friction and lateral acceleration."), + "subtitle": tr("Force-enable live auto-tuning for friction and lateral accel."), "get": lambda: p.get_bool("ForceAutoTune"), "set": lambda s: (p.put_bool("ForceAutoTune", s), s and p.put_bool("ForceAutoTuneOff", False), @@ -216,7 +216,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "ForceAutoTuneOff", "title": tr("Force Auto-Tune Off"), - "subtitle": tr("Force-disable live auto-tuning and use your set values instead."), + "subtitle": tr("Force-disable auto-tuning and use your set values."), "get": lambda: p.get_bool("ForceAutoTuneOff"), "set": lambda s: (p.put_bool("ForceAutoTuneOff", s), s and p.put_bool("ForceAutoTune", False), @@ -228,7 +228,7 @@ class SteeringManagerView(PanelManagerView): toggles.append({ "key": "ForceTorqueController", "title": tr("Force Torque Ctrl"), - "subtitle": tr("Use torque-based steering control instead of angle-based for smoother lane keeping, especially in curves."), + "subtitle": tr("Torque-based steering for smoother lane keeping."), "get": lambda: p.get_bool("ForceTorqueController"), "set": lambda s: (p.put_bool("ForceTorqueController", s), _sync_parent(p, "LateralTune", _LATERAL_TUNE_KEYS)), @@ -249,6 +249,7 @@ class SteeringManagerView(PanelManagerView): desc=td.get("subtitle", ""), is_enabled=td.get("enabled", True), disabled_label=td.get("disabled_label", ""), + show_led=True, )) def _measure_content_height(self, width: float) -> float: @@ -402,7 +403,7 @@ class SteeringManagerView(PanelManagerView): rows.append({ "target_id": "select:SteerDelay", "title": tr("Actuator Delay"), - "subtitle": tr("The time between openpilot's steering command and the vehicle's response."), + "subtitle": tr("Time between steering command and vehicle response."), "get_value": lambda: f"{p.get_float('SteerDelay'):.2f}s", "pill_width": 120, }) @@ -434,7 +435,7 @@ class SteeringManagerView(PanelManagerView): rows.append({ "target_id": "select:SteerRatio", "title": tr("Steer Ratio"), - "subtitle": tr("Adjust the relationship between steering wheel input and road-wheel angle."), + "subtitle": tr("Relationship between steering wheel and road-wheel angle."), "get_value": lambda: f"{p.get_float('SteerRatio'):.2f}", "pill_width": 120, }) @@ -449,7 +450,7 @@ class SteeringManagerView(PanelManagerView): aol_rows = [{ "target_id": "select:PauseAOLOnBrake", "title": tr("Pause AOL On Brake"), - "subtitle": tr("Pause Always On Lateral below this speed while the brake is pressed."), + "subtitle": tr("Pause AOL below this speed while brake is pressed."), "get_value": lambda: f"{p.get_int('PauseAOLOnBrake')} mph", "pill_width": 140, }] @@ -480,14 +481,14 @@ class SteeringManagerView(PanelManagerView): lc_rows.append({ "target_id": "select:LaneDetectionWidth", "title": tr("Min Lane Width"), - "subtitle": tr("Prevent automatic lane changes into lanes narrower than this width."), + "subtitle": tr("Prevent lane changes into narrower lanes."), "get_value": lambda: f"{p.get_float('LaneDetectionWidth'):.1f} ft", "pill_width": 120, }) lc_rows.append({ "target_id": "select:LaneChangeSmoothing", "title": tr("Lane Change Smoothing"), - "subtitle": tr("How smoothly openpilot commits to a lane change. 10 = Stock, 1 = Smoothest."), + "subtitle": tr("Smoothness of lane change commit. 10 = Stock, 1 = Smoothest."), "get_value": lambda: tr("Stock") if p.get_int("LaneChangeSmoothing") == 10 else f"{p.get_int('LaneChangeSmoothing')}", "pill_width": 120, @@ -510,7 +511,7 @@ class SteeringManagerView(PanelManagerView): paus_rows.append({ "target_id": "select:LateralResumeDelay", "title": tr("Resume Delay"), - "subtitle": tr("Delay before lateral resumes after the turn signal is turned off. 0 = Off."), + "subtitle": tr("Delay before lateral resumes after signal off. 0 = Off."), "get_value": lambda: tr("Off") if p.get_float("LateralResumeDelay") == 0 else f"{p.get_float('LateralResumeDelay'):.1f}s", "pill_width": 120, diff --git a/selfdrive/ui/layouts/settings/starpilot/system_settings.py b/selfdrive/ui/layouts/settings/starpilot/system_settings.py index 7640fc543..8deb09aca 100644 --- a/selfdrive/ui/layouts/settings/starpilot/system_settings.py +++ b/selfdrive/ui/layouts/settings/starpilot/system_settings.py @@ -310,6 +310,8 @@ class SystemSettingsManagerView(PanelManagerView): self._connectivity_tile_grid.add_tile(tile) self._connectivity_tile_grid.set_touch_valid_callback(lambda: self._scroll_panel.is_touch_valid()) self._child(self._connectivity_tile_grid) + self._page_grid = self._connectivity_tile_grid + self._set_toggle_pages([self._toggle_defs[i:i+4] for i in range(0, len(self._toggle_defs), 4)]) self._drive_mode_control = self._child( AetherSegmentedControl( @@ -554,7 +556,7 @@ class SystemSettingsManagerView(PanelManagerView): def _draw_connectivity_tiles_column(self, y: float, x: float, width: float, height: float): draw_list_group_shell(rl.Rectangle(x, y, width, height), style=PANEL_STYLE) - self._connectivity_tile_grid.render(rl.Rectangle(x + 12, y + 12, width - 24, height - 24)) + self._render_page_grid(self._connectivity_tile_grid, rl.Rectangle(x + 12, y + 12, width - 24, height - 24)) def _draw_connectivity_tiles_section(self, y: float, x: float, width: float): tile_rows = self._connectivity_tile_grid.get_row_count(len(self._connectivity_tile_grid.tiles), available_width=width) @@ -562,7 +564,7 @@ class SystemSettingsManagerView(PanelManagerView): tiles_content_h = tile_rows * 130 + tile_gaps draw_list_group_shell(rl.Rectangle(x, y, width, tiles_content_h + 24), style=PANEL_STYLE) - self._connectivity_tile_grid.render(rl.Rectangle(x + 12, y + 12, width - 24, tiles_content_h)) + self._render_page_grid(self._connectivity_tile_grid, rl.Rectangle(x + 12, y + 12, width - 24, tiles_content_h)) def _draw_slider_section(self, y: float, x: float, width: float, title: str, keys: list[str]) -> float: draw_section_header(rl.Rectangle(x, y, width, SECTION_HEADER_HEIGHT), title, style=PANEL_STYLE)