From 8e69eb32fd54cf35fa240de9c767a49a4f792f5e Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sat, 8 Aug 2026 16:35:20 -0500 Subject: [PATCH] fla --- scripts/model_compiler.py | 10 ++-- .../components/tools/device_settings.js | 2 +- .../tools/device_settings_layout.json | 8 +++ .../tests/test_device_settings_layout.py | 30 ++++++++++- tools/StarPilot/generate_galaxy_layout.py | 51 ++++++++++++++++--- 5 files changed, 87 insertions(+), 14 deletions(-) diff --git a/scripts/model_compiler.py b/scripts/model_compiler.py index fde534eb6..83045bf4e 100644 --- a/scripts/model_compiler.py +++ b/scripts/model_compiler.py @@ -65,7 +65,7 @@ def build_compile_env() -> dict[str, str]: return env -def wait_for_external_gpu(compile_env: dict[str, str]) -> None: +def wait_for_external_gpu(compile_env: dict[str, str]) -> bool: """Wait for the USB GPU's PCIe link before starting the large model build. The dock can enumerate on USB before its PCIe link has finished training. @@ -101,12 +101,16 @@ def wait_for_external_gpu(compile_env: dict[str, str]) -> None: continue if result.returncode == 0: - return + return True detail = (result.stderr or result.stdout).strip() diagnostics.append((detail[-2000:] if detail else f"probe exited with status {result.returncode}")) detail = diagnostics[-1] if diagnostics else "unknown error" - raise RuntimeError(f"External GPU PCIe link was not ready after {USBGPU_PROBE_ATTEMPTS} probes: {detail}") + print( + f"Warning: external GPU probe did not become ready after {USBGPU_PROBE_ATTEMPTS} probes: {detail}\n" + " Continuing; compile_modeld will perform the authoritative link wait and initialization." + ) + return False def parse_args() -> argparse.Namespace: diff --git a/starpilot/system/the_galaxy/assets/components/tools/device_settings.js b/starpilot/system/the_galaxy/assets/components/tools/device_settings.js index 07100bc57..ff11af30e 100644 --- a/starpilot/system/the_galaxy/assets/components/tools/device_settings.js +++ b/starpilot/system/the_galaxy/assets/components/tools/device_settings.js @@ -11,7 +11,7 @@ const FAVORITE_OPTION_COLLATOR = new Intl.Collator(undefined, { numeric: true, s const FAVORITE_ACTION_PREFIX = "__starpilot_favorite_action__:" const GALAXY_DEVELOPER_MODE_KEY = "GalaxyDeveloperMode" const HIDDEN_SECTION_NAMES = new Set(["Model & Customization"]) -const HIDDEN_SETTING_KEYS = new Set(["DisableWideRoad", "HumanAcceleration", "ReverseCruise"]) +const HIDDEN_SETTING_KEYS = new Set(["HumanAcceleration", "ReverseCruise"]) const GM_MAKES = ["Buick", "Cadillac", "Chevrolet", "GMC", "Holden"] const HKG_MAKES = ["Genesis", "Hyundai", "Kia"] const VEHICLE_SETTING_MAKES = { diff --git a/starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json b/starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json index e8b3185f3..8b57594c5 100644 --- a/starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json +++ b/starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json @@ -2481,6 +2481,14 @@ "ui_type": "toggle", "parent_key": "AdvancedCustomUI", "settings_tier": "simple" + }, + { + "key": "DisableWideRoad", + "label": "Disable Wide Road Camera", + "description": "Only enable this if the wide camera is broken or for development!\n\nDisabling the wide camera may degrade driving performance and cause instability.\n\nRequires a reboot to take effect.", + "data_type": "bool", + "ui_type": "toggle", + "settings_tier": "advanced" } ] }, 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 e5fc44640..97a3d7a00 100644 --- a/starpilot/system/the_galaxy/tests/test_device_settings_layout.py +++ b/starpilot/system/the_galaxy/tests/test_device_settings_layout.py @@ -1,4 +1,5 @@ import json +import importlib.util import re from pathlib import Path @@ -6,6 +7,7 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[4] LAYOUT_PATH = REPO_ROOT / "starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json" PARAM_KEYS_PATH = REPO_ROOT / "common/params_keys.h" +GENERATOR_PATH = REPO_ROOT / "tools/StarPilot/generate_galaxy_layout.py" def _layout(): @@ -29,13 +31,27 @@ def _declared_default(key): return match.group(1) +def _generator_module(): + spec = importlib.util.spec_from_file_location("generate_galaxy_layout", GENERATOR_PATH) + assert spec is not None and spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + def test_galaxy_layout_removes_obsolete_and_duplicate_controls(): layout = _layout() sections = _params_by_section(layout) all_keys = {key for params in sections.values() for key in params} assert "Model & Customization" not in sections - assert {"HumanAcceleration", "ReverseCruise", "DisableWideRoad"}.isdisjoint(all_keys) + assert {"HumanAcceleration", "ReverseCruise"}.isdisjoint(all_keys) + assert "DisableWideRoad" in sections["Visual (Display & UI)"] + assert sum( + param.get("key") == "DisableWideRoad" + for section in layout + for param in section.get("params", []) + ) == 1 def test_galaxy_layout_contains_basic_mode_controls(): @@ -75,6 +91,11 @@ def test_every_galaxy_setting_has_a_shared_settings_tier(): assert None not in tiers +def test_galaxy_layout_generator_is_semantically_idempotent(): + layout = _layout() + assert _generator_module().generate_layout(layout) == layout + + def test_requested_simple_and_advanced_settings_tiers(): sections = _params_by_section(_layout()) lateral = sections["Lateral (Steering)"] @@ -90,7 +111,11 @@ def test_requested_simple_and_advanced_settings_tiers(): ): params = sections[section_name].values() if section_name == "Visual (Display & UI)": - params = [param for param in params if not param["key"].startswith("PIPPreview")] + params = [ + param for param in params + if not param["key"].startswith("PIPPreview") + and param["key"] != "DisableWideRoad" + ] assert {param["settings_tier"] for param in params} == {"simple"} for key in ("AlwaysOnLateral", "LaneChanges", "QOLLateral"): @@ -123,6 +148,7 @@ def test_requested_simple_and_advanced_settings_tiers(): assert developer["UseOldUI"]["settings_tier"] == "simple" assert developer["DeveloperUI"]["settings_tier"] == "advanced" assert developer["RedneckCruise"]["settings_tier"] == "advanced" + assert sections["Visual (Display & UI)"]["DisableWideRoad"]["settings_tier"] == "advanced" def test_hidden_feature_defaults_remain_enabled(): diff --git a/tools/StarPilot/generate_galaxy_layout.py b/tools/StarPilot/generate_galaxy_layout.py index 40cfcbd24..9d6244c8f 100755 --- a/tools/StarPilot/generate_galaxy_layout.py +++ b/tools/StarPilot/generate_galaxy_layout.py @@ -62,7 +62,8 @@ INJECTED_SECTION_PARAMS = { # Keys explicitly hidden from The Galaxy's generic settings UI. HIDDEN_KEYS = { "HumanAcceleration", - "DisableWideRoad", + "HideLeadMarker", + "HideSpeedLimit", "LockDoorsTimer", "NewLongAPI", "ToyotaDoors", @@ -74,6 +75,18 @@ HIDDEN_SECTION_NAMES = {"Model & Customization"} # Keys that are boolean toggles despite ambiguous defaults in starpilot_variables.py. FORCE_BOOL_KEYS = {"EVTuning"} +# These fields are intentionally allowed to differ from the Qt source. Galaxy +# has its own copy, nesting, and browser-only behavior for otherwise shared +# params, so regeneration must not discard those overrides. +GALAXY_OVERRIDE_FIELDS = { + "label", + "description", + "parent_key", + "is_parent_toggle", + "disabled_when_key_true", + "disabled_reason", +} + def get_param_settings_tiers(): params_path = os.path.join(REPO_ROOT, "common/params_keys.h") @@ -105,6 +118,9 @@ def apply_settings_tiers(layout): resolving.add(key) parent_key = params_by_key.get(key, {}).get("parent_key") + if parent_key == "GalaxyDeveloperMode": + resolved[key] = "advanced" + return resolved[key] own_tier = PARAM_SETTINGS_TIERS.get(key) if parent_key: parent_tier = resolve_tier(parent_key, resolving) @@ -601,8 +617,14 @@ def parse_cpp_file(filename): def merge_layouts(existing_layout, generated_layout): - existing_sections = {section["name"]: section for section in existing_layout} generated_sections = {section["name"]: section for section in generated_layout} + existing_keys = { + param["key"] + for section in existing_layout + for param in section.get("params", []) + if "key" in param + } + merged_keys = set(existing_keys) merged_layout = [] @@ -625,16 +647,21 @@ def merge_layouts(existing_layout, generated_layout): for param in existing_params: key = param["key"] if key in generated_by_key: - merged_params.append(generated_by_key[key]) + merged_param = dict(param) + for field, value in generated_by_key[key].items(): + if field not in GALAXY_OVERRIDE_FIELDS and field != "settings_tier": + merged_param[field] = value + merged_params.append(merged_param) else: merged_params.append(param) seen_keys.add(key) for param in generated_params: key = param["key"] - if key not in seen_keys: + if key not in seen_keys and key not in merged_keys: merged_params.append(param) seen_keys.add(key) + merged_keys.add(key) merged_section = dict(section) merged_section["icon"] = generated.get("icon", section.get("icon")) @@ -648,7 +675,8 @@ def merge_layouts(existing_layout, generated_layout): return merged_layout -def main(): + +def generate_layout(existing_layout=None): generated_layout = [] for cat in CATEGORIES: items = parse_cpp_file(cat["file"]) @@ -662,15 +690,22 @@ def main(): "icon": cat["icon"], "params": items }) + + layout = generated_layout if existing_layout is None else merge_layouts(existing_layout, generated_layout) + return apply_settings_tiers(layout) + +def main(): output_path = os.path.join(REPO_ROOT, "starpilot/system/the_galaxy/assets/components/tools/device_settings_layout.json") - layout = generated_layout + existing_layout = None if os.path.exists(output_path): with open(output_path, 'r', encoding='utf-8') as f: existing_layout = json.load(f) - layout = merge_layouts(existing_layout, generated_layout) - layout = apply_settings_tiers(layout) + layout = generate_layout(existing_layout) + if layout == existing_layout: + return with open(output_path, 'w', encoding='utf-8') as f: json.dump(layout, f, indent=2, ensure_ascii=False) + f.write("\n") if __name__ == '__main__': main()