honda/ipedal

This commit is contained in:
firestar5683
2026-05-05 10:29:18 -05:00
parent 2e113835a7
commit e49cfe44b9
6 changed files with 172 additions and 26 deletions
@@ -241,6 +241,7 @@ class CarController(CarControllerBase):
self._ioniq_6_always_ipedal_press_remaining = 0
self._ioniq_6_always_ipedal_retry_frame = 0
self._ioniq_6_always_ipedal_counter = 0
self._ioniq_6_always_ipedal_startup_park_done = False
self._ioniq_6_last_gear = structs.CarState.GearShifter.unknown
self._genesis_g90_long_tuning = GenesisG90LongitudinalTuningState()
@@ -249,41 +250,56 @@ class CarController(CarControllerBase):
self._ioniq_6_always_ipedal_press_remaining = 0
self._ioniq_6_always_ipedal_retry_frame = 0
def _arm_ioniq_6_always_ipedal(self) -> None:
self._ioniq_6_always_ipedal_pending = True
self._ioniq_6_always_ipedal_press_remaining = 0
self._ioniq_6_always_ipedal_retry_frame = self.frame
def _update_ioniq_6_always_ipedal(self, CC, CS, starpilot_toggles):
can_sends = []
if self.CP.carFingerprint != CAR.HYUNDAI_IONIQ_6 or not getattr(starpilot_toggles, "always_ipedal", False):
self._reset_ioniq_6_always_ipedal()
self._ioniq_6_always_ipedal_startup_park_done = False
self._ioniq_6_last_gear = CS.out.gearShifter
return can_sends
drive = CS.out.gearShifter == structs.CarState.GearShifter.drive
gear = CS.out.gearShifter
drive = gear == structs.CarState.GearShifter.drive
park = gear == structs.CarState.GearShifter.park
drive_edge = drive and self._ioniq_6_last_gear != structs.CarState.GearShifter.drive
startup_park = park and not self._ioniq_6_always_ipedal_startup_park_done
startup_park_edge = startup_park and self._ioniq_6_last_gear != structs.CarState.GearShifter.park
target_gear = drive or startup_park
if drive_edge:
self._ioniq_6_always_ipedal_pending = not CS.ipedal_active
self._ioniq_6_always_ipedal_press_remaining = 0
self._ioniq_6_always_ipedal_retry_frame = self.frame
elif not drive or CS.ipedal_active:
if gear == structs.CarState.GearShifter.unknown:
self._ioniq_6_always_ipedal_startup_park_done = False
elif not park and not self._ioniq_6_always_ipedal_startup_park_done:
self._ioniq_6_always_ipedal_startup_park_done = True
if (startup_park_edge or drive_edge) and not CS.ipedal_active:
self._arm_ioniq_6_always_ipedal()
elif not target_gear or CS.ipedal_active:
self._reset_ioniq_6_always_ipedal()
elif CC.enabled:
self._ioniq_6_always_ipedal_pending = False
self._ioniq_6_always_ipedal_press_remaining = 0
if drive and self._ioniq_6_always_ipedal_pending and not CS.ipedal_active and not CC.enabled:
if target_gear and self._ioniq_6_always_ipedal_pending and not CS.ipedal_active and not CC.enabled:
if self._ioniq_6_always_ipedal_press_remaining == 0 and self.frame >= self._ioniq_6_always_ipedal_retry_frame:
self._ioniq_6_always_ipedal_press_remaining = IONIQ_6_IPEDAL_PRESS_SEND_COUNT
self._ioniq_6_always_ipedal_counter = (int(CS.buttons_counter) + 1) % 0x10
self._ioniq_6_always_ipedal_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(CS.buttons_counter)
if self._ioniq_6_always_ipedal_press_remaining > 0 and self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_buttons(self.packer, self.CP, self.CAN, self._ioniq_6_always_ipedal_counter,
base_values=CS.cruise_buttons_msg, left_paddle=True))
self._ioniq_6_always_ipedal_counter = (self._ioniq_6_always_ipedal_counter + 1) % 0x10
can_sends.append(hyundaicanfd.create_ioniq_6_paddle_buttons(self.packer, self.CP, self.CAN,
self._ioniq_6_always_ipedal_counter, left_paddle=True))
self._ioniq_6_always_ipedal_counter = hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(
self._ioniq_6_always_ipedal_counter)
self._ioniq_6_always_ipedal_press_remaining -= 1
if self._ioniq_6_always_ipedal_press_remaining == 0:
self._ioniq_6_always_ipedal_retry_frame = self.frame + IONIQ_6_IPEDAL_RETRY_WAIT_FRAMES
self._ioniq_6_last_gear = CS.out.gearShifter
self._ioniq_6_last_gear = gear
return can_sends
def update(self, CC, CS, now_nanos, starpilot_toggles):
@@ -156,6 +156,50 @@ def create_suppress_lfa(packer, CAN, lfa_block_msg, lka_steering_alt):
return packer.make_can_msg(suppress_msg, CAN.ACAN, values)
IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX = 15
IONIQ_6_CRUISE_BUTTONS_BASE_CHECKSUMS = (
0x56, 0xEF, 0x39, 0x80, 0x88,
0x31, 0xE7, 0x5E, 0xF7, 0x4E,
0x98, 0x21, 0x29, 0x90, 0x46,
)
IONIQ_6_CRUISE_BUTTONS_LEFT_PADDLE_CHECKSUM_XOR = 0x77
IONIQ_6_CRUISE_BUTTONS_RIGHT_PADDLE_CHECKSUM_XOR = 0xD4
def get_ioniq_6_cruise_buttons_next_counter(counter: int) -> int:
return (int(counter) + 1) % IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX
def create_ioniq_6_paddle_buttons(packer, CP, CAN, cnt, left_paddle=False, right_paddle=False):
if left_paddle and right_paddle:
raise ValueError("Ioniq 6 paddle spoof only supports one paddle at a time")
if cnt < 0 or cnt >= IONIQ_6_CRUISE_BUTTONS_COUNTER_MAX:
raise ValueError(f"Invalid Ioniq 6 cruise buttons counter: {cnt}")
values = {
"COUNTER": cnt,
"SET_ME_1": 1,
"CRUISE_BUTTONS": 0,
"ADAPTIVE_CRUISE_MAIN_BTN": 0,
"NORMAL_CRUISE_MAIN_BTN": 0,
"LDA_BTN": 0,
"LEFT_PADDLE": int(left_paddle),
"RIGHT_PADDLE": int(right_paddle),
}
address = packer.dbc.name_to_msg["CRUISE_BUTTONS"].address
dat = packer.pack(address, values)
checksum = IONIQ_6_CRUISE_BUTTONS_BASE_CHECKSUMS[cnt]
if left_paddle:
checksum ^= IONIQ_6_CRUISE_BUTTONS_LEFT_PADDLE_CHECKSUM_XOR
if right_paddle:
checksum ^= IONIQ_6_CRUISE_BUTTONS_RIGHT_PADDLE_CHECKSUM_XOR
dat[0] = checksum
bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_LKA_STEERING else CAN.CAM
return address, bytes(dat), bus
def create_buttons(packer, CP, CAN, cnt, btn=0, base_values=None, left_paddle=False, right_paddle=False):
values = {k: v for k, v in base_values.items() if k not in ("_CHECKSUM", "COUNTER")} if base_values else {}
values.update({
@@ -321,7 +321,25 @@ class TestHyundaiFingerprint:
assert parser.vl["MANUAL_SPEED_LIMIT_ASSIST"]["EV_REGEN_STATE"] == 0x50
assert parser.vl["MANUAL_SPEED_LIMIT_ASSIST"]["EV_REGEN_STATE_2"] == 0x03
def test_ioniq_6_always_ipedal_spoofs_left_paddle_until_latched(self):
@pytest.mark.parametrize(("counter", "expected_hex"), [
(0, "2100002800000000"),
(7, "2970002800000000"),
(14, "31e0002800000000"),
])
def test_ioniq_6_left_paddle_message_matches_stock(self, counter, expected_hex):
CP = CarParams.new_message()
CP.carFingerprint = CAR.HYUNDAI_IONIQ_6
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CANFD_LKA_STEERING)
msg = hyundaicanfd.create_ioniq_6_paddle_buttons(CANPacker(DBC[CP.carFingerprint][Bus.pt]), CP, CanBus(CP),
counter, left_paddle=True)
assert msg[1].hex() == expected_hex
def test_ioniq_6_buttons_counter_wraps_like_stock(self):
assert hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(13) == 14
assert hyundaicanfd.get_ioniq_6_cruise_buttons_next_counter(14) == 0
def test_ioniq_6_always_ipedal_spoofs_left_paddle_in_startup_park_and_drive_until_latched(self):
toggles = get_test_toggles()
toggles.always_ipedal = True
CP = CarInterface.get_params(CAR.HYUNDAI_IONIQ_6, gen_empty_fingerprint(), [], True, False, False, toggles)
@@ -332,7 +350,7 @@ class TestHyundaiFingerprint:
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("CRUISE_BUTTONS", 0)], parser_bus)
cs = SimpleNamespace(
out=SimpleNamespace(gearShifter=structs.CarState.GearShifter.drive),
out=SimpleNamespace(gearShifter=structs.CarState.GearShifter.park),
ipedal_active=False,
buttons_counter=5,
cruise_buttons_msg={
@@ -349,16 +367,26 @@ class TestHyundaiFingerprint:
)
cc = SimpleNamespace(enabled=False)
controller._ioniq_6_last_gear = structs.CarState.GearShifter.reverse
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
parser.update([(1, sends)])
assert sends
assert sends[0][1].hex() == "9060002800000000"
assert parser.vl["CRUISE_BUTTONS"]["LEFT_PADDLE"] == 1
assert parser.vl["CRUISE_BUTTONS"]["COUNTER"] == 6
assert controller._ioniq_6_always_ipedal_pending
assert not controller._ioniq_6_always_ipedal_startup_park_done
controller.frame = 2
cs.out.gearShifter = structs.CarState.GearShifter.drive
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
assert sends
assert sends[0][1].hex() == "9060002800000000"
assert controller._ioniq_6_always_ipedal_pending
assert controller._ioniq_6_always_ipedal_startup_park_done
controller.frame = 4
cs.ipedal_active = True
sends = controller._update_ioniq_6_always_ipedal(cc, cs, toggles)
@@ -6,7 +6,7 @@ from opendbc.car.interfaces import CarControllerBase
from opendbc.car.tesla.teslacan import TeslaCAN
from opendbc.car.tesla.preap.carcontroller import PreAPLongController, init_preap_can
from opendbc.car.tesla.preap.stock_cc_spoofer import StockCCSpoofer
from opendbc.car.tesla.values import CAR, CarControllerParams
from opendbc.car.tesla.values import CANBUS, CAR, CarControllerParams
from opendbc.car.vehicle_model import VehicleModel
+40 -9
View File
@@ -48,7 +48,8 @@ UNWIND_LAT_ACCEL_NEAR_ZERO = 0.3
MIN_LATERAL_CONTROL_SPEED = 0.3
CIVIC_BOSCH_MODIFIED_B_FIXED_FRICTION_THRESHOLD = 0.30
CIVIC_BOSCH_MODIFIED_B_LAT_ACCEL_FACTOR_MULT = 1.20
CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT = 1.10
CIVIC_BOSCH_MODIFIED_A_VARIANT_LAT_ACCEL_FACTOR_MULT = 0.98
CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT = 1.14
CIVIC_BOSCH_MODIFIED_B_TRANSITION_SPEED = 12.0
CIVIC_BOSCH_MODIFIED_B_PHASE_SCALE = 0.10
CIVIC_BOSCH_MODIFIED_B_FF_ONSET = 0.18
@@ -65,16 +66,22 @@ CIVIC_BOSCH_MODIFIED_B_TURN_IN_FRICTION_BOOST_LEFT = 0.02
CIVIC_BOSCH_MODIFIED_B_TURN_IN_FRICTION_BOOST_RIGHT = 0.00
CIVIC_BOSCH_MODIFIED_B_UNWIND_FRICTION_REDUCTION_LEFT = 0.26
CIVIC_BOSCH_MODIFIED_B_UNWIND_FRICTION_REDUCTION_RIGHT = 0.40
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_LEFT = 0.10
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_RIGHT = 0.20
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_LEFT = 0.04
CIVIC_BOSCH_MODIFIED_A_VARIANT_FF_RESTORE_LEFT = 0.05
CIVIC_BOSCH_MODIFIED_A_VARIANT_FF_RESTORE_RIGHT = 0.02
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_BOOST_LEFT = 0.04
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_BOOST_RIGHT = 0.01
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_LEFT = 0.02
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_RIGHT = 0.01
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_LEFT = 0.14
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_RIGHT = 0.22
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_LEFT = 0.02
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_RIGHT = 0.00
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_LEFT = 0.28
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_RIGHT = 0.42
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_LEFT = 0.02
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_LEFT = 0.38
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_TAPER_RIGHT = 0.48
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_LEFT = 0.01
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_RIGHT = 0.00
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_LEFT = 0.16
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_RIGHT = 0.28
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_LEFT = 0.24
CIVIC_BOSCH_MODIFIED_B_VARIANT_UNWIND_FRICTION_REDUCTION_RIGHT = 0.34
BOLT_2022_2023_CARS = (
GM_CAR.CHEVROLET_BOLT_ACC_2022_2023,
@@ -359,6 +366,10 @@ def civic_bosch_modified_lateral_testing_ground_active() -> bool:
return testing_ground.use("8", "B")
def civic_bosch_modified_a_lateral_testing_ground_active() -> bool:
return testing_ground.use("8", "A")
def _civic_bosch_modified_b_low_speed_factor(v_ego: float) -> float:
return 1.0 / (1.0 + (max(v_ego, 0.0) / CIVIC_BOSCH_MODIFIED_B_TRANSITION_SPEED) ** 2)
@@ -386,7 +397,12 @@ def get_civic_bosch_modified_b_ff_scale(desired_lateral_accel: float, desired_la
turn_in_weight = max(phase, 0.0)
unwind_weight = max(-phase, 0.0)
low_speed_factor = _civic_bosch_modified_b_low_speed_factor(v_ego)
a_variant_active = civic_bosch_modified_a_lateral_testing_ground_active()
variant_active = civic_bosch_modified_lateral_testing_ground_active()
if a_variant_active:
base_reduction -= (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_A_VARIANT_FF_RESTORE_LEFT,
CIVIC_BOSCH_MODIFIED_A_VARIANT_FF_RESTORE_RIGHT) * onset * cutoff)
if variant_active:
base_reduction += (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_B_VARIANT_FF_REDUCTION_LEFT,
@@ -396,6 +412,11 @@ def get_civic_bosch_modified_b_ff_scale(desired_lateral_accel: float, desired_la
CIVIC_BOSCH_MODIFIED_B_TURN_IN_BOOST_LEFT,
CIVIC_BOSCH_MODIFIED_B_TURN_IN_BOOST_RIGHT) *
turn_in_weight * (0.40 + 0.60 * low_speed_factor))
if a_variant_active:
turn_in_boost *= 1.0 + (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_BOOST_LEFT,
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_BOOST_RIGHT) *
turn_in_weight * (0.40 + 0.60 * low_speed_factor))
if variant_active:
turn_in_boost *= 1.0 + (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_BOOST_LEFT,
@@ -424,6 +445,7 @@ def get_civic_bosch_modified_b_friction_scale(v_ego: float, desired_lateral_acce
phase = _civic_bosch_modified_b_transition_phase(desired_lateral_accel, desired_lateral_jerk)
turn_in_weight = max(phase, 0.0)
unwind_weight = max(-phase, 0.0)
a_variant_active = civic_bosch_modified_a_lateral_testing_ground_active()
variant_active = civic_bosch_modified_lateral_testing_ground_active()
friction_scale = 1.0
@@ -431,6 +453,11 @@ def get_civic_bosch_modified_b_friction_scale(v_ego: float, desired_lateral_acce
CIVIC_BOSCH_MODIFIED_B_TURN_IN_FRICTION_BOOST_LEFT,
CIVIC_BOSCH_MODIFIED_B_TURN_IN_FRICTION_BOOST_RIGHT) *
envelope * turn_in_weight)
if a_variant_active:
friction_scale += (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_LEFT,
CIVIC_BOSCH_MODIFIED_A_VARIANT_TURN_IN_FRICTION_BOOST_RIGHT) *
envelope * turn_in_weight)
if variant_active:
friction_scale += (_civic_bosch_modified_b_side_value(desired_lateral_accel,
CIVIC_BOSCH_MODIFIED_B_VARIANT_TURN_IN_FRICTION_BOOST_LEFT,
@@ -1113,6 +1140,8 @@ class LatControlTorque(LatControl):
self.torque_params.latAccelFactor *= IONIQ_6_BASE_LAT_ACCEL_FACTOR_MULT
if self.is_civic_bosch_modified:
self.torque_params.latAccelFactor *= CIVIC_BOSCH_MODIFIED_B_LAT_ACCEL_FACTOR_MULT
if civic_bosch_modified_a_lateral_testing_ground_active():
self.torque_params.latAccelFactor *= CIVIC_BOSCH_MODIFIED_A_VARIANT_LAT_ACCEL_FACTOR_MULT
if civic_bosch_modified_lateral_testing_ground_active():
self.torque_params.latAccelFactor *= CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT
if self.is_bolt:
@@ -1130,6 +1159,8 @@ class LatControlTorque(LatControl):
latAccelFactor *= IONIQ_6_BASE_LAT_ACCEL_FACTOR_MULT
if self.is_civic_bosch_modified:
latAccelFactor *= CIVIC_BOSCH_MODIFIED_B_LAT_ACCEL_FACTOR_MULT
if civic_bosch_modified_a_lateral_testing_ground_active():
latAccelFactor *= CIVIC_BOSCH_MODIFIED_A_VARIANT_LAT_ACCEL_FACTOR_MULT
if civic_bosch_modified_lateral_testing_ground_active():
latAccelFactor *= CIVIC_BOSCH_MODIFIED_B_VARIANT_LAT_ACCEL_FACTOR_MULT
self.torque_params.latAccelFactor = latAccelFactor
+28 -1
View File
@@ -429,10 +429,16 @@ class TestLatControl:
assert controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20)
monkeypatch.setattr(latcontrol_torque, "civic_bosch_modified_a_lateral_testing_ground_active", lambda: True)
a_variant_controller = LatControlTorque(CP.as_reader(), CI, DT_CTRL)
assert a_variant_controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20 * 0.98)
monkeypatch.setattr(latcontrol_torque, "civic_bosch_modified_a_lateral_testing_ground_active", lambda: False)
monkeypatch.setattr(latcontrol_torque, "civic_bosch_modified_lateral_testing_ground_active", lambda: True)
variant_controller = LatControlTorque(CP.as_reader(), CI, DT_CTRL)
assert variant_controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20 * 1.10)
assert variant_controller.torque_params.latAccelFactor == pytest.approx(3.0 * 1.20 * 1.14)
def test_modified_civic_b_torque_ff_scale_curve(self):
steady_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.0, 12.0)
@@ -479,6 +485,27 @@ class TestLatControl:
assert variant_unwind_right < base_unwind_right
assert variant_unwind_right_friction < base_unwind_right_friction
def test_modified_civic_a_variant_extra_torque_shaping_curve(self, monkeypatch):
base_steady_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.0, 12.0)
base_steady_right = get_civic_bosch_modified_b_ff_scale(-0.5, 0.0, 12.0)
base_turn_in_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.8, 12.0)
base_turn_in_right = get_civic_bosch_modified_b_ff_scale(-0.5, -0.8, 12.0)
base_turn_in_left_friction = get_civic_bosch_modified_b_friction_scale(12.0, 0.5, 0.8)
monkeypatch.setattr(latcontrol_torque, "civic_bosch_modified_a_lateral_testing_ground_active", lambda: True)
a_variant_steady_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.0, 12.0)
a_variant_steady_right = get_civic_bosch_modified_b_ff_scale(-0.5, 0.0, 12.0)
a_variant_turn_in_left = get_civic_bosch_modified_b_ff_scale(0.5, 0.8, 12.0)
a_variant_turn_in_right = get_civic_bosch_modified_b_ff_scale(-0.5, -0.8, 12.0)
a_variant_turn_in_left_friction = get_civic_bosch_modified_b_friction_scale(12.0, 0.5, 0.8)
assert a_variant_steady_left > base_steady_left
assert a_variant_steady_right > base_steady_right
assert a_variant_turn_in_left > base_turn_in_left
assert a_variant_turn_in_right > base_turn_in_right
assert a_variant_turn_in_left_friction > base_turn_in_left_friction
def test_kia_ev6_testing_ground_update_path(self, monkeypatch):
controller, VM, CS, params, starpilot_toggles = self._build_torque_controller(HYUNDAI.KIA_EV6)
monkeypatch.setattr(latcontrol_torque, "kia_ev6_lateral_testing_ground_active", lambda: True)