diff --git a/cereal/messaging/bridge b/cereal/messaging/bridge
deleted file mode 100755
index d3794ba08..000000000
Binary files a/cereal/messaging/bridge and /dev/null differ
diff --git a/common/libcommon.a b/common/libcommon.a
deleted file mode 100644
index 47bf42a24..000000000
Binary files a/common/libcommon.a and /dev/null differ
diff --git a/common/params_pyx.so b/common/params_pyx.so
deleted file mode 100755
index 3cfe62359..000000000
Binary files a/common/params_pyx.so and /dev/null differ
diff --git a/msgq_repo/msgq/ipc_pyx.so b/msgq_repo/msgq/ipc_pyx.so
deleted file mode 100755
index 86451bfd9..000000000
Binary files a/msgq_repo/msgq/ipc_pyx.so and /dev/null differ
diff --git a/msgq_repo/msgq/visionipc/visionipc_pyx.so b/msgq_repo/msgq/visionipc/visionipc_pyx.so
deleted file mode 100755
index 1dbc75e2e..000000000
Binary files a/msgq_repo/msgq/visionipc/visionipc_pyx.so and /dev/null differ
diff --git a/opendbc_repo/docs/CARS.md b/opendbc_repo/docs/CARS.md
index 73b18045b..62943aa69 100644
--- a/opendbc_repo/docs/CARS.md
+++ b/opendbc_repo/docs/CARS.md
@@ -238,8 +238,8 @@
|Hyundai|Kona Non-SCC 2019|No Smart Cruise Control (Non-SCC)|[Community](community)|
|Hyundai|Nexo 2021|All|[Upstream](#upstream)|
|Hyundai|Palisade 2020-22|All|[Upstream](#upstream)|
-|Hyundai|Palisade 2023-24|HDA2|[Community](#community)|
-|Hyundai|Palisade (with HDA II) 2023-24|Highway Driving Assist II|[Upstream](#upstream)|
+|Hyundai|Palisade 2023-25|HDA2|[Community](#community)|
+|Hyundai|Palisade (with HDA II) 2023-25|Highway Driving Assist II|[Upstream](#upstream)|
|Hyundai|Palisade (without HDA II) 2023-25|Highway Driving Assist|[Upstream](#upstream)|
|Hyundai|Santa Cruz 2022-24|Smart Cruise Control (SCC)|[Upstream](#upstream)|
|Hyundai|Santa Cruz (without HDA II) 2025|Smart Cruise Control (SCC)|[Upstream](#upstream)|
diff --git a/opendbc_repo/opendbc/car/extra_cars.py b/opendbc_repo/opendbc/car/extra_cars.py
index 5ffa42bf4..d3a82e684 100644
--- a/opendbc_repo/opendbc/car/extra_cars.py
+++ b/opendbc_repo/opendbc/car/extra_cars.py
@@ -55,7 +55,7 @@ class CAR(Platforms):
EXTRA_HYUNDAI = ExtraPlatformConfig(
[
- CommunityCarDocs("Hyundai Palisade 2023-24", package="HDA2"),
+ CommunityCarDocs("Hyundai Palisade 2023-25", package="HDA2"),
CommunityCarDocs("Kia Telluride 2023-24", package="HDA2"),
],
)
diff --git a/opendbc_repo/opendbc/car/hyundai/carcontroller.py b/opendbc_repo/opendbc/car/hyundai/carcontroller.py
index b5c6fb9ab..32a4c1097 100644
--- a/opendbc_repo/opendbc/car/hyundai/carcontroller.py
+++ b/opendbc_repo/opendbc/car/hyundai/carcontroller.py
@@ -721,15 +721,25 @@ class CarController(CarControllerBase):
def create_can_msgs(self, apply_steer_req, apply_torque, torque_fault, set_speed_in_units, accel, stopping, hud_control, actuators, CS, CC, lka_icon, lfa_icon):
can_sends = []
can_canfd_blended = bool(self.CP.flags & HyundaiFlags.CAN_CANFD_BLENDED)
+ blended_hda2 = can_canfd_blended and bool(self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING)
# HUD messages
sys_warning, sys_state, left_lane_warning, right_lane_warning = process_hud_alert(CC.enabled, self.car_fingerprint,
hud_control)
- if can_canfd_blended and self.CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
+ if blended_hda2:
can_sends.extend(hyundaicanfd.create_steering_messages(
self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, 0.0,
))
+ if self.long_active_ecu:
+ can_sends.extend(hyundaican.create_lkas11_can_canfd_blended(
+ self.packer, self.frame, self.CP, apply_torque, 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, CS.msg_364,
+ include_alerts=False,
+ counter_mod=0xF,
+ ))
if self.frame % 5 == 0:
can_sends.append(hyundaicanfd.create_suppress_lfa(
self.packer, self.CAN, CS.lfa_block_msg, False,
@@ -760,13 +770,22 @@ class CarController(CarControllerBase):
can_sends.extend(self._create_can_redneck_button_messages(CS))
if self.long_active_ecu and can_canfd_blended:
- can_sends.extend(hyundaican.create_radar_aux_messages(self.packer, self.CAN, self.frame))
+ if blended_hda2:
+ can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame, blended_hda2=True))
+ can_sends.extend(hyundaican.create_radar_aux_messages(self.packer, self.CAN, self.frame, hda2=blended_hda2))
if self.frame % 2 == 0 and self.long_active_ecu:
# TODO: unclear if this is needed
jerk = 3.0 if actuators.longControlState == LongCtrlState.pid else 1.0
use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value
- if can_canfd_blended:
+ if blended_hda2:
+ stopping = stopping and CS.out.vEgoRaw < 0.1
+ can_sends.extend(hyundaican.create_acc_commands_can_canfd_blended_hda2(
+ self.packer, CC.enabled, accel, self.accel_last, jerk, int(self.frame / 2), hud_control,
+ set_speed_in_units, stopping, CC.cruiseControl.override, use_fca, self.CP,
+ ))
+ self.accel_last = accel
+ elif can_canfd_blended:
can_sends.extend(hyundaican.create_acc_commands_can_canfd_blended(self.packer, CC.enabled, accel, jerk,
int(self.frame / 2), hud_control,
set_speed_in_units, stopping,
@@ -777,7 +796,7 @@ class CarController(CarControllerBase):
CC.cruiseControl.override, use_fca, self.CP))
# 20 Hz LFA MFA message
- if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value:
+ if self.frame % 5 == 0 and (self.CP.flags & HyundaiFlags.SEND_LFA.value or (self.long_active_ecu and blended_hda2)):
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled, self.frame, self.CP, lfa_icon))
# 5 Hz ACC options
diff --git a/opendbc_repo/opendbc/car/hyundai/carstate.py b/opendbc_repo/opendbc/car/hyundai/carstate.py
index e2648949a..1f77da735 100644
--- a/opendbc_repo/opendbc/car/hyundai/carstate.py
+++ b/opendbc_repo/opendbc/car/hyundai/carstate.py
@@ -667,7 +667,7 @@ class CarState(CarStateBase):
("CGW2", 5),
("WHL_SPD11", 50),
("SAS11", 100),
- ("SCC12", 50),
+ ("SCC12", 0 if CP.openpilotLongitudinalControl and CP.flags & HyundaiFlags.CANFD_LKA_STEERING else 50),
("EMS12", 100),
("EMS16", 100),
("LVR12", 100),
diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaican.py b/opendbc_repo/opendbc/car/hyundai/hyundaican.py
index 8d3b37a38..203352146 100644
--- a/opendbc_repo/opendbc/car/hyundai/hyundaican.py
+++ b/opendbc_repo/opendbc/car/hyundai/hyundaican.py
@@ -106,7 +106,8 @@ def create_checksum_can_canfd_blended(packer, bus, addr, values):
def create_lkas11_can_canfd_blended(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, msg_364):
+ left_lane_depart, right_lane_depart, msg_364,
+ include_alerts=True, counter_mod=0x10):
bus = CanBus(CP).ECAN
values = {
"CF_Lkas_LdwsActivemode": int(left_lane) + (int(right_lane) << 1),
@@ -116,7 +117,7 @@ def create_lkas11_can_canfd_blended(packer, frame, CP, apply_steer, steer_req,
"CR_Lkas_StrToqReq": apply_steer,
"CF_Lkas_ActToi": steer_req,
"CF_Lkas_ToiFlt": torque_fault,
- "CF_Lkas_MsgCount": frame % 0x10,
+ "CF_Lkas_MsgCount": frame % counter_mod,
"NEW_SIGNAL_1": 0,
"NEW_SIGNAL_5": 100,
}
@@ -130,13 +131,13 @@ def create_lkas11_can_canfd_blended(packer, frame, CP, apply_steer, steer_req,
alerts_364.setdefault("BYTE5", 0)
alerts_364.setdefault("BYTE6", 0)
alerts_364.setdefault("BYTE7", 0)
- alerts_364["COUNTER"] = frame % 0x10
+ alerts_364["COUNTER"] = frame % counter_mod
alerts_364["CHECKSUM"] = create_checksum_can_canfd_blended(packer, bus, "ALERTS_364", alerts_364)
- return [
- packer.make_can_msg("LKAS11", bus, values),
- packer.make_can_msg("ALERTS_364", bus, alerts_364),
- ]
+ ret = [packer.make_can_msg("LKAS11", bus, values)]
+ if include_alerts:
+ ret.append(packer.make_can_msg("ALERTS_364", bus, alerts_364))
+ return ret
def create_clu11(packer, frame, clu11, button, CP):
@@ -233,6 +234,56 @@ def create_acc_commands_can_canfd_blended(packer, enabled, accel, upper_jerk, id
return commands
+def create_acc_commands_can_canfd_blended_hda2(packer, enabled, accel, accel_last, upper_jerk, idx,
+ hud_control, set_speed, stopping, long_override, use_fca, CP):
+ commands = []
+ bus = CanBus(CP).ECAN
+ jerk = 5.0
+
+ if not enabled or long_override:
+ accel_raw, accel_value = 0.0, 0.0
+ else:
+ accel_raw = accel
+ accel_value = max(accel_last - jerk / 50.0, min(accel, accel_last + jerk / 50.0))
+
+ message_values = [
+ ("SCC11", {
+ "aReqRaw": accel_raw,
+ "aReqValue": accel_value,
+ "JerkUpperLimit": upper_jerk,
+ "JerkLowerLimit": jerk if enabled else 1.0,
+ }),
+ ("SCC12", {
+ "MainMode_ACC": 1,
+ "ACCMode_Inactive": 0 if enabled else 1,
+ "TauGapSet": hud_control.leadDistanceBars,
+ "VSetDis": set_speed,
+ "ACC_ObjDist": 1,
+ "ACCMode": 2 if enabled and long_override else 1 if enabled else 0,
+ "StopReq": 1 if stopping else 0,
+ }),
+ ("SCC14", {
+ "ACC_ObjRelSpd": 0,
+ "ObjValid": 0,
+ "ObjStatus": 2 if hud_control.leadVisible and enabled else 1 if hud_control.leadVisible else 0,
+ }),
+ ]
+
+ if use_fca and not (CP.flags & HyundaiFlags.CAMERA_SCC):
+ # These values reproduce the stock status bytes without requesting AEB/FCA actuation.
+ message_values.append(("FCA11", {
+ "cr_vsm_deccmd": 255,
+ "cf_vsm_deccmdact": 0,
+ }))
+
+ for name, values in message_values:
+ values["COUNTER"] = idx % 0xF
+ values["CHECKSUM"] = create_checksum_can_canfd_blended(packer, bus, name, values)
+ commands.append(packer.make_can_msg(name, bus, values))
+
+ return commands
+
+
def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP):
commands = []
@@ -324,17 +375,27 @@ def create_frt_radar_opt(packer):
return packer.make_can_msg("FRT_RADAR11", 0, frt_radar11_values)
-def create_radar_aux_messages(packer, CAN, frame):
+def create_radar_aux_messages(packer, CAN, frame, hda2=False):
commands = []
- for addr, freq, values in (
+ message_specs = (
+ ("RADAR_0x363", 2, {"FCA_ESA": 1}),
+ ("RADAR_0x398", 5, {"BYTE4": 0x80, "BYTE5": 0x5D}),
+ ("RADAR_0x399", 5, {"BYTE2": 0x02}),
+ ("RADAR_0x39a", 5, {"BYTE7": 0xFF}),
+ ("RADAR_0x39b", 5, {}),
+ ("RADAR_0x39c", 5, {"BYTE5": 0xE0, "BYTE6": 0x79}),
+ ("RADAR_0x43a", 20, {"BYTE2": 0x07}),
+ ) if hda2 else (
("RADAR_0x363", 2, {"FCA_ESA": 1}),
("RADAR_0x398", 5, {"BYTE4": 0x80, "BYTE5": 0x10}),
- ):
+ )
+
+ for addr, freq, values in message_specs:
if frame % freq != 0:
continue
- msg_values = values | {"COUNTER": frame % 0x10}
+ msg_values = values | {"COUNTER": frame % (0xF if hda2 else 0x10)}
msg_values["CHECKSUM"] = create_checksum_can_canfd_blended(packer, CAN.ECAN, addr, msg_values)
commands.append(packer.make_can_msg(addr, CAN.ECAN, msg_values))
diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py
index fe5b8b457..911f0c1d8 100644
--- a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py
+++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py
@@ -258,7 +258,7 @@ 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.openpilotLongitudinalControl or send_lfa_status:
+ if (CP.openpilotLongitudinalControl and not CP.flags & HyundaiFlags.CAN_CANFD_BLENDED) or send_lfa_status:
ret.append(packer.make_can_msg("LFA", CAN.ECAN, lfa_values))
if lfa_only:
return ret
@@ -820,7 +820,7 @@ def create_fca_warning_light(packer, CAN, frame):
return ret
-def create_adrv_messages(packer, CAN, frame):
+def create_adrv_messages(packer, CAN, frame, blended_hda2=False):
# messages needed to car happy after disabling
# the ADAS Driving ECU to do longitudinal control
@@ -830,6 +830,9 @@ def create_adrv_messages(packer, CAN, frame):
}
ret.append(packer.make_can_msg("ADRV_0x51", CAN.ACAN, values))
+ if blended_hda2:
+ return ret
+
ret.extend(create_fca_warning_light(packer, CAN, frame))
if frame % 5 == 0:
diff --git a/opendbc_repo/opendbc/car/hyundai/interface.py b/opendbc_repo/opendbc/car/hyundai/interface.py
index 56beda58d..b75082688 100644
--- a/opendbc_repo/opendbc/car/hyundai/interface.py
+++ b/opendbc_repo/opendbc/car/hyundai/interface.py
@@ -9,6 +9,7 @@ from opendbc.car.hyundai.values import HyundaiFlags, CAR, CarControllerParams, \
RADAR_LIVE_LONGITUDINAL_CAR, \
UNSUPPORTED_LONGITUDINAL_CAR, HyundaiSafetyFlags, \
LEGACY_LONGITUDINAL_CAR, \
+ CAN_CANFD_BLENDED_HDA2_LONGITUDINAL_CAR, \
HyundaiStarPilotSafetyFlags, \
hyundai_cancel_button_enables_cruise, \
kia_ev6_gt_line_longitudinal_tuning
@@ -199,7 +200,8 @@ class CarInterface(CarInterfaceBase):
else:
# Shared configuration for non CAN-FD cars
ret.alphaLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR or candidate in LEGACY_LONGITUDINAL_CAR
- if ret.flags & HyundaiFlags.CAN_CANFD_BLENDED and ret.flags & HyundaiFlags.CANFD_LKA_STEERING:
+ if ret.flags & HyundaiFlags.CAN_CANFD_BLENDED and ret.flags & HyundaiFlags.CANFD_LKA_STEERING and \
+ candidate not in CAN_CANFD_BLENDED_HDA2_LONGITUDINAL_CAR:
ret.alphaLongitudinalAvailable = False
ret.enableBsm = 0x58b in fingerprint[CAN.ECAN]
diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py
index 66d548278..6eecf52a7 100644
--- a/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py
+++ b/opendbc_repo/opendbc/car/hyundai/tests/test_hyundai.py
@@ -549,14 +549,17 @@ class TestHyundaiFingerprint:
assert CP.flags & HyundaiFlags.CAN_CANFD_BLENDED
assert CP.flags & HyundaiFlags.CANFD_LKA_STEERING
- assert not CP.alphaLongitudinalAvailable
- assert not CP.openpilotLongitudinalControl
+ assert CP.alphaLongitudinalAvailable
+ assert CP.openpilotLongitudinalControl
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CAN_CANFD_BLENDED
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CANFD_LKA_STEERING
+ assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.LONG
assert can_bus.ACAN == 0
assert can_bus.ECAN == 1
assert parsers[Bus.pt].bus == 1
assert parsers[Bus.cam].bus == 2
+ scc12_state = next(state for state in parsers[Bus.pt].message_states.values() if state.name == "SCC12")
+ assert scc12_state.frequency == 0
assert CarControllerParams(CP).STEER_MAX == 384
def test_palisade_telluride_hda2_sends_lkas_and_camera_suppression(self):
@@ -587,6 +590,41 @@ class TestHyundaiFingerprint:
assert (0x2A4, 0) in msg_addrs_buses
assert not ({0x340, 0x364} & {addr for addr, _, _ in msgs})
+ def test_palisade_telluride_hda2_long_sends_complete_support_set(self):
+ fingerprint = gen_empty_fingerprint()
+ fingerprint[2][0x50] = 16
+ fingerprint[1][0x38D] = 8
+ car_fw = [CarParams.CarFw(ecu=Ecu.adas, fwVersion=b"", address=0x730, brand="hyundai")]
+ CP = CarInterface.get_params(CAR.HYUNDAI_PALISADE_2023, fingerprint, car_fw, True, False, False, None)
+ controller = CarController(DBC[CP.carFingerprint], CP)
+ controller.frame = 0
+
+ hud_control = SimpleNamespace(
+ visualAlert=CarControl.HUDControl.VisualAlert.none,
+ leftLaneVisible=True,
+ rightLaneVisible=True,
+ leftLaneDepart=False,
+ rightLaneDepart=False,
+ leadDistanceBars=3,
+ leadVisible=True,
+ )
+ lfa_block_msg = {f"BYTE{i}": 0 for i in range(3, 24) if i != 7}
+ lfa_block_msg["COUNTER"] = 0
+ CS = SimpleNamespace(lfa_block_msg=lfa_block_msg, redneck_send_button=Buttons.NONE, lkas11={}, msg_364={},
+ out=SimpleNamespace(vEgoRaw=5.0))
+ CC = SimpleNamespace(enabled=True, cruiseControl=SimpleNamespace(cancel=False, resume=False, override=False))
+ actuators = SimpleNamespace(longControlState=LongCtrlState.pid)
+
+ msgs = controller.create_can_msgs(True, 0, False, 42.0, 0.0, False, hud_control, actuators, CS, CC, 2, 2)
+ msg_addrs_buses = {(addr, bus) for addr, _, bus in msgs}
+
+ assert {
+ (0x50, 0), (0x2A4, 0), (0x51, 0),
+ (0x340, 1), (0x485, 1), (0x420, 1), (0x421, 1), (0x389, 1), (0x38D, 1),
+ (0x363, 1), (0x398, 1), (0x399, 1), (0x39A, 1), (0x39B, 1), (0x39C, 1), (0x43A, 1),
+ } <= msg_addrs_buses
+ assert (0x364, 1) not in msg_addrs_buses
+
def test_g70_aol_uses_active_lkas_icon(self):
CP = CarInterface.get_params(CAR.GENESIS_G70_2020, gen_empty_fingerprint(), [], False, False, False, None)
controller = CarController(DBC[CP.carFingerprint], CP)
@@ -2418,6 +2456,46 @@ class TestHyundaiFingerprint:
assert parser.vl["SCC14"]["ObjStatus"] == 1
assert parser.vl["RADAR_0x363"]["FCA_ESA"] == 1
+ def test_can_canfd_blended_hda2_acc_commands_use_hda2_layout(self):
+ CP = CarParams.new_message()
+ CP.carFingerprint = CAR.HYUNDAI_PALISADE_2023
+ CP.flags = int(HyundaiFlags.CAN_CANFD_BLENDED | HyundaiFlags.CANFD_LKA_STEERING | HyundaiFlags.USE_FCA)
+
+ packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
+ parser = CANParser(DBC[CP.carFingerprint][Bus.pt], [
+ ("SCC11", 0),
+ ("SCC12", 0),
+ ("SCC14", 0),
+ ("FCA11", 0),
+ ], 1)
+
+ msgs = hyundaican.create_acc_commands_can_canfd_blended_hda2(
+ packer,
+ enabled=True,
+ accel=-1.0,
+ accel_last=0.0,
+ upper_jerk=2.5,
+ idx=15,
+ hud_control=SimpleNamespace(leadDistanceBars=3, leadVisible=True),
+ set_speed=42,
+ stopping=False,
+ long_override=False,
+ use_fca=True,
+ CP=CP,
+ )
+ parser.update([(1, msgs)])
+
+ assert parser.can_valid
+ assert parser.vl["SCC11"]["aReqRaw"] == pytest.approx(-1.0)
+ assert parser.vl["SCC11"]["aReqValue"] == pytest.approx(-0.1)
+ assert parser.vl["SCC11"]["COUNTER"] == 0
+ assert parser.vl["SCC12"]["VSetDis"] == 42
+ assert parser.vl["SCC14"]["ObjValid"] == 0
+ assert parser.vl["SCC14"]["ObjStatus"] == 2
+ assert parser.vl["FCA11"]["aeb_cmd_act"] == 0
+ assert parser.vl["FCA11"]["fca_cmd_act"] == 0
+ assert next(dat for addr, dat, _ in msgs if addr == 0x38D)[4:7] == b"\xC0\x3F\x7F"
+
def test_can_acc_optional_messages_use_enabled_fca_usm(self):
CP = CarParams.new_message()
CP.carFingerprint = CAR.GENESIS_G90
diff --git a/opendbc_repo/opendbc/car/hyundai/values.py b/opendbc_repo/opendbc/car/hyundai/values.py
index 585389406..eecc2ec7a 100644
--- a/opendbc_repo/opendbc/car/hyundai/values.py
+++ b/opendbc_repo/opendbc/car/hyundai/values.py
@@ -481,7 +481,7 @@ class CAR(Platforms):
[
HyundaiCarDocs("Hyundai Palisade (without HDA II) 2023-25", "Highway Driving Assist",
car_parts=CarParts.common([CarHarness.hyundai_a])),
- HyundaiCarDocs("Hyundai Palisade (with HDA II) 2023-24", "Highway Driving Assist II",
+ HyundaiCarDocs("Hyundai Palisade (with HDA II) 2023-25", "Highway Driving Assist II",
car_parts=CarParts.common([CarHarness.hyundai_r])),
HyundaiCarDocs("Kia Telluride (without HDA II) 2023-25", "Highway Driving Assist",
car_parts=CarParts.common([CarHarness.hyundai_l])),
@@ -968,6 +968,10 @@ CANCEL_BUTTON_ENABLE_CARS = frozenset({
CAR.HYUNDAI_PALISADE_2023,
})
+CAN_CANFD_BLENDED_HDA2_LONGITUDINAL_CAR = frozenset({
+ CAR.HYUNDAI_PALISADE_2023,
+})
+
KIA_EV6_GT_LINE_LONG_TUNING_VDS_PREFIXES = frozenset({
"C4DLC",
})
diff --git a/opendbc_repo/opendbc/car/nissan/carcontroller.py b/opendbc_repo/opendbc/car/nissan/carcontroller.py
index 66a183654..bf83d9024 100644
--- a/opendbc_repo/opendbc/car/nissan/carcontroller.py
+++ b/opendbc_repo/opendbc/car/nissan/carcontroller.py
@@ -1,7 +1,7 @@
import numpy as np
from opendbc.can import CANPacker
-from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs
+from opendbc.car import Bus, DT_CTRL, structs
from opendbc.car.common.filter_simple import FirstOrderFilter
from opendbc.car.lateral import apply_std_steer_angle_limits
from opendbc.car.interfaces import CarControllerBase
@@ -55,7 +55,7 @@ class CarController(CarControllerBase):
CC.longActive and brake_pressure > 0, brake_mode))
if self.frame % 100 == 0:
- can_sends.append(make_tester_present_msg(0x707, 0, suppress_response=True))
+ can_sends.append(nissancan.create_leaf_adas_tester_present())
### STEER ###
steer_hud_alert = 1 if hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw) else 0
diff --git a/opendbc_repo/opendbc/car/nissan/interface.py b/opendbc_repo/opendbc/car/nissan/interface.py
index 734303f16..1a236f3ec 100644
--- a/opendbc_repo/opendbc/car/nissan/interface.py
+++ b/opendbc_repo/opendbc/car/nissan/interface.py
@@ -1,6 +1,9 @@
-from opendbc.car import get_safety_config, structs, uds
+import time
+
+from opendbc.car import get_safety_config, structs
from opendbc.car.disable_ecu import disable_ecu, ecu_log
from opendbc.car.interfaces import CarInterfaceBase
+from opendbc.car.isotp_parallel_query import IsoTpParallelQuery
from opendbc.car.nissan.carcontroller import CarController
from opendbc.car.nissan.carstate import CarState
from opendbc.car.nissan.values import CAR, CarControllerParams, NissanSafetyFlags, \
@@ -9,8 +12,22 @@ from opendbc.car.nissan.values import CAR, CarControllerParams, NissanSafetyFlag
LEAF_ADAS_ECU_ADDR = 0x707
LEAF_ADAS_ECU_BUS = 0
+LEAF_ADAS_COMMAND_BUS = 1
+LEAF_ADAS_COMMAND_ADDRS = frozenset((0x1C3, 0x2B0))
LEAF_2025_SV_PLUS_CAMERA_FW = b'6WK2CDB\x04\x18\x00\x00\x00\x00\x00R=1\x18\x99\x10\x00\x00\x00\x80'
+# This Leaf camera uses KWP2000 rather than UDS for session management.
+LEAF_KWP_AFTER_SALES_REQUEST = b"\x10\xC0"
+LEAF_KWP_AFTER_SALES_RESPONSE = b"\x50\xC0"
+LEAF_KWP_DISABLE_NORMAL_TX = b"\x28\x01"
+LEAF_KWP_ENABLE_NORMAL_TX = b"\x29\x01"
+LEAF_KWP_ENABLE_NORMAL_TX_RESPONSE = b"\x69"
+
+LEAF_KWP_SESSIONS = (
+ (LEAF_KWP_AFTER_SALES_REQUEST, LEAF_KWP_AFTER_SALES_RESPONSE),
+ (NISSAN_DIAGNOSTIC_REQUEST_KWP, NISSAN_DIAGNOSTIC_RESPONSE_KWP),
+)
+
def is_leaf_2025_sv_plus_longitudinal(candidate, car_fw):
return candidate == CAR.NISSAN_LEAF and any(
@@ -19,6 +36,62 @@ def is_leaf_2025_sv_plus_longitudinal(candidate, car_fw):
)
+def leaf_adas_commands_silent(can_recv, settle_time=0.05, observe_time=0.15):
+ """Confirm the stock ADAS command sender stopped while bus 1 is still observable."""
+ if can_recv is None:
+ return False
+
+ try:
+ # Let already-published CAN batches age out, then discard everything queued
+ # before the communication-control response.
+ time.sleep(settle_time)
+ can_recv()
+
+ saw_adas_bus_traffic = False
+ deadline = time.monotonic() + observe_time
+ while time.monotonic() < deadline:
+ packets = can_recv(wait_for_one=True)
+ for packet in packets:
+ for msg in packet:
+ if msg.src != LEAF_ADAS_COMMAND_BUS:
+ continue
+ saw_adas_bus_traffic = True
+ if msg.address in LEAF_ADAS_COMMAND_ADDRS:
+ ecu_log(f"Nissan Leaf ADAS TX still active: {hex(msg.address)} on bus {msg.src}")
+ return False
+ except Exception as e:
+ ecu_log(f"Nissan Leaf ADAS TX silence verification exception: {e}")
+ return False
+
+ if not saw_adas_bus_traffic:
+ ecu_log("Nissan Leaf ADAS TX silence could not be verified: no bus 1 traffic observed")
+ return saw_adas_bus_traffic
+
+
+def restore_leaf_adas_tx(can_recv, can_send):
+ """Re-enable normal KWP message transmission, trying both safe diagnostic sessions."""
+ if can_recv is None or can_send is None:
+ return False
+
+ for diag_request, diag_response in LEAF_KWP_SESSIONS:
+ try:
+ ecu_log(f"Nissan Leaf ADAS TX restore using KWP session {diag_request.hex()}")
+ query = IsoTpParallelQuery(
+ can_send, can_recv, LEAF_ADAS_ECU_BUS, [LEAF_ADAS_ECU_ADDR],
+ [diag_request, LEAF_KWP_ENABLE_NORMAL_TX],
+ [diag_response, LEAF_KWP_ENABLE_NORMAL_TX_RESPONSE],
+ response_offset=NISSAN_RX_OFFSET,
+ )
+ if query.get_data(0.2):
+ ecu_log("Nissan Leaf ADAS normal TX restored")
+ return True
+ except Exception as e:
+ ecu_log(f"Nissan Leaf ADAS TX restore exception: {e}")
+
+ ecu_log("Nissan Leaf ADAS normal TX restore was not confirmed")
+ return False
+
+
class CarInterface(CarInterfaceBase):
CarState = CarState
CarController = CarController
@@ -62,39 +135,36 @@ class CarInterface(CarInterfaceBase):
@staticmethod
def init(CP, can_recv, can_send):
- if not (CP.openpilotLongitudinalControl and CP.carFingerprint == CAR.NISSAN_LEAF):
+ if not (CP.openpilotLongitudinalControl and CP.alphaLongitudinalAvailable and CP.carFingerprint == CAR.NISSAN_LEAF):
return
from openpilot.common.params import Params
params = Params()
- communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL,
- uds.CONTROL_TYPE.ENABLE_RX_DISABLE_TX,
- uds.MESSAGE_TYPE.NORMAL])
- ecu_disabled = disable_ecu(can_recv, can_send, bus=LEAF_ADAS_ECU_BUS, addr=LEAF_ADAS_ECU_ADDR,
- com_cont_req=communication_control, require_response=True, response_offset=NISSAN_RX_OFFSET)
- if not ecu_disabled:
- # Nissan firmware queries use the KWP-style default session. Try it after
- # standard UDS extended-session control, but still require a positive 0x68 response.
+ ecu_disabled = False
+ for diag_request, diag_response in LEAF_KWP_SESSIONS:
+ ecu_log(f"Nissan Leaf ADAS takeover using KWP session {diag_request.hex()}")
ecu_disabled = disable_ecu(can_recv, can_send, bus=LEAF_ADAS_ECU_BUS, addr=LEAF_ADAS_ECU_ADDR,
- com_cont_req=communication_control, require_response=True,
- diag_request=NISSAN_DIAGNOSTIC_REQUEST_KWP, diag_response=NISSAN_DIAGNOSTIC_RESPONSE_KWP,
- response_offset=NISSAN_RX_OFFSET)
- params.put_bool("EcuDisableFailed", not ecu_disabled)
- if ecu_disabled:
- ecu_log("Nissan Leaf ADAS TX disabled; experimental longitudinal control enabled")
+ com_cont_req=LEAF_KWP_DISABLE_NORMAL_TX, require_response=True, retry=3,
+ diag_request=diag_request, diag_response=diag_response, response_offset=NISSAN_RX_OFFSET)
+ if ecu_disabled:
+ break
+
+ takeover_confirmed = ecu_disabled and leaf_adas_commands_silent(can_recv)
+ params.put_bool("EcuDisableFailed", not takeover_confirmed)
+ if takeover_confirmed:
+ ecu_log("Nissan Leaf ADAS TX disable and command silence confirmed; experimental longitudinal control enabled")
else:
+ # A response can be lost after the ECU accepts 0x28. Always attempt to
+ # restore stock transmission before falling back to stock longitudinal.
+ restore_leaf_adas_tx(can_recv, can_send)
CP.safetyConfigs[-1].safetyParam &= ~NissanSafetyFlags.LONG_CONTROL.value
CP.openpilotLongitudinalControl = False
CP.pcmCruise = True
- ecu_log("Nissan Leaf ADAS TX disable failed; falling back to stock longitudinal control")
+ ecu_log("Nissan Leaf ADAS takeover was not confirmed; falling back to stock longitudinal control")
@staticmethod
def deinit(CP, can_recv, can_send):
- if not (CP.openpilotLongitudinalControl and CP.carFingerprint == CAR.NISSAN_LEAF):
+ if not (CP.openpilotLongitudinalControl and CP.alphaLongitudinalAvailable and CP.carFingerprint == CAR.NISSAN_LEAF):
return
- communication_control = bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL,
- 0x80 | uds.CONTROL_TYPE.ENABLE_RX_ENABLE_TX,
- uds.MESSAGE_TYPE.NORMAL])
- disable_ecu(can_recv, can_send, bus=LEAF_ADAS_ECU_BUS, addr=LEAF_ADAS_ECU_ADDR,
- com_cont_req=communication_control, response_offset=NISSAN_RX_OFFSET)
+ restore_leaf_adas_tx(can_recv, can_send)
diff --git a/opendbc_repo/opendbc/car/nissan/nissancan.py b/opendbc_repo/opendbc/car/nissan/nissancan.py
index e49b176a8..8c15b9212 100644
--- a/opendbc_repo/opendbc/car/nissan/nissancan.py
+++ b/opendbc_repo/opendbc/car/nissan/nissancan.py
@@ -6,6 +6,11 @@ from opendbc.car.nissan.values import CAR
nissan_checksum = crcmod.mkCrcFun(0x11d, initCrc=0x00, rev=False, xorOut=0xff)
+def create_leaf_adas_tester_present():
+ """KWP2000 tester-present with a response requested, for the 2025 Leaf ADAS ECU."""
+ return CanData(0x707, b"\x02\x3E\x01\x00\x00\x00\x00\x00", 0)
+
+
def create_accel_command(raw_command, frame, active):
"""Build the Leaf ADAS propulsion/regen request (0x2B0)."""
raw_command = int(raw_command)
diff --git a/opendbc_repo/opendbc/car/nissan/tests/test_nissan.py b/opendbc_repo/opendbc/car/nissan/tests/test_nissan.py
index 0d954b4f9..c8917d957 100644
--- a/opendbc_repo/opendbc/car/nissan/tests/test_nissan.py
+++ b/opendbc_repo/opendbc/car/nissan/tests/test_nissan.py
@@ -2,9 +2,10 @@ from types import SimpleNamespace
import pytest
-from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs, uds
+from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs
+from opendbc.car.can_definitions import CanData
from opendbc.car.nissan.carstate import CarState
-from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW
+from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW, leaf_adas_commands_silent, restore_leaf_adas_tx
from opendbc.car.nissan.values import CAR, CarControllerParams, NissanSafetyFlags
@@ -82,7 +83,7 @@ def test_alpha_long_controller_sends_stock_shaped_commands_and_keepalive():
assert can_sends[0x2B0][1].hex() == "ff6090ac5b000e03"
assert can_sends[0x1C3][1].hex() == "000000006400ff27"
- assert can_sends[0x707][1].hex() == "023e800000000000"
+ assert can_sends[0x707][1].hex() == "023e010000000000"
assert all(can_sends[addr][2] == 1 for addr in (0x2B0, 0x1C3))
assert can_sends[0x707][2] == 0
@@ -137,6 +138,8 @@ def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
return ecu_disabled
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", fake_disable_ecu)
+ monkeypatch.setattr("opendbc.car.nissan.interface.leaf_adas_commands_silent", lambda *_: ecu_disabled)
+ monkeypatch.setattr("opendbc.car.nissan.interface.restore_leaf_adas_tx", lambda *_: True)
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
CarInterface.init(CP, None, None)
@@ -145,9 +148,10 @@ def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
assert calls[0]["bus"] == 0
assert calls[0]["response_offset"] == 0x20
assert calls[0]["require_response"] is True
- assert calls[0]["com_cont_req"] == bytes([uds.SERVICE_TYPE.COMMUNICATION_CONTROL,
- uds.CONTROL_TYPE.ENABLE_RX_DISABLE_TX,
- uds.MESSAGE_TYPE.NORMAL])
+ assert calls[0]["diag_request"] == b"\x10\xc0"
+ assert calls[0]["diag_response"] == b"\x50\xc0"
+ assert calls[0]["com_cont_req"] == b"\x28\x01"
+ assert calls[0]["retry"] == 3
if not ecu_disabled:
assert calls[1]["diag_request"] == b"\x10\x81"
assert calls[1]["diag_response"] == b"\x50\x81"
@@ -161,9 +165,58 @@ def test_leaf_kwp_session_can_confirm_ecu_disable(monkeypatch):
results = iter((False, True))
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: next(results))
+ monkeypatch.setattr("opendbc.car.nissan.interface.leaf_adas_commands_silent", lambda *_: True)
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
CarInterface.init(CP, None, None)
assert CP.openpilotLongitudinalControl
assert not CP.pcmCruise
assert CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL
+
+
+def test_leaf_positive_disable_response_without_command_silence_falls_back(monkeypatch):
+ CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
+ restore_calls = []
+
+ monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: True)
+ monkeypatch.setattr("opendbc.car.nissan.interface.leaf_adas_commands_silent", lambda *_: False)
+ monkeypatch.setattr("opendbc.car.nissan.interface.restore_leaf_adas_tx", lambda *args: restore_calls.append(args) or True)
+ monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
+ CarInterface.init(CP, None, None)
+
+ assert len(restore_calls) == 1
+ assert not CP.openpilotLongitudinalControl
+ assert CP.pcmCruise
+ assert not (CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL)
+
+
+def test_leaf_adas_command_silence_requires_live_bus_without_stock_commands(monkeypatch):
+ monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
+
+ def unrelated_bus_traffic(wait_for_one=False):
+ return [] if not wait_for_one else [[CanData(0x123, b"\x00", 1)]]
+
+ assert leaf_adas_commands_silent(unrelated_bus_traffic, settle_time=0, observe_time=0.001)
+
+ def stock_command_traffic(wait_for_one=False):
+ return [] if not wait_for_one else [[CanData(0x2B0, b"\x00" * 8, 1)]]
+
+ assert not leaf_adas_commands_silent(stock_command_traffic, settle_time=0, observe_time=0.001)
+ assert not leaf_adas_commands_silent(lambda wait_for_one=False: [], settle_time=0, observe_time=0.001)
+
+
+def test_leaf_adas_restore_uses_kwp_enable_normal_transmission(monkeypatch):
+ queries = []
+
+ class FakeQuery:
+ def __init__(self, can_send, can_recv, bus, addrs, request, response, response_offset):
+ queries.append((bus, addrs, request, response, response_offset))
+
+ def get_data(self, timeout):
+ return {(0x707, None): b""}
+
+ monkeypatch.setattr("opendbc.car.nissan.interface.IsoTpParallelQuery", FakeQuery)
+ monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
+
+ assert restore_leaf_adas_tx(lambda **kwargs: [], lambda msgs: None)
+ assert queries == [(0, [0x707], [b"\x10\xc0", b"\x29\x01"], [b"\x50\xc0", b"\x69"], 0x20)]
diff --git a/opendbc_repo/opendbc/safety/modes/hyundai.h b/opendbc_repo/opendbc/safety/modes/hyundai.h
index 9d01c2da8..b2de4b5d7 100644
--- a/opendbc_repo/opendbc/safety/modes/hyundai.h
+++ b/opendbc_repo/opendbc/safety/modes/hyundai.h
@@ -92,13 +92,16 @@ static bool hyundai_legacy = false;
static bool hyundai_can_canfd_blended_hda2 = false;
static bool hyundai_acc_main_on_rx_prev = false;
-#define HYUNDAI_CAN_CANFD_BLENDED_HDA2_RX_CHECKS() \
+#define HYUNDAI_CAN_CANFD_BLENDED_HDA2_COMMON_RX_CHECKS() \
{.msg = {{0x260, 1, 8, 100U, .max_counter = 3U, .ignore_quality_flag = true}, \
{0x371, 1, 8, 100U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }}}, \
{.msg = {{0x386, 1, 8, 50U, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{0x394, 1, 8, 50U, .max_counter = 7U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
{.msg = {{0x251, 1, 8, 50U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
- {.msg = {{0x4F1, 1, 4, 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}}, \
+ {.msg = {{0x4F1, 1, 4, 50U, .ignore_checksum = true, .max_counter = 15U, .ignore_quality_flag = true}, { 0 }, { 0 }}},
+
+#define HYUNDAI_CAN_CANFD_BLENDED_HDA2_RX_CHECKS() \
+ HYUNDAI_CAN_CANFD_BLENDED_HDA2_COMMON_RX_CHECKS() \
HYUNDAI_SCC11_ADDR_CHECK(1) \
HYUNDAI_SCC12_ADDR_CHECK(1, true)
@@ -281,14 +284,21 @@ static bool hyundai_tx_hook(const CANPacket_t *msg) {
bool tx = true;
- // FCA11: Block any potential actuation
+ // FCA11: Block any potential actuation. The blended HDA II layout uses
+ // different static fields, but its explicit AEB/FCA request bits stay zero.
if (msg->addr == 0x38DU) {
- int CR_VSM_DecCmd = msg->data[1];
- bool FCA_CmdAct = GET_BIT(msg, 20U);
- bool CF_VSM_DecCmdAct = GET_BIT(msg, 31U);
+ if (hyundai_can_canfd_blended_hda2) {
+ if (GET_BIT(msg, 16U) || GET_BIT(msg, 19U)) {
+ tx = false;
+ }
+ } else {
+ int CR_VSM_DecCmd = msg->data[1];
+ bool FCA_CmdAct = GET_BIT(msg, 20U);
+ bool CF_VSM_DecCmdAct = GET_BIT(msg, 31U);
- if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) {
- tx = false;
+ if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) {
+ tx = false;
+ }
}
}
@@ -348,7 +358,7 @@ static bool hyundai_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 == 0x7D0U) {
+ if ((msg->addr == 0x7D0U) || (msg->addr == 0x730U)) {
if ((GET_BYTES(msg, 0, 4) != 0x00803E02U) || (GET_BYTES(msg, 4, 4) != 0x0U)) {
tx = false;
}
@@ -399,6 +409,27 @@ static safety_config hyundai_init(uint16_t param) {
{0x2A4, 0, 24, .check_relay = true},
};
+ static const CanMsg HYUNDAI_CAN_CANFD_BLENDED_HDA2_LONG_TX_MSGS[] = {
+ {0x50, 0, 16, .check_relay = true},
+ {0x4F1, 1, 4, .check_relay = false},
+ {0x2A4, 0, 24, .check_relay = true},
+ {0x51, 0, 32, .check_relay = false},
+ {0x730, 1, 8, .check_relay = false},
+ {0x340, 1, 8, .check_relay = true},
+ {0x485, 1, 8, .check_relay = true},
+ {0x420, 1, 8, .check_relay = true},
+ {0x421, 1, 8, .check_relay = true},
+ {0x389, 1, 8, .check_relay = true},
+ {0x38D, 1, 8, .check_relay = false},
+ {0x363, 1, 8, .check_relay = false},
+ {0x398, 1, 8, .check_relay = false},
+ {0x399, 1, 8, .check_relay = false},
+ {0x39A, 1, 8, .check_relay = false},
+ {0x39B, 1, 8, .check_relay = false},
+ {0x39C, 1, 8, .check_relay = false},
+ {0x43A, 1, 8, .check_relay = false},
+ };
+
static const CanMsg HYUNDAI_CAN_CANFD_BLENDED_LONG_TX_MSGS[] = {
{0x340, 0, 8, .check_relay = true},
{0x4F1, 0, 4, .check_relay = false},
@@ -462,10 +493,10 @@ static safety_config hyundai_init(uint16_t param) {
}
if (hyundai_can_canfd_blended_hda2) {
static RxCheck hyundai_can_canfd_blended_hda2_long_rx_checks[] = {
- HYUNDAI_CAN_CANFD_BLENDED_HDA2_RX_CHECKS()
+ HYUNDAI_CAN_CANFD_BLENDED_HDA2_COMMON_RX_CHECKS()
};
SET_RX_CHECKS(hyundai_can_canfd_blended_hda2_long_rx_checks, ret);
- SET_TX_MSGS(HYUNDAI_CAN_CANFD_BLENDED_HDA2_TX_MSGS, ret);
+ SET_TX_MSGS(HYUNDAI_CAN_CANFD_BLENDED_HDA2_LONG_TX_MSGS, ret);
} else if (hyundai_camera_scc) {
if (hyundai_can_refresh_msgs) {
SET_TX_MSGS(HYUNDAI_CAMERA_SCC_LONG_REFRESH_TX_MSGS, ret);
diff --git a/opendbc_repo/opendbc/safety/modes/nissan.h b/opendbc_repo/opendbc/safety/modes/nissan.h
index 05314f0cc..45184d441 100644
--- a/opendbc_repo/opendbc/safety/modes/nissan.h
+++ b/opendbc_repo/opendbc/safety/modes/nissan.h
@@ -174,7 +174,8 @@ static bool nissan_tx_hook(const CANPacket_t *msg) {
}
if (nissan_longitudinal && (msg->addr == 0x707U) && (msg->bus == 0U)) {
- violation |= (msg->data[0] != 0x02U) || (msg->data[1] != 0x3EU) || (msg->data[2] != 0x80U);
+ // KWP2000 TesterPresent, response required. The Leaf camera rejects UDS 0x3E80.
+ violation |= (msg->data[0] != 0x02U) || (msg->data[1] != 0x3EU) || (msg->data[2] != 0x01U);
for (int i = 3; i < 8; i++) {
violation |= msg->data[i] != 0U;
}
diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai.py b/opendbc_repo/opendbc/safety/tests/test_hyundai.py
index a565bff49..998c97f71 100755
--- a/opendbc_repo/opendbc/safety/tests/test_hyundai.py
+++ b/opendbc_repo/opendbc/safety/tests/test_hyundai.py
@@ -254,6 +254,10 @@ class TestHyundaiCanCanfdBlendedSafety(TestHyundaiSafety):
class TestHyundaiCanCanfdBlendedHda2Safety(unittest.TestCase):
TX_MSGS = [[0x50, 0], [0x4F1, 1], [0x2A4, 0]]
+ LONG_TX_MSGS = TX_MSGS + [
+ [0x51, 0], [0x730, 1], [0x340, 1], [0x485, 1], [0x420, 1], [0x421, 1], [0x389, 1], [0x38D, 1],
+ [0x363, 1], [0x398, 1], [0x399, 1], [0x39A, 1], [0x39B, 1], [0x39C, 1], [0x43A, 1],
+ ]
def setUp(self):
self.packer = CANPackerSafety("hyundai_palisade_2023_generated")
@@ -291,6 +295,52 @@ class TestHyundaiCanCanfdBlendedHda2Safety(unittest.TestCase):
self.assertEqual(-1, self.safety.safety_fwd_hook(2, 0x50))
self.assertEqual(-1, self.safety.safety_fwd_hook(2, 0x2A4))
+ def test_hda2_longitudinal_support_messages_require_long_flag(self):
+ flags = HyundaiSafetyFlags.CAN_CANFD_BLENDED | HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG
+ self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, flags)
+ self.safety.init_tests()
+
+ for addr, bus in self.LONG_TX_MSGS:
+ if addr == 0x50:
+ msg = self._lkas_msg()
+ elif addr == 0x420:
+ msg = self.packer.make_can_msg_panda("SCC11", bus, {"aReqRaw": 0.0, "aReqValue": 0.0})
+ elif addr == 0x730:
+ msg = libsafety_py.make_CANPacket(addr, bus, b"\x02\x3E\x80\x00\x00\x00\x00\x00")
+ else:
+ length = 32 if addr == 0x51 else 24 if addr == 0x2A4 else 4 if addr == 0x4F1 else 8
+ msg = common.make_msg(bus, addr, length)
+ self.assertTrue(self.safety.safety_tx_hook(msg), hex(addr))
+
+ self.safety.set_safety_hooks(
+ CarParams.SafetyModel.hyundai,
+ HyundaiSafetyFlags.CAN_CANFD_BLENDED | HyundaiSafetyFlags.CANFD_LKA_STEERING,
+ )
+ self.safety.init_tests()
+ for addr, bus in self.LONG_TX_MSGS[len(self.TX_MSGS):]:
+ length = 32 if addr == 0x51 else 8
+ self.assertFalse(self.safety.safety_tx_hook(common.make_msg(bus, addr, length)), hex(addr))
+
+ def test_hda2_longitudinal_acceleration_and_diagnostics_are_checked(self):
+ flags = HyundaiSafetyFlags.CAN_CANFD_BLENDED | HyundaiSafetyFlags.CANFD_LKA_STEERING | HyundaiSafetyFlags.LONG
+ self.safety.set_safety_hooks(CarParams.SafetyModel.hyundai, flags)
+ self.safety.init_tests()
+ self.safety.set_controls_allowed(True)
+
+ for accel, allowed in ((-3.5, True), (3.5, True), (-3.51, False), (3.51, False)):
+ msg = self.packer.make_can_msg_panda("SCC11", 1, {"aReqRaw": accel, "aReqValue": accel})
+ self.assertEqual(allowed, self.safety.safety_tx_hook(msg))
+
+ valid_tester = libsafety_py.make_CANPacket(0x730, 1, b"\x02\x3E\x80\x00\x00\x00\x00\x00")
+ invalid_tester = libsafety_py.make_CANPacket(0x730, 1, b"\x03\x28\x83\x01\x00\x00\x00\x00")
+ self.assertTrue(self.safety.safety_tx_hook(valid_tester))
+ self.assertFalse(self.safety.safety_tx_hook(invalid_tester))
+
+ fca_status = self.packer.make_can_msg_panda("FCA11", 1, {"cr_vsm_deccmd": 255, "cf_vsm_deccmdact": 0})
+ fca_request = self.packer.make_can_msg_panda("FCA11", 1, {"aeb_cmd_act": 1})
+ self.assertTrue(self.safety.safety_tx_hook(fca_status))
+ self.assertFalse(self.safety.safety_tx_hook(fca_request))
+
class TestHyundaiSafetyFCEV(TestHyundaiSafety):
def setUp(self):
diff --git a/opendbc_repo/opendbc/safety/tests/test_nissan.py b/opendbc_repo/opendbc/safety/tests/test_nissan.py
index 2453d5b92..798274ecb 100755
--- a/opendbc_repo/opendbc/safety/tests/test_nissan.py
+++ b/opendbc_repo/opendbc/safety/tests/test_nissan.py
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import unittest
-from opendbc.car import make_tester_present_msg
from opendbc.car.nissan import nissancan
from opendbc.car.nissan.values import NissanSafetyFlags
from opendbc.car.structs import CarParams
@@ -261,7 +260,7 @@ class TestNissanLeafLongSafety(TestNissanLeafSafety):
self.assertTrue(self._tx(self._brake_msg(0, active=False, brake_mode=False)))
def test_tester_present(self):
- tester_present = make_tester_present_msg(0x707, 0, suppress_response=True)
+ tester_present = nissancan.create_leaf_adas_tester_present()
self.assertTrue(self._tx(self._make_msg(tester_present)))
for index in range(8):
diff --git a/panda/board/obj/gitversion.h b/panda/board/obj/gitversion.h
index 10900ab2b..21fb8c654 100644
--- a/panda/board/obj/gitversion.h
+++ b/panda/board/obj/gitversion.h
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19];
-const uint8_t gitversion[19] = "DEV-50e1c1d3-DEBUG";
+const uint8_t gitversion[19] = "DEV-21805a54-DEBUG";
diff --git a/panda/board/obj/version b/panda/board/obj/version
index 23a1c8855..6698c06fd 100644
--- a/panda/board/obj/version
+++ b/panda/board/obj/version
@@ -1 +1 @@
-DEV-50e1c1d3-DEBUG
\ No newline at end of file
+DEV-21805a54-DEBUG
\ No newline at end of file
diff --git a/selfdrive/modeld/models/commonmodel_pyx.so b/selfdrive/modeld/models/commonmodel_pyx.so
deleted file mode 100755
index edda0400c..000000000
Binary files a/selfdrive/modeld/models/commonmodel_pyx.so and /dev/null differ
diff --git a/starpilot/system/the_galaxy/assets/components/router.js b/starpilot/system/the_galaxy/assets/components/router.js
index 835a49b0c..6e6463dc7 100644
--- a/starpilot/system/the_galaxy/assets/components/router.js
+++ b/starpilot/system/the_galaxy/assets/components/router.js
@@ -11,7 +11,7 @@ import { MapsManager } from "/assets/components/tools/maps.js"
import { NavDestination } from "/assets/components/navigation/navigation_destination.js?v=nav-search-context-2"
import { NavKeys } from "/assets/components/navigation/navigation_keys.js?v=app-keys-session-1"
import { RouteRecordings } from "/assets/components/recordings/dashcam_routes.js"
-import { SettingsView } from "/assets/components/settings.js"
+import { SettingsView } from "/assets/components/settings.js?v=router-cycle-fix-1"
import { ScreenRecordings } from "/assets/components/recordings/screen_recordings.js"
import { Sidebar } from "/assets/components/sidebar.js?v=lateral-tuning-1"
import { SentryMode } from "/assets/components/tools/sentry.js"
diff --git a/starpilot/system/the_galaxy/assets/components/settings.js b/starpilot/system/the_galaxy/assets/components/settings.js
index c8e85f592..168a47b15 100644
--- a/starpilot/system/the_galaxy/assets/components/settings.js
+++ b/starpilot/system/the_galaxy/assets/components/settings.js
@@ -1,6 +1,14 @@
import { html } from "/assets/vendor/arrow-core.js"
import { upperFirst } from "/assets/js/utils.js"
-import { Navigate } from "/assets/components/router.js"
+
+function navigate(href) {
+ // Avoid importing router.js here: settings.js is loaded by router.js, and
+ // a cache-busted router URL would otherwise create a second router module.
+ if (typeof window.__theGalaxyNavigate === "function") {
+ return window.__theGalaxyNavigate(href)
+ }
+ window.location.assign(href)
+}
export function SettingsView({ params }) {
const state = {
@@ -15,7 +23,7 @@ export function SettingsView({ params }) {
const setting = results.find((item) => item.key === state.selectedSubsection) ?? {}
if (!setting.subsettings || Object.keys(setting.subsettings).length === 0) {
- return Navigate(`/settings/${state.selectedSection}`)
+ return navigate(`/settings/${state.selectedSection}`)
}
state.heading = setting.key
diff --git a/starpilot/system/the_galaxy/templates/index.html b/starpilot/system/the_galaxy/templates/index.html
index 06b20f8e5..403a20a36 100644
--- a/starpilot/system/the_galaxy/templates/index.html
+++ b/starpilot/system/the_galaxy/templates/index.html
@@ -48,7 +48,7 @@