[MICI] ui: always offroad (#1695)

* always offroad ui

* remove

* lint

* better

* fix sync issues

* fix sync issues

* update for upstream sync

* move it all to top settings panel

* not red

* no home screen, just buttons

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
This commit is contained in:
Nayan
2026-04-14 23:36:06 -04:00
committed by GitHub
parent 3509fccec7
commit 61915eb914
5 changed files with 65 additions and 2 deletions
-1
View File
@@ -13,7 +13,6 @@ from openpilot.system.ui.lib.application import gui_app
if gui_app.sunnypilot_ui():
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.settings import SettingsLayoutSP as SettingsLayout
ONROAD_DELAY = 2.5 # seconds
@@ -5,18 +5,32 @@ 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.selfdrive.ui.mici.layouts.settings import settings as OP
from openpilot.selfdrive.ui.mici.widgets.button import BigButton
from openpilot.selfdrive.ui.mici.layouts.settings.device import DeviceLayoutMici
from openpilot.selfdrive.ui.mici.widgets.button import BigButton, BigCircleButton
from openpilot.selfdrive.ui.mici.widgets.dialog import BigConfirmationDialog, BigDialog
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.sunnylink import SunnylinkLayoutMici
from openpilot.selfdrive.ui.sunnypilot.mici.layouts.models import ModelsLayoutMici
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.multilang import tr
ICON_SIZE = 70
BIG_ICON_SIZE = 110
class SettingsLayoutSP(OP.SettingsLayout):
def __init__(self):
OP.SettingsLayout.__init__(self)
device_panel = DeviceLayoutMici()
self._scroller._items[2].set_click_callback(lambda: gui_app.push_widget(device_panel))
self.icon_offroad_enable = gui_app.texture("../../sunnypilot/selfdrive/assets/icons_mici/always_offroad.png", BIG_ICON_SIZE,
BIG_ICON_SIZE)
self.icon_offroad_disable = gui_app.texture("../../sunnypilot/selfdrive/assets/icons_mici/disable_offroad.png", BIG_ICON_SIZE,
BIG_ICON_SIZE)
self.icon_offroad_slider = gui_app.texture("icons_mici/settings/device/lkas.png", BIG_ICON_SIZE, BIG_ICON_SIZE)
sunnylink_panel = SunnylinkLayoutMici(back_callback=gui_app.pop_widget)
sunnylink_btn = BigButton("sunnylink", "", gui_app.texture("icons_mici/settings/developer/ssh.png", ICON_SIZE, ICON_SIZE))
sunnylink_btn.set_click_callback(lambda: gui_app.push_widget(sunnylink_panel))
@@ -25,10 +39,53 @@ class SettingsLayoutSP(OP.SettingsLayout):
models_btn = BigButton("models", "", gui_app.texture("../../sunnypilot/selfdrive/assets/offroad/icon_models.png", ICON_SIZE, ICON_SIZE))
models_btn.set_click_callback(lambda: gui_app.push_widget(models_panel))
# onroad: enable button sits at the front (left of toggles)
self._enable_offroad_btn_onroad = BigCircleButton(self.icon_offroad_enable, red=True)
self._enable_offroad_btn_onroad.set_click_callback(lambda: self._handle_always_offroad(True))
self._enable_offroad_btn_onroad.set_visible(lambda: ui_state.started and not ui_state.always_offroad)
# offroad: enable button sits at the end (right of developer)
self._enable_offroad_btn_offroad = BigCircleButton(self.icon_offroad_enable, red=True)
self._enable_offroad_btn_offroad.set_click_callback(lambda: self._handle_always_offroad(True))
self._enable_offroad_btn_offroad.set_visible(lambda: not ui_state.started and not ui_state.always_offroad)
self._disable_offroad_btn = BigCircleButton(self.icon_offroad_disable, red=False)
self._disable_offroad_btn.set_click_callback(lambda: self._handle_always_offroad(False))
self._disable_offroad_btn.set_visible(lambda: ui_state.always_offroad)
items = self._scroller._items.copy()
items.insert(1, sunnylink_btn)
items.insert(2, models_btn)
# front slots (only one ever visible at a time): exit-always-offroad, then enable-onroad
items.insert(0, self._enable_offroad_btn_onroad)
items.insert(0, self._disable_offroad_btn)
# end slot: enable-offroad (right of developer)
items.append(self._enable_offroad_btn_offroad)
self._scroller._items.clear()
for item in items:
self._scroller.add_widget(item)
def _update_state(self):
super()._update_state()
def _handle_always_offroad(self, enable: bool):
def _set_offroad_status(status: bool):
if not ui_state.engaged:
ui_state.params.put_bool("OffroadMode", status)
ui_state.always_offroad = status
if not enable:
dlg = BigConfirmationDialog(tr("slide to exit always offroad"), self.icon_offroad_slider, red=False,
confirm_callback=lambda: _set_offroad_status(False))
else:
if ui_state.engaged:
gui_app.push_widget(BigDialog(tr("disengage to enable always offroad"), "", ))
return
dlg = BigConfirmationDialog(tr("slide to force offroad"), self.icon_offroad_slider, red=True,
confirm_callback=lambda: _set_offroad_status(True))
gui_app.push_widget(dlg)
+1
View File
@@ -146,6 +146,7 @@ class UIStateSP:
self.true_v_ego_ui = self.params.get_bool("TrueVEgoUI")
self.turn_signals = self.params.get_bool("ShowTurnSignals")
self.boot_offroad_mode = self.params.get("DeviceBootMode", return_default=True)
self.always_offroad = self.params.get_bool("OffroadMode")
class DeviceSP:
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e459241d896824f5e8207d568847acab3dedd41caae7af59d4c17e043663b0c9
size 4035
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:27a0fca872d4586f578d246890b83674cdb7ecb03f58b2b0379b4b64a5816053
size 3908