From 330a811114716719da77890f4c9737f7d54a289c Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sat, 25 Apr 2026 20:05:10 -0500 Subject: [PATCH] ioniq tune | blindspot | paddle --- .../opendbc/car/hyundai/carcontroller.py | 4 +++- opendbc_repo/opendbc/car/hyundai/carstate.py | 19 +++++++++++++++-- .../opendbc/car/hyundai/hyundaicanfd.py | 4 +++- .../opendbc/car/hyundai/tests/test_hyundai.py | 14 ++++++++++--- .../dbc/generator/hyundai/hyundai_canfd.dbc | 1 + .../opendbc/dbc/hyundai_canfd_generated.dbc | 1 + selfdrive/controls/lib/latcontrol_torque.py | 8 +++---- selfdrive/controls/lib/lead_behavior.py | 21 +++++++++++++++++++ selfdrive/selfdrived/selfdrived.py | 2 +- 9 files changed, 62 insertions(+), 12 deletions(-) diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py index 8db509fbf5..73526bfaf7 100644 --- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py +++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py @@ -238,7 +238,9 @@ class CarController(CarControllerBase): if CS.blindspots_rear_corners_ts > 0 and CS.blindspots_front_corner_1_ts > 0 and rear_stale and front_stale: can_sends.extend(hyundaicanfd.create_blindspot_status_messages(self.packer, self.CAN, CS.blindspots_rear_corners, - CS.blindspots_front_corner_1)) + CS.blindspots_front_corner_1, + CS.left_blindspot_from_radar, + CS.right_blindspot_from_radar)) if self.frame % 2 == 0: can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override, set_speed_in_units, hud_control)) diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py index 23e4cc9095..1e1d28b45d 100644 --- a/opendbc_repo/opendbc/car/hyundai/carstate.py +++ b/opendbc_repo/opendbc/car/hyundai/carstate.py @@ -21,6 +21,9 @@ ENABLE_BUTTONS = (Buttons.RES_ACCEL, Buttons.SET_DECEL, Buttons.CANCEL) BUTTONS_DICT = {Buttons.RES_ACCEL: ButtonType.accelCruise, Buttons.SET_DECEL: ButtonType.decelCruise, Buttons.GAP_DIST: ButtonType.gapAdjustCruise, Buttons.CANCEL: ButtonType.cancel} +IONIQ_6_BLINDSPOT_RIGHT_MASK = 0x08 +IONIQ_6_BLINDSPOT_LEFT_MASK = 0x10 + def calculate_canfd_speed_limit(CP, FPCP, cp, cp_cam, speed_factor): if not (FPCP.flags & HyundaiStarPilotFlags.SPEED_LIMIT_AVAILABLE): @@ -34,6 +37,11 @@ def calculate_canfd_speed_limit(CP, FPCP, cp, cp_cam, speed_factor): return 0.0 +def decode_ioniq_6_blindspot_radar_state(state: int) -> tuple[bool, bool]: + state_int = int(state) + return bool(state_int & IONIQ_6_BLINDSPOT_LEFT_MASK), bool(state_int & IONIQ_6_BLINDSPOT_RIGHT_MASK) + + class CarState(CarStateBase): @staticmethod def get_canfd_blinker_sig_names(car_fingerprint, use_alt_lamp: bool) -> tuple[str, str]: @@ -82,6 +90,8 @@ class CarState(CarStateBase): self.blindspots_front_corner_1 = {} self.blindspots_rear_corners_ts = 0 self.blindspots_front_corner_1_ts = 0 + self.left_blindspot_from_radar = False + self.right_blindspot_from_radar = False # On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz self.cluster_speed = 0 @@ -290,10 +300,15 @@ class CarState(CarStateBase): cp.vl["BLINKERS"]["USE_ALT_LAMP"] == 1) ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig], cp.vl["BLINKERS"][right_blinker_sig]) + self.left_blindspot_from_radar = False + self.right_blindspot_from_radar = False + if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6: + self.left_blindspot_from_radar, self.right_blindspot_from_radar = decode_ioniq_6_blindspot_radar_state( + cp.vl["BLINDSPOTS_FRONT_CORNER_2"]["SIDE_DETECT_STATE"]) if self.CP.enableBsm: if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6: - ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["LEFT_MB"] != 0 - ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["MORE_LEFT_PROB"] != 0 + ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["LEFT_MB"] != 0 or self.left_blindspot_from_radar + ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["MORE_LEFT_PROB"] != 0 or self.right_blindspot_from_radar else: ret.leftBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FL_INDICATOR"] != 0 ret.rightBlindspot = cp.vl["BLINDSPOTS_REAR_CORNERS"]["FR_INDICATOR"] != 0 diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py index 7d1d261535..d78202f437 100644 --- a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py +++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py @@ -196,10 +196,12 @@ def create_lfahda_cluster(packer, CAN, enabled): return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values) -def create_blindspot_status_messages(packer, CAN, rear_values, front_corner_values): +def create_blindspot_status_messages(packer, CAN, rear_values, front_corner_values, left_blindspot=False, right_blindspot=False): # Reuse the last known-good payload but regenerate the rolling counter/checksum. rear = {k: v for k, v in rear_values.items() if k not in ("CHECKSUM", "COUNTER")} front = {k: v for k, v in front_corner_values.items() if k not in ("CHECKSUM", "COUNTER")} + rear["LEFT_MB"] = int(left_blindspot) + rear["MORE_LEFT_PROB"] = int(right_blindspot) if "NEW_SIGNAL_3" not in front: front["NEW_SIGNAL_3"] = 1 diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py index 41dcbac026..d2d222f7e3 100644 --- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py @@ -7,7 +7,7 @@ from opendbc.can import CANPacker, CANParser from opendbc.car import Bus, ButtonType, gen_empty_fingerprint from opendbc.car.structs import CarParams from opendbc.car.fw_versions import build_fw_dict, match_fw_to_car -from opendbc.car.hyundai.carstate import CarState +from opendbc.car.hyundai.carstate import CarState, decode_ioniq_6_blindspot_radar_state from opendbc.car.hyundai.interface import CarInterface from opendbc.car.hyundai import hyundaicanfd from opendbc.car.hyundai.hyundaicanfd import CanBus @@ -269,15 +269,23 @@ class TestHyundaiFingerprint: "NEW_SIGNAL_1": 0, } - msgs = hyundaicanfd.create_blindspot_status_messages(packer, can_bus, rear, front) + msgs = hyundaicanfd.create_blindspot_status_messages(packer, can_bus, rear, front, left_blindspot=True, right_blindspot=False) parser.update([(1, msgs)]) assert parser.can_valid assert parser.vl["BLINDSPOTS_REAR_CORNERS"]["COUNTER"] == 0 assert parser.vl["BLINDSPOTS_FRONT_CORNER_1"]["COUNTER"] == 0 - assert parser.vl["BLINDSPOTS_REAR_CORNERS"]["LEFT_BLOCKED"] == 0 + assert parser.vl["BLINDSPOTS_REAR_CORNERS"]["LEFT_MB"] == 1 + assert parser.vl["BLINDSPOTS_REAR_CORNERS"]["MORE_LEFT_PROB"] == 0 assert parser.vl["BLINDSPOTS_FRONT_CORNER_1"]["NEW_SIGNAL_3"] == 1 + def test_ioniq_6_blindspot_radar_state_decode(self): + assert decode_ioniq_6_blindspot_radar_state(0x02) == (False, False) + assert decode_ioniq_6_blindspot_radar_state(0x0A) == (False, True) + assert decode_ioniq_6_blindspot_radar_state(0x12) == (True, False) + assert decode_ioniq_6_blindspot_radar_state(0x1A) == (True, True) + assert decode_ioniq_6_blindspot_radar_state(10.0) == (False, True) + def test_sportage_angle_jerk_override_is_scoped(self): sportage = CarParams.new_message() sportage.carFingerprint = CAR.KIA_SPORTAGE_HEV_2026 diff --git a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc index 3f9a4acc8e..96040f2bff 100644 --- a/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc +++ b/opendbc_repo/opendbc/dbc/generator/hyundai/hyundai_canfd.dbc @@ -622,6 +622,7 @@ BO_ 866 CAM_0x362: 32 CAMERA BO_ 874 BLINDSPOTS_FRONT_CORNER_2: 16 XXX SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SIDE_DETECT_STATE : 24|8@1+ (1,0) [0|255] "" XXX BO_ 896 ADAS_0x380: 24 XXX SG_ STOP_SIGN : 83|1@1+ (1,0) [0|1] "" XXX diff --git a/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc b/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc index 532a0a05ba..8b09c9856b 100644 --- a/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc +++ b/opendbc_repo/opendbc/dbc/hyundai_canfd_generated.dbc @@ -859,6 +859,7 @@ BO_ 866 CAM_0x362: 32 CAMERA BO_ 874 BLINDSPOTS_FRONT_CORNER_2: 16 XXX SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX + SG_ SIDE_DETECT_STATE : 24|8@1+ (1,0) [0|255] "" XXX BO_ 896 ADAS_0x380: 24 XXX SG_ STOP_SIGN : 83|1@1+ (1,0) [0|1] "" XXX diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index d6cf48206b..04cddf2b51 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -212,20 +212,20 @@ IONIQ_6_FF_CUTOFF_WIDTH = 0.12 IONIQ_6_TRANSITION_SPEED = 10.0 IONIQ_6_PHASE_SCALE = 0.10 IONIQ_6_TURN_IN_BOOST_LEFT = 0.52 -IONIQ_6_TURN_IN_BOOST_RIGHT = 0.50 +IONIQ_6_TURN_IN_BOOST_RIGHT = 0.44 IONIQ_6_UNWIND_TAPER_LEFT = 0.60 -IONIQ_6_UNWIND_TAPER_RIGHT = 1.08 +IONIQ_6_UNWIND_TAPER_RIGHT = 1.12 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.42 -IONIQ_6_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.92 +IONIQ_6_UNWIND_THRESHOLD_INCREASE_RIGHT = 0.96 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.36 -IONIQ_6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.72 +IONIQ_6_UNWIND_FRICTION_REDUCTION_RIGHT = 0.76 IONIQ_6_CENTER_TAPER_MAX = 0.015 IONIQ_6_CENTER_TAPER_LAT = 0.06 IONIQ_6_CENTER_TAPER_LAT_WIDTH = 0.02 diff --git a/selfdrive/controls/lib/lead_behavior.py b/selfdrive/controls/lib/lead_behavior.py index a909cf57a3..9a2d2ffd62 100644 --- a/selfdrive/controls/lib/lead_behavior.py +++ b/selfdrive/controls/lib/lead_behavior.py @@ -3,6 +3,27 @@ from openpilot.common.constants import CV HIGHWAY_LEAD_BEHAVIOR_MIN_SPEED = 45. * CV.MPH_TO_MS +VISION_LEAD_TRACK_MIN_DISTANCE = 25.0 +VISION_LEAD_TRACK_BASE_TIME_GAP = 1.75 +VISION_LEAD_TRACK_CLOSING_GAIN = 0.20 +VISION_LEAD_TRACK_CLOSING_CAP = 2.50 + + +def should_track_lead(lead_status: bool, lead_distance: float, model_length: float, stop_distance: float, + v_ego: float, *, v_lead: float | None = None, radar: bool = False) -> bool: + if not lead_status: + return False + + tracking_buffer = max(float(stop_distance), 4.0) + model_limit = float(model_length) + tracking_buffer + if radar: + return float(lead_distance) < model_limit + + closing_speed = max(0.0, float(v_ego) - float(v_lead if v_lead is not None else v_ego)) + vision_time_gap = VISION_LEAD_TRACK_BASE_TIME_GAP + min(closing_speed * VISION_LEAD_TRACK_CLOSING_GAIN, + VISION_LEAD_TRACK_CLOSING_CAP) + vision_limit = max(VISION_LEAD_TRACK_MIN_DISTANCE, float(v_ego) * vision_time_gap + tracking_buffer) + return float(lead_distance) < min(model_limit, vision_limit) def get_tracked_lead_catchup_bias(v_ego: float, lead_distance: float, desired_gap: float, closing_speed: float, diff --git a/selfdrive/selfdrived/selfdrived.py b/selfdrive/selfdrived/selfdrived.py index be9013f316..1869c8ba29 100644 --- a/selfdrive/selfdrived/selfdrived.py +++ b/selfdrive/selfdrived/selfdrived.py @@ -242,7 +242,7 @@ class SelfdriveD: if (getattr(self.starpilot_toggles, "nostalgia_mode", False) and self.CP.openpilotLongitudinalControl and - self.sm['carControl'].longActive and + self.enabled and any(be.type == ButtonType.altButton2 for be in CS.buttonEvents)): self.events.add(EventName.buttonCancel)