Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HKG: Car Port for Hyundai Palisade and Kia Telluride 2023-24 (non-HDA2) #1273

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions opendbc/car/hyundai/carcontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ def update(self, CC, CS, now_nanos):
if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True))

# Common shared configuration

can_canfd_hybrid = bool(self.CP.flags & HyundaiFlags.CAN_CANFD_HYBRID)

# CAN-FD platforms
if self.CP.carFingerprint in CANFD_CAR:
hda2 = self.CP.flags & HyundaiFlags.CANFD_HDA2
Expand Down Expand Up @@ -134,10 +138,17 @@ def update(self, CC, CS, now_nanos):
# button presses
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=False))
else:
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
left_lane_warning, right_lane_warning))
# TODO: this can be merged with hyundaican.create_lkas11
if can_canfd_hybrid:
can_sends.append(hyundaican.create_lkas11_can_canfd_hybrid(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
left_lane_warning, right_lane_warning))
else:
can_sends.append(hyundaican.create_lkas11(self.packer, self.frame, self.CP, apply_steer, apply_steer_req,
torque_fault, CS.lkas11, sys_warning, sys_state, CC.enabled,
hud_control.leftLaneVisible, hud_control.rightLaneVisible,
left_lane_warning, right_lane_warning))

if not self.CP.openpilotLongitudinalControl:
can_sends.extend(self.create_button_messages(CC, CS, use_clu11=True))
Expand All @@ -152,7 +163,7 @@ def update(self, CC, CS, now_nanos):

# 20 Hz LFA MFA message
if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled))
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, self.frame, self.CP, CC.enabled))

# 5 Hz ACC options
if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl:
Expand All @@ -174,12 +185,12 @@ def create_button_messages(self, CC: structs.CarControl, CS: CarState, use_clu11
can_sends = []
if use_clu11:
if CC.cruiseControl.cancel:
can_sends.append(hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL, self.CP))
can_sends.append(hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.CANCEL, self.CP, self.CAN))
elif CC.cruiseControl.resume:
# send resume at a max freq of 10Hz
if (self.frame - self.last_button_frame) * DT_CTRL > 0.1:
# send 25 messages at a time to increases the likelihood of resume being accepted
can_sends.extend([hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.RES_ACCEL, self.CP)] * 25)
can_sends.extend([hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.RES_ACCEL, self.CP, self.CAN)] * 25)
if (self.frame - self.last_button_frame) * DT_CTRL >= 0.15:
self.last_button_frame = self.frame
else:
Expand Down
29 changes: 19 additions & 10 deletions opendbc/car/hyundai/carstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,12 @@ def update(self, cp, cp_cam, *_) -> structs.CarState:
ret.cruiseState.standstill = False
ret.cruiseState.nonAdaptive = False
else:
ret.cruiseState.available = cp_cruise.vl["SCC11"]["MainMode_ACC"] == 1
scc_bus = "SCC12" if self.CP.flags & HyundaiFlags.CAN_CANFD_HYBRID else "SCC11"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

scc_bus is a misnomer, it's really scc_msg.

ret.cruiseState.available = cp_cruise.vl[scc_bus]["MainMode_ACC"] == 1
ret.cruiseState.enabled = cp_cruise.vl["SCC12"]["ACCMode"] != 0
ret.cruiseState.standstill = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 4.
ret.cruiseState.nonAdaptive = cp_cruise.vl["SCC11"]["SCCInfoDisplay"] == 2. # Shows 'Cruise Control' on dash
ret.cruiseState.speed = cp_cruise.vl["SCC11"]["VSetDis"] * speed_conv
ret.cruiseState.standstill = cp_cruise.vl[scc_bus]["SCCInfoDisplay"] == 4.
ret.cruiseState.nonAdaptive = cp_cruise.vl[scc_bus]["SCCInfoDisplay"] == 2. # Shows 'Cruise Control' on dash
ret.cruiseState.speed = cp_cruise.vl[scc_bus]["VSetDis"] * speed_conv

# TODO: Find brake pressure
ret.brake = 0
Expand Down Expand Up @@ -151,7 +152,7 @@ def update(self, cp, cp_cam, *_) -> structs.CarState:

ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear))

if not self.CP.openpilotLongitudinalControl:
if not self.CP.openpilotLongitudinalControl and not (self.CP.flags & HyundaiFlags.CAN_CANFD_HYBRID):
aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12"
aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct"
aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0
Expand Down Expand Up @@ -266,9 +267,11 @@ def get_can_parser(self, CP):
if CP.carFingerprint in CANFD_CAR:
return self.get_can_parser_canfd(CP)

mdps12_freq = 100 if CP.flags & HyundaiFlags.CAN_CANFD_HYBRID else 50

messages = [
# address, frequency
("MDPS12", 50),
("MDPS12", mdps12_freq),
("TCS11", 100),
("TCS13", 50),
("TCS15", 10),
Expand All @@ -284,14 +287,18 @@ def get_can_parser(self, CP):

if not CP.openpilotLongitudinalControl and CP.carFingerprint not in CAMERA_SCC_CAR:
messages += [
("SCC11", 50),
("SCC12", 50),
]

if not (CP.flags & HyundaiFlags.CAN_CANFD_HYBRID):
messages.append(("SCC11", 50))

if CP.flags & HyundaiFlags.USE_FCA.value:
messages.append(("FCA11", 50))

if CP.enableBsm:
messages.append(("LCA11", 50))
lca11_freq = 20 if CP.flags & HyundaiFlags.CAN_CANFD_HYBRID else 50
messages.append(("LCA11", lca11_freq))

if CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV):
messages.append(("E_EMS11", 50))
Expand All @@ -310,7 +317,8 @@ def get_can_parser(self, CP):
else:
messages.append(("LVR12", 100))

return CANParser(DBC[CP.carFingerprint]["pt"], messages, 0)
bus = CanBus(CP).ECAN if CP.flags & HyundaiFlags.CAN_CANFD_HYBRID else 0
return CANParser(DBC[CP.carFingerprint]["pt"], messages, bus)

@staticmethod
def get_cam_can_parser(CP):
Expand All @@ -330,7 +338,8 @@ def get_cam_can_parser(CP):
if CP.flags & HyundaiFlags.USE_FCA.value:
messages.append(("FCA11", 50))

return CANParser(DBC[CP.carFingerprint]["pt"], messages, 2)
bus = CanBus(CP).CAM if CP.flags & HyundaiFlags.CAN_CANFD_HYBRID else 2
return CANParser(DBC[CP.carFingerprint]["pt"], messages, bus)

def get_can_parser_canfd(self, CP):
messages = [
Expand Down
15 changes: 15 additions & 0 deletions opendbc/car/hyundai/fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1155,4 +1155,19 @@
b'\xf1\x00US4_ RDR ----- 1.00 1.00 99110-CG000 ',
],
},
CAR.HYUNDAI_PALISADE_2023: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00LX2 MFC AT USA LHD 1.00 1.04 99211-S8150 220622',
b'\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9150 220708',
b'\xf1\x00ON MFC AT USA LHD 1.00 1.00 99211-S9160 230303',
b'\xf1\x00ON MFC AT USA LHD 1.00 1.01 99211-S9160 230802',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00LX2_ SCC ----- 1.00 1.01 99110-S8150 ',
b'\xf1\x00ON__ SCC ----- 1.00 1.01 99110-S9150 ',
b'\xf1\x00LX2_ SCC FHCUP 1.00 1.01 99110-S8150 ',
b'\xf1\x00ON__ SCC FHCUP 1.00 1.01 99110-S9150 ',
b'\xf1\x00ON__ SCC FHCUP 1.00 1.00 99110-S9160 ',
],
},
}
83 changes: 78 additions & 5 deletions opendbc/car/hyundai/hyundaican.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import crcmod
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import CAR, HyundaiFlags

hyundai_checksum = crcmod.mkCrcFun(0x11D, initCrc=0xFD, rev=False, xorOut=0xdf)
Expand Down Expand Up @@ -95,7 +96,61 @@ def create_lkas11(packer, frame, CP, apply_steer, steer_req,
return packer.make_can_msg("LKAS11", 0, values)


def create_clu11(packer, frame, clu11, button, CP):
def create_lkas11_can_canfd_hybrid(packer, frame, CP, apply_steer, steer_req,
torque_fault, lkas11, sys_warning, sys_state, enabled,
left_lane, right_lane,
left_lane_depart, right_lane_depart):
can_canfd_hybrid = CP.flags & HyundaiFlags.CAN_CANFD_HYBRID
bus = CanBus(CP).ECAN if can_canfd_hybrid else 0

lkas11_sigs = [
"CF_Lkas_LdwsActivemode",
"CF_Lkas_LdwsLHWarning",
"CF_Lkas_LdwsRHWarning",
"CF_Lkas_FcwOpt_USM",
]

if not can_canfd_hybrid:
lkas11_sigs += [
"CF_Lkas_LdwsSysState",
"CF_Lkas_SysWarning",
"CF_Lkas_HbaLamp",
"CF_Lkas_FcwBasReq",
"CF_Lkas_HbaSysState",
"CF_Lkas_FcwOpt",
"CF_Lkas_HbaOpt",
"CF_Lkas_FcwSysState",
"CF_Lkas_FcwCollisionWarning",
"CF_Lkas_FusionState",
"CF_Lkas_LdwsOpt_USM",
]

values = {s: lkas11[s] for s in lkas11_sigs}

values["CF_Lkas_LdwsLHWarning"] = left_lane_depart
values["CF_Lkas_LdwsRHWarning"] = right_lane_depart
values["CR_Lkas_StrToqReq"] = apply_steer
values["CF_Lkas_ActToi"] = steer_req
values["CF_Lkas_ToiFlt"] = torque_fault # seems to allow actuation on CR_Lkas_StrToqReq
values["CF_Lkas_MsgCount"] = frame % (0xF if can_canfd_hybrid else 0x10)

values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
values["CF_Lkas_FcwOpt_USM"] = 2 if enabled else 1
values["NEW_SIGNAL_1"] = 0
values["NEW_SIGNAL_5"] = 100

dat = packer.make_can_msg("LKAS11", bus, values)[1]

# CRC Checksum as seen on 2019 Hyundai Santa Fe
dat = dat[1:8] if can_canfd_hybrid else dat[:6] + dat[7:8]
checksum = hyundai_checksum(dat)

values["CF_Lkas_Chksum"] = checksum

return packer.make_can_msg("LKAS11", bus, values)


def create_clu11(packer, frame, clu11, button, CP, CAN):
values = {s: clu11[s] for s in [
"CF_Clu_CruiseSwState",
"CF_Clu_CruiseSwMain",
Expand All @@ -112,19 +167,37 @@ def create_clu11(packer, frame, clu11, button, CP):
]}
values["CF_Clu_CruiseSwState"] = button
values["CF_Clu_AliveCnt1"] = frame % 0x10
# send buttons to camera on camera-scc based cars
bus = 2 if CP.flags & HyundaiFlags.CAMERA_SCC else 0

if CP.flags & HyundaiFlags.CAMERA_SCC: # send buttons to camera on camera-scc based cars
bus = 2
elif CP.flags & HyundaiFlags.CAN_CANFD_HYBRID:
bus = CAN.ECAN
else:
bus = 0

return packer.make_can_msg("CLU11", bus, values)


def create_lfahda_mfc(packer, enabled, hda_set_speed=0):
def create_lfahda_mfc(packer, frame, CP, enabled, hda_set_speed=0):
can_canfd_hybrid = CP.flags & HyundaiFlags.CAN_CANFD_HYBRID
bus = CanBus(CP).ECAN if can_canfd_hybrid else 0

values = {
"LFA_Icon_State": 2 if enabled else 0,
"HDA_Active": 1 if hda_set_speed else 0,
"HDA_Icon_State": 2 if hda_set_speed else 0,
"HDA_VSetReq": hda_set_speed,
}
return packer.make_can_msg("LFAHDA_MFC", 0, values)

if can_canfd_hybrid:
values["COUNTER"] = frame % 0xF

dat = packer.make_can_msg("LFAHDA_MFC", bus, values)[1]
checksum = hyundai_checksum(dat[1:8])
values["CHECKSUM"] = checksum

return packer.make_can_msg("LFAHDA_MFC", bus, values)


def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca):
commands = []
Expand Down
29 changes: 21 additions & 8 deletions opendbc/car/hyundai/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime
hda2 = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
CAN = CanBus(None, fingerprint, hda2)

# detect HDA2 with HDA2-only steering messages
if hda2:
ret.flags |= HyundaiFlags.CANFD_HDA2.value

if candidate in CANFD_CAR:
# Shared configuration for CAN-FD cars
ret.experimentalLongitudinalAvailable = candidate not in (CANFD_UNSUPPORTED_LONGITUDINAL_CAR | CANFD_RADAR_SCC_CAR)
Expand All @@ -30,9 +34,7 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime
if 0x105 in fingerprint[CAN.ECAN]:
ret.flags |= HyundaiFlags.HYBRID.value

# detect HDA2 with ADAS Driving ECU
if hda2:
ret.flags |= HyundaiFlags.CANFD_HDA2.value
if 0x110 in fingerprint[CAN.CAM]:
ret.flags |= HyundaiFlags.CANFD_HDA2_ALT_STEERING.value
else:
Expand All @@ -56,7 +58,6 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime
ret.safetyConfigs = cfgs

if ret.flags & HyundaiFlags.CANFD_HDA2:
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_HDA2
if ret.flags & HyundaiFlags.CANFD_HDA2_ALT_STEERING:
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_HDA2_ALT_STEERING
if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
Expand All @@ -67,25 +68,36 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime
else:
# Shared configuration for non CAN-FD cars
ret.experimentalLongitudinalAvailable = candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | CAMERA_SCC_CAR)
ret.enableBsm = 0x58b in fingerprint[0]
ret.enableBsm = 0x58b in fingerprint[CAN.ECAN]

# Send LFA message on cars with HDA
if 0x485 in fingerprint[2]:
if 0x485 in fingerprint[CAN.CAM]:
ret.flags |= HyundaiFlags.SEND_LFA.value

# These cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
if 0x38d in fingerprint[0] or 0x38d in fingerprint[2]:
if 0x38d in fingerprint[CAN.ECAN] or 0x38d in fingerprint[CAN.CAM]:
ret.flags |= HyundaiFlags.USE_FCA.value

if candidate in LEGACY_SAFETY_MODE_CAR:
# these cars require a special panda safety mode due to missing counters and checksums in the messages
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundaiLegacy)]
else:
ret.safetyConfigs = [get_safety_config(structs.CarParams.SafetyModel.hyundai, 0)]
cfgs = [get_safety_config(structs.CarParams.SafetyModel.hyundai), ]
if CAN.ECAN >= 4:
cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput))
ret.safetyConfigs = cfgs

if candidate in CAMERA_SCC_CAR:
ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HYUNDAI_CAMERA_SCC

if ret.flags & HyundaiFlags.CAN_CANFD_HYBRID:
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CAN_CANFD_HYBRID

# Common shared configuration

if ret.flags & HyundaiFlags.CANFD_HDA2:
ret.safetyConfigs[-1].safetyParam |= Panda.FLAG_HYUNDAI_CANFD_HDA2

# Common lateral control setup

ret.centerToFront = ret.wheelbase * 0.4
Expand Down Expand Up @@ -122,7 +134,8 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime

# Dashcam cars are missing a test route, or otherwise need validation
# TODO: Optima Hybrid 2017 uses a different SCC12 checksum
ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, }
# TODO: Palisade/Telluride 2023-24 HDA2 will be supported in another PR
ret.dashcamOnly = candidate in {CAR.KIA_OPTIMA_H, } or (candidate in (CAR.HYUNDAI_PALISADE_2023, ) and hda2)

return ret

Expand Down
5 changes: 3 additions & 2 deletions opendbc/car/hyundai/tests/test_hyundai.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def test_expected_platform_codes(self, subtests):

# Third and fourth character are usually EV/hybrid identifiers
codes = {code.split(b"-")[0][:2] for code, _ in get_platform_codes(fws)}
if car_model == CAR.HYUNDAI_PALISADE:
if car_model in (CAR.HYUNDAI_PALISADE, CAR.HYUNDAI_PALISADE_2023):
assert codes == {b"LX", b"ON"}, f"Car has unexpected platform codes: {car_model} {codes}"
elif car_model == CAR.HYUNDAI_KONA_EV and ecu[0] == Ecu.fwdCamera:
assert codes == {b"OE", b"OS"}, f"Car has unexpected platform codes: {car_model} {codes}"
Expand All @@ -139,7 +139,8 @@ def test_expected_platform_codes(self, subtests):
def test_platform_code_ecus_available(self, subtests):
# TODO: add queries for these non-CAN FD cars to get EPS
no_eps_platforms = CANFD_CAR | {CAR.KIA_SORENTO, CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.KIA_OPTIMA_H,
CAR.KIA_OPTIMA_H_G4_FL, CAR.HYUNDAI_SONATA_LF, CAR.HYUNDAI_TUCSON, CAR.GENESIS_G90, CAR.GENESIS_G80, CAR.HYUNDAI_ELANTRA}
CAR.KIA_OPTIMA_H_G4_FL, CAR.HYUNDAI_SONATA_LF, CAR.HYUNDAI_TUCSON, CAR.GENESIS_G90,
CAR.GENESIS_G80, CAR.HYUNDAI_ELANTRA, CAR.HYUNDAI_PALISADE_2023}

# Asserts ECU keys essential for fuzzy fingerprinting are available on all platforms
for car_model, ecus in FW_VERSIONS.items():
Expand Down
Loading
Loading