This commit is contained in:
firestar5683
2026-04-12 20:51:49 -05:00
parent 541c4d4735
commit 7568ab4e3d
46 changed files with 197 additions and 83 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+33
View File
@@ -35,6 +35,7 @@ from openpilot.starpilot.common.starpilot_variables import (
LEGACY_BOLT_FP_MIGRATION_FLAG = Path("/data") / "legacy_bolt_fp_migration_v1"
STARPILOT_DEFAULTS_PARITY_MIGRATION_FLAG = Path("/data") / "starpilot_defaults_parity_v1"
STARPILOT_HUMANLIKE_DISABLE_MIGRATION_FLAG = Path("/data") / "starpilot_humanlike_disable_v1"
STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG = Path("/data") / "starpilot_cluster_offset_v1"
STARPILOT_PARAM_RENAME_MIGRATION_FLAG = Path("/data") / "starpilot_param_rename_v1"
STARPILOT_PARAM_CANONICALIZATION_MIGRATION_FLAG = Path("/data") / "starpilot_param_canonicalization_v1"
STARPILOT_PC_ROOT_MIGRATION_FLAG = Path("/data") / "starpilot_pc_root_v1"
@@ -401,6 +402,37 @@ def migrate_disable_humanlike_defaults(params: Params, params_cache: Params) ->
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_HUMANLIKE_DISABLE_MIGRATION_FLAG}")
def migrate_cluster_offset_default(params: Params, params_cache: Params) -> None:
if STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG.exists():
return
legacy_default_detected = False
for params_obj in (params, params_cache):
raw_value = _read_raw_param_bytes(params_obj, "ClusterOffset")
if not raw_value:
continue
try:
parsed_value = float(raw_value.decode("utf-8", errors="strict").strip())
except Exception:
continue
if abs(parsed_value - 1.015) < 1e-6:
legacy_default_detected = True
break
if legacy_default_detected:
params.put_float("ClusterOffset", 1.0)
params_cache.put_float("ClusterOffset", 1.0)
cloudlog.warning("Applied one-time ClusterOffset migration from 1.015 to 1.0")
try:
STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG.parent.mkdir(parents=True, exist_ok=True)
STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG.write_text(f"{datetime.datetime.now(datetime.UTC).isoformat()}\n")
except Exception:
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG}")
def _read_raw_param_bytes(params: Params, key: str | bytes):
try:
path = params.get_param_path(key)
@@ -568,6 +600,7 @@ def manager_init() -> None:
migrate_param_type_canonicalization(params)
migrate_starpilot_default_parity(params, params_cache)
migrate_disable_humanlike_defaults(params, params_cache)
migrate_cluster_offset_default(params, params_cache)
# set unset params to their default value
for k in params.all_keys():
+26
View File
@@ -191,6 +191,32 @@ class TestManager:
assert not params_cache.get_bool("HumanFollowing")
assert not params_cache.get_bool("HumanLaneChanges")
def test_migrate_cluster_offset_default_resets_legacy_default_only(self, tmp_path, monkeypatch):
monkeypatch.setattr(manager, "STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG", tmp_path / "starpilot_cluster_offset_v1")
params = FileBackedFakeParams(tmp_path / "params", {
"ClusterOffset": 1.015,
})
params_cache = FileBackedFakeParams(tmp_path / "cache", {})
manager.migrate_cluster_offset_default(params, params_cache)
assert params.get("ClusterOffset") == "1.0"
assert params_cache.get("ClusterOffset") == "1.0"
def test_migrate_cluster_offset_default_preserves_custom_values(self, tmp_path, monkeypatch):
monkeypatch.setattr(manager, "STARPILOT_CLUSTER_OFFSET_MIGRATION_FLAG", tmp_path / "starpilot_cluster_offset_v1")
params = FileBackedFakeParams(tmp_path / "params", {
"ClusterOffset": 1.02,
})
params_cache = FileBackedFakeParams(tmp_path / "cache", {})
manager.migrate_cluster_offset_default(params, params_cache)
assert params.get("ClusterOffset") == "1.02"
assert params_cache.get("ClusterOffset") is None
@pytest.mark.skip("this test is flaky the way it's currently written, should be moved to test_onroad")
def test_clean_exit(self, subtests):
"""
+33
View File
@@ -218,6 +218,7 @@ class GuiApplication:
self._ffmpeg_queue: queue.Queue | None = None
self._ffmpeg_thread: threading.Thread | None = None
self._ffmpeg_stop_event: threading.Event | None = None
self._progress_hook: Callable[[str], None] | None = None
self._textures: dict[str, rl.Texture] = {}
self._target_fps: int = _DEFAULT_FPS
self._last_fps_log_time: float = time.monotonic()
@@ -447,6 +448,13 @@ class GuiApplication:
if tick_function in self._nav_stack_ticks:
self._nav_stack_ticks.remove(tick_function)
def set_progress_hook(self, hook: Callable[[str], None] | None) -> None:
self._progress_hook = hook
def _mark_progress(self, phase: str) -> None:
if self._progress_hook is not None:
self._progress_hook(phase)
def set_should_render(self, should_render: bool):
self._should_render = should_render
@@ -585,6 +593,7 @@ class GuiApplication:
self._render_profiler.enable()
while not (self._window_close_requested or rl.window_should_close()):
self._mark_progress("gui_app.loop_start")
if PC:
# Thread is not used on PC, need to manually add mouse events
self._mouse._handle_mouse_event()
@@ -596,6 +605,7 @@ class GuiApplication:
# Skip rendering when screen is off
if not self._should_render:
self._mark_progress("gui_app.skip_render")
if PC:
rl.poll_input_events()
time.sleep(1 / self._target_fps)
@@ -603,43 +613,63 @@ class GuiApplication:
continue
if self._render_texture:
self._mark_progress("gui_app.before_begin_texture_mode")
rl.begin_texture_mode(self._render_texture)
self._mark_progress("gui_app.after_begin_texture_mode")
self._mark_progress("gui_app.before_clear_background")
rl.clear_background(rl.BLACK)
self._mark_progress("gui_app.after_clear_background")
else:
self._mark_progress("gui_app.before_begin_drawing")
rl.begin_drawing()
self._mark_progress("gui_app.after_begin_drawing")
self._mark_progress("gui_app.before_clear_background")
rl.clear_background(rl.BLACK)
self._mark_progress("gui_app.after_clear_background")
if self._scale != 1.0:
rl.rl_push_matrix()
rl.rl_scalef(self._scale, self._scale, 1.0)
# Allow a Widget to still run a function regardless of the stack depth
self._mark_progress("gui_app.before_nav_ticks")
for tick in self._nav_stack_ticks:
tick()
self._mark_progress("gui_app.after_nav_ticks")
# Only render top widgets
self._mark_progress("gui_app.before_widget_render")
for widget in self._nav_stack[-self._nav_stack_widgets_to_render:]:
widget.render(rl.Rectangle(0, 0, self.width, self.height))
self._mark_progress("gui_app.after_widget_render")
self._mark_progress("gui_app.frame_ready")
yield True
if self._scale != 1.0:
rl.rl_pop_matrix()
if self._render_texture:
self._mark_progress("gui_app.end_texture_mode")
rl.end_texture_mode()
self._mark_progress("gui_app.before_present_begin_drawing")
rl.begin_drawing()
self._mark_progress("gui_app.after_present_begin_drawing")
self._mark_progress("gui_app.before_present_clear_background")
rl.clear_background(rl.BLACK)
self._mark_progress("gui_app.after_present_clear_background")
src_rect = rl.Rectangle(0, 0, float(self._scaled_width), -float(self._scaled_height))
dst_rect = rl.Rectangle(0, 0, float(self._scaled_width), float(self._scaled_height))
texture = self._render_texture.texture
if texture:
self._mark_progress("gui_app.before_present_draw_texture")
if BURN_IN_MODE and self._burn_in_shader:
rl.begin_shader_mode(self._burn_in_shader)
rl.draw_texture_pro(texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE)
rl.end_shader_mode()
else:
rl.draw_texture_pro(texture, src_rect, dst_rect, rl.Vector2(0, 0), 0.0, rl.WHITE)
self._mark_progress("gui_app.after_present_draw_texture")
if self._show_fps:
rl.draw_fps(10, 10)
@@ -650,7 +680,9 @@ class GuiApplication:
if self._grid_size > 0:
self._draw_grid()
self._mark_progress("gui_app.before_end_drawing")
rl.end_drawing()
self._mark_progress("gui_app.after_end_drawing")
if RECORD:
image = rl.load_image_from_texture(self._render_texture.texture)
@@ -661,6 +693,7 @@ class GuiApplication:
self._monitor_fps()
self._frame += 1
self._mark_progress("gui_app.loop_idle")
if self._profile_render_frames > 0 and self._frame >= self._profile_render_frames:
self._output_render_profile()