mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-09-14 19:44:05 +08:00
custom accel and screen timeout
This commit is contained in:
@@ -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
|
||||
@@ -48,6 +48,14 @@ SAFE_MODE_MANAGED_KEYS = (
|
||||
"AdvancedLongitudinalTune",
|
||||
"EVTuning",
|
||||
"TruckTuning",
|
||||
"CustomAccelProfile",
|
||||
"CustomAccelProfile0MPH",
|
||||
"CustomAccelProfile11MPH",
|
||||
"CustomAccelProfile22MPH",
|
||||
"CustomAccelProfile34MPH",
|
||||
"CustomAccelProfile45MPH",
|
||||
"CustomAccelProfile56MPH",
|
||||
"CustomAccelProfile89MPH",
|
||||
"LongitudinalActuatorDelay",
|
||||
"MaxDesiredAcceleration",
|
||||
"StartAccel",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user