diff --git a/common/params_keys.h b/common/params_keys.h index 90631a79d..34a98c901 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 803374f7e..f75067bc6 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 a80e39ae3..5d1e371c3 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 544394846..8f87098e8 100644 --- a/selfdrive/ui/onroad/cameraview.py +++ b/selfdrive/ui/onroad/cameraview.py @@ -9,6 +9,7 @@ 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 CONNECTION_RETRY_INTERVAL = 0.2 # seconds between connection attempts @@ -67,6 +68,7 @@ class CameraView(Widget): def __init__(self, name: str, stream_type: VisionStreamType): + self.params = Params() super().__init__() self._name = name # Primary stream @@ -218,18 +220,23 @@ 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) + 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 +260,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 +279,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():