This commit is contained in:
firestar5683
2026-10-29 22:13:23 -05:00
parent 77babc4c85
commit 16f31abd75
7 changed files with 75 additions and 5 deletions
@@ -8,6 +8,8 @@ from openpilot.system.ui.lib.multilang import tr, tr_noop
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.selfdrive.ui.layouts.settings.initial_cruise_speed import InitialCruiseSpeedControl
from openpilot.starpilot.ui.slc_offset_feature import SlcOffsetOwner, native_parked
from openpilot.starpilot.galaxy.localization_settings import LocalizationSettingsOwner
from openpilot.starpilot.ui.feature_settings_state import FeatureSettingsRequest
PERSONALITY_TO_INT = log.LongitudinalPersonality.schema.enumerants
@@ -38,6 +40,7 @@ class TogglesLayout(Widget):
def __init__(self):
super().__init__()
self._params = Params()
self._localization = LocalizationSettingsOwner(self._params, lambda: True, lambda: native_parked(ui_state))
self._slc_offsets = SlcOffsetOwner(self._params, lambda: native_parked(ui_state), lambda: ui_state.CP)
self._metric_source = self._slc_offsets._raw("IsMetric")
self._is_release = self._params.get_bool("IsReleaseBranch")
@@ -74,6 +77,12 @@ class TogglesLayout(Widget):
"monitoring.png",
False,
),
"IsRhdDetected": (
lambda: tr("Right Hand Driving"),
"Select the right-hand driver-monitoring side for the next drive. Off selects left-hand. Automatic side detection continues. Park and close driver camera preview before changing.",
"monitoring.png",
False,
),
"RecordFront": (
lambda: tr("Record and Upload Cabin Camera"),
DESCRIPTIONS["RecordFront"],
@@ -211,6 +220,9 @@ class TogglesLayout(Widget):
for toggle_def in self._toggle_defs:
if self._toggle_defs[toggle_def][3] and toggle_def not in self._locked_toggles:
self._toggles[toggle_def].action_item.set_enabled(not ui_state.engaged)
row = self._localization.snapshot().rows[1]
self._rhd_source = row.source
self._toggles["IsRhdDetected"].action_item.set_enabled(row.available and "IsRhdDetected" not in self._locked_toggles)
def _render(self, rect):
self._scroller.render(rect)
@@ -221,6 +233,10 @@ class TogglesLayout(Widget):
def _toggle_callback(self, state: bool, param: str):
if param == "IsRhdDetected":
ok = self._localization.apply(FeatureSettingsRequest(param, self._rhd_source, "On" if state else "Off"))
self._update_toggles()
return ok
if param == "IsMetric":
ok = self._slc_offsets.change_units(state, self._metric_source)
self._toggles[param].action_item.set_state(self._params.get_bool(param))
@@ -7,6 +7,8 @@ from openpilot.selfdrive.ui.layouts.settings.common import restart_needed_callba
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.selfdrive.ui.mici.layouts.settings.initial_cruise_speed import InitialCruiseSpeedButton
from openpilot.starpilot.ui.slc_offset_feature import SlcOffsetOwner, native_parked
from openpilot.starpilot.galaxy.localization_settings import LocalizationSettingsOwner
from openpilot.starpilot.ui.feature_settings_state import FeatureSettingsRequest
PERSONALITY_TO_INT = log.LongitudinalPersonality.schema.enumerants
@@ -18,6 +20,12 @@ class TogglesLayoutMici(NavScroller):
super().__init__()
self._slc_offsets = SlcOffsetOwner(ui_state.params, lambda: native_parked(ui_state), lambda: ui_state.CP)
self._metric_source = self._slc_offsets._raw("IsMetric")
self._localization = LocalizationSettingsOwner(ui_state.params, lambda: True, lambda: native_parked(ui_state))
self._rhd_source = self._slc_offsets._raw("IsRhdDetected")
self._rhd_toggle = BigToggle("right hand driving", initial_state=ui_state.params.get_bool("IsRhdDetected"),
toggle_callback=self._on_rhd,
description="On selects right-hand; Off selects left-hand for the next drive. Automatic side detection continues.")
self._rhd_toggle.set_enabled(lambda: self._localization.snapshot().rows[1].available)
self._personality_toggle = BigMultiParamToggle("driving personality", "LongitudinalPersonality", ["aggressive", "standard", "relaxed"],
description="Standard is recommended.\n" +
@@ -60,6 +68,7 @@ class TogglesLayoutMici(NavScroller):
is_metric_toggle,
ldw_toggle,
always_on_dm_toggle,
self._rhd_toggle,
record_front,
record_mic,
enable_openpilot,
@@ -72,6 +81,7 @@ class TogglesLayoutMici(NavScroller):
("IsMetric", is_metric_toggle),
("IsLdwEnabled", ldw_toggle),
("AlwaysOnDM", always_on_dm_toggle),
("IsRhdDetected", self._rhd_toggle),
("RecordFront", record_front),
("RecordAudio", record_mic),
("OpenpilotEnabledToggle", enable_openpilot),
@@ -131,6 +141,7 @@ class TogglesLayoutMici(NavScroller):
for key, item in self._refresh_toggles:
item.set_checked(ui_state.params.get_bool(key))
self._metric_source = self._slc_offsets._raw("IsMetric")
self._rhd_source = self._slc_offsets._raw("IsRhdDetected")
def _on_metric(self, desired: bool) -> None:
self._slc_offsets.change_units(desired, self._metric_source)
@@ -138,6 +149,11 @@ class TogglesLayoutMici(NavScroller):
self._metric_toggle.set_checked(ui_state.params.get_bool("IsMetric"))
self._update_toggles()
def _on_rhd(self, desired: bool) -> None:
self._localization.apply(FeatureSettingsRequest("IsRhdDetected", self._rhd_source, "On" if desired else "Off"))
self._rhd_source = self._localization.snapshot().rows[1].source
self._rhd_toggle.set_checked(ui_state.params.get_bool("IsRhdDetected"))
def _on_record_audio(self, desired: bool) -> None:
# Keep filesystem waits off the UI thread, and persist the preference before
# publishing the restart request through the same Params writer queue.
+1 -2
View File
@@ -1829,7 +1829,6 @@ class StarMainLayout(MainLayout):
device_scroller._items.insert(1, device_scroller._items.pop())
toggle_items = self._large_panels[Destination.TOGGLES]._scroller._items
toggle_items.insert(2, text_item("Safe Mode", "N/A"))
toggle_items.insert(7, text_item("Right Hand Driving", "N/A"))
from openpilot.common.hardware import HARDWARE
from openpilot.starpilot.ui.starpilot_settings_adapter_large import StarPilotSettingsAdapterLarge
for destination, owner in self._large_panels.items():
@@ -1941,7 +1940,7 @@ class StarMainLayout(MainLayout):
return False
param = {ToggleKey.ENABLED: "OpenpilotEnabledToggle", ToggleKey.EXPERIMENTAL: "ExperimentalMode",
ToggleKey.DISENGAGE_ACCELERATOR: "DisengageOnAccelerator", ToggleKey.LANE_DEPARTURE: "IsLdwEnabled",
ToggleKey.ALWAYS_ON_DM: "AlwaysOnDM", ToggleKey.RECORD_FRONT: "RecordFront",
ToggleKey.ALWAYS_ON_DM: "AlwaysOnDM", ToggleKey.RIGHT_HAND_DRIVING: "IsRhdDetected", ToggleKey.RECORD_FRONT: "RecordFront",
ToggleKey.RECORD_AUDIO: "RecordAudio", ToggleKey.METRIC: "IsMetric"}.get(request.key)
return bool(param is not None and owner.request_toggle(param, request.value))
+5 -2
View File
@@ -822,9 +822,12 @@ class RuntimeSnapshotAdapter:
toggles = TogglesState(enabled=_flag(params, "OpenpilotEnabledToggle"),
experimental=experimental, disengage_accelerator=_flag(params, "DisengageOnAccelerator"),
lane_departure=_flag(params, "IsLdwEnabled"),
always_on_dm=_flag(params, "AlwaysOnDM"), record_front=_flag(params, "RecordFront"),
always_on_dm=_flag(params, "AlwaysOnDM"), right_hand_driving=_flag(params, "IsRhdDetected"),
record_front=_flag(params, "RecordFront"),
record_audio=_flag(params, "RecordAudio"), metric=bool(ui.is_metric), personality=persona,
unavailable=frozenset((ToggleKey.SAFE_MODE, ToggleKey.RIGHT_HAND_DRIVING)))
unavailable=frozenset((ToggleKey.SAFE_MODE,)) | (
frozenset() if confirmed_offroad and not _flag(params, "IsDriverViewEnabled") else
frozenset((ToggleKey.RIGHT_HAND_DRIVING,))))
snapshot = ShellSnapshot(mode, home, settings, onroad, device_state, software, toggles, selected)
if mode == ShellMode.ONROAD:
self._onroad_ancillary = (now_ns, ancillary_key, snapshot)
@@ -62,6 +62,21 @@ class TestC4AudioToggle(unittest.TestCase):
self.panel = toggles.TogglesLayoutMici()
self.audio = next(item for key, item in self.panel._refresh_toggles if key == "RecordAudio")
def test_rhd_control_saves_shared_param_and_rejects_open_preview(self):
from openpilot.starpilot.galaxy.localization_settings import LocalizationSettingsOwner
self.panel._localization = LocalizationSettingsOwner(self.params, lambda: True, lambda: True)
for desired in (True, False):
self.panel._rhd_source = self.panel._localization.snapshot().rows[1].source
self.panel._on_rhd(desired)
self.assertEqual(self.params.get_bool('IsRhdDetected'), desired)
self.assertTrue(self.params.get_bool('OnroadCycleRequested'))
self.assertEqual(self.panel._rhd_toggle._checked, desired)
self.params.put_bool('OnroadCycleRequested', False, block=True)
self.params.put_bool('IsDriverViewEnabled', True, block=True)
self.panel._on_rhd(True)
self.assertFalse(self.params.get_bool('IsRhdDetected'))
self.assertFalse(self.params.get_bool('OnroadCycleRequested'))
def test_release_queues_audio_before_restart_without_blocking_writes(self):
with patch.object(self.params, "put_bool") as save:
self.audio._handle_mouse_release(MousePos(0, 0))
@@ -222,7 +222,8 @@ class NativeSettingsTests(unittest.TestCase):
self.assertIs(layout._large_panels[Destination.SOFTWARE].panel, self.software)
self.assertIs(layout._large_panels[Destination.TOGGLES].panel, toggles)
self.assertEqual(toggles._scroller._items[2].title, 'Safe Mode')
self.assertEqual(toggles._scroller._items[7].title, 'Right Hand Driving')
self.assertFalse(any(item.title == 'Right Hand Driving' for item in toggles._scroller._items),
'RHD belongs to the native toggle owner, not an inserted N/A placeholder')
self.assertEqual(self.device._scroller._items[0].title, 'Galaxy')
self.assertNotIn(self.device._power_off_btn, self.device._scroller._items)
self.assertEqual(session.system_power_action, layout._system_power_action)
@@ -71,6 +71,26 @@ class TestCompactSettingsNavigation(unittest.TestCase):
class TestExistingToggleOwner(unittest.TestCase):
def test_rhd_toggle_saves_through_shared_owner_and_requests_next_drive(self):
from openpilot.starpilot.galaxy.localization_settings import LocalizationSettingsOwner
with tempfile.TemporaryDirectory() as directory:
params = Params(directory)
owner = TogglesLayout.__new__(TogglesLayout)
owner._params = params
owner._localization = LocalizationSettingsOwner(params, lambda: True, lambda: True)
with patch.object(owner, '_update_toggles'):
for enabled in (True, False):
owner._rhd_source = owner._localization.snapshot().rows[1].source
self.assertTrue(owner._toggle_callback(enabled, 'IsRhdDetected'))
self.assertEqual(params.get_bool('IsRhdDetected'), enabled)
self.assertTrue(params.get_bool('OnroadCycleRequested'))
params.put_bool('OnroadCycleRequested', False, block=True)
params.put_bool('IsDriverViewEnabled', True, block=True)
owner._rhd_source = b'0'
self.assertFalse(owner._toggle_callback(True, 'IsRhdDetected'))
self.assertFalse(params.get_bool('IsRhdDetected'))
self.assertFalse(params.get_bool('OnroadCycleRequested'))
def test_personality_no_op_uses_typed_integer_value(self):
owner = TogglesLayout.__new__(TogglesLayout)
owner._long_personality_setting = NS(action_item=NS(enabled=True))