This commit is contained in:
firestar5683
2026-04-26 15:40:15 -05:00
parent 71528fd547
commit bcf78fec02
38 changed files with 76 additions and 68 deletions
@@ -19,7 +19,6 @@ MAX_ANGLE = 85
MAX_ANGLE_FRAMES = 89
MAX_ANGLE_CONSECUTIVE_FRAMES = 2
CANFD_BLINDSPOT_STATUS_STALE_NS = 200_000_000
IONIQ_6_LANE_CHANGE_UI_MIN_SPEED = 20 * CV.MPH_TO_MS
def process_hud_alert(enabled, fingerprint, hud_control):
@@ -213,7 +212,8 @@ class CarController(CarControllerBase):
# steering control
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled,
apply_steer_req, apply_torque, apply_angle))
apply_steer_req, apply_torque, apply_angle,
CS.stock_lfa_msg))
# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
if self.frame % 5 == 0 and lka_steering:
@@ -222,10 +222,7 @@ class CarController(CarControllerBase):
# LFA and HDA icons
if self.frame % 5 == 0 and (not lka_steering or lka_steering_long):
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled))
if self.CP.carFingerprint == CAR.HYUNDAI_IONIQ_6 and self.long_active_ecu and CC.enabled and CS.out.vEgo >= IONIQ_6_LANE_CHANGE_UI_MIN_SPEED:
can_sends.append(hyundaicanfd.create_ioniq_6_lane_change_status(self.CAN, self.frame, CC.leftBlinker, CC.rightBlinker))
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CAN, CC.enabled, CS.stock_lfahda_cluster_msg))
# blinkers
if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
@@ -86,6 +86,8 @@ class CarState(CarStateBase):
self.buttons_counter = 0
self.cruise_info = {}
self.stock_lfa_msg = {}
self.stock_lfahda_cluster_msg = {}
self.blindspots_rear_corners = {}
self.blindspots_front_corner_1 = {}
self.blindspots_rear_corners_ts = 0
@@ -361,6 +363,10 @@ class CarState(CarStateBase):
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
self.lfa_block_msg = copy.copy(cp_cam.vl["CAM_0x362"] if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT
else cp_cam.vl["CAM_0x2a4"])
if cp.ts_nanos["LFA"]["CHECKSUM"] > 0:
self.stock_lfa_msg = copy.copy(cp.vl["LFA"])
if cp.ts_nanos["LFAHDA_CLUSTER"]["CHECKSUM"] > 0:
self.stock_lfahda_cluster_msg = copy.copy(cp.vl["LFAHDA_CLUSTER"])
ret.buttonEvents = [*create_button_events(self.cruise_buttons[-1], prev_cruise_buttons, BUTTONS_DICT),
*create_button_events(self.main_buttons[-1], prev_main_buttons, {1: ButtonType.mainCruise}),
@@ -397,6 +403,10 @@ class CarState(CarStateBase):
msgs.append(("FR_CMR_02_100ms", 10))
else:
cam_msgs.append(("FR_CMR_02_100ms", 0)) # optional: not all non-LKA CANFD cars have this on CAM bus
msgs += [
("LFA", 0), # optional: may stop once OP takes over, but preserve stock UI fields when present
("LFAHDA_CLUSTER", 0), # optional: carries cluster icon state on some variants
]
if CP.flags & HyundaiFlags.EV:
msgs.append(("DRIVE_MODE_EV", 0)) # optional: not all CAN-FD EV variants publish drive mode
msgs.append(("STEERING_WHEEL_MEDIA_BUTTONS", 0)) # optional: absent or slower on some CAN-FD variants
@@ -91,24 +91,29 @@ def _create_angle_adas_cmd_msg(packer, CAN, apply_angle: float, lat_active: bool
return packer.make_can_msg("ADAS_CMD_35_10ms", CAN.ECAN, values)
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, apply_angle):
common_values = {
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, apply_angle, lfa_base_values=None):
control_values = {
"LKA_MODE": 2,
"LKA_ICON": 2 if enabled else 1,
"TORQUE_REQUEST": 0 if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING else apply_torque,
"LKA_ASSIST": 0,
"STEER_REQ": 0 if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING else (1 if lat_active else 0),
"STEER_MODE": 0,
"HAS_LANE_SAFETY": 0, # hide LKAS settings
"NEW_SIGNAL_2": 0,
"DAMP_FACTOR": 100, # can potentially tuned for better perf [3, 200]
}
lkas_values = copy.copy(common_values)
lkas_values = copy.copy(control_values)
lkas_values["LKA_AVAILABLE"] = 0
lfa_values = copy.copy(common_values)
lfa_values["NEW_SIGNAL_1"] = 0
if lfa_base_values:
# Preserve stock UI/status fields and only override the actuation-relevant signals.
lfa_values = {k: v for k, v in lfa_base_values.items() if k not in ("CHECKSUM", "COUNTER")}
lfa_values.update(control_values)
else:
lfa_values = copy.copy(control_values)
lfa_values["HAS_LANE_SAFETY"] = 0 # hide LKAS settings
lfa_values["NEW_SIGNAL_1"] = 0
lfa_values["NEW_SIGNAL_2"] = 0
lfa_values["DAMP_FACTOR"] = 100 # can potentially tuned for better perf [3, 200]
if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING and CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT:
lkas_values["ADAS_StrAnglReqVal"] = apply_angle
@@ -188,36 +193,15 @@ def create_acc_cancel(packer, CP, CAN, cruise_info_copy):
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
def create_lfahda_cluster(packer, CAN, enabled):
values = {
def create_lfahda_cluster(packer, CAN, enabled, base_values=None):
values = {k: v for k, v in base_values.items() if k not in ("CHECKSUM", "COUNTER")} if base_values else {}
values.update({
"HDA_ICON": 1 if enabled else 0,
"LFA_ICON": 2 if enabled else 0,
}
})
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
IONIQ_6_LANE_CHANGE_UI_ADDR = 0x120
IONIQ_6_LANE_CHANGE_UI_TEMPLATE = bytearray.fromhex("0000000000000005ffd9671f46454645d90200000000000000000a0000002040")
IONIQ_6_LANE_CHANGE_UI_BASE = (0x45, 0xD9)
IONIQ_6_LANE_CHANGE_UI_RIGHT = (0x45, 0xDA)
IONIQ_6_LANE_CHANGE_UI_LEFT = (0x46, 0xDD)
def create_ioniq_6_lane_change_status(CAN, counter: int, left_blinker: bool, right_blinker: bool):
dat = bytearray(IONIQ_6_LANE_CHANGE_UI_TEMPLATE)
dat[2] = counter & 0xFF
state = IONIQ_6_LANE_CHANGE_UI_BASE
if left_blinker:
state = IONIQ_6_LANE_CHANGE_UI_LEFT
elif right_blinker:
state = IONIQ_6_LANE_CHANGE_UI_RIGHT
dat[15], dat[16] = state
dat[0:2] = hkg_can_fd_checksum(IONIQ_6_LANE_CHANGE_UI_ADDR, None, dat).to_bytes(2, "little")
return CanData(IONIQ_6_LANE_CHANGE_UI_ADDR, bytes(dat), CAN.ECAN)
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")}
@@ -232,6 +232,49 @@ class TestHyundaiFingerprint:
msgs = hyundaicanfd.create_steering_messages(packer, CP, CanBus(CP), True, True, 1.0, 12.3)
assert [(addr, bus) for addr, _, bus in msgs] == [(0xCB, CanBus(CP).ECAN)]
def test_ioniq_6_lfa_helper_preserves_stock_ui_fields(self):
CP = CarParams.new_message()
CP.carFingerprint = CAR.HYUNDAI_IONIQ_6
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CANFD_LKA_STEERING)
CP.openpilotLongitudinalControl = True
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
can_bus = CanBus(CP)
parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [("LFA", 0)], can_bus.ECAN)
stock_lfa = {
"CHECKSUM": 1234,
"COUNTER": 42,
"LKA_MODE": 6,
"NEW_SIGNAL_1": 3,
"LKA_WARNING": 1,
"LKA_ICON": 1,
"TORQUE_REQUEST": 17,
"STEER_REQ": 0,
"LFA_BUTTON": 1,
"LKA_ASSIST": 1,
"STEER_MODE": 5,
"NEW_SIGNAL_2": 2,
"NEW_SIGNAL_4": 7,
"HAS_LANE_SAFETY": 1,
"DAMP_FACTOR": 0x77,
}
msgs = hyundaicanfd.create_steering_messages(packer, CP, can_bus, True, True, 123, 0.0, stock_lfa)
lfa_msgs = [msg for msg in msgs if msg[0] == 0x12A]
assert len(lfa_msgs) == 1
parser.update([(1, lfa_msgs)])
assert parser.can_valid
assert parser.vl["LFA"]["NEW_SIGNAL_1"] == 3
assert parser.vl["LFA"]["NEW_SIGNAL_2"] == 2
assert parser.vl["LFA"]["HAS_LANE_SAFETY"] == 1
assert parser.vl["LFA"]["DAMP_FACTOR"] == 0x77
assert parser.vl["LFA"]["TORQUE_REQUEST"] == 123
assert parser.vl["LFA"]["STEER_REQ"] == 1
assert parser.vl["LFA"]["LKA_ICON"] == 2
def test_ioniq_6_blindspot_status_helper_regenerates_counter_checksum(self):
CP = CarParams.new_message()
CP.carFingerprint = CAR.HYUNDAI_IONIQ_6
@@ -283,31 +326,6 @@ class TestHyundaiFingerprint:
assert parser.vl["BLINDSPOTS_REAR_CORNERS"]["FR_INDICATOR_ALT"] == 0
assert parser.vl["BLINDSPOTS_FRONT_CORNER_1"]["NEW_SIGNAL_3"] == 1
def test_ioniq_6_lane_change_ui_helper_regenerates_checksum_and_state(self):
CP = CarParams.new_message()
CP.carFingerprint = CAR.HYUNDAI_IONIQ_6
CP.flags = int(HyundaiFlags.CANFD | HyundaiFlags.CANFD_LKA_STEERING)
can_bus = CanBus(CP)
base_msg = hyundaicanfd.create_ioniq_6_lane_change_status(can_bus, 0x12, left_blinker=False, right_blinker=False)
right_msg = hyundaicanfd.create_ioniq_6_lane_change_status(can_bus, 0x34, left_blinker=False, right_blinker=True)
left_msg = hyundaicanfd.create_ioniq_6_lane_change_status(can_bus, 0x56, left_blinker=True, right_blinker=False)
assert base_msg[0] == 0x120
assert base_msg[2] == can_bus.ECAN
assert base_msg[1][2] == 0x12
assert right_msg[1][2] == 0x34
assert left_msg[1][2] == 0x56
assert hyundaicanfd.hkg_can_fd_checksum(base_msg[0], None, bytearray(base_msg[1])) == int.from_bytes(base_msg[1][:2], "little")
assert hyundaicanfd.hkg_can_fd_checksum(right_msg[0], None, bytearray(right_msg[1])) == int.from_bytes(right_msg[1][:2], "little")
assert hyundaicanfd.hkg_can_fd_checksum(left_msg[0], None, bytearray(left_msg[1])) == int.from_bytes(left_msg[1][:2], "little")
assert (base_msg[1][15], base_msg[1][16]) == hyundaicanfd.IONIQ_6_LANE_CHANGE_UI_BASE
assert (right_msg[1][15], right_msg[1][16]) == hyundaicanfd.IONIQ_6_LANE_CHANGE_UI_RIGHT
assert (left_msg[1][15], left_msg[1][16]) == hyundaicanfd.IONIQ_6_LANE_CHANGE_UI_LEFT
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)
@@ -289,7 +289,6 @@ static safety_config hyundai_canfd_init(uint16_t param) {
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(1)
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true)
HYUNDAI_CANFD_BLINDSPOT_DASH_TX_MSGS(1)
{0x120, 1, 32, .check_relay = false}, // IONIQ_6 lane change UI
{0x51, 0, 32, .check_relay = false}, // ADRV_0x51
{0x730, 1, 8, .check_relay = false}, // tester present for ADAS ECU disable
{0x160, 1, 16, .check_relay = false}, // ADRV_0x160
@@ -450,7 +450,7 @@ class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanfdLKASteeringEV):
TX_MSGS = [[0x50, 0], [0x120, 1], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1],
[0x1ba, 1], [0x1e0, 1], [0x1e5, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]]
RELAY_MALFUNCTION_ADDRS = {0: (0x50, 0x2a4), 1: (0x1a0,)} # LKAS, CAM_0x2A4, SCC_CONTROL
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19];
const uint8_t gitversion[19] = "DEV-962e0d74-DEBUG";
const uint8_t gitversion[19] = "DEV-71528fd5-DEBUG";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
DEV-962e0d74-DEBUG
DEV-71528fd5-DEBUG