diff --git a/common/params_keys.h b/common/params_keys.h index ac8a23f3d..3c6d31645 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -517,6 +517,7 @@ inline static std::unordered_map keys = { {"PIPPreviewMask", {PERSISTENT, JSON, "{\"width\":1928,\"height\":1208,\"center_left\":[315,548],\"center_right\":[1571,539],\"crop_size\":580}", "{\"width\":1928,\"height\":1208,\"center_left\":[315,548],\"center_right\":[1571,539],\"crop_size\":580}", 2}}, {"PIPPreviewShowOnBlinker", {PERSISTENT, BOOL, "0", "0", 1}}, {"PIPPreviewShowOnBSM", {PERSISTENT, BOOL, "0", "0", 1}}, + {"PIPPreviewInvert", {PERSISTENT, BOOL, "0", "0", 1}}, {"GalaxyPaired", {PERSISTENT, BOOL, "0", "0", 0}}, {"GalaxyUploadPending", {PERSISTENT, BOOL, "0", "0", 0}}, {"PreferredSchedule", {PERSISTENT, INT, "2", "0", 0}}, diff --git a/selfdrive/ui/onroad/starpilot/pip_sidecam.py b/selfdrive/ui/onroad/starpilot/pip_sidecam.py index 1bc47a125..65dd0284d 100644 --- a/selfdrive/ui/onroad/starpilot/pip_sidecam.py +++ b/selfdrive/ui/onroad/starpilot/pip_sidecam.py @@ -266,6 +266,7 @@ class PipSideCamera(Widget): self._enabled = self._params.get_bool("PIPPreviewEnabled") and self._params.get_bool("GalaxyDeveloperMode") self._show_on_blinker = self._params.get_bool("PIPPreviewShowOnBlinker") self._show_on_bsm = self._params.get_bool("PIPPreviewShowOnBSM") + self._flip_x_value[0] = 0 if self._params.get_bool("PIPPreviewInvert") else 1 try: raw = self._params.get("PIPPreviewMask") if isinstance(raw, (bytes, str)): diff --git a/selfdrive/ui/tests/test_pip_sidecam.py b/selfdrive/ui/tests/test_pip_sidecam.py index dcdd1855a..087f7a2e7 100644 --- a/selfdrive/ui/tests/test_pip_sidecam.py +++ b/selfdrive/ui/tests/test_pip_sidecam.py @@ -29,6 +29,36 @@ def test_pip_driver_camera_shader_mirrors_the_crop(): assert "cropCoord.x = 1.0 - cropCoord.x" in PIP_FRAGMENT_SHADER +class _FakeParams: + def __init__(self, invert: bool = False): + self._invert = invert + + def get_bool(self, key: str) -> bool: + if key == "PIPPreviewInvert": + return self._invert + if key == "GalaxyDeveloperMode": + return True + return False + + def get(self, key: str): + return None + + +def test_pip_flip_value_follows_invert_param(): + camera = PipSideCamera.__new__(PipSideCamera) + camera._closed = True + camera._last_param_refresh = 0.0 + camera._flip_x_value = __import__("pyray").ffi.new("int[1]", [1]) + camera._params = _FakeParams(invert=False) + camera._mask = {} + camera._refresh_config(force=True) + assert camera._flip_x_value[0] == 1 + + camera._params = _FakeParams(invert=True) + camera._refresh_config(force=True) + assert camera._flip_x_value[0] == 0 + + def test_pip_driver_camera_shader_masks_before_sampling_and_keeps_two_texture_reads(): assert "fwidth(radius)" in PIP_FRAGMENT_SHADER assert "if (radius > 1.0 + aa)" in PIP_FRAGMENT_SHADER diff --git a/starpilot/common/assets/device_settings_layout.json b/starpilot/common/assets/device_settings_layout.json index 7ee7b669c..2d0b19230 100644 --- a/starpilot/common/assets/device_settings_layout.json +++ b/starpilot/common/assets/device_settings_layout.json @@ -2296,6 +2296,16 @@ "parent_key": "PIPPreviewEnabled", "settings_tier": "advanced" }, + { + "key": "PIPPreviewInvert", + "label": "Original Camera View", + "description": "Show the side preview exactly as the camera sees it. Leave off for the default mirrored view, which looks like a side mirror.", + "picker_description": "Shows the raw camera feed instead of the horizontally mirrored side-mirror view.", + "data_type": "bool", + "ui_type": "toggle", + "parent_key": "PIPPreviewEnabled", + "settings_tier": "advanced" + }, { "key": "Compass", "label": "Compass", diff --git a/starpilot/system/the_galaxy/tests/test_device_settings_layout.py b/starpilot/system/the_galaxy/tests/test_device_settings_layout.py index 65c832517..7c7aed58f 100644 --- a/starpilot/system/the_galaxy/tests/test_device_settings_layout.py +++ b/starpilot/system/the_galaxy/tests/test_device_settings_layout.py @@ -279,17 +279,20 @@ def test_pip_preview_is_under_driving_screen_widgets_and_configured_only_in_gala sections = _params_by_section(_layout()) visual = sections["Visual (Display & UI)"] - assert {"PIPPreviewEnabled", "PIPPreviewShowOnBlinker", "PIPPreviewShowOnBSM"} <= visual.keys() + assert {"PIPPreviewEnabled", "PIPPreviewShowOnBlinker", "PIPPreviewShowOnBSM", "PIPPreviewInvert"} <= visual.keys() assert visual["PIPPreviewEnabled"]["parent_key"] == "CustomUI" assert visual["PIPPreviewShowOnBlinker"]["parent_key"] == "PIPPreviewEnabled" assert visual["PIPPreviewShowOnBSM"]["parent_key"] == "PIPPreviewEnabled" + assert visual["PIPPreviewInvert"]["parent_key"] == "PIPPreviewEnabled" assert visual["PIPPreviewEnabled"]["settings_tier"] == "advanced" assert visual["PIPPreviewShowOnBlinker"]["settings_tier"] == "advanced" assert visual["PIPPreviewShowOnBSM"]["settings_tier"] == "advanced" + assert visual["PIPPreviewInvert"]["settings_tier"] == "advanced" assert _declared_default("PIPPreviewEnabled") == "0" assert _declared_default("PIPPreviewShowOnBlinker") == "0" assert _declared_default("PIPPreviewShowOnBSM") == "0" + assert _declared_default("PIPPreviewInvert") == "0" assert '"{\\"width\\":1928,\\"height\\":1208,\\"center_left\\":[315,548],\\"center_right\\":[1571,539],\\"crop_size\\":580}"' in PARAM_KEYS_PATH.read_text(encoding="utf-8") physical_settings = ( diff --git a/starpilot/system/the_galaxy/the_galaxy.py b/starpilot/system/the_galaxy/the_galaxy.py index 15c6eaea6..f10ed88f8 100644 --- a/starpilot/system/the_galaxy/the_galaxy.py +++ b/starpilot/system/the_galaxy/the_galaxy.py @@ -111,7 +111,7 @@ GITLAB_SUBMISSIONS_PROJECT_ID = "71992109" GITLAB_TOKEN = os.environ.get("GITLAB_TOKEN", "") LEGACY_LATERAL_METHOD_API_PREFIX = "/api/" + "".join(("f", "t", "m")) VASM_CONFIGURATION_KEYS = {"VASMEnabled", "VASMConfidenceThreshold", "VASMSmoothSeconds", "VASMAnnotationConfig"} -PIP_PREVIEW_CONFIGURATION_KEYS = {"PIPPreviewEnabled", "PIPPreviewMask", "PIPPreviewShowOnBlinker", "PIPPreviewShowOnBSM"} +PIP_PREVIEW_CONFIGURATION_KEYS = {"PIPPreviewEnabled", "PIPPreviewMask", "PIPPreviewShowOnBlinker", "PIPPreviewShowOnBSM", "PIPPreviewInvert"} MODEL_SMOOTHING_KEYS = {"LatSmoothSeconds", "LongSmoothSeconds"} GALAXY_DEVELOPER_ONLY_KEYS = {"TurnSteeringLimitMuteSpeed"} PULSE_GLIDE_BUTTON_KEYS = {