From 447b894aae36d6c17362e9e09b8e6ddbfdbda104 Mon Sep 17 00:00:00 2001 From: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Date: Mon, 6 Apr 2026 02:52:34 -0400 Subject: [PATCH] BigUI WIP: More Settings Porting --- .../layouts/settings/starpilot/aethergrid.py | 12 +++ .../ui/layouts/settings/starpilot/device.py | 24 +++++ .../settings/starpilot/driving_model.py | 38 ++++++++ .../ui/layouts/settings/starpilot/lateral.py | 31 ++++--- .../settings/starpilot/longitudinal.py | 90 ++++++++++++++++++- .../ui/layouts/settings/starpilot/themes.py | 23 +++++ .../ui/layouts/settings/starpilot/visuals.py | 71 +++++++++++++++ .../onroad/starpilot/starpilot_onroad_view.py | 84 ++++++++++++++++- selfdrive/ui/ui_state.py | 1 + 9 files changed, 358 insertions(+), 16 deletions(-) diff --git a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py index a2c66384..f3641c21 100644 --- a/selfdrive/ui/layouts/settings/starpilot/aethergrid.py +++ b/selfdrive/ui/layouts/settings/starpilot/aethergrid.py @@ -204,6 +204,12 @@ class HubTile(AetherTile): for i, line in enumerate(lines): self._draw_text_fit(self._font_title, line, rl.Vector2(face.x + 20, ty + i * (line_h + line_spacing)), max_w, line_h, align_center=True) + if self.desc: + desc_lines = self._wrap_text(self._font_desc, self.desc, max_w, 18, max_lines=3) + desc_y = ty + len(lines) * (line_h + line_spacing) + 18 + for i, line in enumerate(desc_lines): + self._draw_text_fit(self._font_desc, line, rl.Vector2(face.x + 20, desc_y + i * 20), max_w, 18, align_center=True) + class ToggleTile(AetherTile): def __init__(self, title: str, get_state: Callable[[], bool], set_state: Callable[[bool], None], icon_path: str | None = None, @@ -238,6 +244,9 @@ class ToggleTile(AetherTile): state_text = tr("ON") if active else tr("OFF") self._draw_text_fit(self._font, state_text, rl.Vector2(face.x + 20, ty + 28 + 8), max_w, 30, align_center=True, uppercase=True) + if self.desc: + self._draw_text_fit(self._font_desc, self.desc, rl.Vector2(face.x + 20, ty + 28 + 8 + 34), max_w, 18, align_center=True) + class ValueTile(AetherTile): def __init__(self, title: str, get_value: Callable[[], str], on_click: Callable, icon_path: str | None = None, @@ -267,6 +276,9 @@ class ValueTile(AetherTile): val_text = self.get_value() self._draw_text_fit(self._font, val_text, rl.Vector2(face.x + 20, ty + 28 + 8), max_w, 28, align_center=True, uppercase=True) + if self.desc: + self._draw_text_fit(self._font_desc, self.desc, rl.Vector2(face.x + 20, ty + 28 + 8 + 34), max_w, 18, align_center=True) + class AetherSlider(Widget): def __init__(self, min_val: float, max_val: float, step: float, current_val: float, on_change: Callable[[float], None], unit: str = "", labels: dict[float, str] | None = None, color: rl.Color = rl.Color(54, 77, 239, 255)): diff --git a/selfdrive/ui/layouts/settings/starpilot/device.py b/selfdrive/ui/layouts/settings/starpilot/device.py index 1faf4dd2..ceba7620 100644 --- a/selfdrive/ui/layouts/settings/starpilot/device.py +++ b/selfdrive/ui/layouts/settings/starpilot/device.py @@ -129,12 +129,21 @@ class StarPilotScreenLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Screen Settings"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("ScreenManagement"), + "set_state": lambda s: self._params.put_bool("ScreenManagement", s), + "icon": "toggle_icons/icon_light.png", + "color": "#D43D8A", + }, { "title": tr_noop("Brightness (Offroad)"), "type": "value", "get_value": lambda: self._get_brightness("ScreenBrightness"), "on_click": lambda: self._show_brightness_selector("ScreenBrightness"), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("ScreenManagement"), }, { "title": tr_noop("Brightness (Onroad)"), @@ -142,6 +151,7 @@ class StarPilotScreenLayout(StarPilotPanel): "get_value": lambda: self._get_brightness("ScreenBrightnessOnroad"), "on_click": lambda: self._show_brightness_selector("ScreenBrightnessOnroad"), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("ScreenManagement"), }, { "title": tr_noop("Timeout (Offroad)"), @@ -149,6 +159,7 @@ class StarPilotScreenLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('ScreenTimeout')}s", "on_click": lambda: self._show_timeout_selector("ScreenTimeout"), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("ScreenManagement"), }, { "title": tr_noop("Timeout (Onroad)"), @@ -156,6 +167,7 @@ class StarPilotScreenLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('ScreenTimeoutOnroad')}s", "on_click": lambda: self._show_timeout_selector("ScreenTimeoutOnroad"), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("ScreenManagement"), }, { "title": tr_noop("Standby Mode"), @@ -163,6 +175,7 @@ class StarPilotScreenLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("StandbyMode"), "set_state": lambda s: self._params.put_bool("StandbyMode", s), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("ScreenManagement"), }, ] self._rebuild_grid() @@ -210,12 +223,21 @@ class StarPilotDeviceManagementLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Device Settings"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("DeviceManagement"), + "set_state": lambda s: self._params.put_bool("DeviceManagement", s), + "icon": "toggle_icons/icon_device.png", + "color": "#D43D8A", + }, { "title": tr_noop("Low-Voltage Cutoff"), "type": "value", "get_value": lambda: f"{self._params.get_float('LowVoltageShutdown'):.1f}V", "on_click": self._show_voltage_selector, "color": "#D43D8A", + "visible": lambda: self._params.get_bool("DeviceManagement"), }, { "title": tr_noop("Raise Temp Limits"), @@ -223,6 +245,7 @@ class StarPilotDeviceManagementLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("IncreaseThermalLimits"), "set_state": lambda s: self._params.put_bool("IncreaseThermalLimits", s), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("DeviceManagement"), }, { "title": tr_noop("Use Konik Server"), @@ -230,6 +253,7 @@ class StarPilotDeviceManagementLayout(StarPilotPanel): "get_state": lambda: self._get_konik_state(), "set_state": lambda s: self._on_konik_toggle(s), "color": "#D43D8A", + "visible": lambda: self._params.get_bool("DeviceManagement"), }, ] self._rebuild_grid() diff --git a/selfdrive/ui/layouts/settings/starpilot/driving_model.py b/selfdrive/ui/layouts/settings/starpilot/driving_model.py index 9506c5f7..12a4e9bd 100644 --- a/selfdrive/ui/layouts/settings/starpilot/driving_model.py +++ b/selfdrive/ui/layouts/settings/starpilot/driving_model.py @@ -13,6 +13,7 @@ from openpilot.system.ui.widgets import DialogResult from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog, alert_dialog from openpilot.system.ui.widgets.selection_dialog import SelectionDialog from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel +from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog class StarPilotDrivingModelLayout(StarPilotPanel): def __init__(self): @@ -41,6 +42,7 @@ class StarPilotDrivingModelLayout(StarPilotPanel): "icon": "toggle_icons/icon_steering.png", "on_click": self._on_select_model_clicked, "get_value": lambda: self._current_model_name, + "visible": lambda: not self._params.get_bool("ModelRandomizer"), "color": "#597497" }, { @@ -65,6 +67,24 @@ class StarPilotDrivingModelLayout(StarPilotPanel): "set_state": self._on_model_randomizer_toggled, "color": "#597497" }, + { + "title": tr_noop("Recovery Power"), + "type": "value", + "icon": "toggle_icons/icon_road.png", + "get_value": lambda: f"{self._params.get_float('RecoveryPower'):.1f}", + "on_click": self._on_recovery_power_clicked, + "visible": lambda: self._params.get_int("TuningLevel") == 3, + "color": "#597497" + }, + { + "title": tr_noop("Stop Distance"), + "type": "value", + "icon": "toggle_icons/icon_road.png", + "get_value": lambda: f"{self._params.get_float('StopDistance'):.1f}m", + "on_click": self._on_stop_distance_clicked, + "visible": lambda: self._params.get_int("TuningLevel") == 3, + "color": "#597497" + }, { "title": tr_noop("Auto Download"), "type": "toggle", @@ -78,6 +98,7 @@ class StarPilotDrivingModelLayout(StarPilotPanel): "type": "hub", "icon": "toggle_icons/icon_system.png", "on_click": self._on_blacklist_clicked, + "visible": lambda: self._params.get_bool("ModelRandomizer"), "color": "#597497" }, { @@ -85,6 +106,7 @@ class StarPilotDrivingModelLayout(StarPilotPanel): "type": "hub", "icon": "toggle_icons/icon_system.png", "on_click": self._on_scores_clicked, + "visible": lambda: self._params.get_bool("ModelRandomizer"), "color": "#597497" }, ] @@ -220,6 +242,22 @@ class StarPilotDrivingModelLayout(StarPilotPanel): self._show_selection_dialog(tr("Select Driving Model"), installed_models, self._current_model_name, _on_confirm) + def _on_recovery_power_clicked(self): + def on_close(res, val): + if res == DialogResult.CONFIRM: + self._params.put_float("RecoveryPower", float(val)) + self._rebuild_grid() + + gui_app.set_modal_overlay(AetherSliderDialog(tr("Recovery Power"), 0.5, 2.0, 0.1, self._params.get_float("RecoveryPower"), on_close, unit="x", color="#597497")) + + def _on_stop_distance_clicked(self): + def on_close(res, val): + if res == DialogResult.CONFIRM: + self._params.put_float("StopDistance", float(val)) + self._rebuild_grid() + + gui_app.set_modal_overlay(AetherSliderDialog(tr("Stop Distance"), 4.0, 10.0, 0.1, self._params.get_float("StopDistance"), on_close, unit="m", color="#597497")) + def _on_download_clicked(self): is_downloading = self._params_memory.get("ModelToDownload") or self._params_memory.get_bool("DownloadAllModels") if is_downloading: diff --git a/selfdrive/ui/layouts/settings/starpilot/lateral.py b/selfdrive/ui/layouts/settings/starpilot/lateral.py index 42e2bd49..7ca1b2ab 100644 --- a/selfdrive/ui/layouts/settings/starpilot/lateral.py +++ b/selfdrive/ui/layouts/settings/starpilot/lateral.py @@ -12,14 +12,15 @@ class StarPilotAdvancedLateralLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + {"title": tr_noop("Advanced Lateral Tuning"), "type": "toggle", "get_state": lambda: self._params.get_bool("AdvancedLateralTune"), "set_state": lambda x: self._params.put_bool("AdvancedLateralTune", x), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, {"title": tr_noop("Actuator Delay"), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerDelay'):.2f}s", "on_click": lambda: self._show_float_selector("SteerDelay", 0.0, 0.5, 0.01, "s"), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, {"title": tr_noop("Friction"), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerFriction'):.3f}", "on_click": lambda: self._show_float_selector("SteerFriction", 0.0, 0.5, 0.005), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, {"title": tr_noop("Kp Factor"), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerKP'):.2f}", "on_click": lambda: self._show_float_selector("SteerKP", 0.5, 2.5, 0.01), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, {"title": tr_noop("Lateral Accel"), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerLatAccel'):.2f}", "on_click": lambda: self._show_float_selector("SteerLatAccel", 0.5, 5.0, 0.01), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, {"title": tr_noop("Steer Ratio"), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerRatio'):.2f}", "on_click": lambda: self._show_float_selector("SteerRatio", 5.0, 25.0, 0.01), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, - {"title": tr_noop("Force Auto-Tune On"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTune"), "set_state": lambda x: self._params.put_bool("ForceAutoTune", x), "icon": "toggle_icons/icon_tuning.png", "color": "#597497"}, - {"title": tr_noop("Force Auto-Tune Off"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTuneOff"), "set_state": lambda x: self._params.put_bool("ForceAutoTuneOff", x), "icon": "toggle_icons/icon_tuning.png", "color": "#597497"}, - {"title": tr_noop("Force Torque Controller"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceTorqueController"), "set_state": lambda x: self._on_reboot_toggle("ForceTorqueController", x), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"}, + {"title": tr_noop("Force Auto-Tune On"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTune"), "set_state": lambda x: self._params.put_bool("ForceAutoTune", x), "icon": "toggle_icons/icon_tuning.png", "color": "#597497", "visible": lambda: self._params.get_bool("AdvancedLateralTune")}, + {"title": tr_noop("Force Auto-Tune Off"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTuneOff"), "set_state": lambda x: self._params.put_bool("ForceAutoTuneOff", x), "icon": "toggle_icons/icon_tuning.png", "color": "#597497", "visible": lambda: self._params.get_bool("AdvancedLateralTune")}, + {"title": tr_noop("Force Torque Controller"), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceTorqueController"), "set_state": lambda x: self._on_reboot_toggle("ForceTorqueController", x), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": lambda: self._params.get_bool("AdvancedLateralTune")}, ] self._rebuild_grid() @@ -42,8 +43,8 @@ class StarPilotAlwaysOnLateralLayout(StarPilotPanel): super().__init__() self.CATEGORIES = [ {"title": tr_noop("Always On Lateral"), "type": "toggle", "get_state": lambda: self._params.get_bool("AlwaysOnLateral"), "set_state": lambda x: self._on_reboot_toggle("AlwaysOnLateral", x), "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497"}, - {"title": tr_noop("Enable With LKAS"), "type": "toggle", "get_state": lambda: self._params.get_bool("AlwaysOnLateralLKAS"), "set_state": lambda x: self._params.put_bool("AlwaysOnLateralLKAS", x), "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497"}, - {"title": tr_noop("Pause Below"), "type": "value", "get_value": lambda: f"{self._params.get_int('PauseAOLOnBrake')} mph", "on_click": lambda: self._show_speed_selector("PauseAOLOnBrake"), "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497"}, + {"title": tr_noop("Enable With LKAS"), "type": "toggle", "get_state": lambda: self._params.get_bool("AlwaysOnLateralLKAS"), "set_state": lambda x: self._params.put_bool("AlwaysOnLateralLKAS", x), "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497", "visible": lambda: self._params.get_bool("AlwaysOnLateral")}, + {"title": tr_noop("Pause Below"), "type": "value", "get_value": lambda: f"{self._params.get_int('PauseAOLOnBrake')} mph", "on_click": lambda: self._show_speed_selector("PauseAOLOnBrake"), "icon": "toggle_icons/icon_always_on_lateral.png", "color": "#597497", "visible": lambda: self._params.get_bool("AlwaysOnLateral")}, ] self._rebuild_grid() @@ -65,11 +66,11 @@ class StarPilotLaneChangesLayout(StarPilotPanel): super().__init__() self.CATEGORIES = [ {"title": tr_noop("Lane Changes"), "type": "toggle", "get_state": lambda: self._params.get_bool("LaneChanges"), "set_state": lambda s: self._params.put_bool("LaneChanges", s), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, - {"title": tr_noop("Automatic Lane Changes"), "type": "toggle", "get_state": lambda: self._params.get_bool("NudgelessLaneChange"), "set_state": lambda s: self._params.put_bool("NudgelessLaneChange", s), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, - {"title": tr_noop("Lane Change Delay"), "type": "value", "get_value": lambda: f"{self._params.get_float('LaneChangeTime'):.1f}s", "on_click": lambda: self._show_float_selector("LaneChangeTime", 0.0, 5.0, 0.1, "s"), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, - {"title": tr_noop("Min Lane Change Speed"), "type": "value", "get_value": lambda: f"{self._params.get_int('MinimumLaneChangeSpeed')} mph", "on_click": lambda: self._show_speed_selector("MinimumLaneChangeSpeed"), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, - {"title": tr_noop("Minimum Lane Width"), "type": "value", "get_value": lambda: f"{self._params.get_float('LaneDetectionWidth'):.1f} ft", "on_click": lambda: self._show_float_selector("LaneDetectionWidth", 0.0, 15.0, 0.1, " ft"), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, - {"title": tr_noop("One Lane Change Per Signal"), "type": "toggle", "get_state": lambda: self._params.get_bool("OneLaneChange"), "set_state": lambda s: self._params.put_bool("OneLaneChange", s), "icon": "toggle_icons/icon_lane.png", "color": "#597497"}, + {"title": tr_noop("Automatic Lane Changes"), "type": "toggle", "get_state": lambda: self._params.get_bool("NudgelessLaneChange"), "set_state": lambda s: self._params.put_bool("NudgelessLaneChange", s), "icon": "toggle_icons/icon_lane.png", "color": "#597497", "visible": lambda: self._params.get_bool("LaneChanges")}, + {"title": tr_noop("Lane Change Delay"), "type": "value", "get_value": lambda: f"{self._params.get_float('LaneChangeTime'):.1f}s", "on_click": lambda: self._show_float_selector("LaneChangeTime", 0.0, 5.0, 0.1, "s"), "icon": "toggle_icons/icon_lane.png", "color": "#597497", "visible": lambda: self._params.get_bool("LaneChanges")}, + {"title": tr_noop("Min Lane Change Speed"), "type": "value", "get_value": lambda: f"{self._params.get_int('MinimumLaneChangeSpeed')} mph", "on_click": lambda: self._show_speed_selector("MinimumLaneChangeSpeed"), "icon": "toggle_icons/icon_lane.png", "color": "#597497", "visible": lambda: self._params.get_bool("LaneChanges")}, + {"title": tr_noop("Minimum Lane Width"), "type": "value", "get_value": lambda: f"{self._params.get_float('LaneDetectionWidth'):.1f} ft", "on_click": lambda: self._show_float_selector("LaneDetectionWidth", 0.0, 15.0, 0.1, " ft"), "icon": "toggle_icons/icon_lane.png", "color": "#597497", "visible": lambda: self._params.get_bool("LaneChanges")}, + {"title": tr_noop("One Lane Change Per Signal"), "type": "toggle", "get_state": lambda: self._params.get_bool("OneLaneChange"), "set_state": lambda s: self._params.put_bool("OneLaneChange", s), "icon": "toggle_icons/icon_lane.png", "color": "#597497", "visible": lambda: self._params.get_bool("LaneChanges")}, ] self._rebuild_grid() @@ -91,9 +92,10 @@ class StarPilotLateralTuneLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ - {"title": tr_noop("Force Turn Desires"), "type": "toggle", "get_state": lambda: self._params.get_bool("TurnDesires"), "set_state": lambda x: self._params.put_bool("TurnDesires", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"}, - {"title": tr_noop("NNFF"), "type": "toggle", "get_state": lambda: self._params.get_bool("NNFF"), "set_state": lambda x: self._on_reboot_toggle("NNFF", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"}, - {"title": tr_noop("NNFF Lite"), "type": "toggle", "get_state": lambda: self._params.get_bool("NNFFLite"), "set_state": lambda x: self._on_reboot_toggle("NNFFLite", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"}, + {"title": tr_noop("Lateral Tuning"), "type": "toggle", "get_state": lambda: self._params.get_bool("LateralTune"), "set_state": lambda x: self._params.put_bool("LateralTune", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"}, + {"title": tr_noop("Force Turn Desires"), "type": "toggle", "get_state": lambda: self._params.get_bool("TurnDesires"), "set_state": lambda x: self._params.put_bool("TurnDesires", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497", "visible": lambda: self._params.get_bool("LateralTune")}, + {"title": tr_noop("NNFF"), "type": "toggle", "get_state": lambda: self._params.get_bool("NNFF"), "set_state": lambda x: self._on_reboot_toggle("NNFF", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497", "visible": lambda: self._params.get_bool("LateralTune")}, + {"title": tr_noop("NNFF Lite"), "type": "toggle", "get_state": lambda: self._params.get_bool("NNFFLite"), "set_state": lambda x: self._on_reboot_toggle("NNFFLite", x), "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497", "visible": lambda: self._params.get_bool("LateralTune")}, ] self._rebuild_grid() @@ -107,7 +109,8 @@ class StarPilotLateralQOLLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ - {"title": tr_noop("Pause Steering Below"), "type": "value", "get_value": lambda: f"{self._params.get_int('PauseLateralSpeed')} mph", "on_click": lambda: self._show_speed_selector("PauseLateralSpeed"), "icon": "toggle_icons/icon_quality_of_life.png", "color": "#597497"} + {"title": tr_noop("Quality of Life"), "type": "toggle", "get_state": lambda: self._params.get_bool("QOLLateral"), "set_state": lambda x: self._params.put_bool("QOLLateral", x), "icon": "toggle_icons/icon_quality_of_life.png", "color": "#597497"}, + {"title": tr_noop("Pause Steering Below"), "type": "value", "get_value": lambda: f"{self._params.get_int('PauseLateralSpeed')} mph", "on_click": lambda: self._show_speed_selector("PauseLateralSpeed"), "icon": "toggle_icons/icon_quality_of_life.png", "color": "#597497", "visible": lambda: self._params.get_bool("QOLLateral")} ] self._rebuild_grid() diff --git a/selfdrive/ui/layouts/settings/starpilot/longitudinal.py b/selfdrive/ui/layouts/settings/starpilot/longitudinal.py index b9784769..db4259d2 100644 --- a/selfdrive/ui/layouts/settings/starpilot/longitudinal.py +++ b/selfdrive/ui/layouts/settings/starpilot/longitudinal.py @@ -61,12 +61,21 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Advanced Longitudinal Tuning"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("AdvancedLongitudinalTune"), + "set_state": lambda s: self._params.put_bool("AdvancedLongitudinalTune", s), + "icon": "toggle_icons/icon_advanced_longitudinal_tune.png", + "color": "#597497", + }, { "title": tr_noop("EV Tuning"), "type": "toggle", "get_state": lambda: self._params.get_bool("EVTuning"), "set_state": lambda s: self._params.put_bool("EVTuning", s), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Truck Tuning"), @@ -74,6 +83,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("TruckTuning"), "set_state": lambda s: self._params.put_bool("TruckTuning", s), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Actuator Delay"), @@ -81,6 +91,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('LongitudinalActuatorDelay'):.2f}s", "on_click": lambda: self._show_float_selector("LongitudinalActuatorDelay", 0.0, 1.0, 0.01, "s"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Max Acceleration"), @@ -88,6 +99,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('MaxDesiredAcceleration'):.1f}m/s²", "on_click": lambda: self._show_float_selector("MaxDesiredAcceleration", 0.1, 4.0, 0.1, "m/s²"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Start Accel"), @@ -95,6 +107,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('StartAccel'):.2f}m/s²", "on_click": lambda: self._show_float_selector("StartAccel", 0.0, 4.0, 0.01, "m/s²"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Stop Accel"), @@ -102,6 +115,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('StopAccel'):.2f}m/s²", "on_click": lambda: self._show_float_selector("StopAccel", -4.0, 0.0, 0.01, "m/s²"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("Stopping Rate"), @@ -109,6 +123,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('StoppingDecelRate'):.3f}m/s²", "on_click": lambda: self._show_float_selector("StoppingDecelRate", 0.001, 1.0, 0.001, "m/s²"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("VEgo Starting"), @@ -116,6 +131,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('VEgoStarting'):.2f}m/s", "on_click": lambda: self._show_float_selector("VEgoStarting", 0.01, 1.0, 0.01, "m/s"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, { "title": tr_noop("VEgo Stopping"), @@ -123,6 +139,7 @@ class StarPilotAdvancedLongitudinalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_float('VEgoStopping'):.2f}m/s", "on_click": lambda: self._show_float_selector("VEgoStopping", 0.01, 1.0, 0.01, "m/s"), "color": "#597497", + "visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"), }, ] self._rebuild_grid() @@ -141,19 +158,29 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): super().__init__() self.CATEGORIES = [ { - "title": tr_noop("Conditional Experimental"), + "title": tr_noop("Conditional Experimental Mode"), "type": "toggle", "get_state": lambda: self._params.get_bool("ConditionalExperimental"), "set_state": lambda s: self._params.put_bool("ConditionalExperimental", s), "icon": "toggle_icons/icon_conditional.png", "color": "#597497", }, + { + "title": tr_noop("Conditional Experimental"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("ConditionalExperimental"), + "set_state": lambda s: self._params.put_bool("ConditionalExperimental", s), + "icon": "toggle_icons/icon_conditional.png", + "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), + }, { "title": tr_noop("Below Speed"), "type": "value", "get_value": lambda: f"{self._params.get_int('CESpeed')} mph", "on_click": lambda: self._show_speed_selector("CESpeed"), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Curves"), @@ -161,6 +188,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("CECurves"), "set_state": lambda s: self._params.put_bool("CECurves", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Curves Lead"), @@ -176,6 +204,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("CEStopLights"), "set_state": lambda s: self._params.put_bool("CEStopLights", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Lead Detected"), @@ -183,6 +212,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("CELead"), "set_state": lambda s: self._params.put_bool("CELead", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Slower Lead"), @@ -190,6 +220,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("CESlowerLead"), "set_state": lambda s: self._params.put_bool("CESlowerLead", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental") and self._params.get_bool("CELead"), }, { "title": tr_noop("Stopped Lead"), @@ -197,6 +228,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("CEStoppedLead"), "set_state": lambda s: self._params.put_bool("CEStoppedLead", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental") and self._params.get_bool("CELead"), }, { "title": tr_noop("Predicted Stop"), @@ -204,6 +236,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('CEModelStopTime')}s", "on_click": lambda: self._show_int_selector("CEModelStopTime", 0, 10, "s"), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Signal Below"), @@ -211,6 +244,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('CESignalSpeed')} mph", "on_click": lambda: self._show_speed_selector("CESignalSpeed"), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Speed Lead"), @@ -218,6 +252,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('CESpeedLead')} mph", "on_click": lambda: self._show_speed_selector("CESpeedLead"), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, { "title": tr_noop("Signal Lane Detection"), @@ -233,6 +268,7 @@ class StarPilotConditionalExperimentalLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("ShowCEMStatus"), "set_state": lambda s: self._params.put_bool("ShowCEMStatus", s), "color": "#597497", + "visible": lambda: self._params.get_bool("ConditionalExperimental"), }, ] self._rebuild_grid() @@ -258,6 +294,14 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Curve Speed Controller"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("CurveSpeedController"), + "set_state": lambda s: self._params.put_bool("CurveSpeedController", s), + "icon": "toggle_icons/icon_speed_map.png", + "color": "#597497", + }, { "title": tr_noop("Curve Speed Controller"), "desc": tr_noop("Automatically slow down for upcoming curves using data learned from your driving style."), @@ -266,6 +310,7 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("CurveSpeedController", s), "icon": "toggle_icons/icon_speed_map.png", "color": "#597497", + "visible": lambda: self._params.get_bool("CurveSpeedController"), }, { "title": tr_noop("Status Widget"), @@ -274,6 +319,7 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("ShowCSCStatus"), "set_state": lambda s: self._params.put_bool("ShowCSCStatus", s), "color": "#597497", + "visible": lambda: self._params.get_bool("CurveSpeedController"), }, { "title": tr_noop("Calibrated Lateral Accel"), @@ -282,6 +328,7 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): "get_value": lambda: f"{self._params_memory.get_float('CalibratedLateralAcceleration'):.2f} m/s²", "on_click": lambda: None, "color": "#597497", + "visible": lambda: self._params.get_bool("CurveSpeedController"), }, { "title": tr_noop("Calibration Progress"), @@ -290,6 +337,7 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): "get_value": lambda: f"{self._params_memory.get_float('CalibrationProgress'):.2f}%", "on_click": lambda: None, "color": "#597497", + "visible": lambda: self._params.get_bool("CurveSpeedController"), }, { "title": tr_noop("Reset Curve Data"), @@ -297,6 +345,7 @@ class StarPilotCurveSpeedLayout(StarPilotPanel): "type": "hub", "on_click": lambda: self._reset_curve_data(), "color": "#597497", + "visible": lambda: self._params.get_bool("CurveSpeedController"), }, ] self._rebuild_grid() @@ -316,6 +365,14 @@ class StarPilotPersonalitiesLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Driving Personalities"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("CustomPersonalities"), + "set_state": lambda s: self._params.put_bool("CustomPersonalities", s), + "icon": "toggle_icons/icon_personality.png", + "color": "#597497", + }, {"title": tr_noop("Traffic"), "panel": "traffic_personality", "icon": "toggle_icons/icon_personality.png", "color": "#597497"}, {"title": tr_noop("Aggressive"), "panel": "aggressive_personality", "icon": "toggle_icons/icon_personality.png", "color": "#597497"}, {"title": tr_noop("Standard"), "panel": "standard_personality", "icon": "toggle_icons/icon_personality.png", "color": "#597497"}, @@ -420,12 +477,21 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Longitudinal Tuning"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("LongitudinalTune"), + "set_state": lambda s: self._params.put_bool("LongitudinalTune", s), + "icon": "toggle_icons/icon_longitudinal_tune.png", + "color": "#597497", + }, { "title": tr_noop("Acceleration Profile"), "type": "value", "get_value": lambda: self._params.get("AccelerationProfile", encoding='utf-8') or "Standard", "on_click": lambda: self._show_selection("AccelerationProfile", ["Standard", "Eco", "Sport", "Sport+"]), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Deceleration Profile"), @@ -433,6 +499,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_value": lambda: self._params.get("DecelerationProfile", encoding='utf-8') or "Standard", "on_click": lambda: self._show_selection("DecelerationProfile", ["Standard", "Eco", "Sport"]), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Human Acceleration"), @@ -440,6 +507,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("HumanAcceleration"), "set_state": lambda s: self._params.put_bool("HumanAcceleration", s), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Human Following"), @@ -447,6 +515,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("HumanFollowing"), "set_state": lambda s: self._params.put_bool("HumanFollowing", s), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Human Lane Changes"), @@ -454,6 +523,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("HumanLaneChanges"), "set_state": lambda s: self._params.put_bool("HumanLaneChanges", s), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Lead Detection"), @@ -461,6 +531,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('LeadDetectionThreshold')}%", "on_click": lambda: self._show_int_selector("LeadDetectionThreshold", 25, 50, "%"), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, { "title": tr_noop("Taco Tune"), @@ -468,6 +539,7 @@ class StarPilotLongitudinalTuneLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("TacoTune"), "set_state": lambda s: self._params.put_bool("TacoTune", s), "color": "#597497", + "visible": lambda: self._params.get_bool("LongitudinalTune"), }, ] self._rebuild_grid() @@ -493,12 +565,21 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Quality of Life"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("QOLLongitudinal"), + "set_state": lambda s: self._params.put_bool("QOLLongitudinal", s), + "icon": "toggle_icons/icon_quality_of_life.png", + "color": "#597497", + }, { "title": tr_noop("Cruise Interval"), "type": "value", "get_value": lambda: f"{self._params.get_int('CustomCruise')} mph", "on_click": lambda: self._show_speed_selector("CustomCruise"), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Cruise Long"), @@ -506,6 +587,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('CustomCruiseLong')} mph", "on_click": lambda: self._show_speed_selector("CustomCruiseLong"), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Reverse Cruise"), @@ -513,6 +595,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("ReverseCruise"), "set_state": lambda s: self._params.put_bool("ReverseCruise", s), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Force Stops"), @@ -520,6 +603,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("ForceStops"), "set_state": lambda s: self._params.put_bool("ForceStops", s), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Force Standstill State"), @@ -527,6 +611,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("ForceStandstill"), "set_state": lambda s: self._params.put_bool("ForceStandstill", s), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Stopped Distance"), @@ -534,6 +619,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_value": lambda: f"{self._params.get_int('IncreasedStoppedDistance')} ft", "on_click": lambda: self._show_int_selector("IncreasedStoppedDistance", 0, 10, " ft"), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Set Speed Offset"), @@ -541,6 +627,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_value": lambda: f"+{self._params.get_int('SetSpeedOffset')} mph", "on_click": lambda: self._show_int_selector("SetSpeedOffset", 0, 99, " mph"), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Map Gears"), @@ -548,6 +635,7 @@ class StarPilotLongitudinalQOLLayout(StarPilotPanel): "get_state": lambda: self._params.get_bool("MapGears"), "set_state": lambda s: self._params.put_bool("MapGears", s), "color": "#597497", + "visible": lambda: self._params.get_bool("QOLLongitudinal"), }, { "title": tr_noop("Map Acceleration"), diff --git a/selfdrive/ui/layouts/settings/starpilot/themes.py b/selfdrive/ui/layouts/settings/starpilot/themes.py index 39c1169f..7aa09032 100644 --- a/selfdrive/ui/layouts/settings/starpilot/themes.py +++ b/selfdrive/ui/layouts/settings/starpilot/themes.py @@ -91,6 +91,14 @@ class StarPilotThemesLayout(StarPilotPanel): } self.CATEGORIES = [ + { + "title": tr_noop("Custom Themes"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("CustomThemes"), + "set_state": lambda s: self._params.put_bool("CustomThemes", s), + "icon": "toggle_icons/icon_frog.png", + "color": "#542A71", + }, { "title": tr_noop("Personalize openpilot"), "panel": "personalize", @@ -129,6 +137,7 @@ class StarPilotThemesLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("RandomThemes", s), "icon": "toggle_icons/icon_random_themes.png", "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, {"title": tr_noop("Startup Alert"), "type": "hub", "on_click": self._on_startup_alert, "color": "#542A71"}, ] @@ -170,12 +179,20 @@ class StarPilotPersonalizeLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Custom Themes"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("CustomThemes"), + "set_state": lambda s: self._params.put_bool("CustomThemes", s), + "color": "#542A71", + }, { "title": tr_noop("Boot Logo"), "type": "value", "get_value": lambda: self._get_theme_value("BootLogo"), "on_click": lambda: self._show_theme_selector("BootLogo"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Color Scheme"), @@ -183,6 +200,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("ColorScheme"), "on_click": lambda: self._show_theme_selector("ColorScheme"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Distance Icons"), @@ -190,6 +208,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("DistanceIconPack"), "on_click": lambda: self._show_theme_selector("DistanceIconPack"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Icon Pack"), @@ -197,6 +216,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("IconPack"), "on_click": lambda: self._show_theme_selector("IconPack"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Turn Signals"), @@ -204,6 +224,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("SignalAnimation"), "on_click": lambda: self._show_theme_selector("SignalAnimation"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Sound Pack"), @@ -211,6 +232,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("SoundPack"), "on_click": lambda: self._show_theme_selector("SoundPack"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, { "title": tr_noop("Steering Wheel"), @@ -218,6 +240,7 @@ class StarPilotPersonalizeLayout(StarPilotPanel): "get_value": lambda: self._get_theme_value("WheelIcon"), "on_click": lambda: self._show_theme_selector("WheelIcon"), "color": "#542A71", + "visible": lambda: self._params.get_bool("CustomThemes"), }, ] self._rebuild_grid() diff --git a/selfdrive/ui/layouts/settings/starpilot/visuals.py b/selfdrive/ui/layouts/settings/starpilot/visuals.py index 2ff9c4b8..eaf39e9a 100644 --- a/selfdrive/ui/layouts/settings/starpilot/visuals.py +++ b/selfdrive/ui/layouts/settings/starpilot/visuals.py @@ -112,6 +112,14 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Advanced UI Controls"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("AdvancedCustomUI"), + "set_state": lambda s: self._params.put_bool("AdvancedCustomUI", s), + "icon": "toggle_icons/icon_advanced_device.png", + "color": "#8B5CF6", + }, { "title": tr_noop("Hide Speed"), "type": "toggle", @@ -120,6 +128,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("HideSpeed", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, { "title": tr_noop("Hide Lead Marker"), @@ -129,6 +138,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("HideLeadMarker", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, { "title": tr_noop("Hide Max Speed"), @@ -138,6 +148,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("HideMaxSpeed", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, { "title": tr_noop("Hide Alerts"), @@ -147,6 +158,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("HideAlerts", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, { "title": tr_noop("Hide Speed Limit"), @@ -156,6 +168,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("HideSpeedLimit", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, { "title": tr_noop("Wheel Speed"), @@ -165,6 +178,7 @@ class StarPilotAdvancedVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("WheelSpeed", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("AdvancedCustomUI"), }, ] self._rebuild_grid() @@ -194,6 +208,14 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Driving Screen Widgets"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("CustomUI"), + "set_state": lambda s: self._params.put_bool("CustomUI", s), + "icon": "toggle_icons/icon_display.png", + "color": "#8B5CF6", + }, { "title": tr_noop("Acceleration Path"), "type": "toggle", @@ -202,6 +224,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("AccelerationPath", s), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Adjacent Lanes"), @@ -211,6 +234,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("AdjacentPath", s), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Adjacent Lane Metrics"), @@ -220,6 +244,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("AdjacentPathMetrics", s), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Blind Spot Path"), @@ -229,6 +254,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("BlindSpotPath", s), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Compass"), @@ -238,6 +264,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("Compass", s), "icon": "toggle_icons/icon_navigate.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Personality Button"), @@ -247,6 +274,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("OnroadDistanceButton", s), "icon": "toggle_icons/icon_personality.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Pedal Indicators"), @@ -256,6 +284,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("PedalsOnUI", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, { "title": tr_noop("Dynamic Pedals"), @@ -265,6 +294,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._set_exclusive_pedal("DynamicPedalsOnUI", "StaticPedalsOnUI", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI") and self._params.get_bool("PedalsOnUI"), }, { "title": tr_noop("Static Pedals"), @@ -274,6 +304,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._set_exclusive_pedal("StaticPedalsOnUI", "DynamicPedalsOnUI", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI") and self._params.get_bool("PedalsOnUI"), }, { "title": tr_noop("Rotating Wheel"), @@ -283,6 +314,7 @@ class StarPilotVisualWidgetsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("RotatingWheel", s), "icon": "toggle_icons/icon_steering.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("CustomUI"), }, ] self._rebuild_grid() @@ -328,6 +360,14 @@ class StarPilotModelUILayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Model UI"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("ModelUI"), + "set_state": lambda s: self._params.put_bool("ModelUI", s), + "icon": "toggle_icons/icon_road.png", + "color": "#8B5CF6", + }, { "title": tr_noop("Dynamic Path"), "type": "toggle", @@ -336,6 +376,7 @@ class StarPilotModelUILayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("DynamicPathWidth", s), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Lane Line Width"), @@ -345,6 +386,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_int_selector("LaneLinesWidth", 0, 24, self._get_lane_lines_unit()), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Lane Line Color"), @@ -354,6 +396,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_color_selector("LaneLinesColor"), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Path Edge Width"), @@ -363,6 +406,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_int_selector("PathEdgeWidth", 0, 100, "%"), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Path Edge Color"), @@ -372,6 +416,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_color_selector("PathEdgesColor"), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Path Width"), @@ -381,6 +426,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_path_width_selector(), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Path Color"), @@ -390,6 +436,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_color_selector("PathColor"), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, { "title": tr_noop("Road Edge Width"), @@ -399,6 +446,7 @@ class StarPilotModelUILayout(StarPilotPanel): "on_click": lambda: self._show_int_selector("RoadEdgesWidth", 0, 24, self._get_road_edges_unit()), "icon": "toggle_icons/icon_road.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("ModelUI"), }, ] self._rebuild_grid() @@ -484,6 +532,14 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel): def __init__(self): super().__init__() self.CATEGORIES = [ + { + "title": tr_noop("Navigation Widgets"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("NavigationUI"), + "set_state": lambda s: self._params.put_bool("NavigationUI", s), + "icon": "toggle_icons/icon_map.png", + "color": "#8B5CF6", + }, { "title": tr_noop("Road Name"), "type": "toggle", @@ -491,6 +547,7 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("RoadNameUI", s), "icon": "toggle_icons/icon_navigate.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("NavigationUI"), }, { "title": tr_noop("Speed Limits"), @@ -499,6 +556,7 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("ShowSpeedLimits", s), "icon": "toggle_icons/icon_speed_limit.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("NavigationUI"), }, { "title": tr_noop("Mapbox Limits"), @@ -507,6 +565,7 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("SLCMapboxFiller", s), "icon": "toggle_icons/icon_speed_limit.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("NavigationUI") and self._params.get_bool("ShowSpeedLimits"), }, { "title": tr_noop("Vienna Signs"), @@ -515,6 +574,7 @@ class StarPilotNavigationVisualsLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("UseVienna", s), "icon": "toggle_icons/icon_speed_limit.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("NavigationUI"), }, ] self._rebuild_grid() @@ -525,6 +585,14 @@ class StarPilotVisualQOLLayout(StarPilotPanel): super().__init__() self.CAMERA_VIEWS = ["Auto", "Driver", "Standard", "Wide"] self.CATEGORIES = [ + { + "title": tr_noop("Quality of Life"), + "type": "toggle", + "get_state": lambda: self._params.get_bool("QOLVisuals"), + "set_state": lambda s: self._params.put_bool("QOLVisuals", s), + "icon": "toggle_icons/icon_quality_of_life.png", + "color": "#8B5CF6", + }, { "title": tr_noop("Camera View"), "type": "value", @@ -533,6 +601,7 @@ class StarPilotVisualQOLLayout(StarPilotPanel): "on_click": lambda: self._show_camera_view_selector(), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("QOLVisuals"), }, { "title": tr_noop("Driver Camera"), @@ -541,6 +610,7 @@ class StarPilotVisualQOLLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("DriverCamera", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("QOLVisuals"), }, { "title": tr_noop("Stopped Timer"), @@ -549,6 +619,7 @@ class StarPilotVisualQOLLayout(StarPilotPanel): "set_state": lambda s: self._params.put_bool("StoppedTimer", s), "icon": "toggle_icons/icon_display.png", "color": "#8B5CF6", + "visible": lambda: self._params.get_bool("QOLVisuals"), }, ] self._rebuild_grid() diff --git a/selfdrive/ui/onroad/starpilot/starpilot_onroad_view.py b/selfdrive/ui/onroad/starpilot/starpilot_onroad_view.py index d8e5af45..6381f998 100644 --- a/selfdrive/ui/onroad/starpilot/starpilot_onroad_view.py +++ b/selfdrive/ui/onroad/starpilot/starpilot_onroad_view.py @@ -1,4 +1,5 @@ import pyray as rl +import time from msgq.visionipc import VisionStreamType from openpilot.common.params import Params from openpilot.selfdrive.ui import UI_BORDER_SIZE @@ -11,7 +12,7 @@ from openpilot.selfdrive.ui.onroad.starpilot.slc_speed_limit import ( SET_SPEED_WIDTH_IMP, SET_SPEED_WIDTH_MET, SET_SPEED_HEIGHT, SIGN_MARGIN, ) from openpilot.selfdrive.ui.ui_state import ui_state, UIStatus -from openpilot.system.ui.lib.application import MousePos, gui_app +from openpilot.system.ui.lib.application import MousePos, gui_app, FontWeight AOL_COLOR = rl.Color(10, 186, 181, 255) @@ -22,6 +23,9 @@ class StarPilotOnroadView(AugmentedRoadView): self._params = Params() self._personality_button = PersonalityButton() + self._font_bold = gui_app.font(FontWeight.BOLD) + self._font_medium = gui_app.font(FontWeight.MEDIUM) + self._standstill_started_at = 0.0 def _render(self, rect: rl.Rectangle): super()._render(rect) @@ -48,6 +52,8 @@ class StarPilotOnroadView(AugmentedRoadView): def _render_overlays(self): self._position_personality_button() self._personality_button.render() + self._render_road_name() + self._render_standstill_timer() def _render_path_features(self, rect: rl.Rectangle): """Render path-related features (adjacent paths, blind spot, path edges).""" @@ -90,6 +96,82 @@ class StarPilotOnroadView(AugmentedRoadView): self._personality_button.set_position(x, y) + def _render_road_name(self): + if not self._params.get_bool("RoadNameUI"): + return + if not ui_state.sm.valid.get("mapdOut", False): + return + + road_name = getattr(ui_state.sm["mapdOut"], "roadName", "") + if not road_name: + return + + text_size = rl.measure_text_ex(self._font_bold, road_name, 52, 0) + pad_x, pad_y = 28, 18 + box_w = int(text_size.x + pad_x * 2) + box_h = int(text_size.y + pad_y * 2) + x = int((gui_app.width - box_w) / 2) + y = int(gui_app.height - box_h - 22) + + rect = rl.Rectangle(x, y, box_w, box_h) + rl.draw_rectangle_rounded(rect, 0.35, 10, rl.Color(0, 0, 0, 166)) + rl.draw_rectangle_rounded_lines_ex(rect, 0.35, 10, 3, rl.Color(255, 255, 255, 50)) + rl.draw_text_ex( + self._font_bold, + road_name, + rl.Vector2(x + (box_w - text_size.x) / 2, y + (box_h - text_size.y) / 2), + 52, + 0, + rl.WHITE, + ) + + def _render_standstill_timer(self): + if not self._params.get_bool("stopped_timer"): + self._standstill_started_at = 0.0 + return + if not ui_state.sm.valid.get("carState", False): + return + + car_state = ui_state.sm["carState"] + if getattr(car_state, "standstill", False): + if self._standstill_started_at == 0.0: + self._standstill_started_at = time.monotonic() + else: + self._standstill_started_at = 0.0 + return + + if self._standstill_started_at == 0.0: + return + + duration = int(time.monotonic() - self._standstill_started_at) + if duration < 60: + return + + minutes = duration // 60 + seconds = duration % 60 + minute_text = f"{minutes} minute{'s' if minutes != 1 else ''}" + second_text = f"{seconds} second{'s' if seconds != 1 else ''}" + minute_size = rl.measure_text_ex(self._font_bold, minute_text, 176, 0) + second_size = rl.measure_text_ex(self._font_medium, second_text, 66, 0) + + x = gui_app.width / 2 + rl.draw_text_ex( + self._font_bold, + minute_text, + rl.Vector2(x - minute_size.x / 2, 210 - minute_size.y / 2), + 176, + 0, + rl.Color(255, 255, 255, 255), + ) + rl.draw_text_ex( + self._font_medium, + second_text, + rl.Vector2(x - second_size.x / 2, 290 - second_size.y / 2), + 66, + 0, + rl.Color(255, 255, 255, 255), + ) + def _draw_border(self, rect: rl.Rectangle): rl.draw_rectangle_lines_ex(rect, UI_BORDER_SIZE, rl.BLACK) border_rect = rl.Rectangle(rect.x + UI_BORDER_SIZE, rect.y + UI_BORDER_SIZE, diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index bbbb909b..0dedca0e 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -52,6 +52,7 @@ class UIState: "selfdriveState", "longitudinalPlan", "gpsLocationExternal", + "mapdOut", "carOutput", "carControl", "liveParameters",