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 @@