Compare commits

...

1 Commits

Author SHA1 Message Date
whoisdomi 8f6dfae94a Restore CAN-FD steer limits and Ioniq 6 full PID torque range
- CAN-FD STEER_MAX 270 -> 409; below 15 m/s STEER_DELTA_UP/DOWN 10/8
  (Carnival HEV keeps 2/3), carcontroller refreshes params from vEgoRaw
- hyundai_canfd safety: max_torque 409, rt_delta 375, rate up/down 10
- Ioniq6TorquePolicy: PID limits from the 1.22-compensated factor so the
  PID path can reach full torque instead of 1/1.22 of STEER_MAX

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:13:08 -05:00
7 changed files with 22 additions and 21 deletions
@@ -163,6 +163,8 @@ class CarController(CarControllerBase):
self._ray_prev_lat_active = CC.latActive
# steering torque
if self.CP.flags & HyundaiFlags.CANFD:
self.params = CarControllerParams(self.CP, CS.out.vEgoRaw)
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
apply_torque = (0 if self.angle_vm is not None else
apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params))
+8 -4
View File
@@ -17,7 +17,7 @@ class CarControllerParams:
ACCEL_MAX = 2.0 # m/s^2
ANGLE_LIMITS = AngleSteeringLimitsVM(360, MAX_ANGLE_RATE=5)
def __init__(self, CP):
def __init__(self, CP, vEgoRaw=100.):
self.ACCEL_MAX = 3.5 if is_blended_alpha(CP) else type(self).ACCEL_MAX
self.STEER_DELTA_UP = 3
self.STEER_DELTA_DOWN = 7
@@ -28,12 +28,16 @@ class CarControllerParams:
self.STEER_STEP = 1 # 100 Hz
if CP.flags & HyundaiFlags.CANFD:
self.STEER_MAX = 270
self.STEER_MAX = 409
self.STEER_DRIVER_ALLOWANCE = 250
self.STEER_DRIVER_MULTIPLIER = 2
self.STEER_THRESHOLD = 250
self.STEER_DELTA_UP = 2
self.STEER_DELTA_DOWN = 3
if vEgoRaw < 15.0 and CP.carFingerprint != CAR.KIA_CARNIVAL_HEV_4TH_GEN:
self.STEER_DELTA_UP = 10
self.STEER_DELTA_DOWN = 8
else:
self.STEER_DELTA_UP = 2
self.STEER_DELTA_DOWN = 3
# To determine the limit for your car, find the maximum value that the stock LKAS will request.
# If the max stock LKAS request is <384, add your car to this list.
@@ -637,10 +637,10 @@ static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
static bool hyundai_canfd_tx_hook_valid(const CANPacket_t *msg) {
static uint8_t hyundai_canfd_ioniq6_lfa_mirror[4] = {0};
const TorqueSteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = {
.max_torque = 270,
.max_rt_delta = 112,
.max_rate_up = 2,
.max_rate_down = 3,
.max_torque = 409,
.max_rt_delta = 375,
.max_rate_up = 10,
.max_rate_down = 10,
.driver_torque_allowance = 250,
.driver_torque_multiplier = 2,
.type = TorqueDriverLimited,
@@ -31,11 +31,11 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.Drive
STANDSTILL_THRESHOLD = 12 # 0.375 kph
FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]}
MAX_RATE_UP = 2
MAX_RATE_DOWN = 3
MAX_TORQUE_LOOKUP = [0], [270]
MAX_RATE_UP = 10
MAX_RATE_DOWN = 10
MAX_TORQUE_LOOKUP = [0], [409]
MAX_RT_DELTA = 112
MAX_RT_DELTA = 375
DRIVER_TORQUE_ALLOWANCE = 250
DRIVER_TORQUE_FACTOR = 2
+1 -6
View File
@@ -758,14 +758,9 @@ class Ioniq6TorquePolicy:
self.dt = parent.dt
self.is_2025 = is_ioniq_6_2025_model(CP)
self.vehicle_factor = float(CP.lateralTuning.torque.latAccelFactor)
# Startup limits use raw CP calibration before the 1.22 factor; using compensated
# parameters would widen them before the first live torque update.
startup_params = CP.lateralTuning.torque.as_builder()
startup_pos_limit = parent.lateral_accel_from_torque(parent.steer_max, startup_params)
startup_neg_limit = parent.lateral_accel_from_torque(-parent.steer_max, startup_params)
parent.pid = PIDController([[0.0], [KP_INTERP[-1]]], KI, rate=1 / self.dt)
parent.pid.set_limits(startup_pos_limit, startup_neg_limit)
parent.torque_params.latAccelFactor = self.vehicle_factor * IONIQ_6_BASE_LAT_ACCEL_FACTOR_MULT
parent.update_limits()
self.request_buffer_len = int(LAT_ACCEL_REQUEST_BUFFER_SECONDS / self.dt)
self.curvature_request_buffer = deque([0.0] * self.request_buffer_len, maxlen=self.request_buffer_len)
self.jerk_filter = FirstOrderFilter(0.0, 1 / (2 * np.pi * LP_FILTER_CUTOFF_HZ), self.dt)
@@ -114,7 +114,7 @@ class TestControllerSelection(unittest.TestCase):
self.assertAlmostEqual(standard.torque_params.latAccelFactor, cp.lateralTuning.torque.latAccelFactor)
if vehicle == HYUNDAI.HYUNDAI_IONIQ_6:
self.assertEqual(standard.pid.pos_limit, cp.lateralTuning.torque.latAccelFactor)
self.assertEqual(policy.pid.pos_limit, cp.lateralTuning.torque.latAccelFactor)
self.assertEqual(policy.pid.pos_limit, policy.torque_params.latAccelFactor)
self.assertEqual(policy.torque_params.latAccelFactor,
struct.unpack('f', struct.pack('f', cp.lateralTuning.torque.latAccelFactor * 1.22))[0])
for controller, multiplier in ((standard, 1.0), (policy, 1.22)):
@@ -161,7 +161,7 @@ class TestControllerSelection(unittest.TestCase):
legacy = Controls()
self.assertEqual(legacy.lateral_controller_selection, default_selection(cp))
self.assertIsNotNone(selected_policy(legacy.LaC))
self.assertEqual(legacy.LaC.pid.pos_limit, cp.lateralTuning.torque.latAccelFactor)
self.assertEqual(legacy.LaC.pid.pos_limit, legacy.LaC.torque_params.latAccelFactor)
self.assertIsNone(legacy.torque_host)
from openpilot.starpilot.lateral.torque_settings import DOCUMENT_KEY as TORQUE_DOCUMENT_KEY, replace_field, serialize_document
tune = cp.lateralTuning.torque
@@ -41,7 +41,7 @@ class TestEV6DefaultLateral(unittest.TestCase):
self.assertAlmostEqual(lateral.torque_params.latAccelFactor, cp.lateralTuning.torque.latAccelFactor)
controller = CarController(DBC[cp.carFingerprint], cp)
self.assertIsNone(controller.ioniq6_longitudinal)
self.assertEqual(controller.params.STEER_MAX, 270)
self.assertEqual(controller.params.STEER_MAX, 409)
self.assertEqual(controller.params.STEER_DRIVER_ALLOWANCE, 250)
def test_opposing_driver_torque_limits_can_command_and_angle_request(self):