This commit is contained in:
firestar5683
2026-07-16 11:39:24 -05:00
parent 8f3f9cf6c7
commit d935514f78
3 changed files with 75 additions and 6 deletions
+3 -2
View File
@@ -583,7 +583,7 @@ class StarPilotVariables:
self.params.put_float("SteerDelay", full_stock_delay)
self.params.put_bool(STEER_DELAY_MODE_MIGRATION_KEY, True)
def update(self, holiday_theme="stock", started=False):
def update(self, holiday_theme="stock", started=False, clear_update_flag=True):
toggle = self.starpilot_toggles
toggle.tuning_level = self.params.get("TuningLevel") if self.params.get_bool("TuningLevelConfirmed") else TUNING_LEVELS["ADVANCED"]
# CarParams uses this value to select the matching Panda safety configuration.
@@ -1446,4 +1446,5 @@ class StarPilotVariables:
toggle.volt_sng = self.get_value("VoltSNG", condition=toggle.car_model in LEGACY_VOLT_STOCK_ACC_CARS)
process_starpilot_toggles.cache_clear()
self.params_memory.remove("StarPilotTogglesUpdated")
if clear_update_flag:
self.params_memory.remove("StarPilotTogglesUpdated")
@@ -27,6 +27,40 @@ class FakeModelManager:
return None
def test_background_toggle_update_does_not_mutate_active_toggles():
active_toggles = SimpleNamespace(holiday_themes=False, random_themes=False, enabled=False)
class FakeVariables:
def __init__(self):
self.starpilot_toggles = active_toggles
self.clear_update_flag = None
def update(self, holiday_theme, started, clear_update_flag=True):
self.clear_update_flag = clear_update_flag
self.starpilot_toggles.enabled = True
theme_manager = FakeThemeManager()
theme_manager.holiday_theme = "stock"
theme_manager.theme_updated = False
result = {}
starpilot_process.update_toggles_in_background(
result,
FakeVariables(),
True,
theme_manager,
FakeThreadManager(),
False,
FakeParams(),
active_toggles,
)
updated_variables, updated_toggles = result["update"]
assert active_toggles.enabled is False
assert updated_toggles.enabled is True
assert updated_variables.clear_update_flag is False
def test_transition_offroad_skips_invalid_gps_persist():
params = FakeParams()
planner = SimpleNamespace(gps_position={
+38 -4
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
import copy
import datetime
import hashlib
import importlib
@@ -209,11 +210,12 @@ def update_checks(now, model_manager, theme_manager, thread_manager, params, par
time.sleep(1)
def update_toggles(starpilot_variables, started, theme_manager, thread_manager, time_validated, params, starpilot_toggles):
def update_toggles(starpilot_variables, started, theme_manager, thread_manager, time_validated, params, starpilot_toggles,
clear_update_flag=True):
previous_holiday_themes = starpilot_toggles.holiday_themes
previous_random_themes = starpilot_toggles.random_themes
starpilot_variables.update(theme_manager.holiday_theme, started)
starpilot_variables.update(theme_manager.holiday_theme, started, clear_update_flag=clear_update_flag)
starpilot_toggles = starpilot_variables.starpilot_toggles
randomize_theme = starpilot_toggles.holiday_themes != previous_holiday_themes
@@ -224,6 +226,20 @@ def update_toggles(starpilot_variables, started, theme_manager, thread_manager,
return starpilot_toggles
def update_toggles_in_background(result, starpilot_variables, started, theme_manager, thread_manager, time_validated, params,
starpilot_toggles):
"""Reload toggles without mutating the values used by the planner mid-update."""
try:
updated_variables = copy.copy(starpilot_variables)
updated_variables.starpilot_toggles = copy.copy(starpilot_toggles)
updated_toggles = update_toggles(updated_variables, started, theme_manager, thread_manager, time_validated, params,
updated_variables.starpilot_toggles, clear_update_flag=False)
result["update"] = (updated_variables, updated_toggles)
except Exception:
result["failed"] = True
raise
def starpilot_thread():
rate_keeper = Ratekeeper(1 / DT_MDL, None)
@@ -249,6 +265,7 @@ def starpilot_thread():
starpilot_toggles = starpilot_variables.starpilot_toggles
serialized_starpilot_toggles = serialize_starpilot_toggles(starpilot_toggles)
toggle_broadcast_pending = True
toggle_update_result = {}
drive_stats_session = requests.Session()
next_dashboard_analysis_refresh = 0.0
@@ -355,8 +372,9 @@ def starpilot_thread():
elif current_safe_mode and (params_memory.get_bool("StarPilotTogglesUpdated") or rate_keeper.frame % SAFE_MODE_ENFORCE_FRAMES == 0):
apply_safe_mode(params, params_raw, params_memory, ensure_backup=False)
if params_memory.get_bool("StarPilotTogglesUpdated") or theme_manager.theme_updated:
starpilot_toggles = update_toggles(starpilot_variables, started, theme_manager, thread_manager, time_validated, params, starpilot_toggles)
completed_toggle_update = toggle_update_result.pop("update", None)
if completed_toggle_update is not None:
starpilot_variables, starpilot_toggles = completed_toggle_update
serialized_starpilot_toggles = serialize_starpilot_toggles(starpilot_toggles)
toggle_broadcast_pending = True
@@ -365,6 +383,22 @@ def starpilot_thread():
model_manager.randomize_selected_model()
model_randomizer_previously = model_randomizer_enabled
toggle_update_result.pop("failed", None)
toggle_refresh_requested = params_memory.get_bool("StarPilotTogglesUpdated") or theme_manager.theme_updated
toggle_update_running = thread_manager.is_thread_alive("update_toggles_in_background")
if started and toggle_refresh_requested and not toggle_update_running and not toggle_update_result:
# StarPilotVariables.update performs hundreds of param reads and can exceed
# the starpilotPlan liveness timeout. Keep that work off the planner loop.
params_memory.remove("StarPilotTogglesUpdated")
thread_manager.run_with_lock(
update_toggles_in_background,
(toggle_update_result, starpilot_variables, started, theme_manager, thread_manager, time_validated, params, starpilot_toggles),
)
elif not started and toggle_refresh_requested:
starpilot_toggles = update_toggles(starpilot_variables, started, theme_manager, thread_manager, time_validated, params, starpilot_toggles)
serialized_starpilot_toggles = serialize_starpilot_toggles(starpilot_toggles)
toggle_broadcast_pending = True
periodic_update_due = monotonic_now >= next_periodic_update_check
if periodic_update_due:
next_periodic_update_check = get_next_periodic_update_check(monotonic_now, periodic_update_phase)