From 3bba2f5f4f0def03ea790c0b2fd303c9bb9ea3ee Mon Sep 17 00:00:00 2001 From: Comma Device Date: Sun, 26 Apr 2026 04:50:22 +0000 Subject: [PATCH 1/2] Add minimal driving view toggle (hide camera feed) --- common/params_keys.h | 1 + selfdrive/ui/bp/layouts/settings/bluepilot.py | 9 +++++ .../ui/bp/mici/layouts/settings/bluepilot.py | 1 + selfdrive/ui/onroad/cameraview.py | 33 ++++++++++++------- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/common/params_keys.h b/common/params_keys.h index 90631a79db..34a98c901a 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -16,6 +16,7 @@ inline static std::unordered_map keys = { {"AthenadUploadQueue", {PERSISTENT, JSON}}, {"AthenadRecentlyViewedRoutes", {PERSISTENT, STRING}}, {"BootCount", {PERSISTENT, INT}}, + {"BPHideCameraView", {PERSISTENT, BOOL}}, {"CalibrationParams", {PERSISTENT, BYTES}}, {"CameraDebugExpGain", {CLEAR_ON_MANAGER_START, STRING}}, {"CameraDebugExpTime", {CLEAR_ON_MANAGER_START, STRING}}, diff --git a/selfdrive/ui/bp/layouts/settings/bluepilot.py b/selfdrive/ui/bp/layouts/settings/bluepilot.py index 803374f7ee..f75067bc6a 100644 --- a/selfdrive/ui/bp/layouts/settings/bluepilot.py +++ b/selfdrive/ui/bp/layouts/settings/bluepilot.py @@ -125,6 +125,14 @@ def _initialize_items(self): callback=lambda state: self._toggle_callback(state, "BPHideOnroadBorder"), icon="warning.png" ) + #Toggle Minimal Driving View + self._hide_camera_view = toggle_item( + lambda: tr("Minimal Driving View"), + lambda: tr("Hide camera feed and show lane lines only."), + initial_state=self._safe_get_bool(self._params, "BPHideCameraView"), + callback=lambda state: self._toggle_callback(state, "BPHideCameraView"), + icon="chffr_wheel.png" +) # Show confidence ball toggle self._show_confidence_ball = toggle_item( @@ -418,6 +426,7 @@ def _initialize_items(self): self._vbatt_pause_charging, SectionHeader(tr("Visuals")), self._hide_onroad_border, + self._hide_camera_view, self._disable_lane_line_status_color, self._show_blindspot, self._show_brake_status, diff --git a/selfdrive/ui/bp/mici/layouts/settings/bluepilot.py b/selfdrive/ui/bp/mici/layouts/settings/bluepilot.py index a80e39ae32..5d1e371c33 100644 --- a/selfdrive/ui/bp/mici/layouts/settings/bluepilot.py +++ b/selfdrive/ui/bp/mici/layouts/settings/bluepilot.py @@ -45,6 +45,7 @@ def __init__(self, back_callback: Callable): self.show_brake_status = BigParamControlBP("show brake status", "ShowBrakeStatus") self.show_blindspot_ui = BigParamControlBP("show blindspot overlay", "ShowBlindspotOverlay") self.rainbow_mode = BigParamControlBP("rainbow mode", "RainbowMode") + self.hide_camera_view = BigParamControlBP("minimal driving view (hide camera)", "BPHideCameraView") self.enable_human_turn_detection = BigParamControlBP("enable human turn detection", "enable_human_turn_detection") self.lane_change_factor_high = BigParamFloatControl("lane change factor high", "lane_change_factor_high", min=0.5, max=1.0) self.enable_lane_positioning = BigParamControlBP("enable lane positioning", "enable_lane_positioning", tint=rl.GREEN) diff --git a/selfdrive/ui/onroad/cameraview.py b/selfdrive/ui/onroad/cameraview.py index 5443948465..aff450ab90 100644 --- a/selfdrive/ui/onroad/cameraview.py +++ b/selfdrive/ui/onroad/cameraview.py @@ -9,6 +9,12 @@ from openpilot.system.ui.lib.egl import init_egl, create_egl_image, destroy_egl_image, bind_egl_image_to_texture, EGLImage from openpilot.system.ui.widgets import Widget from openpilot.selfdrive.ui.ui_state import ui_state +from openpilot.common.params import Params +params = Params() +try: + hide_camera = params.get_bool("BPHideCameraView") +except Exception: + hide_camera = False CONNECTION_RETRY_INTERVAL = 0.2 # seconds between connection attempts @@ -220,16 +226,18 @@ def _render(self, rect: rl.Rectangle): dst_rect = rl.Rectangle(x_offset, y_offset, scale_x, scale_y) # Render with appropriate method + if hide_camera: + rl.draw_rectangle_rec(rect, rl.BLACK) if TICI: - self._render_egl(src_rect, dst_rect) + self._render_egl(src_rect, dst_rect, hide_camera) else: - self._render_textures(src_rect, dst_rect) + self._render_textures(src_rect, dst_rect, hide_camera) def _draw_placeholder(self, rect: rl.Rectangle): if self._placeholder_color: rl.draw_rectangle_rec(rect, self._placeholder_color) - def _render_egl(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> None: + def _render_egl(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle, hide_camera) -> None: """Render using EGL for direct buffer access""" if self.frame is None or self.egl_texture is None: return @@ -253,11 +261,11 @@ def _render_egl(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> None: bind_egl_image_to_texture(self.egl_texture.id, egl_image) # Render with shader - rl.begin_shader_mode(self.shader) - rl.draw_texture_pro(self.egl_texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) - rl.end_shader_mode() - - def _render_textures(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> None: + if not hide_camera: + rl.begin_shader_mode(self.shader) + rl.draw_texture_pro(self.egl_texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) + rl.end_shader_mode() + def _render_textures(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle, hide_camera) -> None: """Render using texture copies""" if not self.texture_y or not self.texture_uv or self.frame is None: return @@ -272,10 +280,11 @@ def _render_textures(self, src_rect: rl.Rectangle, dst_rect: rl.Rectangle) -> No self._texture_needs_update = False # Render with shader - rl.begin_shader_mode(self.shader) - rl.set_shader_value_texture(self.shader, self._texture1_loc, self.texture_uv) - rl.draw_texture_pro(self.texture_y, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) - rl.end_shader_mode() + if not hide_camera: + rl.begin_shader_mode(self.shader) + rl.set_shader_value_texture(self.shader, self._texture1_loc, self.texture_uv) + rl.draw_texture_pro(self.texture_y, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE) + rl.end_shader_mode() def _ensure_connection(self) -> bool: if not self.client.is_connected(): From aa800db0ffba42d09528a5dd219f426c7860c518 Mon Sep 17 00:00:00 2001 From: Comma Device Date: Sun, 26 Apr 2026 23:43:18 +0000 Subject: [PATCH 2/2] Make camera toggle update in real-time without requiring reboot --- selfdrive/ui/onroad/cameraview.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/selfdrive/ui/onroad/cameraview.py b/selfdrive/ui/onroad/cameraview.py index aff450ab90..8f87098e8d 100644 --- a/selfdrive/ui/onroad/cameraview.py +++ b/selfdrive/ui/onroad/cameraview.py @@ -10,11 +10,6 @@ from openpilot.system.ui.widgets import Widget from openpilot.selfdrive.ui.ui_state import ui_state from openpilot.common.params import Params -params = Params() -try: - hide_camera = params.get_bool("BPHideCameraView") -except Exception: - hide_camera = False CONNECTION_RETRY_INTERVAL = 0.2 # seconds between connection attempts @@ -73,6 +68,7 @@ class CameraView(Widget): def __init__(self, name: str, stream_type: VisionStreamType): + self.params = Params() super().__init__() self._name = name # Primary stream @@ -224,10 +220,13 @@ def _render(self, rect: rl.Rectangle): y_offset += transform[1, 2] * rect.height / 2 dst_rect = rl.Rectangle(x_offset, y_offset, scale_x, scale_y) - + + #Read Param Live Every Frame + hide_camera = self.params.get_bool("BPHideCameraView") # Render with appropriate method if hide_camera: rl.draw_rectangle_rec(rect, rl.BLACK) + return if TICI: self._render_egl(src_rect, dst_rect, hide_camera) else: