From a6086fa7985d1842e2208b0b393e1c2e8924c688 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Thu, 23 Apr 2026 21:38:33 -0500 Subject: [PATCH] VOLT NO CAM | IONIQ | KIA --- opendbc_repo/opendbc/car/car_helpers.py | 17 +++++++++ opendbc_repo/opendbc/car/hyundai/values.py | 2 +- .../opendbc/car/tests/test_can_fingerprint.py | 14 +++++++ selfdrive/controls/lib/latcontrol_torque.py | 38 +++++++++++++------ selfdrive/controls/tests/test_latcontrol.py | 6 +++ 5 files changed, 64 insertions(+), 13 deletions(-) diff --git a/opendbc_repo/opendbc/car/car_helpers.py b/opendbc_repo/opendbc/car/car_helpers.py index 1c1d6b96b..9b8ff70da 100644 --- a/opendbc_repo/opendbc/car/car_helpers.py +++ b/opendbc_repo/opendbc/car/car_helpers.py @@ -52,6 +52,8 @@ LEGACY_FORCED_CANDIDATE_MAP = { GM_CANDIDATE_PREFIXES = ("CHEVROLET_", "GMC_", "CADILLAC_", "BUICK_", "HOLDEN_") GM_CORE_FINGERPRINT_MSGS = frozenset((190, 201, 209, 211, 241)) +GM_CAMERA_BUS = 2 +GM_VOLT_CAMERA_MSG = 0x320 def _normalize_forced_candidate(candidate: str | None) -> str | None: @@ -106,6 +108,19 @@ def _normalize_gm_bolt_candidate(candidate: str | None, fingerprints: dict[int, return candidate +def _normalize_gm_volt_candidate(candidate: str | None, fingerprints: dict[int, dict]) -> str | None: + cam = fingerprints.get(GM_CAMERA_BUS, {}) + has_live_camera_msg = GM_VOLT_CAMERA_MSG in cam + + if candidate == "CHEVROLET_VOLT_CAMERA" and not has_live_camera_msg: + return "CHEVROLET_VOLT" + + if candidate == "CHEVROLET_VOLT" and has_live_camera_msg: + return "CHEVROLET_VOLT_CAMERA" + + return candidate + + def _is_gm_candidate(candidate: str | None) -> bool: return isinstance(candidate, str) and candidate.startswith(GM_CANDIDATE_PREFIXES) @@ -119,6 +134,7 @@ def _get_gm_stored_candidate_fallback(fingerprints: dict[int, dict], stored_cand return None for candidate in (_normalize_forced_candidate(stored_candidate), _normalize_forced_candidate(cached_candidate)): + candidate = _normalize_gm_volt_candidate(candidate, fingerprints) if _is_gm_candidate(candidate) and candidate != MOCK.MOCK and candidate in interfaces: return candidate @@ -244,6 +260,7 @@ def get_car(can_recv: CanRecvCallable, can_send: CanSendCallable, set_obd_multip is_release: bool, params: Params, num_pandas: int = 1, cached_params: CarParamsT | None = None, starpilot_toggles: SimpleNamespace = None): candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(can_recv, can_send, set_obd_multiplexing, num_pandas, cached_params) candidate = _normalize_gm_bolt_candidate(candidate, fingerprints) + candidate = _normalize_gm_volt_candidate(candidate, fingerprints) candidate = _normalize_forced_candidate(candidate) fingerprinted_candidate = candidate stored_candidate = _normalize_forced_candidate(params.get("CarModel")) diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py index 16db67279..433ef07ac 100644 --- a/opendbc_repo/opendbc/car/hyundai/values.py +++ b/opendbc_repo/opendbc/car/hyundai/values.py @@ -25,7 +25,7 @@ class CarControllerParams: MAX_ANGLE_RATE=5, ) ANGLE_MAX_TORQUE_REDUCTION_GAIN = 1.0 - ANGLE_MIN_TORQUE_REDUCTION_GAIN = 0.1 + ANGLE_MIN_TORQUE_REDUCTION_GAIN = 0.6 ANGLE_ACTIVE_TORQUE_REDUCTION_GAIN = 0.6 def __init__(self, CP, vEgoRaw=100.): diff --git a/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py b/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py index f6b767b64..c3e29c1d5 100644 --- a/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py +++ b/opendbc_repo/opendbc/car/tests/test_can_fingerprint.py @@ -70,6 +70,20 @@ class TestCanFingerprint: assert candidate == "CHEVROLET_VOLT_CC" + def test_gm_stored_candidate_fallback_demotes_volt_camera_without_live_camera_msg(self): + fingerprints = {0: {190: 6, 201: 8, 209: 7, 211: 2, 241: 6}, 2: {}} + + candidate = _get_gm_stored_candidate_fallback(fingerprints, "CHEVROLET_VOLT_CAMERA", None) + + assert candidate == "CHEVROLET_VOLT" + + def test_gm_stored_candidate_fallback_promotes_volt_when_live_camera_msg_present(self): + fingerprints = {0: {190: 6, 201: 8, 209: 7, 211: 2, 241: 6}, 2: {0x320: 3}} + + candidate = _get_gm_stored_candidate_fallback(fingerprints, "CHEVROLET_VOLT", None) + + assert candidate == "CHEVROLET_VOLT_CAMERA" + def test_gm_stored_candidate_fallback_ignores_non_gm_fingerprint(self): fingerprints = {0: {1: 1, 2: 2, 3: 3, 4: 4}} diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index bcb2bdfc3..39fa8fa24 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -207,25 +207,30 @@ IONIQ_6_FF_GAIN_LEFT = 0.04 IONIQ_6_FF_GAIN_RIGHT = 0.015 IONIQ_6_FF_ONSET = 0.10 IONIQ_6_FF_ONSET_WIDTH = 0.04 -IONIQ_6_FF_CUTOFF = 0.72 -IONIQ_6_FF_CUTOFF_WIDTH = 0.18 +IONIQ_6_FF_CUTOFF = 0.60 +IONIQ_6_FF_CUTOFF_WIDTH = 0.14 IONIQ_6_TRANSITION_SPEED = 10.0 IONIQ_6_PHASE_SCALE = 0.10 -IONIQ_6_TURN_IN_BOOST_LEFT = 0.34 -IONIQ_6_TURN_IN_BOOST_RIGHT = 0.28 -IONIQ_6_UNWIND_TAPER_LEFT = 0.24 -IONIQ_6_UNWIND_TAPER_RIGHT = 0.38 +IONIQ_6_TURN_IN_BOOST_LEFT = 0.38 +IONIQ_6_TURN_IN_BOOST_RIGHT = 0.32 +IONIQ_6_UNWIND_TAPER_LEFT = 0.34 +IONIQ_6_UNWIND_TAPER_RIGHT = 0.54 IONIQ_6_FRICTION_MULT = 0.995 IONIQ_6_FRICTION_LAT_RISE = 0.20 IONIQ_6_FRICTION_JERK_RISE = 0.24 IONIQ_6_TURN_IN_THRESHOLD_REDUCTION_LEFT = 0.12 IONIQ_6_TURN_IN_THRESHOLD_REDUCTION_RIGHT = 0.10 -IONIQ_6_UNWIND_THRESHOLD_INCREASE_LEFT = 0.16 -IONIQ_6_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.24 +IONIQ_6_UNWIND_THRESHOLD_INCREASE_LEFT = 0.24 +IONIQ_6_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.36 IONIQ_6_TURN_IN_FRICTION_BOOST_LEFT = 0.05 IONIQ_6_TURN_IN_FRICTION_BOOST_RIGHT = 0.04 -IONIQ_6_UNWIND_FRICTION_REDUCTION_LEFT = 0.12 -IONIQ_6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.18 +IONIQ_6_UNWIND_FRICTION_REDUCTION_LEFT = 0.18 +IONIQ_6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.28 +IONIQ_6_CENTER_TAPER_MAX = 0.05 +IONIQ_6_CENTER_TAPER_LAT = 0.10 +IONIQ_6_CENTER_TAPER_LAT_WIDTH = 0.02 +IONIQ_6_CENTER_TAPER_SPEED = 20.0 +IONIQ_6_CENTER_TAPER_SPEED_WIDTH = 2.5 KIA_EV6_LATERAL_TESTING_GROUND_ID = testing_ground.id_6 KIA_EV6_LATERAL_TESTING_GROUND_VARIANT = "C" @@ -730,6 +735,13 @@ def get_ioniq_6_friction_scale(v_ego: float, desired_lateral_accel: float, desir return min(max(friction_scale, 0.82), 1.08) +def get_ioniq_6_center_taper_scale(desired_lateral_accel: float, v_ego: float) -> float: + speed_weight = _ioniq_6_sigmoid((v_ego - IONIQ_6_CENTER_TAPER_SPEED) / IONIQ_6_CENTER_TAPER_SPEED_WIDTH) + center_weight = _ioniq_6_sigmoid((IONIQ_6_CENTER_TAPER_LAT - abs(desired_lateral_accel)) / IONIQ_6_CENTER_TAPER_LAT_WIDTH) + reduction = IONIQ_6_CENTER_TAPER_MAX * speed_weight * center_weight + return 1.0 - reduction + + def kia_ev6_lateral_testing_ground_active() -> bool: return testing_ground.use(KIA_EV6_LATERAL_TESTING_GROUND_ID, KIA_EV6_LATERAL_TESTING_GROUND_VARIANT) @@ -993,6 +1005,7 @@ class LatControlTorque(LatControl): kia_ev6_test_active = self.is_kia_ev6 and kia_ev6_lateral_testing_ground_active() volt_plexy_test_active = self.is_volt_cc and volt_plexy_lateral_testing_ground_active() volt_standard_center_taper = get_volt_standard_center_taper_scale(setpoint, CS.vEgo) if volt_standard_test_active else 1.0 + ioniq_6_center_taper = get_ioniq_6_center_taper_scale(setpoint, CS.vEgo) if ioniq_6_test_active else 1.0 friction_threshold = get_friction_threshold(CS.vEgo) friction_scale = 1.0 if bolt_2022_2023_tuned_path_active: @@ -1012,9 +1025,10 @@ class LatControlTorque(LatControl): friction_threshold = get_genesis_g90_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk) friction_scale = get_genesis_g90_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk) elif ioniq_6_test_active: - ff *= get_ioniq_6_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) - friction_threshold = get_ioniq_6_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk) + ff *= get_ioniq_6_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) * ioniq_6_center_taper + friction_threshold = get_ioniq_6_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk) / max(ioniq_6_center_taper, 1e-3) friction_scale = get_ioniq_6_friction_scale(CS.vEgo, setpoint, desired_lateral_jerk) + friction_scale = 1.0 + ((friction_scale - 1.0) * ioniq_6_center_taper) elif kia_ev6_test_active: ff *= get_kia_ev6_ff_scale(setpoint, desired_lateral_jerk, CS.vEgo) friction_threshold = get_kia_ev6_friction_threshold(CS.vEgo, setpoint, desired_lateral_jerk) diff --git a/selfdrive/controls/tests/test_latcontrol.py b/selfdrive/controls/tests/test_latcontrol.py index 1fa175599..da947ebc9 100644 --- a/selfdrive/controls/tests/test_latcontrol.py +++ b/selfdrive/controls/tests/test_latcontrol.py @@ -30,6 +30,7 @@ from openpilot.selfdrive.controls.lib.latcontrol_torque import ( get_genesis_g90_ff_scale, get_genesis_g90_friction_scale, get_genesis_g90_friction_threshold, + get_ioniq_6_center_taper_scale, get_ioniq_6_ff_scale, get_ioniq_6_friction_scale, get_ioniq_6_friction_threshold, @@ -229,6 +230,11 @@ class TestLatControl: assert left_turn_in > right_turn_in > base assert base > left_unwind > right_unwind + def test_ioniq_6_center_taper_curve(self): + assert get_ioniq_6_center_taper_scale(0.0, 30.0) < get_ioniq_6_center_taper_scale(0.0, 10.0) + assert get_ioniq_6_center_taper_scale(0.0, 30.0) < get_ioniq_6_center_taper_scale(0.2, 30.0) + assert abs(get_ioniq_6_center_taper_scale(0.2, 30.0) - 1.0) < 1e-3 + def test_kia_ev6_ff_scale_curve(self): assert get_kia_ev6_ff_scale(0.0, 0.0, 20.0) == 1.0 assert get_kia_ev6_ff_scale(-0.3, 0.0, 20.0) > get_kia_ev6_ff_scale(0.3, 0.0, 20.0)