The Fairlife Milk Out of Stock Ya'll

This commit is contained in:
firestar5683
2026-07-20 21:34:47 -05:00
parent b34e968f91
commit eb3eb116eb
13 changed files with 263 additions and 95 deletions
@@ -253,6 +253,11 @@ class CarInterface(CarInterfaceBase):
ret.vEgoStarting = 0.5
ret.vEgoStopping = 0.35
if candidate == CAR.HYUNDAI_ELANTRA_2021:
ret.longitudinalActuatorDelay = 0.22
ret.stopAccel = -1.5
ret.stoppingDecelRate = 0.5
if candidate == CAR.HYUNDAI_IONIQ_6:
ret.longitudinalActuatorDelay = 0.6
@@ -704,6 +704,14 @@ class TestHyundaiFingerprint:
assert CP.vEgoStopping == pytest.approx(0.35)
assert CP.stoppingDecelRate == pytest.approx(0.35)
def test_elantra_2021_longitudinal_params_match_observed_response(self):
toggles = get_test_toggles()
CP = CarInterface.get_params(CAR.HYUNDAI_ELANTRA_2021, gen_empty_fingerprint(), [], True, False, False, toggles)
assert CP.longitudinalActuatorDelay == pytest.approx(0.22)
assert CP.stopAccel == pytest.approx(-1.5)
assert CP.stoppingDecelRate == pytest.approx(0.5)
def test_kia_niro_phev_2022_longitudinal_params_soften_final_stop_hold(self):
toggles = get_test_toggles()
CP = CarInterface.get_params(CAR.KIA_NIRO_PHEV_2022, gen_empty_fingerprint(), [], True, False, False, toggles)
@@ -18,6 +18,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
# Toyota LTA also has torque
"TOYOTA_RAV4_TSS2_2023" = [nan, 3.0, nan]
"TOYOTA_MATRIX_RETROFIT" = [4.05, 1.84, 0.10]
"TOYOTA_RAV4_PRIME" = [1.7, 2.0, 0.14]
# Tesla angle based controllers
"TESLA_MODEL_3" = [nan, 2.5, nan]
@@ -9,7 +9,6 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"TOYOTA_ALPHARD_TSS2" = "TOYOTA_SIENNA"
"TOYOTA_PRIUS_V" = "TOYOTA_PRIUS"
"TOYOTA_RAV4_PRIME" = "TOYOTA_RAV4_TSS2"
"TOYOTA_SIENNA_4TH_GEN" = "TOYOTA_RAV4_TSS2"
"LEXUS_IS" = "LEXUS_NX"
"LEXUS_CTH" = "LEXUS_NX"
@@ -53,6 +53,8 @@ class TestToyotaInterfaces:
assert default_params.lateralTuning.which() == "pid"
assert forced_params.lateralTuning.which() == "torque"
assert forced_params.lateralTuning.torque.latAccelFactor == pytest.approx(1.7)
assert forced_params.lateralTuning.torque.friction == pytest.approx(0.14)
def test_tss2_dbc(self):
# We make some assumptions about TSS2 platforms,
+95
View File
@@ -0,0 +1,95 @@
from enum import StrEnum
import pyray as rl
from openpilot.starpilot.common.experimental_state import requested_experimental_mode
class ModeBannerVariant(StrEnum):
CHILL = "chill"
EXPERIMENTAL = "experimental"
CONDITIONAL_EXPERIMENTAL = "conditional_experimental"
CONDITIONAL_CHILL = "conditional_chill"
def get_mode_banner_variant(params, params_memory=None) -> ModeBannerVariant:
if params.get_bool("SafeMode"):
return ModeBannerVariant.CHILL
if params.get_bool("ConditionalExperimental"):
return ModeBannerVariant.CONDITIONAL_EXPERIMENTAL
if params.get_bool("ConditionalChill"):
return ModeBannerVariant.CONDITIONAL_CHILL
if requested_experimental_mode(params, params_memory):
return ModeBannerVariant.EXPERIMENTAL
return ModeBannerVariant.CHILL
def _color(red: int, green: int, blue: int, alpha: int) -> rl.Color:
return rl.Color(red, green, blue, alpha)
def _lerp_color(start: rl.Color, end: rl.Color, progress: float, alpha: int) -> rl.Color:
progress = max(0.0, min(1.0, progress))
return rl.Color(
round(start.r + (end.r - start.r) * progress),
round(start.g + (end.g - start.g) * progress),
round(start.b + (end.b - start.b) * progress),
alpha,
)
def _conditional_colors(variant: ModeBannerVariant, alpha: int) -> tuple[rl.Color, rl.Color, rl.Color, rl.Color]:
blue = _color(35, 149, 255, alpha)
mint = _color(20, 255, 171, alpha)
orange = _color(255, 138, 22, alpha)
red = _color(219, 56, 34, alpha)
if variant == ModeBannerVariant.CONDITIONAL_EXPERIMENTAL:
return blue, mint, orange, red
return orange, red, blue, mint
def mode_banner_color(variant: ModeBannerVariant, progress: float, alpha: int = 255) -> rl.Color:
progress = max(0.0, min(1.0, progress))
if variant == ModeBannerVariant.CHILL:
return _lerp_color(_color(20, 255, 171, alpha), _color(35, 149, 255, alpha), progress, alpha)
if variant == ModeBannerVariant.EXPERIMENTAL:
return _lerp_color(_color(255, 155, 63, alpha), _color(219, 56, 34, alpha), progress, alpha)
dominant_start, dominant_end, target_start, target_end = _conditional_colors(variant, alpha)
if progress <= 0.58:
return _lerp_color(dominant_start, dominant_end, progress / 0.58, alpha)
if progress <= 0.80:
return _lerp_color(dominant_end, target_start, (progress - 0.58) / 0.22, alpha)
return _lerp_color(target_start, target_end, ((progress - 0.80) / 0.20) * 0.67, alpha)
def mode_atom_color(variant: ModeBannerVariant, progress: float, alpha: int = 255) -> rl.Color:
# The compact atom reads left-to-right as blue to mint in fixed Chill mode.
if variant == ModeBannerVariant.CHILL:
progress = 1.0 - progress
return mode_banner_color(variant, progress, alpha)
def draw_mode_banner_gradient(rect: rl.Rectangle, variant: ModeBannerVariant, alpha: int = 255) -> None:
if variant in (ModeBannerVariant.CHILL, ModeBannerVariant.EXPERIMENTAL):
rl.draw_rectangle_gradient_h(
int(rect.x), int(rect.y), int(rect.width), int(rect.height),
mode_banner_color(variant, 0.0, alpha), mode_banner_color(variant, 1.0, alpha),
)
return
transition_start = int(rect.x + rect.width * 0.58)
transition_end = int(rect.x + rect.width * 0.80)
right = int(rect.x + rect.width)
rl.draw_rectangle_gradient_h(
int(rect.x), int(rect.y), transition_start - int(rect.x), int(rect.height),
mode_banner_color(variant, 0.0, alpha), mode_banner_color(variant, 0.58, alpha),
)
rl.draw_rectangle_gradient_h(
transition_start, int(rect.y), transition_end - transition_start, int(rect.height),
mode_banner_color(variant, 0.58, alpha), mode_banner_color(variant, 0.80, alpha),
)
rl.draw_rectangle_gradient_h(
transition_end, int(rect.y), right - transition_end, int(rect.height),
mode_banner_color(variant, 0.80, alpha), mode_banner_color(variant, 1.0, alpha),
)
+69 -4
View File
@@ -5,11 +5,13 @@ import time
from cereal import log
import pyray as rl
from collections.abc import Callable
from importlib.resources import as_file
from openpilot.system.ui.widgets import Widget
from openpilot.system.ui.widgets.layouts import HBoxLayout
from openpilot.system.ui.widgets.icon_widget import IconWidget
from openpilot.system.ui.widgets.label import UnifiedLabel
from openpilot.system.ui.lib.application import gui_app, FontWeight, MousePos
from openpilot.system.ui.lib.application import ASSETS_DIR, gui_app, FontWeight, MousePos
from openpilot.selfdrive.ui.lib.mode_banner import ModeBannerVariant, get_mode_banner_variant, mode_atom_color
from openpilot.selfdrive.ui.lib.starpilot_version import STARPILOT_DISPLAY_VERSION
from openpilot.selfdrive.ui.ui_state import ui_state
@@ -81,6 +83,68 @@ class NetworkIcon(Widget):
rl.draw_texture_ex(draw_net_txt, rl.Vector2(draw_x, draw_y), 0.0, 1.0, rl.Color(255, 255, 255, int(255 * 0.9)))
class ModeStatusAtom(Widget):
def __init__(self):
super().__init__()
self._variant = ModeBannerVariant.CHILL
self._textures = self._make_textures()
self.set_rect(rl.Rectangle(0, 0, 48, 48))
self.set_enabled(False)
self.refresh()
@staticmethod
def _make_textures() -> dict[ModeBannerVariant, rl.Texture]:
textures = {}
with as_file(ASSETS_DIR.joinpath("icons_mici/experimental_mode.png")) as asset_path:
source = rl.load_image(asset_path.as_posix())
pixel_count = source.width * source.height
source_pixels = bytearray(rl.ffi.buffer(source.data, pixel_count * 4))
try:
for variant in ModeBannerVariant:
tinted = rl.image_copy(source)
tinted_pixels = bytearray(source_pixels)
gradient = [mode_atom_color(variant, x / max(source.width - 1, 1)) for x in range(source.width)]
for y in range(source.height):
for x in range(source.width):
offset = (y * source.width + x) * 4
opacity = source_pixels[offset + 3]
if opacity == 0:
continue
color = gradient[x]
source_shade = max(source_pixels[offset:offset + 3]) / 255.0
shade = 0.65 + 0.35 * source_shade
tinted_pixels[offset] = round(color.r * shade)
tinted_pixels[offset + 1] = round(color.g * shade)
tinted_pixels[offset + 2] = round(color.b * shade)
tinted_pixels[offset + 3] = opacity
rl.ffi.buffer(tinted.data, len(tinted_pixels))[:] = bytes(tinted_pixels)
texture = rl.load_texture_from_image(tinted)
rl.set_texture_filter(texture, rl.TextureFilter.TEXTURE_FILTER_BILINEAR)
rl.set_texture_wrap(texture, rl.TextureWrap.TEXTURE_WRAP_CLAMP)
rl.unload_image(tinted)
textures[variant] = texture
finally:
rl.unload_image(source)
return textures
def refresh(self) -> None:
self._variant = get_mode_banner_variant(ui_state.params, ui_state.params_memory)
def _render(self, rect: rl.Rectangle) -> None:
texture = self._textures[self._variant]
source = rl.Rectangle(0, 0, texture.width, texture.height)
rl.draw_texture_pro(texture, source, rect, rl.Vector2(0, 0), 0, rl.WHITE)
def __del__(self):
if rl.is_window_ready():
for texture in getattr(self, "_textures", {}).values():
if texture.id != 0:
rl.unload_texture(texture)
class MiciHomeLayout(Widget):
def __init__(self):
super().__init__()
@@ -95,7 +159,7 @@ class MiciHomeLayout(Widget):
self._experimental_mode = False
self._current_model_name = "default"
self._experimental_icon = IconWidget("icons_mici/experimental_mode.png", (48, 48))
self._mode_status_atom = ModeStatusAtom()
self._egpu_icon = IconWidget("icons_mici/egpu.png", (50, 37))
self._egpu_icon_gray = IconWidget("icons_mici/egpu_gray.png", (50, 37))
self._mic_icon = IconWidget("icons_mici/microphone.png", (32, 46))
@@ -103,7 +167,7 @@ class MiciHomeLayout(Widget):
self._status_bar_layout = HBoxLayout([
IconWidget("icons_mici/settings.png", (48, 48), opacity=0.9),
NetworkIcon(),
self._experimental_icon,
self._mode_status_atom,
self._egpu_icon,
self._egpu_icon_gray,
self._mic_icon,
@@ -123,6 +187,7 @@ class MiciHomeLayout(Widget):
def _update_params(self):
self._experimental_mode = ui_state.params.get_bool("ExperimentalMode")
self._mode_status_atom.refresh()
def _clean_model_name(value: str) -> str:
return re.sub(r"[🗺️👀📡]", "", value).replace("(Default)", "").strip()
@@ -152,6 +217,7 @@ class MiciHomeLayout(Widget):
if ui_state.has_longitudinal_control:
self._experimental_mode = not self._experimental_mode
ui_state.params.put("ExperimentalMode", self._experimental_mode)
self._mode_status_atom.refresh()
self._mouse_down_t = None
self._did_long_press = True
@@ -214,7 +280,6 @@ class MiciHomeLayout(Widget):
self._version_commit_label.render()
# ***** Center-aligned bottom section icons *****
self._experimental_icon.set_visible(self._experimental_mode)
self._egpu_icon.set_visible(ui_state.usbgpu_active)
self._egpu_icon_gray.set_visible(ui_state.usbgpu and not ui_state.usbgpu_active)
self._mic_icon.set_visible(ui_state.recording_audio)
+50
View File
@@ -0,0 +1,50 @@
from openpilot.selfdrive.ui.lib.mode_banner import ModeBannerVariant, get_mode_banner_variant, mode_atom_color, mode_banner_color
class FakeParams:
def __init__(self, bools=None, ints=None):
self.bools = bools or {}
self.ints = ints or {}
def get_bool(self, key):
return self.bools.get(key, False)
def get_int(self, key, default=0):
return self.ints.get(key, default)
def _rgb(color):
return color.r, color.g, color.b
def test_mode_banner_variant_tracks_fixed_and_conditional_modes():
assert get_mode_banner_variant(FakeParams()) == ModeBannerVariant.CHILL
assert get_mode_banner_variant(FakeParams({"ExperimentalMode": True})) == ModeBannerVariant.EXPERIMENTAL
assert get_mode_banner_variant(FakeParams({"ConditionalExperimental": True})) == ModeBannerVariant.CONDITIONAL_EXPERIMENTAL
assert get_mode_banner_variant(FakeParams({"ConditionalChill": True})) == ModeBannerVariant.CONDITIONAL_CHILL
assert get_mode_banner_variant(FakeParams({"SafeMode": True, "ConditionalExperimental": True})) == ModeBannerVariant.CHILL
def test_conditional_gradients_keep_full_major_and_partial_minor_colors():
conditional_experimental = ModeBannerVariant.CONDITIONAL_EXPERIMENTAL
assert _rgb(mode_banner_color(conditional_experimental, 0.0)) == (35, 149, 255)
assert _rgb(mode_banner_color(conditional_experimental, 0.58)) == (20, 255, 171)
assert _rgb(mode_banner_color(conditional_experimental, 0.80)) == (255, 138, 22)
assert _rgb(mode_banner_color(conditional_experimental, 1.0)) == (231, 83, 30)
conditional_chill = ModeBannerVariant.CONDITIONAL_CHILL
assert _rgb(mode_banner_color(conditional_chill, 0.0)) == (255, 138, 22)
assert _rgb(mode_banner_color(conditional_chill, 0.58)) == (219, 56, 34)
assert _rgb(mode_banner_color(conditional_chill, 0.80)) == (35, 149, 255)
assert _rgb(mode_banner_color(conditional_chill, 1.0)) == (25, 220, 199)
def test_atom_gradients_use_compact_icon_directions():
assert _rgb(mode_atom_color(ModeBannerVariant.CHILL, 0.0)) == (35, 149, 255)
assert _rgb(mode_atom_color(ModeBannerVariant.CHILL, 1.0)) == (20, 255, 171)
assert _rgb(mode_atom_color(ModeBannerVariant.EXPERIMENTAL, 0.0)) == (255, 155, 63)
assert _rgb(mode_atom_color(ModeBannerVariant.EXPERIMENTAL, 1.0)) == (219, 56, 34)
for variant in (ModeBannerVariant.CONDITIONAL_EXPERIMENTAL, ModeBannerVariant.CONDITIONAL_CHILL):
assert _rgb(mode_atom_color(variant, 0.0)) == _rgb(mode_banner_color(variant, 0.0))
assert _rgb(mode_atom_color(variant, 1.0)) == _rgb(mode_banner_color(variant, 1.0))
+6 -61
View File
@@ -4,6 +4,7 @@ from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.lib.text_measure import measure_text_cached
from openpilot.system.ui.widgets import Widget
from openpilot.selfdrive.ui.lib.mode_banner import ModeBannerVariant, draw_mode_banner_gradient, get_mode_banner_variant
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.starpilot.common.experimental_state import requested_experimental_mode
@@ -18,74 +19,18 @@ class ExperimentalModeButton(Widget):
self.params = Params()
self.experimental_mode = requested_experimental_mode(self.params, ui_state.params_memory)
self.conditional_mode = self._get_conditional_mode()
self.mode_variant = get_mode_banner_variant(self.params, ui_state.params_memory)
self.chill_pixmap = gui_app.texture("icons/couch.png", self.img_width, self.img_width)
self.experimental_pixmap = gui_app.texture("icons/experimental_grey.png", self.img_width, self.img_width)
def show_event(self):
self.experimental_mode = requested_experimental_mode(self.params, ui_state.params_memory)
self.conditional_mode = self._get_conditional_mode()
def _get_conditional_mode(self):
if self.params.get_bool("SafeMode"):
return None
if self.params.get_bool("ConditionalExperimental"):
return "experimental"
if self.params.get_bool("ConditionalChill"):
return "chill"
return None
def _get_gradient_colors(self):
alpha = 0xCC if self.is_pressed else 0xFF
if self.experimental_mode:
return rl.Color(255, 155, 63, alpha), rl.Color(219, 56, 34, alpha)
else:
return rl.Color(20, 255, 171, alpha), rl.Color(35, 149, 255, alpha)
def _draw_gradient_background(self, rect):
if self.conditional_mode:
alpha = 0xCC if self.is_pressed else 0xFF
blue = rl.Color(35, 149, 255, alpha)
mint = rl.Color(20, 255, 171, alpha)
orange = rl.Color(255, 138, 22, alpha)
red = rl.Color(219, 56, 34, alpha)
if self.conditional_mode == "experimental":
dominant_start, dominant_end = blue, mint
target_start, target_end = orange, red
else:
dominant_start, dominant_end = orange, red
target_start, target_end = blue, mint
transition_start = int(rect.x + rect.width * 0.58)
transition_end = int(rect.x + rect.width * 0.80)
right = int(rect.x + rect.width)
dominant_width = transition_start - int(rect.x)
target_width = right - transition_end
target_progress = 0.67
target_visible_end = rl.Color(
round(target_start.r + (target_end.r - target_start.r) * target_progress),
round(target_start.g + (target_end.g - target_start.g) * target_progress),
round(target_start.b + (target_end.b - target_start.b) * target_progress),
alpha,
)
rl.draw_rectangle_gradient_h(int(rect.x), int(rect.y), dominant_width, int(rect.height),
dominant_start, dominant_end)
rl.draw_rectangle_gradient_h(transition_start, int(rect.y), transition_end - transition_start, int(rect.height),
dominant_end, target_start)
rl.draw_rectangle_gradient_h(transition_end, int(rect.y), target_width, int(rect.height),
target_start, target_visible_end)
return
start_color, end_color = self._get_gradient_colors()
rl.draw_rectangle_gradient_h(int(rect.x), int(rect.y), int(rect.width), int(rect.height),
start_color, end_color)
self.mode_variant = get_mode_banner_variant(self.params, ui_state.params_memory)
def _render(self, rect):
rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
self._draw_gradient_background(rect)
draw_mode_banner_gradient(rect, self.mode_variant, 0xCC if self.is_pressed else 0xFF)
rl.draw_rectangle_rounded_lines_ex(self._rect, 0.19, 10, 5, rl.BLACK)
rl.end_scissor_mode()
@@ -95,9 +40,9 @@ class ExperimentalModeButton(Widget):
rl.draw_line_ex(rl.Vector2(line_x, rect.y), rl.Vector2(line_x, rect.y + rect.height), 3, separator_color)
# Draw text label (left aligned)
if self.conditional_mode == "experimental":
if self.mode_variant == ModeBannerVariant.CONDITIONAL_EXPERIMENTAL:
text = tr("CONDITIONAL EXPERIMENTAL")
elif self.conditional_mode == "chill":
elif self.mode_variant == ModeBannerVariant.CONDITIONAL_CHILL:
text = tr("CONDITIONAL CHILL")
else:
text = tr("EXPERIMENTAL MODE ON") if self.experimental_mode else tr("CHILL MODE ON")
+3 -17
View File
@@ -284,13 +284,6 @@ EXCLUDED_KEYS = {
"UptimeOffroad"
}
TUNING_LEVELS = {
"MINIMAL": 0,
"STANDARD": 1,
"ADVANCED": 2,
"DEVELOPER": 3
}
# Shared params handles for modules that import these from starpilot_variables.
params = Params(return_defaults=True)
params_memory = Params(memory=True)
@@ -419,8 +412,6 @@ class StarPilotVariables:
toggle = self.starpilot_toggles
self.default_values = {key.decode(): self.params.get_default_value(key) for key in self.params.all_keys()}
self.tuning_levels = {key.decode(): self.params.get_tuning_level(key) for key in self.params.all_keys()}
branch = get_build_metadata().channel
self.release_branch = branch == "StarPilot"
self.staging_branch = branch == "StarPilot-Staging"
@@ -431,8 +422,6 @@ class StarPilotVariables:
# Development/vetting branches are no longer gated into dashcam mode.
toggle.block_user = False
toggle.tuning_level = self.params.get("TuningLevel") if self.params.get_bool("TuningLevelConfirmed") else TUNING_LEVELS["ADVANCED"]
device_management = self.get_value("DeviceManagement")
toggle.use_higher_bitrate = device_management
@@ -460,8 +449,8 @@ class StarPilotVariables:
return f"#{color.get('alpha', 255):02X}{color.get('red', 255):02X}{color.get('green', 255):02X}{color.get('blue', 255):02X}"
return "#FFFFFFFF"
def get_value(self, key, cast=bool, condition=True, conversion=None, default=None, min=None, max=None, respect_tuning_level=True):
if not condition or (respect_tuning_level and self.starpilot_toggles.tuning_level < self.tuning_levels.get(key, 0)):
def get_value(self, key, cast=bool, condition=True, conversion=None, default=None, min=None, max=None):
if not condition:
if default is not None:
value = default
elif cast is bool:
@@ -509,9 +498,7 @@ class StarPilotVariables:
return value
def get_button_function(self, key, condition=True):
# Tuning level should hide wheel-mapping controls, not silently revert their
# runtime behavior to defaults after the driver has configured them.
return self.get_value(key, cast=float, condition=condition, respect_tuning_level=False)
return self.get_value(key, cast=float, condition=condition)
def migrate_prius_cluster_offset(self, car_model):
if car_model not in PRIUS_CLUSTER_OFFSET_CARS or self.params_raw.get_bool(PRIUS_CLUSTER_OFFSET_MIGRATION_KEY):
@@ -595,7 +582,6 @@ class StarPilotVariables:
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.
toggle.tesla_cooperative_steering = self.params.get_bool("TeslaCoopSteering")
@@ -160,15 +160,13 @@ def test_cancel_button_migration_copies_distance_actions_once():
assert params.get_int("CancelButtonControl") == 3
def test_button_function_ignores_tuning_level_gate():
def test_runtime_values_ignore_legacy_tuning_level_metadata():
params = _FakeParams(ints={"LKASButtonControl": spv.BUTTON_FUNCTIONS["AOL_TOGGLE"]})
variables = object.__new__(spv.StarPilotVariables)
variables.params = params
variables.starpilot_toggles = SimpleNamespace(tuning_level=spv.TUNING_LEVELS["STANDARD"])
variables.tuning_levels = {"LKASButtonControl": spv.TUNING_LEVELS["ADVANCED"]}
variables.default_values = {"LKASButtonControl": str(spv.BUTTON_FUNCTIONS["EXPERIMENTAL_MODE"])}
assert variables.get_value("LKASButtonControl", cast=int) == spv.BUTTON_FUNCTIONS["EXPERIMENTAL_MODE"]
assert variables.get_value("LKASButtonControl", cast=int) == spv.BUTTON_FUNCTIONS["AOL_TOGGLE"]
assert variables.get_button_function("LKASButtonControl") == spv.BUTTON_FUNCTIONS["AOL_TOGGLE"]
@@ -2629,6 +2629,8 @@ def _apply_param_bundle(params: Params, bundle: dict[str, Any]) -> None:
elif kind == "string":
params.put(key, str(value or ""))
Params(memory=True).put_bool("StarPilotTogglesUpdated", True)
def _merge_flm_override_state(base: dict[str, Any], delta: dict[str, Any]) -> dict[str, Any]:
base = normalize_flm_overrides(base)
@@ -2815,6 +2817,7 @@ def accept_trial_as_baseline() -> dict[str, Any]:
params.put_bool("FLMTrialApplied", False)
params.put("FLMActiveProfileId", "")
_clear_persistent_trial_baseline(params)
Params(memory=True).put_bool("StarPilotTogglesUpdated", True)
for path in paths["snapshots"].glob("*.json"):
path.unlink()
@@ -22,44 +22,51 @@ def _simple_module(name, **attrs):
def _install_flm_import_stubs(tmp_path):
class FakeParams:
_store = {}
_memory_store = {}
def __init__(self, return_defaults=False):
def __init__(self, return_defaults=False, memory=False):
self.return_defaults = return_defaults
self.memory = memory
@property
def _values(self):
return type(self)._memory_store if self.memory else type(self)._store
def get(self, key, block=False, return_default=False, encoding=None, default=None):
del block, return_default
value = self._store.get(key, default)
value = self._values.get(key, default)
if encoding and isinstance(value, bytes):
return value.decode(encoding, errors="replace")
return value
def get_bool(self, key, default=False):
value = self._store.get(key, default)
value = self._values.get(key, default)
if isinstance(value, bool):
return value
return str(value).strip().lower() in ("1", "true", "yes", "on")
def get_float(self, key, block=False, return_default=False, default=0.0):
del block, return_default
value = self._store.get(key, default)
value = self._values.get(key, default)
try:
return float(value)
except Exception:
return default
def put(self, key, value):
self._store[key] = value
self._values[key] = value
def put_bool(self, key, value):
self._store[key] = bool(value)
self._values[key] = bool(value)
def put_float(self, key, value):
self._store[key] = float(value)
self._values[key] = float(value)
def remove(self, key):
self._store.pop(key, None)
self._values.pop(key, None)
FakeParams._store = {}
FakeParams._memory_store = {}
class FakeHyundaiFlags:
CANFD = 1
@@ -850,7 +857,9 @@ def test_apply_and_revert_trial_profile_round_trip(tmp_path):
assert fake_params_cls._store["FLMTrialBaseline"]["params"]["SteerLatAccel"] == pytest.approx(1.5)
assert fake_params_cls._store["FLMActiveOverrides"]["vehicleKnobs"]["hyundai_ioniq_6.turn_in_boost_left"] == pytest.approx(0.08)
assert fake_params_cls._store["FLMActiveOverrides"]["vehicleKnobs"]["hyundai_ioniq_6.unwind_taper_left"] == pytest.approx(0.55)
assert fake_params_cls._memory_store["StarPilotTogglesUpdated"] is True
fake_params_cls._memory_store["StarPilotTogglesUpdated"] = False
revert_result = module.revert_trial_profile()
assert revert_result["snapshot"]["profileId"] == profile_id
assert fake_params_cls._store["AdvancedLateralTune"] is False
@@ -858,6 +867,7 @@ def test_apply_and_revert_trial_profile_round_trip(tmp_path):
assert fake_params_cls._store["FLMTrialApplied"] is False
assert "FLMTrialBaseline" not in fake_params_cls._store
assert fake_params_cls._store["FLMActiveOverrides"]["vehicleKnobs"]["hyundai_ioniq_6.unwind_taper_left"] == pytest.approx(0.55)
assert fake_params_cls._memory_store["StarPilotTogglesUpdated"] is True
def test_repeated_trial_revisions_revert_to_original_baseline(tmp_path):
@@ -1040,6 +1050,7 @@ def test_irrecoverable_trial_can_keep_current_values_as_new_baseline(tmp_path):
assert fake_params_cls._store["FLMActiveOverrides"]["vehicleKnobs"]["generic.turn_in_boost_left"] == pytest.approx(0.1)
assert fake_params_cls._store["FLMActiveProfileId"] == ""
assert fake_params_cls._store["FLMTrialApplied"] is False
assert fake_params_cls._memory_store["StarPilotTogglesUpdated"] is True
def test_workspace_hydrates_display_metadata_for_existing_active_trial(tmp_path):