mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-09-30 03:23:52 +08:00
[TIZI/TICI] ui: Steering panel (#1540)
* commaai/openpilot:d05cb31e2e916fba41ba8167030945f427fd811b * bump opendbc * bump opendbc * bump opendbc * bump opendbc * bump opendbc * sunnypilot: remove Qt * cabana: revert to stock Qt * commaai/openpilot:5198b1b079c37742c1050f02ce0aa6dd42b038b9 * commaai/openpilot:954b567b9ba0f3d1ae57d6aa7797fa86dd92ec6e * commaai/openpilot:7534b2a160faa683412c04c1254440e338931c5e * sum more * bump opendbc * not yet * should've been symlink'ed * raylib says wut * quiet mode back * more fixes * no more * too extra red diff on the side * need to bring this back * too extra * let's update docs here * Revert "let's update docs here" This reverts commit 51fe03cd5121e6fdf14657b2c33852c34922b851. * param to control stock vs sp ui * init styles * SP Toggles * Lint * optimizations * multi-button * Lint * param to control stock vs sp ui * init styles * SP Toggles * Lint * optimizations * Panels. With Icons. And Scroller. * patience, grasshopper * more patience, grasshopper * sp raylib preview * fix callback * fix ui preview * add ui previews * Option Control * Need this * sunnylink state * introducing ui_state_sp for py * poll from ui_state_sp * cloudlog & ruff * param to control stock vs sp ui * better * sponsor & pairing qr * init panel elements * backup & restore * fruit loops * update * enable, disable, enable, disable * handle layout updates * not needed * add ui_update callback * change it up * better padding * this * support for next line multi-button * uhh * disabled colors * better * listitem -> listitemsp * listitem -> listitemsp * Revert "add ui_update callback" This reverts commit 4da32cc0097434aab0aa6a3c35465eabb23c8958. * add show_description method * remove padding from line separator. like, WHY? 😩😩 * simplify * I. SAID. SIMPLIFY. * AAARGGGGGG..... * option control value fix * left button * more init * simple_button, yay * simple_button, yay * more more init * scroller -> scroller_tici * scroller -> scroller_tici * ui: `GuiApplicationExt` * simple button * simple button * add to readme * use gui_app.sunnypilot_ui() * use gui_app.sunnypilot_ui() * use gui_app.sunnypilot_ui() * optimizations * change order * subpanels * lane change timer * update toggles * update toggles * add cp_sp to ui_state * mads * add cp_sp to ui_state_sp * fix ui crash * update params * ui_state changes * descriptions * Update scroller.py * wrong pr * listen nessa, yes nessa * i've got something to confessa * some bs * # Conflicts: # selfdrive/ui/sunnypilot/layouts/settings/steering.py # selfdrive/ui/sunnypilot/layouts/settings/vehicle.py # system/ui/sunnypilot/widgets/list_view.py * sine * more * Delete selfdrive/ui/sunnypilot/layouts/vehicle_settings/platform_selector.py * Update styles.py * allow sunnylink * nah * more * sync * lint * revert * button is always shown, just disabled if off * revert * Fix SimpleButtonActionSP not respecting enabled state * some changes * new pr * some more * ui: `ButtonSP` * slight cleanup * fixes * no * fix * much better * ui: `LineSeparatorSP` * ui: add `inline` to `option_item_sp` * small cleanup mads * lane change * allow changing title * torque settings init * lont * more logic * import directly * more --------- Co-authored-by: Jason Wen <haibin.wen3@gmail.com> Co-authored-by: DevTekVE <devtekve@gmail.com> Co-authored-by: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com> Co-authored-by: discountchubbs <alexgrant990@gmail.com>
This commit is contained in:
@@ -4,27 +4,147 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
from openpilot.common.params import Params
|
||||
from cereal import car
|
||||
from enum import IntEnum
|
||||
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp, simple_button_item_sp, option_item_sp, LineSeparatorSP
|
||||
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.steering_sub_layouts.lane_change_settings import LaneChangeSettingsLayout
|
||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.steering_sub_layouts.mads_settings import MadsSettingsLayout
|
||||
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.steering_sub_layouts.torque_settings import TorqueSettingsLayout
|
||||
|
||||
|
||||
class PanelType(IntEnum):
|
||||
STEERING = 0
|
||||
MADS = 1
|
||||
LANE_CHANGE = 2
|
||||
TORQUE_CONTROL = 3
|
||||
|
||||
|
||||
class SteeringLayout(Widget):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self._params = Params()
|
||||
self._current_panel = PanelType.STEERING
|
||||
self._lane_change_settings_layout = LaneChangeSettingsLayout(lambda: self._set_current_panel(PanelType.STEERING))
|
||||
self._mads_settings_layout = MadsSettingsLayout(lambda: self._set_current_panel(PanelType.STEERING))
|
||||
self._torque_control_layout = TorqueSettingsLayout(lambda: self._set_current_panel(PanelType.STEERING))
|
||||
|
||||
items = self._initialize_items()
|
||||
self._scroller = Scroller(items, line_separator=True, spacing=0)
|
||||
self._scroller = Scroller(items, line_separator=False, spacing=0)
|
||||
|
||||
def _initialize_items(self):
|
||||
items = [
|
||||
self._mads_base_desc = tr("Enable the beloved MADS feature. " +
|
||||
"Disable toggle to revert back to stock sunnypilot engagement/disengagement.")
|
||||
self._mads_limited_desc = tr("This platform supports limited MADS settings.")
|
||||
self._mads_full_desc = tr("This platform supports all MADS settings.")
|
||||
self._mads_check_compat_desc = tr("Start the vehicle to check vehicle compatibility.")
|
||||
|
||||
self._mads_toggle = toggle_item_sp(
|
||||
param="Mads",
|
||||
title=lambda: tr("Modular Assistive Driving System (MADS)"),
|
||||
description=self._mads_base_desc,
|
||||
)
|
||||
self._mads_settings_button = simple_button_item_sp(
|
||||
button_text=lambda: tr("Customize MADS"),
|
||||
button_width=800,
|
||||
callback=lambda: self._set_current_panel(PanelType.MADS)
|
||||
)
|
||||
self._lane_change_settings_button = simple_button_item_sp(
|
||||
button_text=lambda: tr("Customize Lane Change"),
|
||||
button_width=800,
|
||||
callback=lambda: self._set_current_panel(PanelType.LANE_CHANGE)
|
||||
)
|
||||
self._blinker_control_toggle = toggle_item_sp(
|
||||
param="BlinkerPauseLateralControl",
|
||||
description=lambda: tr("Pause lateral control with blinker when traveling below the desired speed selected."),
|
||||
title=lambda: tr("Pause Lateral Control with Blinker"),
|
||||
)
|
||||
self._blinker_control_options = option_item_sp(
|
||||
param="BlinkerMinLateralControlSpeed",
|
||||
title=lambda: tr("Minimum Speed to Pause Lateral Control"),
|
||||
min_value=0,
|
||||
max_value=255,
|
||||
value_change_step=5,
|
||||
description="",
|
||||
label_callback=lambda speed: f'{speed} {"km/h" if ui_state.is_metric else "mph"}',
|
||||
)
|
||||
self._torque_control_toggle = toggle_item_sp(
|
||||
param="EnforceTorqueControl",
|
||||
title=lambda: tr("Enforce Torque Lateral Control"),
|
||||
description=lambda: tr("Enable this to enforce sunnypilot to steer with Torque lateral control."),
|
||||
)
|
||||
self._torque_customization_button = simple_button_item_sp(
|
||||
button_text=lambda: tr("Customize Torque Params"),
|
||||
button_width=850,
|
||||
callback=lambda: self._set_current_panel(PanelType.TORQUE_CONTROL)
|
||||
)
|
||||
self._nnlc_toggle = toggle_item_sp(
|
||||
param="NeuralNetworkLateralControl",
|
||||
title=lambda: tr("Neural Network Lateral Control (NNLC)"),
|
||||
description=""
|
||||
)
|
||||
|
||||
items = [
|
||||
self._mads_toggle,
|
||||
self._mads_settings_button,
|
||||
LineSeparatorSP(40),
|
||||
self._lane_change_settings_button,
|
||||
LineSeparatorSP(40),
|
||||
self._blinker_control_toggle,
|
||||
self._blinker_control_options,
|
||||
LineSeparatorSP(40),
|
||||
self._torque_control_toggle,
|
||||
self._torque_customization_button,
|
||||
LineSeparatorSP(40),
|
||||
self._nnlc_toggle,
|
||||
]
|
||||
return items
|
||||
|
||||
def _set_current_panel(self, panel: PanelType):
|
||||
self._current_panel = panel
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
|
||||
torque_allowed = True
|
||||
if ui_state.CP is not None:
|
||||
mads_main_desc = self._mads_limited_desc if self._mads_settings_layout._mads_limited_settings() else self._mads_full_desc
|
||||
self._mads_toggle.set_description(f"<b>{mads_main_desc}</b><br><br>{self._mads_base_desc}")
|
||||
|
||||
if ui_state.CP.steerControlType == car.CarParams.SteerControlType.angle:
|
||||
ui_state.params.remove("EnforceTorqueControl")
|
||||
ui_state.params.remove("NeuralNetworkLateralControl")
|
||||
torque_allowed = False
|
||||
else:
|
||||
self._mads_toggle.set_description(f"<b>{self._mads_check_compat_desc}</b><br><br>{self._mads_base_desc}")
|
||||
ui_state.params.remove("EnforceTorqueControl")
|
||||
ui_state.params.remove("NeuralNetworkLateralControl")
|
||||
torque_allowed = False
|
||||
|
||||
self._mads_toggle.action_item.set_enabled(ui_state.is_offroad())
|
||||
self._mads_settings_button.action_item.set_enabled(ui_state.is_offroad() and self._mads_toggle.action_item.get_state())
|
||||
self._blinker_control_options.set_visible(self._blinker_control_toggle.action_item.get_state())
|
||||
|
||||
enforce_torque_enabled = self._torque_control_toggle.action_item.get_state()
|
||||
nnlc_enabled = self._nnlc_toggle.action_item.get_state()
|
||||
self._nnlc_toggle.action_item.set_enabled(ui_state.is_offroad() and torque_allowed and not enforce_torque_enabled)
|
||||
self._torque_control_toggle.action_item.set_enabled(ui_state.is_offroad() and torque_allowed and not nnlc_enabled)
|
||||
self._torque_customization_button.action_item.set_enabled(self._torque_control_toggle.action_item.get_state())
|
||||
|
||||
def _render(self, rect):
|
||||
self._scroller.render(rect)
|
||||
if self._current_panel == PanelType.LANE_CHANGE:
|
||||
self._lane_change_settings_layout.render(rect)
|
||||
elif self._current_panel == PanelType.MADS:
|
||||
self._mads_settings_layout.render(rect)
|
||||
elif self._current_panel == PanelType.TORQUE_CONTROL:
|
||||
self._torque_control_layout.render(rect)
|
||||
else:
|
||||
self._scroller.render(rect)
|
||||
|
||||
def show_event(self):
|
||||
self._set_current_panel(PanelType.STEERING)
|
||||
self._scroller.show_event()
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
"""
|
||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
from collections.abc import Callable
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp, option_item_sp, LineSeparatorSP
|
||||
from openpilot.system.ui.widgets.network import NavButton
|
||||
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
from openpilot.sunnypilot.selfdrive.controls.lib.auto_lane_change import AutoLaneChangeMode
|
||||
|
||||
|
||||
class LaneChangeSettingsLayout(Widget):
|
||||
def __init__(self, back_btn_callback: Callable):
|
||||
super().__init__()
|
||||
self._back_button = NavButton(tr("Back"))
|
||||
self._back_button.set_click_callback(back_btn_callback)
|
||||
|
||||
items = self._initialize_items()
|
||||
self._scroller = Scroller(items, line_separator=False, spacing=0)
|
||||
|
||||
def _initialize_items(self):
|
||||
self._lane_change_timer = option_item_sp(
|
||||
title=lambda: tr("Auto Lane Change by Blinker"),
|
||||
param="AutoLaneChangeTimer",
|
||||
description=lambda: tr("Set a timer to delay the auto lane change operation when the blinker is used. " +
|
||||
"No nudge on the steering wheel is required to auto lane change if a timer is set. Default is Nudge.<br>" +
|
||||
"Please use caution when using this feature. Only use the blinker when traffic and road conditions permit."),
|
||||
min_value=-1,
|
||||
max_value=5,
|
||||
value_change_step=1,
|
||||
label_callback=(lambda x:
|
||||
tr("Off") if x == -1 else
|
||||
tr("Nudge") if x == 0 else
|
||||
tr("Nudgeless") if x == 1 else
|
||||
f"0.5 {tr('s')}" if x == 2 else
|
||||
f"1 {tr('s')}" if x == 3 else
|
||||
f"2 {tr('s')}" if x == 4 else
|
||||
f"3 {tr('s')}")
|
||||
)
|
||||
self._bsm_delay = toggle_item_sp(
|
||||
param="AutoLaneChangeBsmDelay",
|
||||
title=lambda: tr("Auto Lane Change: Delay with Blind Spot"),
|
||||
description=lambda: tr("Toggle to enable a delay timer for seamless lane changes when blind spot monitoring " +
|
||||
"(BSM) detects a obstructing vehicle, ensuring safe maneuvering."),
|
||||
)
|
||||
|
||||
items = [
|
||||
self._lane_change_timer,
|
||||
LineSeparatorSP(40),
|
||||
self._bsm_delay,
|
||||
]
|
||||
|
||||
return items
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
self._update_toggles()
|
||||
|
||||
def _render(self, rect):
|
||||
self._back_button.set_position(self._rect.x, self._rect.y + 20)
|
||||
self._back_button.render()
|
||||
# subtract button
|
||||
content_rect = rl.Rectangle(rect.x, rect.y + self._back_button.rect.height + 40, rect.width, rect.height - self._back_button.rect.height - 40)
|
||||
self._scroller.render(content_rect)
|
||||
|
||||
def show_event(self):
|
||||
self._scroller.show_event()
|
||||
|
||||
def _update_toggles(self):
|
||||
enable_bsm = ui_state.CP and ui_state.CP.enableBsm
|
||||
if not enable_bsm and ui_state.params.get_bool("AutoLaneChangeBsmDelay"):
|
||||
ui_state.params.remove("AutoLaneChangeBsmDelay")
|
||||
self._bsm_delay.action_item.set_enabled(enable_bsm and ui_state.params.get("AutoLaneChangeTimer", return_default=True) > AutoLaneChangeMode.NUDGE)
|
||||
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
from collections.abc import Callable
|
||||
import pyray as rl
|
||||
|
||||
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.multilang import tr, tr_noop
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
from openpilot.system.ui.widgets.network import NavButton
|
||||
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
||||
from openpilot.system.ui.sunnypilot.widgets.list_view import multiple_button_item_sp, toggle_item_sp
|
||||
|
||||
MADS_STEERING_MODE_OPTIONS = [
|
||||
(tr("Remain Active"), tr_noop("Remain Active: ALC will remain active when the brake pedal is pressed.")),
|
||||
(tr("Pause"), tr_noop("Pause: ALC will pause when the brake pedal is pressed.")),
|
||||
(tr("Disengage"), tr_noop("Disengage: ALC will disengage when the brake pedal is pressed.")),
|
||||
]
|
||||
|
||||
MADS_MAIN_CRUISE_BASE_DESC = tr("Note: For vehicles without LFA/LKAS button, disabling this will prevent lateral control engagement.")
|
||||
MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC = "{engage}<br><h4>{note}</h4>".format(
|
||||
engage=tr("Engage lateral and longitudinal control with cruise control engagement."),
|
||||
note=tr("Note: Once lateral control is engaged via UEM, it will remain engaged until it is manually disabled via the MADS button or car shut off."),
|
||||
)
|
||||
|
||||
STATUS_CHECK_COMPATIBILITY = tr("Start the vehicle to check vehicle compatibility.")
|
||||
DEFAULT_TO_OFF = tr("This feature defaults to OFF, and does not allow selection due to vehicle limitations.")
|
||||
DEFAULT_TO_ON = tr("This feature defaults to ON, and does not allow selection due to vehicle limitations.")
|
||||
STATUS_DISENGAGE_ONLY = tr("This platform only supports Disengage mode due to vehicle limitations.")
|
||||
|
||||
|
||||
class MadsSettingsLayout(Widget):
|
||||
def __init__(self, back_btn_callback: Callable):
|
||||
super().__init__()
|
||||
self._back_button = NavButton(tr("Back"))
|
||||
self._back_button.set_click_callback(back_btn_callback)
|
||||
self._initialize_items()
|
||||
self._scroller = Scroller(self.items, line_separator=True, spacing=0)
|
||||
|
||||
def _initialize_items(self):
|
||||
self._main_cruise_toggle = toggle_item_sp(
|
||||
title=lambda: tr("Toggle with Main Cruise"),
|
||||
description=MADS_MAIN_CRUISE_BASE_DESC,
|
||||
param="MadsMainCruiseAllowed",
|
||||
)
|
||||
self._unified_engagement_toggle = toggle_item_sp(
|
||||
title=lambda: tr("Unified Engagement Mode (UEM)"),
|
||||
description=MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC,
|
||||
param="MadsUnifiedEngagementMode"
|
||||
)
|
||||
self._steering_mode = multiple_button_item_sp(
|
||||
param="MadsSteeringMode",
|
||||
title=lambda: tr("Steering Mode on Brake Pedal"),
|
||||
description="",
|
||||
buttons=[opt[0] for opt in MADS_STEERING_MODE_OPTIONS],
|
||||
inline=False,
|
||||
button_width=350,
|
||||
callback=self._update_steering_mode_description,
|
||||
)
|
||||
|
||||
self.items = [
|
||||
self._main_cruise_toggle,
|
||||
self._unified_engagement_toggle,
|
||||
self._steering_mode,
|
||||
]
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
self._update_toggles()
|
||||
|
||||
def _render(self, rect):
|
||||
self._back_button.set_position(self._rect.x, self._rect.y + 20)
|
||||
self._back_button.render()
|
||||
# subtract button
|
||||
content_rect = rl.Rectangle(rect.x, rect.y + self._back_button.rect.height + 40, rect.width, rect.height - self._back_button.rect.height - 40)
|
||||
self._scroller.render(content_rect)
|
||||
|
||||
def show_event(self):
|
||||
self._scroller.show_event()
|
||||
|
||||
@staticmethod
|
||||
def _mads_limited_settings() -> bool:
|
||||
brand = ""
|
||||
if ui_state.is_offroad():
|
||||
bundle = ui_state.params.get("CarPlatformBundle")
|
||||
if bundle:
|
||||
brand = bundle.get("brand", "")
|
||||
if not brand:
|
||||
brand = ui_state.CP.brand if ui_state.CP else ""
|
||||
|
||||
if brand == "rivian":
|
||||
return True
|
||||
elif brand == "tesla":
|
||||
return not (ui_state.CP_SP and ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
|
||||
return False
|
||||
|
||||
def _update_steering_mode_description(self, button_index: int):
|
||||
base_desc = tr("Choose how Automatic Lane Centering (ALC) behaves after the brake pedal is manually pressed in sunnypilot.")
|
||||
result = base_desc + "<br><br>"
|
||||
for opt in MADS_STEERING_MODE_OPTIONS:
|
||||
desc = "<b>" + opt[1] + "</b>" if button_index == MADS_STEERING_MODE_OPTIONS.index(opt) else opt[1]
|
||||
result += desc + "<br>"
|
||||
self._steering_mode.set_description(result)
|
||||
self._steering_mode.show_description(True)
|
||||
|
||||
def _update_toggles(self):
|
||||
self._update_steering_mode_description(self._steering_mode.action_item.get_selected_button())
|
||||
if self._mads_limited_settings():
|
||||
ui_state.params.remove("MadsMainCruiseAllowed")
|
||||
ui_state.params.put_bool("MadsUnifiedEngagementMode", True)
|
||||
ui_state.params.put("MadsSteeringMode", 2)
|
||||
|
||||
self._main_cruise_toggle.action_item.set_enabled(False)
|
||||
self._main_cruise_toggle.action_item.set_state(False)
|
||||
self._main_cruise_toggle.set_description("<b>" + DEFAULT_TO_OFF + "</b><br>" + MADS_MAIN_CRUISE_BASE_DESC)
|
||||
|
||||
self._unified_engagement_toggle.action_item.set_enabled(False)
|
||||
self._unified_engagement_toggle.action_item.set_state(True)
|
||||
self._unified_engagement_toggle.set_description("<b>" + DEFAULT_TO_ON + "</b><br>" + MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC)
|
||||
|
||||
self._steering_mode.action_item.set_enabled(False)
|
||||
self._steering_mode.set_description(STATUS_DISENGAGE_ONLY)
|
||||
self._steering_mode.action_item.set_selected_button(2)
|
||||
else:
|
||||
self._main_cruise_toggle.action_item.set_enabled(True)
|
||||
self._main_cruise_toggle.set_description(MADS_MAIN_CRUISE_BASE_DESC)
|
||||
|
||||
self._unified_engagement_toggle.action_item.set_enabled(True)
|
||||
self._unified_engagement_toggle.set_description(MADS_UNIFIED_ENGAGEMENT_MODE_BASE_DESC)
|
||||
|
||||
self._steering_mode.action_item.set_enabled(True)
|
||||
@@ -0,0 +1,115 @@
|
||||
"""
|
||||
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||
|
||||
This file is part of sunnypilot and is licensed under the MIT License.
|
||||
See the LICENSE.md file in the root directory for more details.
|
||||
"""
|
||||
from collections.abc import Callable
|
||||
import pyray as rl
|
||||
|
||||
from openpilot.selfdrive.ui.ui_state import ui_state
|
||||
from openpilot.system.ui.lib.multilang import tr
|
||||
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp, option_item_sp
|
||||
from openpilot.system.ui.widgets.network import NavButton
|
||||
from openpilot.system.ui.widgets.scroller_tici import Scroller
|
||||
from openpilot.system.ui.widgets import Widget
|
||||
|
||||
|
||||
class TorqueSettingsLayout(Widget):
|
||||
def __init__(self, back_btn_callback: Callable):
|
||||
super().__init__()
|
||||
self._back_button = NavButton(tr("Back"))
|
||||
self._back_button.set_click_callback(back_btn_callback)
|
||||
items = self._initialize_items()
|
||||
self._scroller = Scroller(items, line_separator=True, spacing=0)
|
||||
|
||||
def _initialize_items(self):
|
||||
self._self_tune_toggle = toggle_item_sp(
|
||||
param="LiveTorqueParamsToggle",
|
||||
title=lambda: tr("Self-Tune"),
|
||||
description=lambda: tr("Enables self-tune for Torque lateral control for platforms that do not use " +
|
||||
"Torque lateral control by default."),
|
||||
)
|
||||
self._relaxed_tune_toggle = toggle_item_sp(
|
||||
param="LiveTorqueParamsRelaxedToggle",
|
||||
title=lambda: tr("Less Restrict Settings for Self-Tune (Beta)"),
|
||||
description=lambda: tr("Less strict settings when using Self-Tune. This allows torqued to be more " +
|
||||
"forgiving when learning values."),
|
||||
)
|
||||
self._custom_tune_toggle = toggle_item_sp(
|
||||
param="CustomTorqueParams",
|
||||
title=lambda: tr("Enable Custom Tuning"),
|
||||
description=lambda: tr("Enables custom tuning for Torque lateral control. " +
|
||||
"Modifying Lateral Acceleration Factor and Friction below will override the offline values " +
|
||||
"indicated in the YAML files within \"opendbc/car/torque_data\". " +
|
||||
"The values will also be used live when \"Manual Real-Time Tuning\" toggle is enabled."),
|
||||
)
|
||||
self._torque_prams_override_toggle = toggle_item_sp(
|
||||
param="TorqueParamsOverrideEnabled",
|
||||
title=lambda: tr("Manual Real-Time Tuning"),
|
||||
description=lambda: tr("Enforces the torque lateral controller to use the fixed values instead of the learned " +
|
||||
"values from Self-Tune. Enabling this toggle overrides Self-Tune values."),
|
||||
)
|
||||
self._torque_lat_accel_factor = option_item_sp(
|
||||
title=lambda: tr("Lateral Acceleration Factor"),
|
||||
param="TorqueParamsOverrideLatAccelFactor",
|
||||
description="",
|
||||
min_value=1,
|
||||
max_value=500,
|
||||
value_change_step=1,
|
||||
label_callback=(lambda x: f"{x/100} m/s^2"),
|
||||
use_float_scaling=True
|
||||
)
|
||||
|
||||
self._torque_friction = option_item_sp(
|
||||
title=lambda: tr("Friction"),
|
||||
param="TorqueParamsOverrideFriction",
|
||||
description="",
|
||||
min_value=1,
|
||||
max_value=100,
|
||||
value_change_step=1,
|
||||
label_callback=(lambda x: f"{x/100}"),
|
||||
use_float_scaling=True
|
||||
)
|
||||
|
||||
items = [
|
||||
self._self_tune_toggle,
|
||||
self._relaxed_tune_toggle,
|
||||
self._custom_tune_toggle,
|
||||
self._torque_prams_override_toggle,
|
||||
self._torque_lat_accel_factor,
|
||||
self._torque_friction,
|
||||
]
|
||||
return items
|
||||
|
||||
def _update_state(self):
|
||||
super()._update_state()
|
||||
if not ui_state.params.get_bool("LiveTorqueParamsToggle"):
|
||||
ui_state.params.remove("LiveTorqueParamsRelaxedToggle")
|
||||
self._relaxed_tune_toggle.action_item.set_state(False)
|
||||
self._self_tune_toggle.action_item.set_enabled(ui_state.is_offroad())
|
||||
self._relaxed_tune_toggle.action_item.set_enabled(ui_state.is_offroad() and self._self_tune_toggle.action_item.get_state())
|
||||
self._custom_tune_toggle.action_item.set_enabled(ui_state.is_offroad())
|
||||
custom_tune_enabled = self._custom_tune_toggle.action_item.get_state()
|
||||
self._torque_prams_override_toggle.set_visible(custom_tune_enabled)
|
||||
self._torque_lat_accel_factor.set_visible(custom_tune_enabled)
|
||||
self._torque_friction.set_visible(custom_tune_enabled)
|
||||
|
||||
self._torque_prams_override_toggle.action_item.set_enabled(ui_state.is_offroad())
|
||||
sliders_enabled = self._torque_prams_override_toggle.action_item.get_state() or ui_state.is_offroad()
|
||||
self._torque_lat_accel_factor.action_item.set_enabled(sliders_enabled)
|
||||
self._torque_friction.action_item.set_enabled(sliders_enabled)
|
||||
|
||||
title_text = tr("Real-Time & Offline") if ui_state.params.get("TorqueParamsOverrideEnabled") else tr("Offline Only")
|
||||
self._torque_lat_accel_factor.set_title(lambda: tr("Lateral Acceleration Factor") + " (" + title_text + ")")
|
||||
self._torque_friction.set_title(lambda: tr("Friction") + " (" + title_text + ")")
|
||||
|
||||
def _render(self, rect):
|
||||
self._back_button.set_position(self._rect.x, self._rect.y + 20)
|
||||
self._back_button.render()
|
||||
# subtract button
|
||||
content_rect = rl.Rectangle(rect.x, rect.y + self._back_button.rect.height + 40, rect.width, rect.height - self._back_button.rect.height - 40)
|
||||
self._scroller.render(content_rect)
|
||||
|
||||
def show_event(self):
|
||||
self._scroller.show_event()
|
||||
Reference in New Issue
Block a user