This commit is contained in:
firestar5683
2026-08-08 14:42:00 -05:00
parent 89d8b1cb1b
commit 57ac82d148
29 changed files with 227 additions and 64 deletions
+6 -6
View File
@@ -208,7 +208,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"CECurves", {PERSISTENT, BOOL, "0", "0", 1, SETTINGS_SIMPLE}},
{"CECurvesLead", {PERSISTENT, BOOL, "0", "0", 1}},
{"CELead", {PERSISTENT, BOOL, "1", "0", 1, SETTINGS_SIMPLE}},
{"CEModelStopTime", {PERSISTENT, FLOAT, "7.0", "0.0", 2, SETTINGS_SIMPLE}},
{"CEModelStopTime", {PERSISTENT, FLOAT, "9.0", "0.0", 2, SETTINGS_SIMPLE}},
{"CESignalLaneDetection", {PERSISTENT, BOOL, "1", "0", 2}},
{"CESignalSpeed", {PERSISTENT, FLOAT, "0.0", "0.0", 2, SETTINGS_SIMPLE}},
{"CESlowerLead", {PERSISTENT, BOOL, "1", "0", 1, SETTINGS_SIMPLE}},
@@ -289,11 +289,11 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"DownloadAllModels", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"DownloadMaps", {CLEAR_ON_MANAGER_START, BOOL, "0", "0"}},
{"DriverCamera", {PERSISTENT, BOOL, "0", "0", 1, SETTINGS_SIMPLE}},
{"Model", {PERSISTENT, STRING, "sc2", "sc2", 1}},
{"ModelVersion", {PERSISTENT, STRING, "v11", "v11", 1}},
{"DrivingModel", {PERSISTENT, STRING, "sc2", "sc2", 1}},
{"DrivingModelName", {PERSISTENT, STRING, "South Carolina", "South Carolina", 1}},
{"DrivingModelVersion", {PERSISTENT, STRING, "v11", "v11", 1}},
{"Model", {PERSISTENT, STRING, "rdf", "rdf", 1}},
{"ModelVersion", {PERSISTENT, STRING, "v15", "v15", 1}},
{"DrivingModel", {PERSISTENT, STRING, "rdf", "rdf", 1}},
{"DrivingModelName", {PERSISTENT, STRING, "Regret Driven Framework", "Regret Driven Framework", 1}},
{"DrivingModelVersion", {PERSISTENT, STRING, "v15", "v15", 1}},
{"DynamicPathWidth", {PERSISTENT, BOOL, "0", "0", 2, SETTINGS_SIMPLE}},
{"DynamicPedalsOnUI", {PERSISTENT, BOOL, "1", "0", 1, SETTINGS_SIMPLE}},
{"EngageVolume", {PERSISTENT, INT, "101", "101", 2, SETTINGS_SIMPLE}},
@@ -32,6 +32,7 @@ HYUNDAI_CANFD_SCC_DECEL_STEP = 12.5 / 50.0
IONIQ_6_RESPONSE_MULTIPLIER = 1.2
IONIQ_6_CANFD_SCC_ACCEL_STEP = (6.0 / 50.0) * IONIQ_6_RESPONSE_MULTIPLIER
IONIQ_6_CANFD_SCC_DECEL_STEP = (15.0 / 50.0) * IONIQ_6_RESPONSE_MULTIPLIER
EV9_CANFD_SCC_DECEL_STEP = 10.0 / 50.0
GENESIS_G90_STOP_HOLD_SPEED_BP = [0.0, 0.03, 0.08, 0.16, 0.3, 0.5, 0.8, 1.2, 2.0, 3.0]
GENESIS_G90_STOP_HOLD_ACCEL_V = [-0.10, -0.10, -0.12, -0.18, -0.30, -0.50, -0.75, -1.00, -1.40, -1.80]
GENESIS_G90_STOP_HOLD_RELAX_SPEED_BP = [0.0, 0.08, 0.16, 0.3, 0.5, 0.8, 1.2, 2.0, 3.0]
@@ -80,6 +81,10 @@ def egmp_dynamic_longitudinal_tuning(CP) -> bool:
kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, getattr(CP, "carVin", ""))
def get_canfd_scc_decel_step(CP) -> float:
return EV9_CANFD_SCC_DECEL_STEP if CP.carFingerprint == CAR.KIA_EV9 else IONIQ_6_CANFD_SCC_DECEL_STEP
def should_reset_ev6_gt_line_longitudinal_tuning(CP, long_control_state: LongCtrlState) -> bool:
return kia_ev6_gt_line_longitudinal_tuning(CP.carFingerprint, getattr(CP, "carVin", "")) and \
long_control_state == LongCtrlState.off
@@ -627,8 +632,9 @@ class CarController(CarControllerBase):
accel = self._ioniq_6_long_tuning.actual_accel
stopping = self._ioniq_6_long_tuning.stopping
else:
decel_step = get_canfd_scc_decel_step(self.CP)
accel = float(np.clip(accel_cmd,
self.accel_last - IONIQ_6_CANFD_SCC_DECEL_STEP,
self.accel_last - decel_step,
self.accel_last + IONIQ_6_CANFD_SCC_ACCEL_STEP))
self._ioniq_6_long_tuning.desired_accel = accel_cmd
self._ioniq_6_long_tuning.actual_accel = accel
@@ -13,6 +13,7 @@ from opendbc.car.hyundai.carcontroller import CarController, Ioniq6LongitudinalT
reset_egmp_longitudinal_tuning, \
update_ioniq_6_longitudinal_tuning, \
update_genesis_g90_longitudinal_tuning, egmp_dynamic_longitudinal_tuning, \
get_canfd_scc_decel_step, \
should_reset_ev6_gt_line_longitudinal_tuning, reset_ev6_gt_line_longitudinal_tuning, \
direct_angle_request_allowed, get_angle_smoothing_alpha, \
should_use_ev6_gt_line_stop_direct_tracking
@@ -1319,6 +1320,13 @@ class TestHyundaiFingerprint:
ioniq_6_cp = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, gen_empty_fingerprint(), [], True, False, False, toggles)
assert CarInterface.get_pid_accel_limits(ioniq_6_cp, 0.0, 0.0)[1] == pytest.approx(CarControllerParams.ACCEL_MAX)
def test_ev9_uses_softer_direct_brake_handoff_than_ioniq_6(self):
ev9_cp = SimpleNamespace(carFingerprint=CAR.KIA_EV9)
ioniq_6_cp = SimpleNamespace(carFingerprint=CAR.HYUNDAI_IONIQ_6)
assert get_canfd_scc_decel_step(ev9_cp) == pytest.approx(0.20)
assert get_canfd_scc_decel_step(ioniq_6_cp) == pytest.approx(0.36)
def test_ioniq_5_pe_longitudinal_params_match_observed_response(self):
toggles = get_test_toggles()
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_5_PE, gen_empty_fingerprint(), [], True, False, False, toggles)
+7 -3
View File
@@ -20,7 +20,8 @@ class CarState(CarStateBase):
cp = can_parsers[Bus.pt]
cp_cam = can_parsers[Bus.cam]
cp_alt = can_parsers[Bus.alt]
cp_angle = cp_cam if self.CP.flags & SubaruFlags.D_PLATFORM else cp
cp_main = can_parsers[Bus.main] if self.CP.flags & SubaruFlags.D_PLATFORM else cp
cp_angle = cp_main if self.CP.flags & SubaruFlags.D_PLATFORM else cp
ret = structs.CarState()
throttle_msg = cp.vl["Throttle"] if not (self.CP.flags & SubaruFlags.HYBRID) else cp_alt.vl["Throttle_Hybrid"]
@@ -55,7 +56,7 @@ class CarState(CarStateBase):
cp.vl["Dashlights"]["RIGHT_BLINKER"])
if self.CP.enableBsm:
cp_bsm = cp_cam if self.CP.flags & SubaruFlags.D_PLATFORM else cp
cp_bsm = cp_main if self.CP.flags & SubaruFlags.D_PLATFORM else cp
ret.leftBlindspot = (cp_bsm.vl["BSD_RCTA"]["L_ADJACENT"] == 1) or (cp_bsm.vl["BSD_RCTA"]["L_APPROACHING"] == 1)
ret.rightBlindspot = (cp_bsm.vl["BSD_RCTA"]["R_ADJACENT"] == 1) or (cp_bsm.vl["BSD_RCTA"]["R_APPROACHING"] == 1)
@@ -146,8 +147,11 @@ class CarState(CarStateBase):
@staticmethod
def get_can_parsers(CP):
return {
parsers = {
Bus.pt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.main_for_cp(CP)),
Bus.cam: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.camera),
Bus.alt: CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.alt_for_cp(CP))
}
if CP.flags & SubaruFlags.D_PLATFORM:
parsers[Bus.main] = CANParser(DBC[CP.carFingerprint][Bus.pt], [], CanBus.main)
return parsers
+1 -1
View File
@@ -29,7 +29,7 @@ class CarInterface(CarInterfaceBase):
ret.enableBsm = 0x25c in fingerprint[0]
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.subaruPreglobal)]
else:
bsm_bus = CanBus.camera if ret.flags & SubaruFlags.D_PLATFORM else CanBus.main
bsm_bus = CanBus.main
ret.enableBsm = 0x228 in fingerprint[bsm_bus]
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.subaru)]
if ret.flags & SubaruFlags.GLOBAL_GEN2:
@@ -131,27 +131,35 @@ def test_torque_platform_does_not_enable_angle_safety():
def test_outback_2023_uses_d_platform_bus_layout():
CP = CarInterface.get_non_essential_params(CAR.SUBARU_OUTBACK_2023)
parsers = CarState.get_can_parsers(CP)
controller = CarController({}, CP)
assert CP.flags & SubaruFlags.D_PLATFORM
assert CP.safetyConfigs[0].safetyParam & SubaruSafetyFlags.D_PLATFORM
assert CanBus.main_for_cp(CP) == CanBus.alt
assert CanBus.angle_for_cp(CP) == CanBus.camera
assert CanBus.angle_for_cp(CP) == CanBus.main
assert parsers[Bus.pt].bus == CanBus.alt
assert parsers[Bus.cam].bus == CanBus.camera
assert parsers[Bus.alt].bus == CanBus.alt
assert parsers[Bus.main].bus == CanBus.main
assert controller.angle_bus == CanBus.main
assert controller.status_bus == CanBus.camera
def test_legacy_2025_uses_d_platform_bus_layout():
CP = CarInterface.get_non_essential_params(CAR.SUBARU_LEGACY_2025)
parsers = CarState.get_can_parsers(CP)
controller = CarController({}, CP)
assert CP.flags & SubaruFlags.D_PLATFORM
assert CP.safetyConfigs[0].safetyParam & SubaruSafetyFlags.D_PLATFORM
assert CanBus.main_for_cp(CP) == CanBus.alt
assert CanBus.angle_for_cp(CP) == CanBus.camera
assert CanBus.angle_for_cp(CP) == CanBus.main
assert parsers[Bus.pt].bus == CanBus.alt
assert parsers[Bus.cam].bus == CanBus.camera
assert parsers[Bus.alt].bus == CanBus.alt
assert parsers[Bus.main].bus == CanBus.main
assert controller.angle_bus == CanBus.main
assert controller.status_bus == CanBus.camera
def test_other_angle_platforms_keep_existing_bus_layout():
+1 -1
View File
@@ -113,7 +113,7 @@ class CanBus:
@staticmethod
def angle_for_cp(CP):
return CanBus.camera if CP.flags & SubaruFlags.D_PLATFORM else CanBus.main
return CanBus.main
class Footnote(Enum):
+4 -4
View File
@@ -56,7 +56,7 @@
{MSG_SUBARU_ES_Distance, alt_bus, 8, .check_relay = false}, \
#define SUBARU_D_PLATFORM_ANGLE_TX_MSGS() \
{MSG_SUBARU_ES_LKAS_ANGLE, SUBARU_CAM_BUS, 8, .check_relay = true}, \
{MSG_SUBARU_ES_LKAS_ANGLE, SUBARU_MAIN_BUS, 8, .check_relay = true}, \
{MSG_SUBARU_ES_DashStatus, SUBARU_CAM_BUS, 8, .check_relay = true}, \
{MSG_SUBARU_ES_LKAS_State, SUBARU_CAM_BUS, 8, .check_relay = true}, \
{MSG_SUBARU_ES_Infotainment, SUBARU_CAM_BUS, 8, .check_relay = true}, \
@@ -93,8 +93,8 @@
#define SUBARU_D_PLATFORM_ANGLE_RX_CHECKS() \
{.msg = {{MSG_SUBARU_Throttle, SUBARU_ALT_BUS, 8, 100U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_CAM_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Steering_2, SUBARU_CAM_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Steering_2, SUBARU_MAIN_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Wheel_Speeds, SUBARU_ALT_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_Brake_Status, SUBARU_ALT_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{MSG_SUBARU_ES_Brake, SUBARU_ALT_BUS, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
@@ -127,7 +127,7 @@ static uint32_t subaru_compute_checksum(const CANPacket_t *msg) {
static void subaru_rx_hook(const CANPacket_t *msg) {
const unsigned int alt_main_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS;
const unsigned int status_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_CAM_BUS;
const unsigned int steering_bus = subaru_d_platform ? SUBARU_CAM_BUS : SUBARU_MAIN_BUS;
const unsigned int steering_bus = SUBARU_MAIN_BUS;
const unsigned int main_bus = subaru_d_platform ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS;
if ((msg->addr == MSG_SUBARU_Steering_Torque) && (msg->bus == steering_bus)) {
@@ -967,6 +967,9 @@ class SafetyTest(SafetyTestBase):
continue
if attr.startswith('TestSubaruGen') and current_test.startswith('TestSubaruGen'):
continue
if 'TestSubaruDPlatformAngleSafety' in {attr, current_test} and \
'Angle' in attr and 'Angle' in current_test:
continue
if attr.startswith('TestSubaruPreglobal') and current_test.startswith('TestSubaruPreglobal'):
continue
if {attr, current_test}.issubset({'TestVolkswagenPqSafety', 'TestVolkswagenPqStockSafety', 'TestVolkswagenPqLongSafety'}):
@@ -343,21 +343,21 @@ class TestSubaruGen2AngleStockLongitudinalSafety(TestSubaruStockLongitudinalSafe
class TestSubaruDPlatformAngleSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruAngleSafetyBase):
FLAGS = SubaruSafetyFlags.GEN2 | SubaruSafetyFlags.LKAS_ANGLE | SubaruSafetyFlags.D_PLATFORM
ALT_MAIN_BUS = SUBARU_ALT_BUS
TX_MSGS = [[SubaruMsg.ES_LKAS_ANGLE, SUBARU_CAM_BUS],
TX_MSGS = [[SubaruMsg.ES_LKAS_ANGLE, SUBARU_MAIN_BUS],
[SubaruMsg.ES_DashStatus, SUBARU_CAM_BUS],
[SubaruMsg.ES_LKAS_State, SUBARU_CAM_BUS],
[SubaruMsg.ES_Infotainment, SUBARU_CAM_BUS],
[SubaruMsg.ES_Distance, SUBARU_ALT_BUS]]
RELAY_MALFUNCTION_ADDRS = {SUBARU_CAM_BUS: (SubaruMsg.ES_LKAS_ANGLE, SubaruMsg.ES_DashStatus,
SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment)}
D_PLATFORM_STATUS_ADDRS = (SubaruMsg.ES_LKAS_ANGLE, SubaruMsg.ES_DashStatus,
SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment)
RELAY_MALFUNCTION_ADDRS = {SUBARU_MAIN_BUS: (SubaruMsg.ES_LKAS_ANGLE,),
SUBARU_CAM_BUS: (SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State,
SubaruMsg.ES_Infotainment)}
FWD_BLACKLISTED_ADDRS = {
SUBARU_MAIN_BUS: D_PLATFORM_STATUS_ADDRS,
SUBARU_MAIN_BUS: [SubaruMsg.ES_DashStatus, SubaruMsg.ES_LKAS_State, SubaruMsg.ES_Infotainment],
SUBARU_CAM_BUS: [SubaruMsg.ES_LKAS_ANGLE],
}
def _torque_driver_msg(self, torque):
return self.packer.make_can_msg_safety("Steering_Torque", SUBARU_CAM_BUS, {"Steer_Torque_Sensor": torque})
return self.packer.make_can_msg_safety("Steering_Torque", SUBARU_MAIN_BUS, {"Steer_Torque_Sensor": torque})
def _user_gas_msg(self, gas):
return self.packer.make_can_msg_safety("Throttle", SUBARU_ALT_BUS, {"Throttle_Pedal": gas})
@@ -367,10 +367,10 @@ class TestSubaruDPlatformAngleSafety(TestSubaruStockLongitudinalSafetyBase, Test
self.safety.set_timer(self.angle_cmd_cnt * int(1e6 / self.LATERAL_FREQUENCY))
self.angle_cmd_cnt += 1
values = {"LKAS_Output": angle, "LKAS_Request": enabled, "SET_3": 3}
return self.packer.make_can_msg_safety("ES_LKAS_ANGLE", SUBARU_CAM_BUS, values)
return self.packer.make_can_msg_safety("ES_LKAS_ANGLE", SUBARU_MAIN_BUS, values)
def _angle_meas_msg(self, angle):
return self.packer.make_can_msg_safety("Steering_2", SUBARU_CAM_BUS, {"Steering_Angle": angle})
return self.packer.make_can_msg_safety("Steering_2", SUBARU_MAIN_BUS, {"Steering_Angle": angle})
class TestSubaruGen2LongitudinalSafety(TestSubaruLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase):
@@ -362,6 +362,7 @@ class LatControlTorque(LatControl):
friction_scale = get_prius_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk)
friction_scale = 1.0 + ((friction_scale - 1.0) * prius_center_taper)
elif camry_active:
ff *= get_camry_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo)
friction_threshold = get_camry_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk)
elif rav4_prime_active:
ff *= get_rav4_prime_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo)
@@ -821,6 +821,11 @@ CAMRY_CENTER_FRICTION_THRESHOLD_LAT = 0.22
CAMRY_CENTER_FRICTION_THRESHOLD_LAT_WIDTH = 0.06
CAMRY_CENTER_FRICTION_THRESHOLD_SPEED = 18.0
CAMRY_CENTER_FRICTION_THRESHOLD_SPEED_WIDTH = 3.0
CAMRY_UNWIND_FF_REDUCTION = 0.08
CAMRY_UNWIND_LAT_ONSET = 0.18
CAMRY_UNWIND_LAT_WIDTH = 0.07
CAMRY_UNWIND_SPEED_ONSET = 15.0
CAMRY_UNWIND_SPEED_WIDTH = 3.0
RAV4_PRIME_PHASE_SCALE = 0.12
RAV4_PRIME_TURN_IN_FF_BOOST_LEFT = 0.055
@@ -1191,6 +1196,15 @@ def get_camry_friction_threshold(v_ego: float, desired_lateral_accel: float = 0.
return get_standard_friction_threshold(v_ego) * (1.0 + gain * speed_weight * center_weight)
def get_camry_ff_scale(desired_lateral_accel: float, desired_lateral_jerk: float, v_ego: float) -> float:
phase = math.tanh((desired_lateral_accel * desired_lateral_jerk) / 0.10)
unwind_weight = max(-phase, 0.0)
lat_weight = _sigmoid((abs(desired_lateral_accel) - CAMRY_UNWIND_LAT_ONSET) / CAMRY_UNWIND_LAT_WIDTH)
speed_weight = _sigmoid((v_ego - CAMRY_UNWIND_SPEED_ONSET) / CAMRY_UNWIND_SPEED_WIDTH)
reduction = _flm_vehicle_knob("toyota_camry.unwind_ff_reduction", CAMRY_UNWIND_FF_REDUCTION)
return 1.0 - reduction * unwind_weight * lat_weight * speed_weight
def _rav4_prime_side_value(desired_lateral_accel: float, left_value: float, right_value: float) -> float:
return left_value if desired_lateral_accel >= 0.0 else right_value
@@ -3319,6 +3333,7 @@ FLM_SUPPORTED_VEHICLE_KNOBS = {
"toyota_prius.unwind_threshold_increase_right": {"profile": "toyota_prius", "min": 0.0, "max": 0.90, "precision": 0.001, "deltaType": "absolute", "safeLiveTrial": True, "defaultValue": PRIUS_UNWIND_THRESHOLD_INCREASE_RIGHT},
"toyota_prius.center_friction_threshold_gain": {"profile": "toyota_prius", "min": 0.0, "max": 0.20, "precision": 0.001, "deltaType": "absolute", "safeLiveTrial": True, "defaultValue": PRIUS_CENTER_FRICTION_THRESHOLD_GAIN},
"toyota_camry.center_friction_threshold_gain": {"profile": "toyota_camry", "min": 0.0, "max": 0.15, "precision": 0.001, "deltaType": "absolute", "safeLiveTrial": True, "defaultValue": CAMRY_CENTER_FRICTION_THRESHOLD_GAIN},
"toyota_camry.unwind_ff_reduction": {"profile": "toyota_camry", "min": 0.0, "max": 0.20, "precision": 0.001, "deltaType": "absolute", "safeLiveTrial": True, "defaultValue": CAMRY_UNWIND_FF_REDUCTION},
}
@@ -81,6 +81,7 @@ from openpilot.selfdrive.controls.lib.latcontrol_torque import (
get_sienna_4th_gen_friction_threshold,
get_sienna_4th_gen_high_speed_output_taper_scale,
get_lexus_is_ff_scale,
get_camry_ff_scale,
get_ioniq_5_ff_scale,
get_ioniq_5_friction_scale,
get_ioniq_5_friction_threshold,
@@ -1086,6 +1087,11 @@ class TestLatControl:
assert unwind_right < unwind_left < steady_left
assert unwind_right < low_speed_unwind_right < 1.0
def test_camry_ff_scale_reduces_high_speed_unwind(self):
assert get_camry_ff_scale(0.6, 0.0, 22.0) == pytest.approx(1.0)
assert get_camry_ff_scale(0.6, -0.5, 22.0) < 1.0
assert get_camry_ff_scale(0.6, -0.5, 5.0) > get_camry_ff_scale(0.6, -0.5, 22.0)
def test_volt_plexy_friction_threshold_curve(self):
base = get_gm_base_friction_threshold(6.0)
left_turn_in = get_volt_plexy_friction_threshold(6.0, 0.7, 0.8)
+9 -6
View File
@@ -48,8 +48,9 @@ from openpilot.starpilot.common.starpilot_variables import get_starpilot_toggles
PROCESS_NAME = "selfdrive.modeld.modeld"
SEND_RAW_PRED = os.getenv('SEND_RAW_PRED')
BUILTIN_MODEL_KEY = "sc2"
BUILTIN_MODEL_ALIASES = {BUILTIN_MODEL_KEY, "sc"}
BUILTIN_MODEL_KEY = "rdf"
BUILTIN_MODEL_ALIASES = {BUILTIN_MODEL_KEY}
MODEL_ID_ALIASES = {"sc": "sc2"}
LAT_SMOOTH_SECONDS = 0.1
@@ -116,7 +117,9 @@ def _resolve_mirrored_param(params: Params, primary_key: str, secondary_key: str
def _canonical_model_id(model_id: str) -> str:
key = (model_id or "").strip().lower()
return BUILTIN_MODEL_KEY if key in BUILTIN_MODEL_ALIASES else key
if key in BUILTIN_MODEL_ALIASES:
return BUILTIN_MODEL_KEY
return MODEL_ID_ALIASES.get(key, key)
def get_action_from_model(model_output: dict[str, np.ndarray], prev_action: log.ModelDataV2.Action,
@@ -301,9 +304,9 @@ class ModelState:
model_version = str(json.loads(versions_path.read_text()).get(model_id) or "")
except Exception:
pass
if loaded_builtin and not use_builtin:
model_version = str(artifact.get("behavior_version") or "v11")
self.policy_generation = model_version or ("v11" if loaded_builtin else "v8")
if loaded_builtin:
model_version = str(artifact.get("behavior_version") or "v15")
self.policy_generation = model_version or ("v15" if loaded_builtin else "v8")
self.is_v9 = self.policy_generation == "v9"
self.is_v14 = self.policy_generation == "v14"
self.is_v15 = self.policy_generation == "v15"
@@ -0,0 +1 @@
3
@@ -0,0 +1 @@
339e80b0864c7a955f197a47e5ff745025eefb3a5a5dcfff121d3bd50bc31018 driving_tinygrad.pkl
@@ -820,19 +820,19 @@ class StarPilotDrivingModelLayout(_SettingsPage):
default_key = self._params.get_default_value("Model") or self._params.get_default_value("DrivingModel")
if isinstance(default_key, bytes):
default_key = default_key.decode("utf-8", errors="ignore")
return canonical_model_key(str(default_key or "").strip()) or "sc2"
return canonical_model_key(str(default_key or "").strip()) or "rdf"
def _default_model_name(self) -> str:
default_name = self._params.get_default_value("DrivingModelName")
if isinstance(default_name, bytes):
default_name = default_name.decode("utf-8", errors="ignore")
return _clean_model_name(default_name or "") or "South Carolina"
return _clean_model_name(default_name or "") or "Regret Driven Framework"
def _default_model_version(self) -> str:
default_version = self._params.get_default_value("ModelVersion") or self._params.get_default_value("DrivingModelVersion")
if isinstance(default_version, bytes):
default_version = default_version.decode("utf-8", errors="ignore")
return str(default_version or "").strip() or "v11"
return str(default_version or "").strip() or "v15"
def _current_selected_key(self) -> str:
current_key = self._params.get("Model", encoding="utf-8") or self._params.get("DrivingModel", encoding="utf-8") or ""
@@ -272,7 +272,7 @@ class ConditionalDriveModeView(AdjustorTogglesPanelView):
"CESpeed": {"title": tr("Below Speed"), "subtitle": "", "min": 0, "max": max_speed, "step": 1.0, "unit": speed_unit, "presets": [0, 20, 35, 55, 75], "labels": {}, "get": lambda: float(self._controller._params.get_int("CESpeed"))},
"CESpeedLead": {"title": tr("Speed w/ Lead"), "subtitle": "", "min": 0, "max": max_speed, "step": 1.0, "unit": speed_unit, "presets": [0, 20, 35, 55, 75], "labels": {}, "get": lambda: float(self._controller._params.get_int("CESpeedLead"))},
"CESignalSpeed": {"title": tr("Turn Signal Below"), "subtitle": "", "min": 0, "max": max_speed, "step": 1.0, "unit": speed_unit, "presets": [0, 20, 35, 55, 75], "labels": {0.0: tr("Off")}, "get": lambda: float(self._controller._params.get_int("CESignalSpeed"))},
"CEModelStopTime": {"title": tr("Predicted Stop In"), "subtitle": "", "min": 0, "max": 10.0, "step": 1.0, "unit": "s", "presets": [0, 3, 5, 7, 10], "labels": {0.0: tr("Off")}, "get": lambda: float(self._controller._params.get_int("CEModelStopTime"))},
"CEModelStopTime": {"title": tr("Predicted Stop In"), "subtitle": "", "min": 0, "max": 10.0, "step": 1.0, "unit": "s", "presets": [0, 3, 5, 9, 10], "labels": {0.0: tr("Off")}, "get": lambda: float(self._controller._params.get_int("CEModelStopTime"))},
"CCMSpeed": {"title": tr("Above Speed"), "subtitle": "", "min": 0, "max": max_speed, "step": 1.0, "unit": speed_unit, "presets": [0, 35, 55, 65, 80], "labels": {}, "get": lambda: float(self._controller._params.get_int("CCMSpeed"))},
"CCMSpeedLead": {"title": tr("Speed w/ Lead"), "subtitle": "", "min": 0, "max": max_speed, "step": 1.0, "unit": speed_unit, "presets": [0, 35, 55, 65, 80], "labels": {}, "get": lambda: float(self._controller._params.get_int("CCMSpeedLead"))},
"CCMSetSpeedMargin": {"title": tr("Set Speed Margin"), "subtitle": "", "min": 0, "max": 30.0 if is_metric else 15.0, "step": 1.0, "unit": speed_unit, "presets": [0, 5, 10, 15], "labels": {}, "get": lambda: float(self._controller._params.get_int("CCMSetSpeedMargin"))},
@@ -306,7 +306,7 @@ class ConditionalDriveModeView(AdjustorTogglesPanelView):
"CESpeed": {"title": tr("Below Speed"), "min": 0, "max": max_speed, "unit": speed_unit, "labels": {}, "presets": [0, 20, 35, 55, 75]},
"CESpeedLead": {"title": tr("Speed w/ Lead"), "min": 0, "max": max_speed, "unit": speed_unit, "labels": {}, "presets": [0, 20, 35, 55, 75]},
"CESignalSpeed": {"title": tr("Turn Signal Below"), "min": 0, "max": max_speed, "unit": speed_unit, "labels": {0.0: tr("Off")}, "presets": [0, 20, 35, 55, 75]},
"CEModelStopTime": {"title": tr("Predicted Stop In"), "min": 0, "max": 10.0, "unit": "s", "labels": {0.0: tr("Off")}, "presets": [0, 3, 5, 7, 10]},
"CEModelStopTime": {"title": tr("Predicted Stop In"), "min": 0, "max": 10.0, "unit": "s", "labels": {0.0: tr("Off")}, "presets": [0, 3, 5, 9, 10]},
"CCMSpeed": {"title": tr("Above Speed"), "min": 0, "max": max_speed, "unit": speed_unit, "labels": {}, "presets": [0, 35, 55, 65, 80]},
"CCMSpeedLead": {"title": tr("Speed w/ Lead"), "min": 0, "max": max_speed, "unit": speed_unit, "labels": {}, "presets": [0, 35, 55, 65, 80]},
"CCMSetSpeedMargin": {"title": tr("Set Speed Margin"), "min": 0, "max": 30.0 if is_metric else 15.0, "unit": speed_unit, "labels": {}, "presets": [0, 5, 10, 15]},
@@ -706,9 +706,9 @@ class DrivingModelBigButton(BigButton):
default_key = default_key.decode("utf-8", errors="ignore")
default_key = str(default_key or "").strip()
if not default_key:
default_key = "sc"
default_key = "rdf"
# Manifest can expose legacy IDs like "sc2" while default remains "sc".
# Keep the built-in model selectable even when the manifest omits it.
if key == default_key:
return True
if default_key.endswith("2") and key == default_key[:-1]:
+7 -7
View File
@@ -24,13 +24,13 @@ from openpilot.starpilot.common.starpilot_utilities import delete_file
from openpilot.starpilot.common.starpilot_variables import MODELS_PATH
MANIFEST_CANDIDATES = ("v22",)
DEFAULT_MODEL_KEY = "sc2"
DEFAULT_MODEL_KEY = "rdf"
LOCAL_MODEL_PREFIX = "local-"
LOCAL_MODEL_SERIES = "Local Series"
ARTIFACT_URLS_CACHE = ".model_artifact_urls.json"
ARTIFACT_METADATA_CACHE = ".model_artifacts.json"
MODEL_KEY_CANONICAL_MAP = {
"sc": DEFAULT_MODEL_KEY,
"sc": "sc2",
}
CANCEL_DOWNLOAD_PARAM = "CancelModelDownload"
@@ -181,7 +181,7 @@ class ModelManager:
selected_model = self._selected_model()
current_version = self._resolve_mirrored_param("ModelVersion", "DrivingModelVersion")
if not current_version:
current_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or "v11"
current_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or ("v15" if is_builtin_model_key(selected_model) else "v11")
selected_name = self._param_text("DrivingModelName")
if not selected_name and selected_model in self.available_models:
@@ -359,7 +359,7 @@ class ModelManager:
model_version = version_map.get(model_key) or version_map.get(canonical_key) or ""
if not model_version and is_builtin_model_key(canonical_key):
model_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or "v11"
model_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or "v15"
artifact_format = artifact_format_map.get(model_key) or artifact_format_map.get(canonical_key) or ""
if not self._is_model_downloaded(model_key, artifact_format):
@@ -415,7 +415,7 @@ class ModelManager:
fallback_version = self._resolve_mirrored_param("ModelVersion", "DrivingModelVersion")
if not fallback_version:
fallback_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or "v11"
fallback_version = self._default_param_text("ModelVersion") or self._default_param_text("DrivingModelVersion") or ("v15" if is_builtin_model_key(selected) else "v11")
self._set_model_param_keys(selected, name_map.get(selected, ""), fallback_version)
@staticmethod
@@ -590,12 +590,12 @@ class ModelManager:
default_name = (
self.available_model_names[default_index]
if default_index is not None and default_index < len(self.available_model_names)
else "South Carolina"
else "Regret Driven Framework"
)
default_version = (
self.model_versions[default_index]
if default_index is not None and default_index < len(self.model_versions)
else "v11"
else "v15"
)
self._set_model_param_keys(DEFAULT_MODEL_KEY, default_name, default_version)
self.params_memory.put(DOWNLOAD_PROGRESS_PARAM, "Selected model unavailable; using built-in model.")
+5 -5
View File
@@ -1208,13 +1208,13 @@ class StarPilotVariables:
toggle.recovery_power = self.get_value("RecoveryPower", cast=float, condition=longitudinal_tuning, default=1.0, min=0.5, max=2.0)
toggle.taco_tune = self.get_value("TacoTune", condition=longitudinal_tuning)
toggle.model = self.get_value("Model", cast=None, default="sc2")
toggle.model = self.get_value("Model", cast=None, default="rdf")
if not toggle.model:
toggle.model = self.get_value("DrivingModel", cast=None, default="sc2")
toggle.model_name = self.get_value("DrivingModelName", cast=None, default="South Carolina")
toggle.model_version = self.get_value("ModelVersion", cast=None, default="v11")
toggle.model = self.get_value("DrivingModel", cast=None, default="rdf")
toggle.model_name = self.get_value("DrivingModelName", cast=None, default="Regret Driven Framework")
toggle.model_version = self.get_value("ModelVersion", cast=None, default="v15")
if not toggle.model_version:
toggle.model_version = self.get_value("DrivingModelVersion", cast=None, default="v11")
toggle.model_version = self.get_value("DrivingModelVersion", cast=None, default="v15")
if isinstance(toggle.model, bytes):
toggle.model = toggle.model.decode("utf-8", "ignore")
if isinstance(toggle.model_name, bytes):
+3 -3
View File
@@ -5363,14 +5363,14 @@ def setup(app):
def _default_model_key():
default_key = _param_text(params.get_default_value("Model") or params.get_default_value("DrivingModel"))
return canonical_model_key(default_key) or "sc2"
return canonical_model_key(default_key) or "rdf"
def _default_model_name():
return _param_text(params.get_default_value("DrivingModelName")) or "South Carolina"
return _param_text(params.get_default_value("DrivingModelName")) or "Regret Driven Framework"
def _default_model_version():
default_version = _param_text(params.get_default_value("ModelVersion") or params.get_default_value("DrivingModelVersion"))
return default_version or "v11"
return default_version or "v15"
def _current_model_key():
current_model = _param_text(params.get("Model", encoding="utf-8") or params.get("DrivingModel", encoding="utf-8"))
+3 -3
View File
@@ -22,18 +22,18 @@ QString builtinDefaultModelKey(const Params &params) {
if (key.isEmpty()) {
key = paramDefaultValue(params, "DrivingModel");
}
return key.isEmpty() ? QStringLiteral("sc2") : key;
return key.isEmpty() ? QStringLiteral("rdf") : key;
}
QString builtinDefaultModelName(const Params &params) {
QString name = paramDefaultValue(params, "DrivingModelName");
return name.isEmpty() ? QStringLiteral("South Carolina") : name;
return name.isEmpty() ? QStringLiteral("Regret Driven Framework") : name;
}
QStringList builtinDefaultModelAliases(const QString &defaultKey) {
QString canonical = defaultKey.trimmed();
if (canonical.isEmpty()) {
canonical = QStringLiteral("sc2");
canonical = QStringLiteral("rdf");
}
QStringList aliases{canonical};
+75 -2
View File
@@ -67,6 +67,8 @@ STARPILOT_PARAM_RENAME_MIGRATION_FLAG = Path("/data") / "starpilot_param_rename_
STARPILOT_PARAM_CANONICALIZATION_MIGRATION_FLAG = Path("/data") / "starpilot_param_canonicalization_v1"
STARPILOT_PC_ROOT_MIGRATION_FLAG = Path("/data") / "starpilot_pc_root_v1"
STARPILOT_PARAMS_CACHE_MIGRATION_FLAG = Path("/data") / "starpilot_params_cache_v1"
STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG = Path("/data") / "starpilot_default_model_rdf_v1"
STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG = Path("/data") / "starpilot_ce_model_stop_time_v1"
STARPILOT_LEGACY_CACHE_MARKER_KEYS = ("RemapCancelToDistance",)
STARPILOT_REMOVED_PARAM_KEYS = ("CoastUpToLeads", "HumanAcceleration", "HumanFollowing", "PrioritizeSmoothFollowing")
LEGACY_CARMODEL_MIGRATIONS = {
@@ -559,8 +561,8 @@ def migrate_starpilot_default_parity(params: Params, params_cache: Params) -> No
seeded_keys.append(key)
if not _has_persisted_param_file(params, "CEModelStopTime") and not _has_persisted_param_file(params_cache, "CEModelStopTime"):
params.put_float("CEModelStopTime", 7.0)
params_cache.put_float("CEModelStopTime", 7.0)
params.put_float("CEModelStopTime", 9.0)
params_cache.put_float("CEModelStopTime", 9.0)
seeded_keys.append("CEModelStopTime")
# Rebase default regression fix:
@@ -588,6 +590,75 @@ def migrate_starpilot_default_parity(params: Params, params_cache: Params) -> No
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_DEFAULTS_PARITY_MIGRATION_FLAG}")
def migrate_starpilot_default_model(params: Params, params_cache: Params) -> None:
"""Move the old bundled South Carolina selection to the bundled RDF model once."""
if STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG.exists():
return
def persisted_text(key: str) -> str:
for params_obj in (params, params_cache):
raw_value = _read_raw_param_bytes(params_obj, key)
if raw_value:
return _to_text(raw_value).strip()
return ""
selected_model = persisted_text("Model") or persisted_text("DrivingModel")
selected_version = persisted_text("ModelVersion") or persisted_text("DrivingModelVersion")
selected_name = persisted_text("DrivingModelName").lower()
is_legacy_default = selected_model.lower() in {"sc", "sc2"}
is_legacy_metadata = (not selected_version or selected_version.lower() == "v11") and (not selected_name or selected_name.startswith("south carolina"))
if is_legacy_default and is_legacy_metadata:
for key, value in {
"Model": "rdf",
"DrivingModel": "rdf",
"DrivingModelName": "Regret Driven Framework",
"ModelVersion": "v15",
"DrivingModelVersion": "v15",
}.items():
params.put(key, value)
params_cache.put(key, value)
cloudlog.warning("Migrated the bundled default model from South Carolina to RDF")
try:
STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG.parent.mkdir(parents=True, exist_ok=True)
STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG.write_text(f"{datetime.datetime.now(datetime.UTC).isoformat()}\n")
except Exception:
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG}")
def migrate_starpilot_ce_model_stop_time(params: Params, params_cache: Params) -> None:
"""Move the old persisted 7-second stop prediction default to 9 seconds once."""
if STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG.exists():
return
legacy_default_detected = False
for params_obj in (params, params_cache):
raw_value = _read_raw_param_bytes(params_obj, "CEModelStopTime")
if not raw_value:
continue
try:
parsed_value = float(raw_value.decode("utf-8", errors="strict").strip())
except Exception:
continue
if abs(parsed_value - 7.0) < 1e-6:
legacy_default_detected = True
break
if legacy_default_detected:
params.put_float("CEModelStopTime", 9.0)
params_cache.put_float("CEModelStopTime", 9.0)
cloudlog.warning("Migrated CEModelStopTime from 7 seconds to 9 seconds")
try:
STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG.parent.mkdir(parents=True, exist_ok=True)
STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG.write_text(f"{datetime.datetime.now(datetime.UTC).isoformat()}\n")
except Exception:
cloudlog.exception(f"Failed to write migration flag: {STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG}")
def migrate_disable_humanlike_defaults(params: Params, params_cache: Params) -> None:
if STARPILOT_HUMANLIKE_DISABLE_MIGRATION_FLAG.exists():
return
@@ -922,6 +993,8 @@ def manager_init() -> None:
migrate_param_type_canonicalization(params)
cleanup_removed_starpilot_params(params, params_cache)
migrate_starpilot_default_parity(params, params_cache)
migrate_starpilot_default_model(params, params_cache)
migrate_starpilot_ce_model_stop_time(params, params_cache)
migrate_disable_humanlike_defaults(params, params_cache)
migrate_cluster_offset_default(params, params_cache)
migrate_traffic_mode_smooth_defaults(params, params_cache)
+33
View File
@@ -240,6 +240,39 @@ class TestManager:
assert params.get("CEModelStopTime") == "3.5"
assert params_cache.get_bool("NNFF")
def test_migrate_starpilot_default_model(self, tmp_path, monkeypatch):
monkeypatch.setattr(manager, "STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG", tmp_path / "starpilot_default_model_rdf_v1")
params = FileBackedFakeParams(tmp_path / "params", {
"Model": "sc2",
"DrivingModel": "sc2",
"DrivingModelName": "South Carolina",
"ModelVersion": "v11",
"DrivingModelVersion": "v11",
})
params_cache = FileBackedFakeParams(tmp_path / "cache")
manager.migrate_starpilot_default_model(params, params_cache)
assert params.get("Model") == "rdf"
assert params.get("DrivingModel") == "rdf"
assert params.get("DrivingModelName") == "Regret Driven Framework"
assert params.get("ModelVersion") == "v15"
assert params_cache.get("DrivingModel") == "rdf"
assert manager.STARPILOT_DEFAULT_MODEL_MIGRATION_FLAG.exists()
def test_migrate_starpilot_ce_model_stop_time(self, tmp_path, monkeypatch):
monkeypatch.setattr(manager, "STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG", tmp_path / "starpilot_ce_model_stop_time_v1")
params = FileBackedFakeParams(tmp_path / "params", {"CEModelStopTime": 7.0})
params_cache = FileBackedFakeParams(tmp_path / "cache")
manager.migrate_starpilot_ce_model_stop_time(params, params_cache)
assert params.get("CEModelStopTime") == "9.0"
assert params_cache.get("CEModelStopTime") == "9.0"
assert manager.STARPILOT_CE_MODEL_STOP_TIME_MIGRATION_FLAG.exists()
def test_migrate_disable_humanlike_defaults(self, tmp_path, monkeypatch):
monkeypatch.setattr(manager, "STARPILOT_HUMANLIKE_DISABLE_MIGRATION_FLAG", tmp_path / "starpilot_humanlike_disable_v1")
@@ -222,10 +222,11 @@ class CustomASM24Controller:
self._f0_out_buf, self._f0_out_mv = alloc_cbuffer(0x1000) # for f0 and e4, allocate big enough for e4
self._f0_in_buf, _ = alloc_cbuffer(8)
# Custom firmware now boots with PCIe off. Power it on before probing the link.
ltssm = self.read(0xB450, 1)[0]
if ltssm != 0x78: self.set_pcie_power(True)
ltssm = self.read(0xB450, 1)[0]
if (ltssm := self.read(0xB450, 1)[0]) != 0x78:
self.set_pcie_power(True)
grace_period = time.monotonic() + 5.0
while time.monotonic() < grace_period and (ltssm := self.read(0xB450, 1)[0]) != 0x78:
time.sleep(0.1)
if ltssm != 0x78: raise RuntimeError(f"PCIe link not up (LTSSM=0x{ltssm:02X}), custom firmware not ready")
def set_pcie_power(self, enabled:bool, timeout:int=10000):