Merge branch 'upstream/opendbc/master' into sync-20260405

# Conflicts:
#	docs/CARS.md
This commit is contained in:
Jason Wen
2026-04-05 13:20:05 -04:00
18 changed files with 153 additions and 103 deletions

View File

@@ -3,7 +3,9 @@ We need these details to verify your pull request.
Find your device's dongle ID and a route at https://connect.comma.ai.
Ideally, the route is recorded with the exact branch of your pull request.
If you are porting a car with a new harness variant, please add it to https://github.com/commaai/opendbc/blob/master/opendbc/car/docs_definitions.py. Let us know and we can add it to the shop at the time of merge.
-->
Validation
* Dongle ID:
* Route:
* Dongle ID:
* Route:

View File

@@ -1,6 +1,6 @@
<!--- AUTOGENERATED FROM selfdrive/car/CARS_template.md, DO NOT EDIT. --->
# Support Information for 410 Known Cars
# Support Information for 417 Known Cars
|Make|Model|Package|Support Level|
|---|---|---|:---:|
@@ -10,17 +10,18 @@
|Acura|Integra 2023-25|All|[Community](#community)|
|Acura|MDX 2015-16|Advance Package|[Community](#community)|
|Acura|MDX 2017-20|All|[Community](#community)|
|Acura|MDX 2022-24|All|[Community](#community)|
|Acura|MDX 2022-24|All|[Upstream](#upstream)|
|Acura|MDX 2025-26|All except Type S|[Upstream](#upstream)|
|Acura|MDX Hybrid 2017-20|All|[Community](#community)|
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|[Upstream](#upstream)|
|Acura|RDX 2019-21|All|[Upstream](#upstream)|
|Acura|RDX 2022-25|All|[Community](#community)|
|Acura|RDX 2022-24|All|[Dashcam mode](#dashcam)|
|Acura|RDX 2025|All|[Community](#community)|
|Acura|RLX 2017|Advance Package or Technology Package|[Community](#community)|
|Acura|TLX 2015-17|Advance Package|[Community](#community)|
|Acura|TLX 2018-20|All|[Community](#community)|
|Acura|TLX 2021|All|[Upstream](#upstream)|
|Acura|TLX 2022-23|All|[Community](#community)|
|Acura|TLX 2021-22|All|[Upstream](#upstream)|
|Acura|TLX 2023|All|[Community](#community)|
|Acura|TLX 2025|All|[Upstream](#upstream)|
|Acura|ZDX 2024|All|[Not compatible](#can-bus-security)|
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
@@ -29,6 +30,7 @@
|Audi|A5 2016-24|All|[Not compatible](#flexray)|
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Audi|Q5 2013-17|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
|Audi|Q5 2017-24|All|[Not compatible](#flexray)|
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
@@ -130,6 +132,7 @@
|Honda|N-Box 2018|All|[Upstream](#upstream)|
|Honda|Odyssey 2018-20|Honda Sensing|[Upstream](#upstream)|
|Honda|Odyssey 2021-26|All|[Upstream](#upstream)|
|Honda|Odyssey (Singapore) 2021|Honda Sensing|[Upstream](#upstream)|
|Honda|Odyssey (Taiwan) 2018-19|Honda Sensing|[Upstream](#upstream)|
|Honda|Passport 2019-25|All|[Upstream](#upstream)|
|Honda|Passport 2026|All|[Upstream](#upstream)|
@@ -187,6 +190,7 @@
|Hyundai|Tucson Hybrid 2022-24|All|[Upstream](#upstream)|
|Hyundai|Tucson Plug-in Hybrid 2024|All|[Upstream](#upstream)|
|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Jeep|Cherokee 2019-23|Adaptive Cruise Control (ACC)|[Dashcam mode](#dashcam)|
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
@@ -202,17 +206,18 @@
|Kia|Forte Non-SCC 2021|No Smart Cruise Control (Non-SCC)|[Dashcam mode](#dashcam)|
|Kia|K5 2021-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|K7 2017|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|K8 Hybrid (with HDA II) 2023|Highway Driving Assist II|[Upstream](#upstream)|
|Kia|Niro EV 2019|All|[Upstream](#upstream)|
|Kia|Niro EV 2020|All|[Upstream](#upstream)|
|Kia|Niro EV 2021|All|[Upstream](#upstream)|
|Kia|Niro EV 2022|All|[Upstream](#upstream)|
|Kia|Niro EV (with HDA II) 2025|Highway Driving Assist II|[Upstream](#upstream)|
|Kia|Niro EV (with HDA II) 2024-25|Highway Driving Assist II|[Upstream](#upstream)|
|Kia|Niro EV (without HDA II) 2023-25|All|[Upstream](#upstream)|
|Kia|Niro Hybrid 2018|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Hybrid 2023|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Hybrid 2023-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Plug-in Hybrid 2018-19|All|[Upstream](#upstream)|
|Kia|Niro Plug-in Hybrid 2020|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Kia|Niro Plug-in Hybrid 2021|Smart Cruise Control (SCC)|[Upstream](#upstream)|
@@ -278,7 +283,9 @@
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|Rivian|R1S 2022-24|All|[Upstream](#upstream)|
|Rivian|R1S 2025|All|[Upstream](#upstream)|
|Rivian|R1T 2022-24|All|[Upstream](#upstream)|
|Rivian|R1T 2025|All|[Upstream](#upstream)|
|SEAT|Alhambra 2018-20|Adaptive Cruise Control (ACC) & Lane Assist|[Dashcam mode](#dashcam)|
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)|

View File

@@ -81,15 +81,12 @@ class DBC:
self._parse_file(name)
else:
dbc_path = os.path.join(DBC_PATH, name + ".dbc")
if os.path.exists(dbc_path):
if content := get_generated_dbcs().get(name):
self._parse_content(name, content)
elif os.path.exists(dbc_path):
self._parse_file(dbc_path)
else:
# try in-memory generated DBC
generated = get_generated_dbcs()
content = generated.get(name)
if content is None:
raise FileNotFoundError(f"DBC not found: {name}")
self._parse_content(name, content)
raise FileNotFoundError(f"DBC not found: {name}")
def _parse_file(self, path: str):
self.name = os.path.basename(path).replace(".dbc", "")

View File

@@ -139,7 +139,8 @@ class CarHarness(EnumBase):
mazda = BaseCarHarness("Mazda connector")
ford_q3 = BaseCarHarness("Ford Q3 connector")
ford_q4 = BaseCarHarness("Ford Q4 connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable])
rivian = BaseCarHarness("Rivian A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable])
rivian_a = BaseCarHarness("Rivian A connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable])
rivian_b = BaseCarHarness("Rivian B connector", parts=[Accessory.harness_box, Accessory.comma_power, Cable.long_obdc_cable])
tesla_a = BaseCarHarness("Tesla A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])
tesla_b = BaseCarHarness("Tesla B connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])
psa_a = BaseCarHarness("PSA A connector", parts=[Accessory.harness_box, Cable.long_obdc_cable])

View File

@@ -89,10 +89,6 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
if not CC.latActive:
apply_torque = 0
# Hold torque with induced temporary fault when cutting the actuation bit
# FIXME: we don't use this with CAN FD?
torque_fault = CC.latActive and not apply_steer_req
self.apply_torque_last = apply_torque
# accel + longitudinal
@@ -109,12 +105,12 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
self.CP.openpilotLongitudinalControl:
# for longitudinal control, either radar or ADAS driving ECU
addr, bus = 0x7d0, self.CAN.ECAN if self.CP.flags & HyundaiFlags.CANFD else 0
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value:
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG.value:
addr, bus = 0x730, self.CAN.ECAN
can_sends.append(make_tester_present_msg(addr, bus, suppress_response=True))
# for blinkers
if self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
if self.CP.flags & HyundaiFlags.CANFD_ENABLE_BLINKERS:
can_sends.append(make_tester_present_msg(0x7b1, self.CAN.ECAN, suppress_response=True))
# *** CAN/CAN FD specific ***
@@ -122,6 +118,10 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
can_sends.extend(self.create_canfd_msgs(apply_steer_req, apply_torque, set_speed_in_units, accel,
stopping, hud_control, CS, CC))
else:
# Hold torque with induced temporary fault when cutting the actuation bit
# FIXME: we don't use this with CAN FD?
torque_fault = CC.latActive and not apply_steer_req
can_sends.extend(self.create_can_msgs(apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel,
stopping, hud_control, actuators, CS, CC))
@@ -187,7 +187,7 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
def create_canfd_msgs(self, apply_steer_req, apply_torque, set_speed_in_units, accel, stopping, hud_control, CS, CC):
can_sends = []
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
# steering control
@@ -196,14 +196,14 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
# 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:
can_sends.append(hyundaicanfd.create_suppress_lfa(self.packer, self.CAN, CS.lfa_block_msg,
self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT))
self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG_ALT))
# 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, self.lfa_icon))
# blinkers
if lka_steering and self.CP.flags & HyundaiFlags.ENABLE_BLINKERS:
if lka_steering and self.CP.flags & HyundaiFlags.CANFD_ENABLE_BLINKERS:
can_sends.extend(hyundaicanfd.create_spas_messages(self.packer, self.CAN, CC.leftBlinker, CC.rightBlinker))
if self.CP.openpilotLongitudinalControl:

View File

@@ -298,8 +298,8 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
self.buttons_counter = cp.vl[self.cruise_btns_msg_canfd]["COUNTER"]
ret.accFaulted = cp.vl["TCS"]["ACCEnable"] != 0 # 0 ACC CONTROL ENABLED, 1-3 ACC CONTROL DISABLED
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
if self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
self.lfa_block_msg = copy.copy(cp_cam.vl["CAM_0x362"] if self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG_ALT
else cp_cam.vl["CAM_0x2a4"])
MadsCarState.update_mads_canfd(self, ret, can_parsers)

View File

@@ -10,7 +10,7 @@ class CanBus(CanBusBase):
super().__init__(CP, fingerprint)
if lka_steering is None:
lka_steering = CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value if CP is not None else False
lka_steering = CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG.value if CP is not None else False
# On the CAN-FD platforms, the LKAS camera is on both A-CAN and E-CAN. LKA steering cars
# have a different harness than the LFA steering variants in order to split
@@ -49,8 +49,8 @@ def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque,
}
ret = []
if CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT else "LKAS"
if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG_ALT else "LKAS"
if CP.openpilotLongitudinalControl:
ret.append(packer.make_can_msg("LFA", CAN.ECAN, values))
ret.append(packer.make_can_msg(lkas_msg, CAN.ACAN, values))
@@ -80,7 +80,7 @@ def create_buttons(packer, CP, CAN, cnt, btn):
"CRUISE_BUTTONS": btn,
}
bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_LKA_STEERING else CAN.CAM
bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG else CAN.CAM
return packer.make_can_msg("CRUISE_BUTTONS", bus, values)

View File

@@ -30,16 +30,17 @@ class CarInterface(CarInterfaceBase):
def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_long, is_release, docs) -> structs.CarParams:
ret.brand = "hyundai"
# "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera.
# Generally means our LKAS message is forwarded to another ECU (commonly ADAS ECU)
# that finally retransmits our steering command in LFA or LFA_ALT to the MDPS.
# "LFA steering" if camera directly sends LFA to the MDPS
cam_can = CanBus(None, fingerprint).CAM
lka_steering = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
CAN = CanBus(None, fingerprint, lka_steering)
if ret.flags & HyundaiFlags.CANFD:
# Shared configuration for CAN-FD cars
# "LKA steering" if LKAS or LKAS_ALT messages are seen coming from the camera.
# Generally means our LKAS message is forwarded to another ECU (commonly ADAS ECU)
# that finally retransmits our steering command in LFA or LFA_ALT to the MDPS.
# "LFA steering" if camera directly sends LFA to the MDPS
cam_can = CanBus(None, fingerprint).CAM
lka_steering = 0x50 in fingerprint[cam_can] or 0x110 in fingerprint[cam_can]
CAN = CanBus(None, fingerprint, lka_steering)
ret.alphaLongitudinalAvailable = not (ret.flags & HyundaiFlags.CANFD_NO_RADAR_DISABLE)
if lka_steering and Ecu.adas not in [fw.ecu for fw in car_fw]:
# this needs to be figured out for cars without an ADAS ECU
@@ -53,14 +54,14 @@ class CarInterface(CarInterfaceBase):
if lka_steering:
# detect LKA steering
ret.flags |= HyundaiFlags.CANFD_LKA_STEERING.value
ret.flags |= HyundaiFlags.CANFD_LKA_STEER_MSG.value
if 0x110 in fingerprint[CAN.CAM]:
ret.flags |= HyundaiFlags.CANFD_LKA_STEERING_ALT.value
ret.flags |= HyundaiFlags.CANFD_LKA_STEER_MSG_ALT.value
else:
# no LKA steering
if 0x1cf not in fingerprint[CAN.ECAN]:
ret.flags |= HyundaiFlags.CANFD_ALT_BUTTONS.value
if not ret.flags & HyundaiFlags.RADAR_SCC:
if not ret.flags & HyundaiFlags.CANFD_RADAR_SCC:
ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value
# Some LKA steering cars have alternative messages for gear checks
@@ -76,10 +77,10 @@ class CarInterface(CarInterfaceBase):
cfgs.insert(0, get_safety_config(structs.CarParams.SafetyModel.noOutput))
ret.safetyConfigs = cfgs
if ret.flags & HyundaiFlags.CANFD_LKA_STEERING:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING.value
if ret.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT.value
if ret.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEER_MSG.value
if ret.flags & HyundaiFlags.CANFD_LKA_STEER_MSG_ALT:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT.value
if ret.flags & HyundaiFlags.CANFD_ALT_BUTTONS:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
@@ -234,12 +235,12 @@ class CarInterface(CarInterfaceBase):
if CP.openpilotLongitudinalControl and not ((CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)) or
(CP_SP.flags & HyundaiFlagsSP.ENHANCED_SCC)):
addr, bus = 0x7d0, CanBus(CP).ECAN if CP.flags & HyundaiFlags.CANFD else 0
if CP.flags & HyundaiFlags.CANFD_LKA_STEERING.value:
if CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG.value:
addr, bus = 0x730, CanBus(CP).ECAN
disable_ecu(can_recv, can_send, bus=bus, addr=addr, com_cont_req=communication_control)
# for blinkers
if CP.flags & HyundaiFlags.ENABLE_BLINKERS:
if CP.flags & HyundaiFlags.CANFD_ENABLE_BLINKERS:
disable_ecu(can_recv, can_send, bus=CanBus(CP).ECAN, addr=0x7B1, com_cont_req=communication_control)
@staticmethod

View File

@@ -53,7 +53,7 @@ class TestHyundaiFingerprint(unittest.TestCase):
cam_can = CanBus(None, fingerprint).CAM
fingerprint[cam_can] = [0x50, 0x110] # LKA steering messages
CP = CarInterface.get_params(CAR.KIA_EV6, fingerprint, [], False, False, False)
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEERING) == lka_steering
assert bool(CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG) == lka_steering
# radar available
for radar in (True, False):

View File

@@ -62,32 +62,53 @@ class HyundaiSafetyFlags(IntFlag):
HYBRID_GAS = 2
LONG = 4
CAMERA_SCC = 8
CANFD_LKA_STEERING = 16
CANFD_LKA_STEER_MSG = 16
CANFD_ALT_BUTTONS = 32
ALT_LIMITS = 64
CANFD_LKA_STEERING_ALT = 128
CANFD_LKA_STEER_MSG_ALT = 128
FCEV_GAS = 256
ALT_LIMITS_2 = 512
# Hyundai/Kia/Genesis SCC (Smart Cruise Control) and steering architecture:
#
# CAN cars:
# - Default: Radar sends SCC messages on bus 0. For longitudinal control, disable radar
# (0x7d0) and send our own SCC messages. AEB is lost since radar is disabled.
# - CAMERA_SCC: Camera sends SCC and AEB/FCA messages (all on bus 2). Block camera SCC
# and send our own. Stock FCA/AEB messages from camera are forwarded through.
#
# CAN-FD cars:
# - CANFD_LKA_STEER_MSG (typically HDA2 with ADAS ECU): Camera sends LKA steering
# message, ADAS DRV ECU forwards it as LFA to MDPS. For longitudinal, disable ADAS
# ECU (0x730) and send ACC on ECAN. OP also suppresses LFA from ADAS ECU to prevent
# fighting. Some cars lack the ADAS ECU (long not available).
# - Non-LKA (HDA1): Camera sends LFA steering directly to MDPS (no ADAS ECU).
# + CANFD_CAMERA_SCC: Camera also sends SCC (no CANFD_RADAR_SCC flag set).
# Block camera SCC and send our own.
# + CANFD_RADAR_SCC: Radar handles SCC instead.
# Disable radar (0x7d0 on ECAN) for longitudinal.
# - CANFD_NO_RADAR_DISABLE: Some CAN-FD cars refuse the communication control disable
# request (0x7F2822 'conditions not correct') — longitudinal not available.
class HyundaiFlags(IntFlag):
# Dynamic Flags
# Default assumption: all cars use LFA (ADAS) steering from the camera.
# CANFD_LKA_STEERING/CANFD_LKA_STEERING_ALT cars typically have both LKA (camera) and LFA (ADAS) steering messages,
# Default assumption: all cars use LFA (ADAS) steering from the camera (HDA1).
# CANFD_LKA_STEER_MSG/CANFD_LKA_STEER_MSG_ALT cars typically have both LKA (camera) and LFA (ADAS) steering messages,
# with LKA commands forwarded to the ADAS DRV ECU.
# Most HDA2 trims are assumed to be equipped with the ADAS DRV ECU, though some variants may not be equipped with one.
CANFD_LKA_STEERING = 1
CANFD_LKA_STEER_MSG = 1
CANFD_ALT_BUTTONS = 2
CANFD_ALT_GEARS = 2 ** 2
CANFD_CAMERA_SCC = 2 ** 3
ALT_LIMITS = 2 ** 4
ENABLE_BLINKERS = 2 ** 5
CANFD_ENABLE_BLINKERS = 2 ** 5
CANFD_ALT_GEARS_2 = 2 ** 6
SEND_LFA = 2 ** 7
USE_FCA = 2 ** 8
CANFD_LKA_STEERING_ALT = 2 ** 9
CANFD_LKA_STEER_MSG_ALT = 2 ** 9
# these cars use a different gas signal
HYBRID = 2 ** 10
@@ -101,7 +122,7 @@ class HyundaiFlags(IntFlag):
CANFD = 2 ** 13
# The radar does SCC on these cars when HDA I, rather than the camera
RADAR_SCC = 2 ** 14
CANFD_RADAR_SCC = 2 ** 14
# The camera does SCC on these cars, rather than the radar
CAMERA_SCC = 2 ** 15
CHECKSUM_CRC8 = 2 ** 16
@@ -508,7 +529,7 @@ class CAR(Platforms):
KIA_SORENTO_4TH_GEN = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Kia Sorento 2021-23", car_parts=CarParts.common([CarHarness.hyundai_k]))],
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
flags=HyundaiFlags.RADAR_SCC,
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig(
[
@@ -516,7 +537,7 @@ class CAR(Platforms):
HyundaiCarDocs("Kia Sorento Plug-in Hybrid 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
],
CarSpecs(mass=4395 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
flags=HyundaiFlags.RADAR_SCC,
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
KIA_STINGER = HyundaiPlatformConfig(
[HyundaiCarDocs("Kia Stinger 2018-20", video="https://www.youtube.com/watch?v=MJ94qoofYw0",
@@ -547,7 +568,7 @@ class CAR(Platforms):
HyundaiCarDocs("Kia Carnival (China only) 2023", car_parts=CarParts.common([CarHarness.hyundai_k]))
],
CarSpecs(mass=2087, wheelbase=3.09, steerRatio=14.23),
flags=HyundaiFlags.RADAR_SCC,
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
# Genesis
@@ -581,7 +602,7 @@ class CAR(Platforms):
HyundaiCarDocs("Genesis GV70 (3.5T Trim, without HDA II) 2022-23", "All", car_parts=CarParts.common([CarHarness.hyundai_m])),
],
CarSpecs(mass=1950, wheelbase=2.87, steerRatio=14.6),
flags=HyundaiFlags.RADAR_SCC,
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
GENESIS_GV70_ELECTRIFIED_1ST_GEN = HyundaiCanFDPlatformConfig(
[
@@ -607,7 +628,7 @@ class CAR(Platforms):
GENESIS_GV80 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Genesis GV80 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_m]))],
CarSpecs(mass=2258, wheelbase=2.95, steerRatio=14.14),
flags=HyundaiFlags.RADAR_SCC,
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
# port extensions

View File

@@ -28,8 +28,6 @@ class ModelYear(StrEnum):
@dataclass
class RivianCarDocs(CarDocs):
package: str = "All"
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.rivian]))
setup_video: str = "https://youtu.be/uaISd1j7Z4U"
@dataclass
@@ -52,8 +50,10 @@ class RivianSafetyFlags(IntFlag):
class CAR(Platforms):
RIVIAN_R1 = RivianPlatformConfig(
[
RivianCarDocs("Rivian R1S 2022-25"),
RivianCarDocs("Rivian R1T 2022-25"),
RivianCarDocs("Rivian R1S 2022-24", setup_video="https://youtu.be/uaISd1j7Z4U", car_parts=CarParts.common([CarHarness.rivian_a])),
RivianCarDocs("Rivian R1S 2025", car_parts=CarParts.common([CarHarness.rivian_b])),
RivianCarDocs("Rivian R1T 2022-24", setup_video="https://youtu.be/uaISd1j7Z4U", car_parts=CarParts.common([CarHarness.rivian_a])),
RivianCarDocs("Rivian R1T 2025", car_parts=CarParts.common([CarHarness.rivian_b])),
],
CarSpecs(mass=3206., wheelbase=3.08, steerRatio=15.2),
wmis={WMI.RIVIAN_TRUCK, WMI.RIVIAN_MPV},

View File

@@ -1,10 +1,30 @@
from opendbc.car import gen_empty_fingerprint
from opendbc.car.structs import CarParams
from opendbc.car.tesla.interface import CarInterface
from opendbc.car.tesla.fingerprints import FW_VERSIONS
from opendbc.car.tesla.radar_interface import RADAR_START_ADDR
from opendbc.car.tesla.values import CAR
from opendbc.car.tesla.values import CAR, FSD_14_FW
Ecu = CarParams.Ecu
class TestTeslaFingerprint:
def test_fsd_14_fw(self):
for car_model, ecus in FW_VERSIONS.items():
for fw in ecus.get((Ecu.eps, 0x730, None), []):
_, _, version = fw.partition(b',')
is_fsd_14 = fw in FSD_14_FW.get(car_model, [])
if car_model == CAR.TESLA_MODEL_3:
# Model 3: FSD 14 FW has 'P' in the Highland suffix (E4HP vs E4H)
assert is_fsd_14 == version.startswith(b'E4HP'), f"{fw}"
elif car_model == CAR.TESLA_MODEL_Y:
# Model Y: FSD 14 FW is Y4x version >= 003.04
prefix, _, ver = version.partition(b'.')
y4_003 = prefix.startswith(b'Y4') and prefix.endswith(b'003') # Y4=HW4, 003=version series (002 is never FSD 14)
high_version = y4_003 and int(ver.split(b'.')[0]) >= 4
assert is_fsd_14 == high_version, f"{fw}"
def test_radar_detection(self):
# Test radar availability detection for cars with radar DBC defined
for radar in (True, False):

View File

@@ -84,6 +84,7 @@ FSD_14_FW = {
CAR.TESLA_MODEL_3: [
b'TeMYG4_Main_0.0.0 (77),E4HP015.04.5',
b'TeMYG4_Main_0.0.0 (78),E4HP015.05.0',
b'TeMYG4_Main_0.0.0 (77),E4H015.04.5',
],
CAR.TESLA_MODEL_Y: [
b'TeMYG4_Legacy3Y_0.0.0 (6),Y4003.04.0',

View File

@@ -6,12 +6,12 @@
#define HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(bus) \
{0x1CF, bus, 8, .check_relay = false}, /* CRUISE_BUTTON */ \
#define HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(a_can, e_can) \
#define HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(a_can, e_can) \
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \
{0x50, a_can, 16, .check_relay = (a_can) == 0}, /* LKAS */ \
{0x2A4, a_can, 24, .check_relay = (a_can) == 0}, /* CAM_0x2A4 */ \
#define HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(a_can, e_can) \
#define HYUNDAI_CANFD_LKA_STEER_MSG_ALT_COMMON_TX_MSGS(a_can, e_can) \
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(e_can) \
{0x110, a_can, 32, .check_relay = (a_can) == 0}, /* LKAS_ALT */ \
{0x362, a_can, 32, .check_relay = (a_can) == 0}, /* CAM_0x362 */ \
@@ -46,10 +46,10 @@
{.msg = {{0x1a0, (scc_bus), 32, 50U, .max_counter = 0xffU, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
static bool hyundai_canfd_alt_buttons = false;
static bool hyundai_canfd_lka_steering_alt = false;
static bool hyundai_canfd_lka_steer_msg_alt = false;
static unsigned int hyundai_canfd_get_lka_addr(void) {
return hyundai_canfd_lka_steering_alt ? 0x110U : 0x50U;
return hyundai_canfd_lka_steer_msg_alt ? 0x110U : 0x50U;
}
static uint8_t hyundai_canfd_get_counter(const CANPacket_t *msg) {
@@ -69,7 +69,7 @@ static uint32_t hyundai_canfd_get_checksum(const CANPacket_t *msg) {
static void hyundai_canfd_rx_hook(const CANPacket_t *msg) {
const unsigned pt_bus = hyundai_canfd_lka_steering ? 1U : 0U;
const unsigned pt_bus = hyundai_canfd_lka_steer_msg ? 1U : 0U;
const unsigned int scc_bus = hyundai_camera_scc ? 2U : pt_bus;
if (msg->bus == pt_bus) {
@@ -161,7 +161,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
bool tx = true;
// steering
const unsigned int steer_addr = (hyundai_canfd_lka_steering && !hyundai_longitudinal) ? hyundai_canfd_get_lka_addr() : 0x12aU;
const unsigned int steer_addr = (hyundai_canfd_lka_steer_msg && !hyundai_longitudinal) ? hyundai_canfd_get_lka_addr() : 0x12aU;
if (msg->addr == steer_addr) {
int desired_torque = (((msg->data[6] & 0xFU) << 7U) | (msg->data[5] >> 1U)) - 1024U;
bool steer_req = GET_BIT(msg, 52U);
@@ -185,7 +185,7 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
}
// UDS: only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address
if (((msg->addr == 0x730U) && hyundai_canfd_lka_steering) || ((msg->addr == 0x7D0U) && !hyundai_camera_scc)) {
if (((msg->addr == 0x730U) && hyundai_canfd_lka_steer_msg) || ((msg->addr == 0x7D0U) && !hyundai_camera_scc)) {
if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) {
tx = false;
}
@@ -225,19 +225,19 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) {
}
static safety_config hyundai_canfd_init(uint16_t param) {
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT = 128;
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT = 128;
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1)
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
};
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(0, 1)
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_ALT_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEER_MSG_ALT_COMMON_TX_MSGS(0, 1)
};
static const CanMsg HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEERING_COMMON_TX_MSGS(0, 1)
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_LONG_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(1)
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true)
{0x51, 0, 32, .check_relay = false}, // ADRV_0x51
@@ -275,16 +275,16 @@ static safety_config hyundai_canfd_init(uint16_t param) {
gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut);
hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS);
hyundai_canfd_lka_steering_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT);
hyundai_canfd_lka_steer_msg_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT);
safety_config ret;
if (hyundai_longitudinal) {
if (hyundai_canfd_lka_steering) {
static RxCheck hyundai_canfd_lka_steering_long_rx_checks[] = {
if (hyundai_canfd_lka_steer_msg) {
static RxCheck hyundai_canfd_lka_steer_msg_long_rx_checks[] = {
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1)
};
ret = BUILD_SAFETY_CFG(hyundai_canfd_lka_steering_long_rx_checks, HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS);
ret = BUILD_SAFETY_CFG(hyundai_canfd_lka_steer_msg_long_rx_checks, HYUNDAI_CANFD_LKA_STEER_MSG_LONG_TX_MSGS);
} else {
// Longitudinal checks for LFA steering
@@ -314,20 +314,20 @@ static safety_config hyundai_canfd_init(uint16_t param) {
}
} else {
if (hyundai_canfd_lka_steering) {
if (hyundai_canfd_lka_steer_msg) {
// *** LKA steering checks ***
// E-CAN is on bus 1, SCC messages are sent on cars with ADRV ECU.
// Does not use the alt buttons message
static RxCheck hyundai_canfd_lka_steering_rx_checks[] = {
static RxCheck hyundai_canfd_lka_steer_msg_rx_checks[] = {
HYUNDAI_CANFD_STD_BUTTONS_RX_CHECKS(1)
HYUNDAI_CANFD_SCC_ADDR_CHECK(1)
};
SET_RX_CHECKS(hyundai_canfd_lka_steering_rx_checks, ret);
if (hyundai_canfd_lka_steering_alt) {
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_ALT_TX_MSGS, ret);
SET_RX_CHECKS(hyundai_canfd_lka_steer_msg_rx_checks, ret);
if (hyundai_canfd_lka_steer_msg_alt) {
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEER_MSG_ALT_TX_MSGS, ret);
} else {
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_TX_MSGS, ret);
SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS, ret);
}
} else if (!hyundai_camera_scc) {

View File

@@ -37,8 +37,8 @@ bool hyundai_longitudinal = false;
extern bool hyundai_camera_scc;
bool hyundai_camera_scc = false;
extern bool hyundai_canfd_lka_steering;
bool hyundai_canfd_lka_steering = false;
extern bool hyundai_canfd_lka_steer_msg;
bool hyundai_canfd_lka_steer_msg = false;
extern bool hyundai_alt_limits;
bool hyundai_alt_limits = false;
@@ -73,7 +73,7 @@ void hyundai_common_init(uint16_t param) {
const uint16_t HYUNDAI_PARAM_EV_GAS = 1;
const uint16_t HYUNDAI_PARAM_HYBRID_GAS = 2;
const uint16_t HYUNDAI_PARAM_CAMERA_SCC = 8;
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEERING = 16;
const uint16_t HYUNDAI_PARAM_CANFD_LKA_STEER_MSG = 16;
const uint16_t HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags
const uint16_t HYUNDAI_PARAM_FCEV_GAS = 256;
const uint16_t HYUNDAI_PARAM_ALT_LIMITS_2 = 512;
@@ -81,7 +81,7 @@ void hyundai_common_init(uint16_t param) {
hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS);
hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS);
hyundai_camera_scc = GET_FLAG(param, HYUNDAI_PARAM_CAMERA_SCC);
hyundai_canfd_lka_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING);
hyundai_canfd_lka_steer_msg = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG);
hyundai_alt_limits = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS);
hyundai_fcev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_FCEV_GAS);
hyundai_alt_limits_2 = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS_2);

View File

@@ -23,8 +23,8 @@ def is_steering_msg(mode, param, addr):
elif mode in (CarParams.SafetyModel.hyundai, CarParams.SafetyModel.hyundaiLegacy):
ret = addr == 832
elif mode == CarParams.SafetyModel.hyundaiCanfd:
ret = addr == (0x110 if param & HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT else
0x50 if param & HyundaiSafetyFlags.CANFD_LKA_STEERING else
ret = addr == (0x110 if param & HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT else
0x50 if param & HyundaiSafetyFlags.CANFD_LKA_STEER_MSG else
0x12A)
elif mode == CarParams.SafetyModel.chrysler:
ret = addr == 0x292

View File

@@ -185,7 +185,7 @@ class TestHyundaiCanfdLKASteeringEV(TestHyundaiCanfdBase):
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS)
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS)
self.safety.init_tests()
@@ -204,8 +204,8 @@ class TestHyundaiCanfdLKASteeringAltEV(TestHyundaiCanfdBase):
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.EV_GAS |
HyundaiSafetyFlags.CANFD_LKA_STEERING_ALT)
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG | HyundaiSafetyFlags.EV_GAS |
HyundaiSafetyFlags.CANFD_LKA_STEER_MSG_ALT)
self.safety.init_tests()
@@ -226,7 +226,7 @@ class TestHyundaiCanfdLKASteeringLongEV(HyundaiLongitudinalBase, TestHyundaiCanf
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEERING |
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CANFD_LKA_STEER_MSG |
HyundaiSafetyFlags.LONG | HyundaiSafetyFlags.EV_GAS)
self.safety.init_tests()

View File

@@ -25,7 +25,7 @@ class CarStateExt:
if self.CP.flags & HyundaiFlags.CANFD:
if self.CP_SP.flags & HyundaiFlagsSP.SPEED_LIMIT_AVAILABLE:
bus = cp if self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING else cp_cam
bus = cp if self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG else cp_cam
speed_limit = bus.vl["FR_CMR_02_100ms"]["ISLW_SpdCluMainDis"]
else:
nav, cam = 0, 0