BigUI WIP: Cleanup

This commit is contained in:
firestarsdog
2026-04-07 02:15:45 -04:00
parent 0b0fb3957a
commit 2d1376cd86
4 changed files with 415 additions and 164 deletions
@@ -1,11 +1,11 @@
from __future__ import annotations
from openpilot.system.hardware import HARDWARE
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_master_toggle_panel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.tabbed_panel import TabSectionSpec, TabbedSectionHost
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog
@@ -13,18 +13,93 @@ 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", "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")},
{"title": tr_noop("Actuator Delay"), "desc": tr_noop("The time between openpilot's steering command and the vehicle's response."), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerDelay'):.2f}s", "on_click": lambda: self._show_float_selector("SteerDelay", 0.01, 1.0, 0.01, "s"), "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": self._show_steer_delay},
{"title": tr_noop("Friction"), "desc": tr_noop("Compensates for steering friction around center."), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerFriction'):.3f}", "on_click": self._show_steer_friction_selector, "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": self._show_steer_friction},
{"title": tr_noop("Kp Factor"), "desc": tr_noop("How strongly openpilot corrects lateral position."), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerKP'):.2f}", "on_click": self._show_steer_kp_selector, "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": self._show_steer_kp},
{"title": tr_noop("Lateral Acceleration"), "desc": tr_noop("Maps steering torque to turning response."), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerLatAccel'):.2f}", "on_click": self._show_steer_lat_accel_selector, "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": self._show_steer_lat_accel},
{"title": tr_noop("Steer Ratio"), "desc": tr_noop("Adjust the relationship between steering wheel input and road-wheel angle."), "type": "value", "get_value": lambda: f"{self._params.get_float('SteerRatio'):.2f}", "on_click": self._show_steer_ratio_selector, "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497", "visible": self._show_steer_ratio},
{"title": tr_noop("Force Auto-Tune On"), "desc": tr_noop("Force-enable live auto-tuning for friction and lateral acceleration."), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTune"), "set_state": self._set_force_auto_tune, "icon": "toggle_icons/icon_tuning.png", "color": "#597497", "visible": self._show_force_auto_tune},
{"title": tr_noop("Force Auto-Tune Off"), "desc": tr_noop("Force-disable live auto-tuning and use your set values instead."), "type": "toggle", "get_state": lambda: self._params.get_bool("ForceAutoTuneOff"), "set_state": self._set_force_auto_tune_off, "icon": "toggle_icons/icon_tuning.png", "color": "#597497", "visible": self._show_force_auto_tune_off},
{"title": tr_noop("Force Torque Controller"), "desc": tr_noop("Use torque-based steering control instead of the stock steering mode when supported."), "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": self._show_force_torque_controller},
]
self._rebuild_grid()
def _advanced_enabled(self):
return self._params.get_bool("AdvancedLateralTune")
def _using_nnff(self):
return starpilot_state.car_state.hasNNFFLog and self._params.get_bool("LateralTune") and self._params.get_bool("NNFF")
def _forcing_auto_tune(self):
return not starpilot_state.car_state.hasAutoTune and self._params.get_bool("ForceAutoTune")
def _forcing_auto_tune_off(self):
return starpilot_state.car_state.hasAutoTune and self._params.get_bool("ForceAutoTuneOff")
def _forcing_torque_controller(self):
return not starpilot_state.car_state.isAngleCar and self._params.get_bool("ForceTorqueController")
def _torque_tuning_active(self):
return starpilot_state.car_state.isTorqueCar or self._forcing_torque_controller() or self._using_nnff()
def _manual_tuning_values_enabled(self):
if starpilot_state.car_state.hasAutoTune:
return self._forcing_auto_tune_off()
return not self._forcing_auto_tune()
def _show_steer_delay(self):
return self._advanced_enabled() and starpilot_state.car_state.steerActuatorDelay != 0
def _show_steer_friction(self):
return (self._advanced_enabled() and starpilot_state.car_state.friction != 0 and self._torque_tuning_active()
and not self._using_nnff() and self._manual_tuning_values_enabled())
def _show_steer_kp(self):
return (self._advanced_enabled() and starpilot_state.car_state.steerKp != 0 and self._torque_tuning_active()
and not starpilot_state.car_state.isAngleCar)
def _show_steer_lat_accel(self):
return (self._advanced_enabled() and starpilot_state.car_state.latAccelFactor != 0 and self._torque_tuning_active()
and not self._using_nnff() and self._manual_tuning_values_enabled())
def _show_steer_ratio(self):
return self._advanced_enabled() and starpilot_state.car_state.steerRatio != 0 and self._manual_tuning_values_enabled()
def _show_force_auto_tune(self):
return (self._advanced_enabled() and not starpilot_state.car_state.hasAutoTune and not starpilot_state.car_state.isAngleCar
and self._torque_tuning_active())
def _show_force_auto_tune_off(self):
return self._advanced_enabled() and starpilot_state.car_state.hasAutoTune and not starpilot_state.car_state.isAngleCar
def _show_force_torque_controller(self):
return self._advanced_enabled() and not starpilot_state.car_state.isAngleCar and not starpilot_state.car_state.isTorqueCar
def _set_force_auto_tune(self, state):
self._params.put_bool("ForceAutoTune", state)
if state:
self._params.put_bool("ForceAutoTuneOff", False)
def _set_force_auto_tune_off(self, state):
self._params.put_bool("ForceAutoTuneOff", state)
if state:
self._params.put_bool("ForceAutoTune", False)
def _show_steer_friction_selector(self):
self._show_float_selector("SteerFriction", 0.0, max(1.0, starpilot_state.car_state.friction * 1.5), 0.01)
def _show_steer_kp_selector(self):
base = max(0.01, starpilot_state.car_state.steerKp)
self._show_float_selector("SteerKP", base * 0.5, base * 1.5, 0.01)
def _show_steer_lat_accel_selector(self):
base = max(0.01, starpilot_state.car_state.latAccelFactor)
self._show_float_selector("SteerLatAccel", base * 0.5, base * 1.5, 0.01)
def _show_steer_ratio_selector(self):
base = max(0.01, starpilot_state.car_state.steerRatio)
self._show_float_selector("SteerRatio", base * 0.5, base * 1.5, 0.01)
def _show_float_selector(self, key, min_v, max_v, step, unit=""):
def on_close(res, val):
if res == DialogResult.CONFIRM:
@@ -68,9 +143,9 @@ class StarPilotLaneChangesLayout(StarPilotPanel):
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", "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("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") and self._params.get_bool("NudgelessLaneChange")},
{"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("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") and self._params.get_bool("NudgelessLaneChange")},
{"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()
@@ -93,13 +168,26 @@ class StarPilotLateralTuneLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self.CATEGORIES = [
{"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")},
{"title": tr_noop("Force Turn Desires Below Lane Change Speed"), "desc": tr_noop("Allow openpilot to follow turn intent below the minimum lane change speed when signaling."), "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": self._lateral_enabled},
{"title": tr_noop("Neural Network Feedforward (NNFF)"), "desc": tr_noop("Use the full neural-network feedforward steering controller when available."), "type": "toggle", "get_state": lambda: self._params.get_bool("NNFF"), "set_state": self._set_nnff, "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497", "visible": self._show_nnff},
{"title": tr_noop("Neural Network Feedforward (NNFF) Lite"), "desc": tr_noop("Use the lightweight NNFF steering logic when the full model is off."), "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": self._show_nnff_lite},
]
self._rebuild_grid()
def _lateral_enabled(self):
return self._params.get_bool("LateralTune")
def _show_nnff(self):
return self._lateral_enabled() and starpilot_state.car_state.hasNNFFLog and not starpilot_state.car_state.isAngleCar
def _show_nnff_lite(self):
return self._lateral_enabled() and not self._params.get_bool("NNFF") and not starpilot_state.car_state.isAngleCar
def _set_nnff(self, state):
self._params.put_bool("NNFF", state)
if state:
self._params.put_bool("NNFFLite", False)
def _on_reboot_toggle(self, key, state):
self._params.put_bool(key, state)
from openpilot.selfdrive.ui.ui_state import ui_state
@@ -132,9 +220,33 @@ class StarPilotLateralLayout(StarPilotPanel):
"always_on_lateral": StarPilotAlwaysOnLateralLayout(),
"qol": StarPilotLateralQOLLayout(),
})
tune_panel = create_tile_panel([
{"title": tr_noop("Advanced Tuning"), "panel": "advanced_lateral", "icon": "toggle_icons/icon_advanced_lateral_tune.png", "color": "#597497"},
{"title": tr_noop("Lateral Tuning"), "panel": "lateral_tune", "icon": "toggle_icons/icon_lateral_tune.png", "color": "#597497"},
tune_panel = create_master_toggle_panel([
{
"title": tr_noop("Advanced Lateral Tuning"),
"desc": tr_noop("Advanced steering control changes to fine-tune how openpilot drives."),
"manage_title": tr_noop("Advanced Settings"),
"manage_desc": tr_noop("Adjust steering response, torque controller behavior, and auto-tuning controls."),
"manage_label": tr_noop("Configure"),
"disabled_label": tr_noop("Enable First"),
"panel": "advanced_lateral",
"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("Lateral Tuning"),
"desc": tr_noop("Miscellaneous steering control changes such as turn desires and NNFF modes."),
"manage_title": tr_noop("Lateral Settings"),
"manage_desc": tr_noop("Open turn-intent and neural-network feedforward controls."),
"manage_label": tr_noop("Configure"),
"disabled_label": tr_noop("Enable First"),
"panel": "lateral_tune",
"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",
},
], {
"advanced_lateral": StarPilotAdvancedLateralLayout(),
"lateral_tune": StarPilotLateralTuneLayout(),
@@ -6,27 +6,80 @@ from openpilot.system.ui.widgets import DialogResult
from openpilot.system.ui.widgets.confirm_dialog import ConfirmDialog
from openpilot.system.ui.widgets.selection_dialog import SelectionDialog
from openpilot.system.ui.widgets.input_dialog import InputDialog
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.panel import StarPilotPanel, create_master_toggle_panel, create_tile_panel
from openpilot.selfdrive.ui.layouts.settings.starpilot.tabbed_panel import TabSectionSpec, TabbedSectionHost
from openpilot.selfdrive.ui.layouts.settings.starpilot.aethergrid import AetherSliderDialog
from openpilot.starpilot.common.accel_profile import (
ACCELERATION_PROFILES,
DECELERATION_PROFILES,
normalize_acceleration_profile,
normalize_deceleration_profile,
)
ACCELERATION_PROFILE_OPTIONS = [
(ACCELERATION_PROFILES["STANDARD"], "Standard"),
(ACCELERATION_PROFILES["ECO"], "Eco"),
(ACCELERATION_PROFILES["SPORT"], "Sport"),
(ACCELERATION_PROFILES["SPORT_PLUS"], "Sport+"),
]
DECELERATION_PROFILE_OPTIONS = [
(DECELERATION_PROFILES["STANDARD"], "Standard"),
(DECELERATION_PROFILES["ECO"], "Eco"),
(DECELERATION_PROFILES["SPORT"], "Sport"),
]
class StarPilotLongitudinalLayout(StarPilotPanel):
def __init__(self):
super().__init__()
tune_panel = create_tile_panel([
{"title": tr_noop("Longitudinal Tuning"), "panel": "tuning", "icon": "toggle_icons/icon_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Advanced Tuning"), "panel": "advanced", "icon": "toggle_icons/icon_advanced_longitudinal_tune.png", "color": "#597497"},
{"title": tr_noop("Driving Personalities"), "panel": "personalities", "icon": "toggle_icons/icon_personality.png", "color": "#597497"},
longitudinal_tune_panel = StarPilotLongitudinalTuneLayout()
advanced_longitudinal_panel = StarPilotAdvancedLongitudinalLayout()
tune_panel = create_master_toggle_panel([
{
"title": tr_noop("Longitudinal Tuning"),
"desc": tr_noop("Acceleration and braking control changes to fine-tune how openpilot drives."),
"manage_title": tr_noop("Longitudinal Settings"),
"manage_desc": tr_noop("Open acceleration profiles, human-like behavior, lead detection, and turn-speed controls."),
"manage_label": tr_noop("Configure"),
"disabled_label": tr_noop("Enable First"),
"panel": "tuning",
"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("Advanced Longitudinal Tuning"),
"desc": tr_noop("Advanced acceleration and braking changes for refining launch, stopping, and actuator response."),
"manage_title": tr_noop("Advanced Settings"),
"manage_desc": tr_noop("Adjust actuator delay, launch and stop behavior, and powertrain-specific tuning options."),
"manage_label": tr_noop("Configure"),
"disabled_label": tr_noop("Enable First"),
"panel": "advanced",
"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",
},
], {
"tuning": StarPilotLongitudinalTuneLayout(),
"advanced": StarPilotAdvancedLongitudinalLayout(),
"tuning": longitudinal_tune_panel,
"advanced": advanced_longitudinal_panel,
"personalities": StarPilotPersonalitiesLayout(),
"traffic_personality": StarPilotPersonalityProfileLayout("Traffic"),
"aggressive_personality": StarPilotPersonalityProfileLayout("Aggressive"),
"standard_personality": StarPilotPersonalityProfileLayout("Standard"),
"relaxed_personality": StarPilotPersonalityProfileLayout("Relaxed"),
})
}, extra_categories=[
{
"title": tr_noop("Driving Personalities"),
"desc": tr_noop("Customize the Traffic, Aggressive, Standard, and Relaxed profiles to match your driving style."),
"panel": "personalities",
"icon": "toggle_icons/icon_personality.png",
"color": "#597497",
},
])
adaptive_panel = create_tile_panel([
{"title": tr_noop("Conditional Experimental"), "panel": "conditional", "icon": "toggle_icons/icon_conditional.png", "color": "#597497"},
@@ -73,89 +126,113 @@ 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"),
"desc": tr_noop("Use acceleration tuning intended for EV and direct-drive vehicles."),
"type": "toggle",
"get_state": lambda: self._params.get_bool("EVTuning"),
"set_state": lambda s: self._params.put_bool("EVTuning", s),
"set_state": self._set_ev_tuning,
"color": "#597497",
"visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"),
"is_enabled": lambda: not self._params.get_bool("TruckTuning"),
"disabled_label": tr_noop("Truck Active"),
"visible": self._advanced_enabled,
},
{
"title": tr_noop("Truck Tuning"),
"desc": tr_noop("Use stronger launch and acceleration behavior intended for heavier vehicles."),
"type": "toggle",
"get_state": lambda: self._params.get_bool("TruckTuning"),
"set_state": lambda s: self._params.put_bool("TruckTuning", s),
"set_state": self._set_truck_tuning,
"color": "#597497",
"visible": lambda: self._params.get_bool("AdvancedLongitudinalTune"),
"is_enabled": lambda: not self._params.get_bool("EVTuning"),
"disabled_label": tr_noop("EV Active"),
"visible": self._advanced_enabled,
},
{
"title": tr_noop("Actuator Delay"),
"desc": tr_noop("The time between an acceleration or brake command and the vehicle's response."),
"type": "value",
"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"),
"visible": self._advanced_enabled,
},
{
"title": tr_noop("Max Acceleration"),
"title": tr_noop("Maximum Acceleration"),
"desc": tr_noop("Limit the strongest acceleration openpilot is allowed to command."),
"type": "value",
"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"),
"visible": self._advanced_enabled,
},
{
"title": tr_noop("Start Accel"),
"title": tr_noop("Start Acceleration"),
"desc": tr_noop("Extra acceleration applied when moving away from a stop."),
"type": "value",
"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"),
"visible": lambda: self._advanced_enabled() and not self._using_human_acceleration(),
},
{
"title": tr_noop("Stop Accel"),
"title": tr_noop("Stop Acceleration"),
"desc": tr_noop("Brake force used to hold the vehicle at a complete stop."),
"type": "value",
"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"),
"visible": self._advanced_enabled,
},
{
"title": tr_noop("Stopping Rate"),
"desc": tr_noop("How quickly braking ramps up when openpilot is bringing the car to a stop."),
"type": "value",
"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"),
"visible": self._show_stop_tuning_values,
},
{
"title": tr_noop("VEgo Starting"),
"title": tr_noop("Start Speed"),
"desc": tr_noop("The speed where openpilot transitions out of the stopped state."),
"type": "value",
"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"),
"visible": self._show_stop_tuning_values,
},
{
"title": tr_noop("VEgo Stopping"),
"title": tr_noop("Stop Speed"),
"desc": tr_noop("The speed where openpilot considers the vehicle fully stopped."),
"type": "value",
"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"),
"visible": self._show_stop_tuning_values,
},
]
self._rebuild_grid()
def _advanced_enabled(self):
return self._params.get_bool("AdvancedLongitudinalTune")
def _using_human_acceleration(self):
return self._params.get_bool("LongitudinalTune") and self._params.get_bool("HumanAcceleration")
def _show_stop_tuning_values(self):
return self._advanced_enabled() and not (starpilot_state.car_state.isToyota and self._params.get_bool("FrogsGoMoosTweak"))
def _set_ev_tuning(self, state: bool):
self._params.put_bool("EVTuning", state)
if state:
self._params.put_bool("TruckTuning", False)
def _set_truck_tuning(self, state: bool):
self._params.put_bool("TruckTuning", state)
if state:
self._params.put_bool("EVTuning", False)
def _show_float_selector(self, key, min_v, max_v, step, unit=""):
def on_close(res, val):
if res == DialogResult.CONFIRM:
@@ -470,80 +547,106 @@ 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"),
"desc": tr_noop("Choose how quickly openpilot speeds up."),
"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+"]),
"get_value": self._get_acceleration_profile_label,
"on_click": self._show_acceleration_profile_selector,
"color": "#597497",
"visible": lambda: self._params.get_bool("LongitudinalTune"),
"visible": self._longitudinal_enabled,
},
{
"title": tr_noop("Deceleration Profile"),
"desc": tr_noop("Choose how firmly openpilot slows the car down."),
"type": "value",
"get_value": lambda: self._params.get("DecelerationProfile", encoding='utf-8') or "Standard",
"on_click": lambda: self._show_selection("DecelerationProfile", ["Standard", "Eco", "Sport"]),
"get_value": self._get_deceleration_profile_label,
"on_click": self._show_deceleration_profile_selector,
"color": "#597497",
"visible": lambda: self._params.get_bool("LongitudinalTune"),
"visible": self._longitudinal_enabled,
},
{
"title": tr_noop("Human Acceleration"),
"title": tr_noop("Human-Like Acceleration"),
"desc": tr_noop("Smooth throttle behavior at low speed with stronger takeoff from a stop."),
"type": "toggle",
"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"),
"visible": self._longitudinal_enabled,
},
{
"title": tr_noop("Human Following"),
"title": tr_noop("Human-Like Following"),
"desc": tr_noop("Adjust following behavior to feel more natural behind other vehicles."),
"type": "toggle",
"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"),
"visible": self._longitudinal_enabled,
},
{
"title": tr_noop("Human Lane Changes"),
"title": tr_noop("Human-Like Lane Changes"),
"desc": tr_noop("Use radar-informed behavior during lane changes when radar support is available."),
"type": "toggle",
"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"),
"visible": lambda: self._longitudinal_enabled() and starpilot_state.car_state.hasRadar,
},
{
"title": tr_noop("Lead Detection"),
"title": tr_noop("Lead Detection Sensitivity"),
"desc": tr_noop("Control how aggressively openpilot detects and reacts to vehicles ahead."),
"type": "value",
"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"),
"visible": self._longitudinal_enabled,
},
{
"title": tr_noop("Taco Tune"),
"title": tr_noop("\"Taco Bell Run\" Turn Speed Hack"),
"desc": tr_noop("Slow down more assertively for turns."),
"type": "toggle",
"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"),
"visible": self._longitudinal_enabled,
},
]
self._rebuild_grid()
def _show_selection(self, key, options):
def _longitudinal_enabled(self):
return self._params.get_bool("LongitudinalTune")
def _get_acceleration_profile_label(self):
value = normalize_acceleration_profile(self._params.get("AccelerationProfile", encoding='utf-8'))
return self._profile_label_for_value(value, ACCELERATION_PROFILE_OPTIONS)
def _get_deceleration_profile_label(self):
value = normalize_deceleration_profile(self._params.get("DecelerationProfile", encoding='utf-8'))
return self._profile_label_for_value(value, DECELERATION_PROFILE_OPTIONS)
def _show_acceleration_profile_selector(self):
self._show_selection("Acceleration Profile", "AccelerationProfile", ACCELERATION_PROFILE_OPTIONS, normalize_acceleration_profile(self._params.get("AccelerationProfile", encoding='utf-8')))
def _show_deceleration_profile_selector(self):
self._show_selection("Deceleration Profile", "DecelerationProfile", DECELERATION_PROFILE_OPTIONS, normalize_deceleration_profile(self._params.get("DecelerationProfile", encoding='utf-8')))
def _profile_label_for_value(self, value, options):
for option_value, option_label in options:
if option_value == value:
return tr(option_label)
return tr(options[0][1])
def _show_selection(self, title, key, options, current_value):
option_labels = [tr(option_label) for _, option_label in options]
label_to_value = {tr(option_label): option_value for option_value, option_label in options}
default_option = next((tr(option_label) for option_value, option_label in options if option_value == current_value), option_labels[0])
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put(key, val)
self._params.put_int(key, label_to_value[val])
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr(key), options, self._params.get(key, encoding='utf-8') or "Standard", on_close=on_select))
gui_app.set_modal_overlay(SelectionDialog(tr(title), option_labels, default_option, on_close=on_select))
def _show_int_selector(self, key, min_v, max_v, unit=""):
def on_close(res, val):
@@ -89,7 +89,13 @@ class StarPilotPanel(Widget):
bg_color=cat.get("color"),
)
elif tile_type == "toggle":
tile = ToggleTile(title=tr(cat["title"]), get_state=cat["get_state"], set_state=cat["set_state"], icon_path=cat.get("icon"), bg_color=cat.get("color"), desc=tr(cat.get("desc", "")), is_enabled=cat.get("is_enabled"), disabled_label=cat.get("disabled_label", ""))
raw_set_state = cat["set_state"]
def on_toggle(state: bool, setter=raw_set_state):
setter(state)
self._rebuild_grid()
tile = ToggleTile(title=tr(cat["title"]), get_state=cat["get_state"], set_state=on_toggle, icon_path=cat.get("icon"), bg_color=cat.get("color"), desc=tr(cat.get("desc", "")), is_enabled=cat.get("is_enabled"), disabled_label=cat.get("disabled_label", ""))
elif tile_type == "value":
tile = ValueTile(title=tr(cat["title"]), get_value=cat["get_value"], on_click=cat["on_click"], icon_path=cat.get("icon"), bg_color=cat.get("color"), is_enabled=cat.get("is_enabled"), desc=tr(cat.get("desc", "")))
else:
@@ -138,3 +144,41 @@ def create_tile_panel(categories: list[dict], sub_panels: dict[str, Widget] | No
panel._rebuild_grid()
return panel
def create_master_toggle_panel(toggle_specs: list[dict], sub_panels: dict[str, Widget] | None = None,
extra_categories: list[dict] | None = None) -> StarPilotPanel:
panel = create_tile_panel([], sub_panels)
categories: list[dict] = []
for spec in toggle_specs:
get_state = spec["get_state"]
visible = spec.get("visible")
manage_enabled = spec.get("manage_enabled", get_state)
categories.append({
"title": spec["title"],
"desc": spec.get("desc", ""),
"type": "toggle",
"get_state": get_state,
"set_state": spec["set_state"],
"icon": spec.get("icon"),
"color": spec.get("color"),
"visible": visible,
})
categories.append({
"title": spec.get("manage_title", "Settings"),
"desc": spec.get("manage_desc", ""),
"type": "value",
"get_value": lambda enabled=get_state, active_label=spec.get("manage_label", "Manage"), inactive_label=spec.get("disabled_label", "Enable First"): tr(active_label) if enabled() else tr(inactive_label),
"on_click": lambda sub_panel=spec["panel"]: panel._navigate_to(sub_panel),
"is_enabled": manage_enabled,
"icon": spec.get("manage_icon", spec.get("icon")),
"color": spec.get("color"),
"visible": visible,
})
panel.CATEGORIES = categories + list(extra_categories or [])
panel._rebuild_grid()
return panel
@@ -1,7 +1,4 @@
from __future__ import annotations
import os
import re
from pathlib import Path
from openpilot.system.hardware import HARDWARE
from openpilot.system.ui.lib.application import gui_app
@@ -12,73 +9,11 @@ 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, TileGrid, HubTile, ToggleTile, ValueTile
from openpilot.selfdrive.ui.lib.starpilot_state import starpilot_state
MAKE_TO_FOLDER = {
"acura": "honda",
"audi": "volkswagen",
"buick": "gm",
"cadillac": "gm",
"chevrolet": "gm",
"chrysler": "chrysler",
"cupra": "volkswagen",
"dodge": "chrysler",
"ford": "ford",
"genesis": "hyundai",
"gmc": "gm",
"holden": "gm",
"honda": "honda",
"hyundai": "hyundai",
"jeep": "chrysler",
"kia": "hyundai",
"lexus": "toyota",
"lincoln": "ford",
"man": "volkswagen",
"mazda": "mazda",
"nissan": "nissan",
"peugeot": "psa",
"ram": "chrysler",
"rivian": "rivian",
"seat": "volkswagen",
"škoda": "volkswagen",
"subaru": "subaru",
"tesla": "tesla",
"toyota": "toyota",
"volkswagen": "volkswagen",
}
def get_car_names(car_make: str):
folder = MAKE_TO_FOLDER.get(car_make.lower())
if not folder:
return [], {}
# Path to values.py in opendbc
values_path = Path(__file__).parents[4] / "opendbc" / "car" / folder / "values.py"
if not values_path.exists():
return [], {}
with open(values_path, "r") as f:
content = f.read()
# Clean comments
content = re.sub(r'#.*', '', content)
# Find platforms and car names
platforms = re.findall(r'(\w+)\s*=\s*\w+\s*\(', content)
car_models = {}
car_names = []
# This is a simplified version of the C++ regex logic
# In values.py, CarDocs often appears as CarDocs("Name", ...)
matches = re.finditer(r'CarDocs\w*\s*\(\s*"([^"]+)"', content)
for match in matches:
name = match.group(1)
if name.lower().startswith(car_make.lower()):
# Find the platform name by looking backwards for the nearest platform assignment
# For now, we'll just store the name
car_names.append(name)
return sorted(list(set(car_names))), car_models
from openpilot.selfdrive.ui.mici.layouts.settings.fingerprint_catalog import (
FingerprintModelOption,
get_fingerprint_catalog,
shorten_model_label,
)
def _lock_doors_timer_labels():
@@ -91,6 +26,7 @@ def _lock_doors_timer_labels():
class StarPilotVehicleSettingsLayout(StarPilotPanel):
def __init__(self):
super().__init__()
self._make_options, self._models_by_make, self._models_by_value, self._make_by_model = get_fingerprint_catalog()
self._sub_panels = {
"gm": StarPilotGMVehicleLayout(),
"hkg": StarPilotHKGVehicleLayout(),
@@ -103,14 +39,14 @@ class StarPilotVehicleSettingsLayout(StarPilotPanel):
{
"title": tr_noop("Car Make"),
"type": "value",
"get_value": lambda: self._params.get("CarMake", encoding='utf-8') or tr("None"),
"get_value": self._get_display_make,
"on_click": self._on_select_make,
"color": "#64748B",
},
{
"title": tr_noop("Car Model"),
"type": "value",
"get_value": lambda: self._params.get("CarModelName", encoding='utf-8') or tr("None"),
"get_value": self._get_display_model,
"on_click": self._on_select_model,
"color": "#64748B",
},
@@ -189,37 +125,93 @@ class StarPilotVehicleSettingsLayout(StarPilotPanel):
self._tile_grid.add_tile(tile)
def _get_display_make(self):
make = self._params.get("CarMake", encoding='utf-8') or ""
if make:
return make
model = self._params.get("CarModel", encoding='utf-8') or ""
if model:
return self._make_by_model.get(model, tr("None"))
return tr("None")
def _get_selected_model_option(self) -> FingerprintModelOption | None:
model = self._params.get("CarModel", encoding='utf-8') or ""
if not model:
return None
model_name = self._params.get("CarModelName", encoding='utf-8') or ""
make = self._params.get("CarMake", encoding='utf-8') or self._make_by_model.get(model, "")
if make and model_name:
for option in self._models_by_make.get(make, ()):
if option.value == model and option.label == model_name:
return option
return self._models_by_value.get(model)
def _get_display_model(self):
selected_option = self._get_selected_model_option()
if selected_option is not None:
return selected_option.button_label
model = self._params.get("CarModel", encoding='utf-8') or ""
model_name = self._params.get("CarModelName", encoding='utf-8') or ""
make = self._params.get("CarMake", encoding='utf-8') or self._make_by_model.get(model, "")
if model_name:
return shorten_model_label(make, model_name) if make else model_name
if model and model in self._models_by_value:
return self._models_by_value[model].button_label
return tr("None")
def _on_select_make(self):
makes = sorted(list(MAKE_TO_FOLDER.keys()))
makes = [m.capitalize() for m in makes]
makes = list(self._make_options)
if not makes:
gui_app.set_modal_overlay(ConfirmDialog(tr("No fingerprint list available."), tr("OK"), on_close=lambda r: None))
return
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put("CarMake", val)
self._params.remove("CarModel")
self._params.remove("CarModelName")
current_model = self._params.get("CarModel", encoding='utf-8') or ""
available_models = {option.value for option in self._models_by_make.get(val, ())}
if current_model not in available_models:
self._params.remove("CarModel")
self._params.remove("CarModelName")
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Select Make"), makes, self._params.get("CarMake", encoding='utf-8') or "", on_close=on_select))
current_make = self._params.get("CarMake", encoding='utf-8') or ""
default_make = current_make if current_make in makes else makes[0]
gui_app.set_modal_overlay(SelectionDialog(tr("Select Make"), makes, default_make, on_close=on_select))
def _on_select_model(self):
make = self._params.get("CarMake", encoding='utf-8')
make = self._params.get("CarMake", encoding='utf-8') or ""
if not make:
gui_app.set_modal_overlay(ConfirmDialog(tr("Please select a Car Make first!"), tr("OK"), on_close=lambda r: None))
return
models, _ = get_car_names(make)
if not models:
gui_app.set_modal_overlay(ConfirmDialog(tr("No models found for this make."), tr("OK"), on_close=lambda r: None))
model_options = self._models_by_make.get(make, ())
if not model_options:
gui_app.set_modal_overlay(ConfirmDialog(tr("No models available for this make."), tr("OK"), on_close=lambda r: None))
return
option_labels = [option.option_label for option in model_options]
selected_by_label = {option.option_label: option for option in model_options}
current_model = self._params.get("CarModel", encoding='utf-8') or ""
current_model_name = self._params.get("CarModelName", encoding='utf-8') or ""
default_option = next((option.option_label for option in model_options if option.value == current_model and option.label == current_model_name), None)
if default_option is None:
default_option = next((option.option_label for option in model_options if option.value == current_model), option_labels[0])
def on_select(res, val):
if res == DialogResult.CONFIRM:
self._params.put("CarModelName", val)
# In a real build we'd map name to platform code here
selected_option = selected_by_label[val]
self._params.put("CarModel", selected_option.value)
self._params.put("CarModelName", selected_option.label)
self._params.put("CarMake", make)
self._rebuild_grid()
gui_app.set_modal_overlay(SelectionDialog(tr("Select Model"), models, self._params.get("CarModelName", encoding='utf-8') or "", on_close=on_select))
gui_app.set_modal_overlay(SelectionDialog(tr("Select Model"), option_labels, default_option, on_close=on_select))
def _on_disable_long(self, state):
if state: