Files
StarPilot/system/manager/launch_param_migrations.py
firestar5683 261b139bcc honda
2026-05-04 11:19:22 -05:00

189 lines
6.6 KiB
Python

#!/usr/bin/env python3
from __future__ import annotations
import sys
from pathlib import Path
from typing import Protocol
LONG_PITCH_KEY = "LongPitch"
STEER_KP_KEY = "SteerKP"
STEER_KP_STOCK_KEY = "SteerKPStock"
DEFAULT_STEER_KP = 0.6
LEGACY_STEER_KP = 0.7
QT_STEER_KP_PLACEHOLDER = 1.0
LAUNCH_PARAM_MIGRATION_MARKER = ".starpilot_launch_param_migrations_v2"
BRANCH_DEFAULTS_MIGRATION_MARKER = ".starpilot_branch_defaults_migrations_v1"
ACCELERATION_PROFILE_MIGRATION_MARKER = ".starpilot_acceleration_profile_default_v1"
MARKER_DIRNAME = ".starpilot_param_migrations"
LEGACY_CE_STOPPED_LEAD_DEFAULT = True
LEGACY_FORCE_STOPS_DEFAULT = False
LEGACY_AGGRESSIVE_FOLLOW_HIGH_DEFAULT = 1.25
LEGACY_STANDARD_FOLLOW_HIGH_DEFAULT = 1.45
LEGACY_RELAXED_FOLLOW_DEFAULT = 1.75
LEGACY_RELAXED_FOLLOW_HIGH_DEFAULT = 1.75
LEGACY_JERK_DEFAULT = 50.0
LEGACY_ACCELERATION_PROFILE_DEFAULT = 2
STANDARD_ACCELERATION_PROFILE = 0
BRANCH_BOOL_MIGRATIONS = {
"CEStoppedLead": (LEGACY_CE_STOPPED_LEAD_DEFAULT, False),
"ForceStops": (LEGACY_FORCE_STOPS_DEFAULT, True),
}
BRANCH_FLOAT_MIGRATIONS = {
"AggressiveFollowHigh": (LEGACY_AGGRESSIVE_FOLLOW_HIGH_DEFAULT, 1.0),
"StandardFollowHigh": (LEGACY_STANDARD_FOLLOW_HIGH_DEFAULT, 1.2),
"StandardJerkAcceleration": (LEGACY_JERK_DEFAULT, 100.0),
"StandardJerkDeceleration": (LEGACY_JERK_DEFAULT, 100.0),
"StandardJerkSpeed": (LEGACY_JERK_DEFAULT, 100.0),
"StandardJerkSpeedDecrease": (LEGACY_JERK_DEFAULT, 100.0),
"RelaxedFollow": (LEGACY_RELAXED_FOLLOW_DEFAULT, 1.6),
"RelaxedFollowHigh": (LEGACY_RELAXED_FOLLOW_HIGH_DEFAULT, 1.4),
"RelaxedJerkAcceleration": (LEGACY_JERK_DEFAULT, 100.0),
"RelaxedJerkDeceleration": (LEGACY_JERK_DEFAULT, 100.0),
"RelaxedJerkSpeed": (LEGACY_JERK_DEFAULT, 100.0),
"RelaxedJerkSpeedDecrease": (LEGACY_JERK_DEFAULT, 100.0),
}
ACCELERATION_PROFILE_MIGRATION = {
"AccelerationProfile": (LEGACY_ACCELERATION_PROFILE_DEFAULT, STANDARD_ACCELERATION_PROFILE),
}
class ParamsLike(Protocol):
def get_param_path(self, key: str = "") -> str: ...
def get_bool(self, key: str) -> bool: ...
def get_int(self, key: str) -> int: ...
def get_float(self, key: str) -> float: ...
def put_bool(self, key: str, value: bool) -> None: ...
def put_int(self, key: str, value: int) -> None: ...
def put_float(self, key: str, value: float) -> None: ...
def _approx_equal(lhs: float, rhs: float, tolerance: float = 1e-6) -> bool:
return abs(lhs - rhs) <= tolerance
def _default_marker_path(params: ParamsLike) -> Path:
return _marker_dir_path(params) / LAUNCH_PARAM_MIGRATION_MARKER
def _branch_defaults_marker_path(params: ParamsLike) -> Path:
return _marker_dir_path(params) / BRANCH_DEFAULTS_MIGRATION_MARKER
def _acceleration_profile_marker_path(params: ParamsLike) -> Path:
return _marker_dir_path(params) / ACCELERATION_PROFILE_MIGRATION_MARKER
def _marker_dir_path(params: ParamsLike) -> Path:
params_path = Path(params.get_param_path())
# Params.clear_all() removes unknown files inside the params directory, so
# one-time migration markers must live alongside it, not inside it.
return params_path.parent / MARKER_DIRNAME / params_path.name
def _param_file_exists(params: ParamsLike, key: str) -> bool:
return Path(params.get_param_path(key)).exists()
def _should_migrate_bool_param(params: ParamsLike, key: str, legacy_default: bool) -> bool:
return not _param_file_exists(params, key) or params.get_bool(key) == legacy_default
def _should_migrate_int_param(params: ParamsLike, key: str, legacy_default: int) -> bool:
return not _param_file_exists(params, key) or params.get_int(key) == legacy_default
def _should_migrate_float_param(params: ParamsLike, key: str, legacy_default: float) -> bool:
return not _param_file_exists(params, key) or _approx_equal(params.get_float(key), legacy_default)
def _apply_legacy_launch_param_migrations(params: ParamsLike, marker: Path) -> None:
if marker.exists():
return
marker.parent.mkdir(parents=True, exist_ok=True)
if not params.get_bool(LONG_PITCH_KEY):
params.put_bool(LONG_PITCH_KEY, True)
steer_kp = params.get_float(STEER_KP_KEY)
if _approx_equal(steer_kp, 0.0) or _approx_equal(steer_kp, LEGACY_STEER_KP):
params.put_float(STEER_KP_KEY, DEFAULT_STEER_KP)
steer_kp_stock = params.get_float(STEER_KP_STOCK_KEY)
if (_approx_equal(steer_kp_stock, 0.0) or
_approx_equal(steer_kp_stock, LEGACY_STEER_KP) or
_approx_equal(steer_kp_stock, QT_STEER_KP_PLACEHOLDER)):
params.put_float(STEER_KP_STOCK_KEY, DEFAULT_STEER_KP)
# Initialize UsePrebuilt to True if never explicitly set, so the UI default
# matches the shell script's default of USE_PREBUILT=1.
if not Path(params.get_param_path("UsePrebuilt")).exists():
params.put_bool("UsePrebuilt", True)
marker.touch()
def _apply_branch_default_migration(params: ParamsLike, marker: Path) -> None:
if marker.exists():
return
marker.parent.mkdir(parents=True, exist_ok=True)
for key, (legacy_default, new_default) in BRANCH_BOOL_MIGRATIONS.items():
if _should_migrate_bool_param(params, key, legacy_default):
params.put_bool(key, new_default)
for key, (legacy_default, new_default) in BRANCH_FLOAT_MIGRATIONS.items():
if _should_migrate_float_param(params, key, legacy_default):
params.put_float(key, new_default)
marker.touch()
def _apply_acceleration_profile_default_migration(params: ParamsLike, marker: Path) -> None:
if marker.exists():
return
marker.parent.mkdir(parents=True, exist_ok=True)
for key, (legacy_default, new_default) in ACCELERATION_PROFILE_MIGRATION.items():
if _should_migrate_int_param(params, key, legacy_default):
params.put_int(key, new_default)
marker.touch()
def apply_launch_param_migrations(params: ParamsLike, marker_path: Path | None = None,
branch_defaults_marker_path: Path | None = None,
acceleration_profile_marker_path: Path | None = None) -> None:
_apply_legacy_launch_param_migrations(params, marker_path or _default_marker_path(params))
# Keep branch-default rollout on its own marker so older installs that already
# have the legacy marker still receive this one-time param reset.
_apply_branch_default_migration(params, branch_defaults_marker_path or _branch_defaults_marker_path(params))
_apply_acceleration_profile_default_migration(
params, acceleration_profile_marker_path or _acceleration_profile_marker_path(params)
)
def main() -> int:
try:
from openpilot.common.params import Params
apply_launch_param_migrations(Params())
except Exception as exc:
print(f"launch_param_migrations.py failed: {exc}", file=sys.stderr)
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())