custom accel and screen timeout

This commit is contained in:
firestar5683
2026-04-04 19:12:45 -05:00
parent 5f1e0eeb3a
commit 4ebe5a277a
49 changed files with 424 additions and 117 deletions
+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/env python3
from __future__ import annotations
from openpilot.selfdrive.controls.lib.longitudinal_planner import get_max_accel
ACCELERATION_PROFILES = {
"STANDARD": 0,
"ECO": 1,
"SPORT": 2,
"SPORT_PLUS": 3,
}
DECELERATION_PROFILES = {
"STANDARD": 0,
"ECO": 1,
"SPORT": 2,
}
# MPH = [0.0, 11, 22, 34, 45, 56, 89]
A_CRUISE_MAX_BP_CUSTOM = [0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 40.0]
CUSTOM_ACCEL_PROFILE_PARAM_SPECS = [
("CustomAccelProfile0MPH", 0),
("CustomAccelProfile11MPH", 11),
("CustomAccelProfile22MPH", 22),
("CustomAccelProfile34MPH", 34),
("CustomAccelProfile45MPH", 45),
("CustomAccelProfile56MPH", 56),
("CustomAccelProfile89MPH", 89),
]
CUSTOM_ACCEL_PROFILE_PARAM_KEYS = [key for key, _ in CUSTOM_ACCEL_PROFILE_PARAM_SPECS]
CUSTOM_ACCEL_PROFILE_VALUE_MIN = 0.0
CUSTOM_ACCEL_PROFILE_VALUE_MAX = 6.0
A_CRUISE_MAX_VALS_ECO_EV = [1.25, 1.25, 1.25, 1.25, 1.45, 1.50, 2.00]
A_CRUISE_MAX_VALS_STANDARD_EV = [1.35, 1.35, 1.35, 1.35, 1.60, 1.60, 2.10]
A_CRUISE_MAX_VALS_SPORT_EV = [1.55, 1.55, 1.55, 1.55, 1.84, 1.84, 2.42]
A_CRUISE_MAX_VALS_SPORT_PLUS_EV = [1.7825, 1.7825, 1.7825, 1.7825, 2.116, 2.116, 2.783]
A_CRUISE_MAX_VALS_ECO_GAS = [2.0, 1.5, 1.0, 0.8, 0.6, 0.4, 0.2]
A_CRUISE_MAX_VALS_SPORT_GAS = [3.0, 2.5, 2.0, 1.5, 1.0, 0.8, 0.6]
A_CRUISE_MAX_VALS_ECO_TRUCK = [3.00, 1.05, 0.60, 0.50, 0.50, 0.45, 0.35]
A_CRUISE_MAX_VALS_STANDARD_TRUCK = [6.00, 1.10, 0.70, 0.60, 0.55, 0.45, 0.35]
A_CRUISE_MAX_VALS_SPORT_TRUCK = [6.00, 1.15, 0.75, 0.70, 0.60, 0.50, 0.40]
A_CRUISE_MAX_VALS_SPORT_PLUS_TRUCK = [6.00, 1.30, 0.90, 0.80, 0.70, 0.60, 0.45]
def akima_interp(x, xp, fp):
if x <= xp[0]:
return fp[0]
if x >= xp[-1]:
return fp[-1]
i = max(0, min(len(xp) - 2, int(next(idx for idx, bp in enumerate(xp[1:], start=1) if bp >= x) - 1)))
t = (x - xp[i]) / float(xp[i + 1] - xp[i])
t2 = t * t
t3 = t2 * t
t4 = t2 * t2
return (fp[i] * (1 - 10 * t3 + 15 * t4 - 6 * t3 * t2)
+ fp[i + 1] * (10 * t3 - 15 * t4 + 6 * t3 * t2))
def normalize_acceleration_profile(value):
return _normalize_profile(value, ACCELERATION_PROFILES, ACCELERATION_PROFILES["STANDARD"])
def normalize_deceleration_profile(value):
return _normalize_profile(value, DECELERATION_PROFILES, DECELERATION_PROFILES["STANDARD"])
def get_accel_profile_curve_values(acceleration_profile, ev_tuning=True, truck_tuning=False):
profile = normalize_acceleration_profile(acceleration_profile)
if truck_tuning:
ev_tuning = False
if profile == ACCELERATION_PROFILES["ECO"]:
if ev_tuning:
return list(A_CRUISE_MAX_VALS_ECO_EV)
if truck_tuning:
return list(A_CRUISE_MAX_VALS_ECO_TRUCK)
return list(A_CRUISE_MAX_VALS_ECO_GAS)
if profile == ACCELERATION_PROFILES["SPORT"]:
if ev_tuning:
return list(A_CRUISE_MAX_VALS_SPORT_EV)
if truck_tuning:
return list(A_CRUISE_MAX_VALS_SPORT_TRUCK)
return list(A_CRUISE_MAX_VALS_SPORT_GAS)
if profile == ACCELERATION_PROFILES["SPORT_PLUS"]:
if ev_tuning:
return list(A_CRUISE_MAX_VALS_SPORT_PLUS_EV)
if truck_tuning:
return list(A_CRUISE_MAX_VALS_SPORT_PLUS_TRUCK)
return [float(akima_interp(v_ego, [0.0, 5.0, 20.0], [4.0, 4.0, 2.0])) for v_ego in A_CRUISE_MAX_BP_CUSTOM]
if ev_tuning:
return list(A_CRUISE_MAX_VALS_STANDARD_EV)
if truck_tuning:
return list(A_CRUISE_MAX_VALS_STANDARD_TRUCK)
return [float(get_max_accel(v_ego)) for v_ego in A_CRUISE_MAX_BP_CUSTOM]
def interpolate_accel_profile(v_ego, curve_values):
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, curve_values))
def get_max_allowed_accel(v_ego, ev_tuning=True, truck_tuning=False):
return interpolate_accel_profile(v_ego, get_accel_profile_curve_values(ACCELERATION_PROFILES["SPORT_PLUS"], ev_tuning, truck_tuning))
def build_custom_accel_profile_defaults(acceleration_profile, ev_tuning=True, truck_tuning=False):
curve_values = get_accel_profile_curve_values(acceleration_profile, ev_tuning, truck_tuning)
return {
key: float(curve_values[idx])
for idx, key in enumerate(CUSTOM_ACCEL_PROFILE_PARAM_KEYS)
}
def coerce_custom_accel_profile_values(raw_values, acceleration_profile, ev_tuning=True, truck_tuning=False):
defaults = get_accel_profile_curve_values(acceleration_profile, ev_tuning, truck_tuning)
values = []
for idx, default in enumerate(defaults):
try:
value = float(raw_values[idx])
except (IndexError, TypeError, ValueError):
value = default
values.append(min(CUSTOM_ACCEL_PROFILE_VALUE_MAX, max(CUSTOM_ACCEL_PROFILE_VALUE_MIN, value)))
return values
def _normalize_profile(value, profile_map, fallback):
if isinstance(value, bytes):
value = value.decode("utf-8", errors="replace")
if isinstance(value, str):
normalized = value.strip().upper().replace("+", "_PLUS").replace(" ", "_")
if normalized in profile_map:
return profile_map[normalized]
try:
return int(float(value))
except (TypeError, ValueError):
return fallback
+8
View File
@@ -48,6 +48,14 @@ SAFE_MODE_MANAGED_KEYS = (
"AdvancedLongitudinalTune",
"EVTuning",
"TruckTuning",
"CustomAccelProfile",
"CustomAccelProfile0MPH",
"CustomAccelProfile11MPH",
"CustomAccelProfile22MPH",
"CustomAccelProfile34MPH",
"CustomAccelProfile45MPH",
"CustomAccelProfile56MPH",
"CustomAccelProfile89MPH",
"LongitudinalActuatorDelay",
"MaxDesiredAcceleration",
"StartAccel",
+24 -2
View File
@@ -10,6 +10,7 @@ from pathlib import Path
from types import SimpleNamespace
import cereal.messaging as messaging
import numpy as np
from cereal import car, custom, log
from opendbc.car import gen_empty_fingerprint
@@ -25,6 +26,16 @@ from openpilot.common.constants import CV
from openpilot.common.params import Params
from openpilot.selfdrive.controls.lib.latcontrol_torque import KP
from openpilot.selfdrive.modeld.constants import ModelConstants
from openpilot.starpilot.common.accel_profile import (
ACCELERATION_PROFILES,
CUSTOM_ACCEL_PROFILE_PARAM_KEYS,
CUSTOM_ACCEL_PROFILE_VALUE_MAX,
CUSTOM_ACCEL_PROFILE_VALUE_MIN,
DECELERATION_PROFILES,
build_custom_accel_profile_defaults,
normalize_acceleration_profile,
normalize_deceleration_profile,
)
from openpilot.system.hardware import HARDWARE
from openpilot.system.hardware.hw import Paths
from openpilot.system.hardware.power_monitoring import VBATT_PAUSE_CHARGING
@@ -787,8 +798,19 @@ class StarPilotVariables:
toggle.lock_doors_timer = self.get_value("LockDoorsTimer", cast=float, condition=(toggle.car_make == "toyota"))
longitudinal_tuning = toggle.openpilot_longitudinal and self.get_value("LongitudinalTune")
toggle.acceleration_profile = self.get_value("AccelerationProfile", cast=float, condition=longitudinal_tuning)
toggle.deceleration_profile = self.get_value("DecelerationProfile", cast=float, condition=longitudinal_tuning)
toggle.acceleration_profile = normalize_acceleration_profile(
self.get_value("AccelerationProfile", cast=None, condition=longitudinal_tuning, default=ACCELERATION_PROFILES["SPORT"])
)
toggle.deceleration_profile = normalize_deceleration_profile(
self.get_value("DecelerationProfile", cast=None, condition=longitudinal_tuning, default=DECELERATION_PROFILES["ECO"])
)
toggle.custom_accel_profile = self.get_value("CustomAccelProfile", condition=longitudinal_tuning)
custom_accel_defaults = build_custom_accel_profile_defaults(toggle.acceleration_profile, toggle.ev_tuning, toggle.truck_tuning)
toggle.custom_accel_profile_values = [
self.get_value(key, cast=float, condition=longitudinal_tuning, default=custom_accel_defaults[key],
min=CUSTOM_ACCEL_PROFILE_VALUE_MIN, max=CUSTOM_ACCEL_PROFILE_VALUE_MAX)
for key in CUSTOM_ACCEL_PROFILE_PARAM_KEYS
]
toggle.human_acceleration = self.get_value("HumanAcceleration", condition=longitudinal_tuning)
toggle.human_following = self.get_value("HumanFollowing", condition=longitudinal_tuning)
toggle.human_lane_changes = has_radar and self.get_value("HumanLaneChanges", condition=longitudinal_tuning)
@@ -3,6 +3,14 @@ import numpy as np
from openpilot.selfdrive.controls.lib.longitudinal_planner import A_CRUISE_MIN, get_max_accel
from openpilot.starpilot.common.accel_profile import (
ACCELERATION_PROFILES,
DECELERATION_PROFILES,
coerce_custom_accel_profile_values,
get_accel_profile_curve_values,
get_max_allowed_accel as get_profile_max_allowed_accel,
interpolate_accel_profile,
)
from openpilot.starpilot.common.starpilot_variables import CITY_SPEED_LIMIT
def cubic_interp(x, xp, fp):
@@ -45,56 +53,20 @@ def akima_interp(x, xp, fp):
A_CRUISE_MIN_ECO = A_CRUISE_MIN / 2
A_CRUISE_MIN_SPORT = A_CRUISE_MIN * 2
# MPH = [0.0, 11, 22, 34, 45, 56, 89]
A_CRUISE_MAX_BP_CUSTOM = [0.0, 5., 10., 15., 20., 25., 40.]
A_CRUISE_MAX_VALS_ECO_EV = [1.25, 1.25, 1.25, 1.25, 1.45, 1.50, 2.00]
A_CRUISE_MAX_VALS_STANDARD_EV = [1.35, 1.35, 1.35, 1.35, 1.60, 1.60, 2.10]
A_CRUISE_MAX_VALS_SPORT_EV = [1.55, 1.55, 1.55, 1.55, 1.84, 1.84, 2.42]
A_CRUISE_MAX_VALS_SPORT_PLUS_EV = [1.7825, 1.7825, 1.7825, 1.7825, 2.116, 2.116, 2.783]
A_CRUISE_MAX_VALS_ECO_GAS = [2.0, 1.5, 1.0, 0.8, 0.6, 0.4, 0.2]
A_CRUISE_MAX_VALS_SPORT_GAS = [3.0, 2.5, 2.0, 1.5, 1.0, 0.8, 0.6]
A_CRUISE_MAX_VALS_ECO_TRUCK = [3.00, 1.05, 0.60, 0.50, 0.50, 0.45, 0.35]
A_CRUISE_MAX_VALS_STANDARD_TRUCK = [6.00, 1.10, 0.70, 0.60, 0.55, 0.45, 0.35]
A_CRUISE_MAX_VALS_SPORT_TRUCK = [6.00, 1.15, 0.75, 0.70, 0.60, 0.50, 0.40]
A_CRUISE_MAX_VALS_SPORT_PLUS_TRUCK = [6.00, 1.30, 0.90, 0.80, 0.70, 0.60, 0.45]
ACCELERATION_PROFILES = {
"STANDARD": 0,
"ECO": 1,
"SPORT": 2,
"SPORT_PLUS": 3
}
DECELERATION_PROFILES = {
"STANDARD": 0,
"ECO": 1,
"SPORT": 2
}
def get_max_accel_eco(v_ego, ev_tuning=True, truck_tuning=False):
if ev_tuning:
cruise_vals = A_CRUISE_MAX_VALS_ECO_EV
elif truck_tuning:
cruise_vals = A_CRUISE_MAX_VALS_ECO_TRUCK
else:
cruise_vals = A_CRUISE_MAX_VALS_ECO_GAS
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, cruise_vals))
return interpolate_accel_profile(v_ego, get_accel_profile_curve_values(ACCELERATION_PROFILES["ECO"], ev_tuning, truck_tuning))
def get_max_accel_sport(v_ego, ev_tuning=True, truck_tuning=False):
if ev_tuning:
cruise_vals = A_CRUISE_MAX_VALS_SPORT_EV
elif truck_tuning:
cruise_vals = A_CRUISE_MAX_VALS_SPORT_TRUCK
else:
cruise_vals = A_CRUISE_MAX_VALS_SPORT_GAS
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, cruise_vals))
return interpolate_accel_profile(v_ego, get_accel_profile_curve_values(ACCELERATION_PROFILES["SPORT"], ev_tuning, truck_tuning))
def get_max_accel_standard(v_ego, ev_tuning=True, truck_tuning=False):
if ev_tuning:
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_STANDARD_EV))
if truck_tuning:
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_STANDARD_TRUCK))
return get_max_accel(v_ego)
if ev_tuning or truck_tuning:
return interpolate_accel_profile(v_ego, get_accel_profile_curve_values(ACCELERATION_PROFILES["STANDARD"], ev_tuning, truck_tuning))
return float(get_max_accel(v_ego))
def get_max_accel_custom(v_ego, custom_curve, acceleration_profile, ev_tuning=True, truck_tuning=False):
curve_values = coerce_custom_accel_profile_values(custom_curve, acceleration_profile, ev_tuning, truck_tuning)
return interpolate_accel_profile(v_ego, curve_values)
def get_max_accel_low_speeds(max_accel, v_cruise):
return float(akima_interp(v_cruise, [0., CITY_SPEED_LIMIT / 2, CITY_SPEED_LIMIT], [max_accel / 4, max_accel / 2, max_accel]))
@@ -103,11 +75,7 @@ def get_max_accel_ramp_off(max_accel, v_cruise, v_ego):
return float(akima_interp(v_cruise - v_ego, [0., 1., 5., 10.], [0., 0.5, 1.0, max_accel]))
def get_max_allowed_accel(v_ego, ev_tuning=True, truck_tuning=False):
if ev_tuning:
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT_PLUS_EV))
if truck_tuning:
return float(akima_interp(v_ego, A_CRUISE_MAX_BP_CUSTOM, A_CRUISE_MAX_VALS_SPORT_PLUS_TRUCK))
return float(akima_interp(v_ego, [0., 5., 20.], [4.0, 4.0, 2.0])) # ISO 15622:2018
return float(get_profile_max_allowed_accel(v_ego, ev_tuning, truck_tuning))
class StarPilotAcceleration:
def __init__(self, StarPilotPlanner):
@@ -121,8 +89,12 @@ class StarPilotAcceleration:
sport_gear = sm["starpilotCarState"].sportGear
ev_tuning = getattr(starpilot_toggles, "ev_tuning", True)
truck_tuning = getattr(starpilot_toggles, "truck_tuning", False)
custom_accel_profile = getattr(starpilot_toggles, "custom_accel_profile", False)
custom_accel_profile_values = getattr(starpilot_toggles, "custom_accel_profile_values", [])
if sm["starpilotCarState"].trafficModeEnabled:
if custom_accel_profile:
self.max_accel = get_max_accel_custom(v_ego, custom_accel_profile_values, starpilot_toggles.acceleration_profile, ev_tuning, truck_tuning)
elif sm["starpilotCarState"].trafficModeEnabled:
self.max_accel = get_max_accel_standard(v_ego, ev_tuning, truck_tuning)
elif starpilot_toggles.map_acceleration and (eco_gear or sport_gear):
if eco_gear:
@@ -6,6 +6,7 @@ const endpointOptionsInflight = {}
// Plain variables — scheduling/routing flags that must NOT be reactive
let syncScheduled = false
let lastParams = null
const DYNAMIC_DEFAULT_DEP_KEYS = new Set(["AccelerationProfile", "EVTuning", "TruckTuning"])
// Module-level state (persists across route changes)
const state = reactive({
@@ -141,6 +142,21 @@ async function fetchDefaultValues() {
}
}
async function refreshParamsAndDefaults() {
await fetchDefaultValues()
try {
const valuesRes = await fetch("/api/params/all")
if (valuesRes.ok) {
const data = await valuesRes.json()
state.values = data || {}
}
} catch (e) {
console.error("Failed to refresh param values:", e)
}
scheduleSyncInputs()
}
async function fetchLayoutAndParams() {
state.loadingLayout = true
state.loadingValues = true
@@ -176,14 +192,13 @@ async function fetchLayoutAndParams() {
// Pull params once at page load; local state handles subsequent edits.
try {
const valuesRes = await fetch("/api/params/all")
const data = await valuesRes.json()
state.values = data
if (!(await fetchDefaultValues())) {
state.defaultValues = {}
}
const valuesRes = await fetch("/api/params/all")
const data = await valuesRes.json()
state.values = data
} catch (e) {
console.error("Failed to fetch param values:", e)
state.defaultValues = {}
@@ -520,7 +535,11 @@ async function updateParam(key, elType) {
const updated = (data.updated && typeof data.updated === "object") ? data.updated : {}
state.values = { ...state.values, [key]: formattedVal, ...updated }
showParamSnackbar(data.message || `Parameter '${key}' updated.`)
scheduleSyncInputs()
if (DYNAMIC_DEFAULT_DEP_KEYS.has(key)) {
await refreshParamsAndDefaults()
} else {
scheduleSyncInputs()
}
} else {
revertInput(key, current, elType)
showParamSnackbar(data.error || "Failed to update parameter", "error")
@@ -254,6 +254,99 @@
"ui_type": "toggle",
"parent_key": "AdvancedLongitudinalTune"
},
{
"key": "CustomAccelProfile",
"label": "Custom Accel Profile",
"description": "Replace the built-in acceleration profile with your own per-speed max-acceleration values. Breakpoint speeds stay fixed, and the starting defaults mirror the currently selected acceleration profile plus EV or Truck tuning.",
"data_type": "bool",
"ui_type": "toggle",
"is_parent_toggle": true,
"parent_key": "AdvancedLongitudinalTune"
},
{
"key": "CustomAccelProfile0MPH",
"label": "0 mph",
"description": "Max acceleration in m/s² at the fixed 0 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile11MPH",
"label": "11 mph",
"description": "Max acceleration in m/s² at the fixed 11 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile22MPH",
"label": "22 mph",
"description": "Max acceleration in m/s² at the fixed 22 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile34MPH",
"label": "34 mph",
"description": "Max acceleration in m/s² at the fixed 34 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile45MPH",
"label": "45 mph",
"description": "Max acceleration in m/s² at the fixed 45 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile56MPH",
"label": "56 mph",
"description": "Max acceleration in m/s² at the fixed 56 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "CustomAccelProfile89MPH",
"label": "89 mph",
"description": "Max acceleration in m/s² at the fixed 89 mph breakpoint.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.0,
"max": 6.0,
"step": 0.01,
"precision": 2,
"parent_key": "CustomAccelProfile"
},
{
"key": "LongitudinalActuatorDelay",
"label": "Actuator Delay",
+83 -47
View File
@@ -41,6 +41,11 @@ from openpilot.system.version import get_build_metadata
from panda import Panda
from openpilot.starpilot.assets.theme_manager import HOLIDAY_THEME_PATH, THEME_COMPONENT_PARAMS
from openpilot.starpilot.common.accel_profile import (
CUSTOM_ACCEL_PROFILE_PARAM_KEYS,
build_custom_accel_profile_defaults,
normalize_acceleration_profile,
)
from openpilot.starpilot.common.maps_catalog import (
MAPS_CATALOG,
MAP_SCHEDULE_OPTIONS,
@@ -629,6 +634,8 @@ _TROUBLESHOOT_ADVANCED_LONGITUDINAL_KEYS = [
"AdvancedLongitudinalTune",
"EVTuning",
"TruckTuning",
"CustomAccelProfile",
*CUSTOM_ACCEL_PROFILE_PARAM_KEYS,
"LongitudinalActuatorDelay",
"StartAccel",
"VEgoStarting",
@@ -1663,6 +1670,7 @@ def _get_layout_type_overrides():
_cached_allowed_keys = None
_cached_param_types = None
_cached_default_values = None
_cached_static_default_values = None
def _get_param_type_info():
global _cached_allowed_keys, _cached_param_types
@@ -1699,15 +1707,18 @@ def _get_param_type_info():
_cached_param_types = types
return _cached_allowed_keys, _cached_param_types
def _get_default_param_values():
global _cached_default_values
if _cached_default_values is None:
_cached_default_values = {
def _get_static_default_param_values():
global _cached_static_default_values
if _cached_static_default_values is None:
_cached_static_default_values = {
key: default_val
for key, default_val, _, _ in starpilot_default_params
if key not in EXCLUDED_KEYS
}
default_values = dict(_cached_default_values)
return _cached_static_default_values
def _get_default_param_values():
default_values = dict(_get_static_default_param_values())
default_values.update(_get_runtime_default_param_overrides())
return default_values
@@ -1790,6 +1801,7 @@ def _has_runtime_default_value(key, raw_value):
def _get_runtime_default_param_overrides():
overrides = {}
static_defaults = _get_static_default_param_values()
for key, stock_key in _RUNTIME_DEFAULT_STOCK_KEYS.items():
stock_raw = _safe_params_get_live_raw(stock_key)
@@ -1798,40 +1810,60 @@ def _get_runtime_default_param_overrides():
overrides[stock_key] = stock_raw
cp_bytes = _safe_params_get_live_raw("CarParamsPersistent")
if not cp_bytes:
return overrides
if cp_bytes:
try:
with car.CarParams.from_bytes(cp_bytes) as cp:
overrides["EVTuning"] = default_ev_tuning_enabled(cp)
try:
with car.CarParams.from_bytes(cp_bytes) as cp:
overrides["EVTuning"] = default_ev_tuning_enabled(cp)
car_param_defaults = {
"SteerDelay": getattr(cp, "steerActuatorDelay", None),
"SteerRatio": getattr(cp, "steerRatio", None),
"LongitudinalActuatorDelay": getattr(cp, "longitudinalActuatorDelay", None),
"StartAccel": getattr(cp, "startAccel", None),
"StopAccel": getattr(cp, "stopAccel", None),
"StoppingDecelRate": getattr(cp, "stoppingDecelRate", None),
"VEgoStarting": getattr(cp, "vEgoStarting", None),
"VEgoStopping": getattr(cp, "vEgoStopping", None),
}
car_param_defaults = {
"SteerDelay": getattr(cp, "steerActuatorDelay", None),
"SteerRatio": getattr(cp, "steerRatio", None),
"LongitudinalActuatorDelay": getattr(cp, "longitudinalActuatorDelay", None),
"StartAccel": getattr(cp, "startAccel", None),
"StopAccel": getattr(cp, "stopAccel", None),
"StoppingDecelRate": getattr(cp, "stoppingDecelRate", None),
"VEgoStarting": getattr(cp, "vEgoStarting", None),
"VEgoStopping": getattr(cp, "vEgoStopping", None),
}
for key, value in car_param_defaults.items():
if key in overrides or value is None:
continue
if key not in _RUNTIME_DEFAULT_ZERO_OK_KEYS and float(value) == 0.0:
continue
overrides[key] = value
except Exception:
pass
for key, value in car_param_defaults.items():
if key in overrides or value is None:
continue
if key not in _RUNTIME_DEFAULT_ZERO_OK_KEYS and float(value) == 0.0:
continue
overrides[key] = value
except Exception:
pass
ev_tuning_raw = _safe_params_get_live_raw("EVTuning")
truck_tuning_raw = _safe_params_get_live_raw("TruckTuning")
acceleration_profile_raw = _safe_params_get_live_raw("AccelerationProfile")
ev_tuning = _coerce_param_value(
ev_tuning_raw if not _is_blank_param_raw(ev_tuning_raw) else overrides.get("EVTuning", static_defaults.get("EVTuning", "0")),
bool,
)
truck_tuning = _coerce_param_value(
truck_tuning_raw if not _is_blank_param_raw(truck_tuning_raw) else static_defaults.get("TruckTuning", "0"),
bool,
)
if truck_tuning:
ev_tuning = False
acceleration_profile = normalize_acceleration_profile(
acceleration_profile_raw if not _is_blank_param_raw(acceleration_profile_raw) else static_defaults.get("AccelerationProfile", "0")
)
overrides.update(build_custom_accel_profile_defaults(acceleration_profile, ev_tuning, truck_tuning))
return overrides
def _get_current_param_value(key, value_type):
safe_type = value_type or str
if safe_type == bool:
return params.get_bool(key)
return _coerce_param_value(params.get(key), safe_type)
def _get_current_param_value(key, value_type, defaults_lookup=None):
raw_value = _safe_params_get_live_raw(key)
if _is_blank_param_raw(raw_value):
if defaults_lookup is None:
defaults_lookup = _get_default_param_values()
raw_value = defaults_lookup.get(key)
return _coerce_param_value(raw_value, value_type)
def _serialize_param_write_value(raw_value):
if isinstance(raw_value, bool):
@@ -3108,6 +3140,22 @@ def setup(app):
if key == "AutomaticUpdates" and params.get_bool("IsOnroad"):
return jsonify({"error": "Cannot change Automatic Updates while driving."}), 403
if key in {"EVTuning", "TruckTuning"}:
enabled = str_val.strip() in ("1", "true", "True")
params.put_bool(key, enabled)
updated = {key: enabled}
if enabled:
other_key = "TruckTuning" if key == "EVTuning" else "EVTuning"
params.put_bool(other_key, False)
updated[other_key] = False
update_starpilot_toggles()
return jsonify({
"message": f"Parameter '{key}' updated successfully.",
"updated": updated,
}), 200
if key == "CarMake":
catalog = _get_fingerprint_catalog()
normalized_make = _normalize_fingerprint_make_key(str_val)
@@ -3225,25 +3273,13 @@ def setup(app):
def get_all_params():
_enforce_cancel_remap_lkas_lock()
allowed_keys, types = _get_param_type_info()
defaults_lookup = _get_default_param_values()
result = {}
for key in allowed_keys:
t = types.get(key, str)
try:
if t == bool:
result[key] = params.get_bool(key)
else:
raw = params.get(key)
raw_str = raw.decode("utf-8", errors="replace") if isinstance(raw, bytes) else str(raw or "")
if not raw_str:
result[key] = 0.0 if t == float else (0 if t == int else "")
elif t == float:
result[key] = float(raw_str)
elif t == int:
result[key] = int(float(raw_str))
else:
result[key] = raw_str
result[key] = _get_current_param_value(key, t, defaults_lookup)
except Exception:
result[key] = None