Compare commits

..

21 Commits

Author SHA1 Message Date
royjr 714904ebd9 Merge branch 'master' into visuals-hide-camera 2026-06-30 21:35:52 -04:00
royjr 2ac48084a8 Merge branch 'master' into visuals-hide-camera 2026-06-09 11:45:28 -04:00
royjr 978366d817 Merge branch 'master' into visuals-hide-camera 2026-06-08 23:54:39 -04:00
royjr e97dd7f9cd Merge branch 'master' into visuals-hide-camera 2026-06-08 23:45:45 -04:00
royjr d3c05b2ef8 yaml 2026-06-08 23:45:28 -04:00
royjr 74f4f0f10e Merge branch 'master' into visuals-hide-camera 2026-06-08 23:23:11 -04:00
royjr 0491242b4a Merge branch 'master' into visuals-hide-camera 2026-03-15 15:14:12 -04:00
royjr 1b89608ccc Merge branch 'master' into visuals-hide-camera 2026-03-02 02:42:15 -05:00
royjr 53a24655d2 move to visuals 2026-02-13 22:18:08 -05:00
royjr c9f92a8c76 no mici toggle 2026-02-13 22:11:36 -05:00
royjr 10b1d673c9 Apply description suggestion from @sunnyhaibin
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-13 22:10:02 -05:00
Jason Wen 7080167daf Merge branch 'master' into visuals-hide-camera 2026-02-13 17:03:34 -05:00
Jason Wen c7a1c70504 Merge remote-tracking branch 'sunnypilot/sunnypilot/master' into visuals-hide-camera
# Conflicts:
#	selfdrive/ui/sunnypilot/ui_state.py
2026-02-13 16:55:01 -05:00
royjr c6a6caf6ff Merge branch 'master' into visuals-hide-camera 2026-02-05 00:52:57 -05:00
royjr 8d49a44f52 Merge branch 'master' into visuals-hide-camera 2025-12-31 15:09:29 -05:00
royjr 3434ca9d3e bool 2025-12-31 14:19:32 -05:00
royjr e4f8a5edd1 Update params_keys.h 2025-12-29 14:45:47 -05:00
royjr 1f4f9bd4bd big ui 2025-12-29 02:00:42 -05:00
royjr 455e730c4c simpler 2025-12-29 01:53:12 -05:00
royjr b243d4e356 fix param 2025-12-29 01:12:00 -05:00
royjr de0550d47b init 2025-12-29 01:06:47 -05:00
9 changed files with 22 additions and 243 deletions
+1
View File
@@ -54,6 +54,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"GsmRoaming", {PERSISTENT | BACKUP, BOOL}},
{"HardwareSerial", {PERSISTENT, STRING}},
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
{"HideCamera", {PERSISTENT | BACKUP, BOOL, "0"}},
{"InstallDate", {PERSISTENT, TIME}},
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
{"IsEngaged", {PERSISTENT, BOOL}},
@@ -213,6 +213,8 @@ class AugmentedRoadView(CameraView):
# Render the base camera view
super()._render(self._content_rect)
if ui_state.hide_camera:
rl.draw_rectangle_rec(self._content_rect, rl.BLACK)
# Draw all UI overlays
self._model_renderer.render(self._content_rect)
@@ -86,6 +86,8 @@ class AugmentedRoadView(CameraView, AugmentedRoadViewSP):
# Render the base camera view
super()._render(rect)
if ui_state.hide_camera:
rl.draw_rectangle_rec(self._content_rect, rl.BLACK)
# Draw all UI overlays
self.model_renderer.render(self._content_rect)
@@ -93,6 +93,11 @@ class VisualsLayout(Widget):
"This displays what the car is currently doing, not what the planner is requesting."),
None,
),
"HideCamera": (
lambda: tr("Hide Camera"),
tr("Hide the camera live view from the driving screen."),
None,
),
}
self._toggles = {}
for param, (title, desc, callback) in self._toggle_defs.items():
+1
View File
@@ -150,6 +150,7 @@ class UIStateSP:
self.chevron_metrics = self.params.get("ChevronInfo")
self.custom_interactive_timeout = self.params.get("InteractivityTimeout", return_default=True)
self.developer_ui = self.params.get("DevUIInfo")
self.hide_camera = self.params.get_bool("HideCamera")
self.hide_v_ego_ui = self.params.get_bool("HideVEgoUI")
self.onroad_brightness = int(float(self.params.get("OnroadScreenOffBrightness", return_default=True)))
self.onroad_brightness_timer_param = self.params.get("OnroadScreenOffTimer", return_default=True)
+1 -1
View File
@@ -69,7 +69,7 @@ class ModularAssistiveDrivingSystem:
return False
def should_silent_lkas_enable(self, CS: structs.CarState) -> bool:
if self.steering_mode_on_brake == MadsSteeringModeOnBrake.PAUSE and (CS.brakePressed or CS.regenBraking or self.pedal_pressed_non_gas_pressed(CS)):
if self.steering_mode_on_brake == MadsSteeringModeOnBrake.PAUSE and self.pedal_pressed_non_gas_pressed(CS):
return False
if self.events_sp.contains_in_list(GEARS_ALLOW_PAUSED_SILENT):
@@ -1,242 +0,0 @@
"""
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.
"""
import pytest
from cereal import log, custom
from opendbc.car import structs
from openpilot.selfdrive.selfdrived.events import Events
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
EventName = log.OnroadEvent.EventName
EventNameSP = custom.OnroadEventSP.EventName
SafetyModel = structs.CarParams.SafetyModel
def make_car_state(brake_pressed=False, regen_braking=False, standstill=False, v_ego=0.0):
cs = structs.CarState()
cs.brakePressed = brake_pressed
cs.regenBraking = regen_braking
cs.standstill = standstill
cs.vEgo = v_ego
cs.cruiseState.available = True
return cs
def make_panda_state(mocker, controls_allowed_lateral=True):
ps = mocker.MagicMock()
ps.controlsAllowedLateral = controls_allowed_lateral
ps.safetyModel = SafetyModel.hyundai
return ps
def make_mads(mocker, steering_mode):
sd = mocker.MagicMock()
sd.CP = structs.CarParams()
sd.CP.brand = "hyundai"
sd.CP_SP = structs.CarParamsSP()
sd.params = mocker.MagicMock()
sd.params.get_bool = mocker.MagicMock(side_effect=lambda k: {
"Mads": True, "MadsMainCruiseAllowed": False,
"DisengageOnAccelerator": True, "MadsUnifiedEngagementMode": False,
}.get(k, False))
sd.params.get = mocker.MagicMock(return_value=steering_mode)
sd.events = Events()
sd.events_sp = EventsSP()
sd.enabled = False
sd.enabled_prev = False
sd.initialized = True
sd.CS_prev = make_car_state()
sd.sm = {'pandaStates': [make_panda_state(mocker)]}
sd.state_machine = mocker.MagicMock()
mads = ModularAssistiveDrivingSystem(sd)
mads.enabled_toggle = True
mads.steering_mode_on_brake = steering_mode
return mads, sd
def run_frames(mads, sd, cs, n=1):
for _ in range(n):
mads.update(cs)
sd.CS_prev = cs
sd.events.clear()
sd.events_sp.clear()
# should_silent_lkas_enable across all modes
class TestShouldSilentLkasEnable:
@pytest.mark.parametrize("brake,regen", [(True, False), (False, True)])
def test_pause_blocks_reenable_on_braking_at_standstill(self, mocker, brake, regen):
mads, _ = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
cs = make_car_state(brake_pressed=brake, regen_braking=regen, standstill=True)
assert mads.should_silent_lkas_enable(cs) is False
def test_pause_allows_reenable_on_brake_release(self, mocker):
mads, _ = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
cs = make_car_state(standstill=True)
assert mads.should_silent_lkas_enable(cs) is True
def test_remain_active_ignores_brake(self, mocker):
mads, _ = make_mads(mocker, MadsSteeringModeOnBrake.REMAIN_ACTIVE)
cs = make_car_state(brake_pressed=True, standstill=True)
assert mads.should_silent_lkas_enable(cs) is True
def test_disengage_ignores_brake_for_silent_enable(self, mocker):
mads, _ = make_mads(mocker, MadsSteeringModeOnBrake.DISENGAGE)
cs = make_car_state(brake_pressed=True, standstill=True)
assert mads.should_silent_lkas_enable(cs) is True
# pause
class TestPauseMode:
def test_stays_paused_at_standstill_brake_held(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
mads.state_machine.state = State.enabled
mads.enabled = True
mads.active = True
sd.events.add(EventName.pedalPressed)
run_frames(mads, sd, make_car_state(brake_pressed=True, v_ego=15.0))
assert mads.state_machine.state == State.paused
sd.sm['pandaStates'] = [make_panda_state(mocker, False)]
run_frames(mads, sd, make_car_state(brake_pressed=True, standstill=True), n=250)
assert mads.state_machine.state == State.paused
def test_resumes_on_brake_release_at_standstill(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
mads.state_machine.state = State.paused
mads.enabled = True
mads.active = False
run_frames(mads, sd, make_car_state(standstill=True))
assert mads.state_machine.state == State.enabled
def test_full_cycle_moving_to_standstill(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
mads.state_machine.state = State.enabled
mads.enabled = True
mads.active = True
sd.events.add(EventName.pedalPressed)
run_frames(mads, sd, make_car_state(brake_pressed=True, v_ego=15.0))
assert mads.state_machine.state == State.paused
sd.sm['pandaStates'] = [make_panda_state(mocker, False)]
run_frames(mads, sd, make_car_state(brake_pressed=True, standstill=True), n=250)
assert mads.state_machine.state == State.paused
sd.sm['pandaStates'] = [make_panda_state(mocker, True)]
run_frames(mads, sd, make_car_state(standstill=True))
assert mads.state_machine.state == State.enabled
# disengage
class TestDisengageMode:
def test_brake_while_enabled_disables(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.DISENGAGE)
mads.state_machine.state = State.enabled
mads.enabled = True
mads.active = True
sd.events.add(EventName.pedalPressed)
run_frames(mads, sd, make_car_state(brake_pressed=True, v_ego=10.0))
assert mads.state_machine.state == State.disabled
def test_brake_sends_lkas_disable_when_enabled(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.DISENGAGE)
mads.state_machine.state = State.enabled
mads.enabled = True
mads.active = True
sd.events.add(EventName.pedalPressed)
mads.update_events(make_car_state(brake_pressed=True, v_ego=5.0))
assert sd.events_sp.has(EventNameSP.lkasDisable)
# remain active
class TestRemainActiveMode:
def test_brake_does_not_pause_or_disable(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.REMAIN_ACTIVE)
mads.state_machine.state = State.enabled
mads.enabled = True
mads.active = True
sd.events.add(EventName.pedalPressed)
run_frames(mads, sd, make_car_state(brake_pressed=True, v_ego=10.0))
assert mads.state_machine.state == State.enabled
# lateral mismatch counter
class TestLateralMismatchCounter:
def test_no_accumulation_while_paused(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
mads.state_machine.state = State.paused
mads.enabled = True
mads.active = False
sd.sm['pandaStates'] = [make_panda_state(mocker, False)]
run_frames(mads, sd, make_car_state(brake_pressed=True, standstill=True), n=250)
assert mads.lateral_mismatch_counter == 0
def test_accumulates_when_active_and_panda_disagrees(self, mocker):
mads, sd = make_mads(mocker, MadsSteeringModeOnBrake.PAUSE)
mads.enabled = True
mads.active = True
sd.sm['pandaStates'] = [make_panda_state(mocker, False)]
for _ in range(200):
mads.data_sample()
assert mads.lateral_mismatch_counter == 200
# brand restrictions
class TestBrandSteeringModeRestrictions:
def test_rivian_forced_to_disengage(self, mocker):
CP = structs.CarParams()
CP.brand = "rivian"
CP_SP = structs.CarParamsSP()
params = mocker.MagicMock()
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
params.get.assert_not_called()
def test_tesla_without_vehicle_bus_forced_to_disengage(self, mocker):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = 0
params = mocker.MagicMock()
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
def test_tesla_with_vehicle_bus_uses_param(self, mocker):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
params = mocker.MagicMock()
params.get = mocker.MagicMock(return_value=MadsSteeringModeOnBrake.REMAIN_ACTIVE)
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
@pytest.mark.parametrize("brand", ["hyundai", "toyota", "honda", "gm"])
def test_other_brands_use_param(self, mocker, brand):
CP = structs.CarParams()
CP.brand = brand
CP_SP = structs.CarParamsSP()
params = mocker.MagicMock()
params.get = mocker.MagicMock(return_value=MadsSteeringModeOnBrake.REMAIN_ACTIVE)
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
+6
View File
@@ -1296,6 +1296,12 @@
"title": "Display Turn Signals",
"description": "When enabled, visual turn indicators are drawn on the HUD."
},
{
"key": "HideCamera",
"widget": "toggle",
"title": "Hide Camera",
"description": "Hide the camera live view from the driving screen."
},
{
"key": "RoadNameToggle",
"widget": "toggle",
@@ -24,6 +24,10 @@ sections:
widget: toggle
title: Display Turn Signals
description: When enabled, visual turn indicators are drawn on the HUD.
- key: HideCamera
widget: toggle
title: Hide Camera
description: Hide the camera live view from the driving screen.
- key: RoadNameToggle
widget: toggle
title: Display Road Name