Compare commits

..

1 Commits

Author SHA1 Message Date
github-actions[bot] 66bdc1665d sunnypilot v2026.07.27-4598
version: sunnypilot v2026.003.000 (feature-branch)
date: 2026-07-27T19:54:46
master commit: 3a05c03079
2026-07-27 19:54:46 +00:00
53 changed files with 645 additions and 469 deletions
@@ -130,6 +130,7 @@ class CarHarness(EnumBase):
hyundai_p = BaseCarHarness("Hyundai P connector")
hyundai_q = BaseCarHarness("Hyundai Q connector")
hyundai_r = BaseCarHarness("Hyundai R connector")
hyundai_s = BaseCarHarness("Hyundai S connector")
custom = BaseCarHarness("Developer connector")
obd_ii = BaseCarHarness("OBD-II connector", parts=[Cable.long_obdc_cable], has_connector=False)
gm = BaseCarHarness("GM connector", parts=[Accessory.harness_box])
@@ -200,6 +200,7 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
lka_steering = self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl
ccnc_non_hda2 = self.CP.flags & HyundaiFlags.CCNC and not lka_steering
# steering control
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque, self.lkas_icon))
@@ -211,7 +212,12 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
# 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))
if ccnc_non_hda2:
can_sends.extend(hyundaicanfd.create_ccnc(self.packer, self.CAN, self.CP.openpilotLongitudinalControl, CC.enabled, CC.hudControl, CC.leftBlinker,
CC.rightBlinker, CS.msg_161, CS.msg_162, CS.msg_1b5, CS.is_metric, CS.out, CS.main_cruise_enabled,
self.lfa_icon))
else:
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.CANFD_ENABLE_BLINKERS:
@@ -220,11 +226,12 @@ class CarController(CarControllerBase, EsccCarController, LeadDataCarController,
if self.CP.openpilotLongitudinalControl:
if lka_steering:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.CAN, self.frame))
else:
elif not ccnc_non_hda2:
can_sends.extend(hyundaicanfd.create_fca_warning_light(self.packer, self.CAN, self.frame))
if self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CAN, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units, hud_control, self.lead_data, CS.main_cruise_enabled, self.tuning))
set_speed_in_units, hud_control, self.lead_data, CS.main_cruise_enabled, self.tuning,
CS.cruise_info if ccnc_non_hda2 else None))
self.accel_last = accel
else:
# button presses
+9 -6
View File
@@ -64,6 +64,7 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
self.buttons_counter = 0
self.cruise_info = {}
self.msg_161, self.msg_162, self.msg_1b5 = {}, {}, {}
# On some cars, CLU15->CF_Clu_VehicleSpeed can oscillate faster than the dash updates. Sample at 5 Hz
self.cluster_speed = 0
@@ -256,12 +257,14 @@ class CarState(CarStateBase, EsccCarStateBase, MadsCarState, CarStateExt):
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0
# TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP']
left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP"
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN:
left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT"
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
cp.vl["BLINKERS"][right_blinker_sig])
alt = ""
if self.CP.flags & HyundaiFlags.CCNC:
alt = "_ALT"
if not self.CP.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
self.msg_161, self.msg_162, self.msg_1b5 = map(copy.copy, (cp_cam.vl["CCNC_0x161"], cp_cam.vl["CCNC_0x162"], cp_cam.vl["FR_CMR_03_50ms"]))
self.cruise_info = copy.copy((cp_cam if self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC else cp).vl["SCC_CONTROL"])
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][f"LEFT_LAMP{alt}"],
cp.vl["BLINKERS"][f"RIGHT_LAMP{alt}"])
if self.CP.enableBsm:
ret.leftBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_LtIndSta"])
ret.rightBlindspot = bool(cp.vl["ADAS_CMD_50_50ms"]["BCW_RtIndSta"])
@@ -220,6 +220,16 @@ FW_VERSIONS = {
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.07 99211-L1000 211223',
],
},
CAR.HYUNDAI_SONATA_2024: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DN8 MFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.01 99211-L1800 230512',
b'\xf1\x00DN8 MFC AT USA LHD 1.00 1.02 99211-L1800 250613',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
],
},
CAR.HYUNDAI_SONATA_LF: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00LF__ SCC F-CUP 1.00 1.00 96401-C2200 ',
@@ -570,6 +580,16 @@ FW_VERSIONS = {
b'\xf1\x00OS9 LKAS AT USA LHD 1.00 1.00 95740-J9300 g21',
],
},
CAR.HYUNDAI_KONA_2ND_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.03 99211-BE000 230517',
b'\xf1\x00SX2 MFC AT USA LHD 1.00 1.07 99211-BE000 240611',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
],
},
CAR.KIA_CEED: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CD__ SCC F-CUP 1.00 1.00 99110-J7500 ',
@@ -605,6 +625,17 @@ FW_VERSIONS = {
b'\xf1\x00BD__ SCC H-CUP 1.00 1.02 99110-M6000 ',
],
},
CAR.KIA_K4_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00CL4 MFC AT CAN LHD 1.00 1.02 99210-GG000 240708',
b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.02 99210-GG000 240708',
b'\xf1\x00CL4 MFC AT USA LHD 1.00 1.04 99210-GG100 251205',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG000 ',
b'\xf1\x00CL4_ RDR ----- 1.00 1.01 99110-GG100 ',
],
},
CAR.KIA_K5_2021: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DL3_ SCC F-CUP 1.00 1.03 99110-L2100 ',
@@ -637,6 +668,14 @@ FW_VERSIONS = {
b'\xf1\x00DL ESC \t 102"\x08\x10 58910-L3800',
],
},
CAR.KIA_K5_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DL3 MFC AT USA LHD 1.00 1.04 99210-L2500 240117',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DL3_ RDR ----- 1.00 1.01 99110-L2500 ',
],
},
CAR.KIA_K5_HEV_2020: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DLhe SCC FHCUP 1.00 1.02 99110-L7000 ',
@@ -723,6 +762,7 @@ FW_VERSIONS = {
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00SX2EMFC AT KOR LHD 1.00 1.00 99211-BF000 230410',
b'\xf1\x00SX2EMFC AT USA LHD 1.00 1.02 99211-BF000 230823',
],
},
CAR.KIA_NIRO_EV: {
@@ -981,6 +1021,17 @@ FW_VERSIONS = {
b'\xf1\x00OSH LKAS AT KOR LHD 1.00 1.01 95740-CM000 l31',
],
},
CAR.HYUNDAI_KONA_HEV_2ND_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00SX2HMFC AT AUS RHD 1.00 1.00 99211-BE001 241015',
b'\xf1\x00SX2HMFC AT EUR LHD 1.00 1.01 99211-BE001 250117',
b'\xf1\x00SX2HMFC AT EUR RHD 1.00 1.04 99211-BE000 231010',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE000 ',
b'\xf1\x00SX2_ RDR ----- 1.00 1.02 99110-BE500 ',
],
},
CAR.HYUNDAI_SONATA_HYBRID: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DNhe SCC F-CUP 1.00 1.02 99110-L5000 ',
@@ -1002,6 +1053,15 @@ FW_VERSIONS = {
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.07 99211-L1000 211223',
],
},
CAR.HYUNDAI_SONATA_HEV_2024: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00DN8HMFC AT KOR LHD 1.00 1.01 99211-L1800 230512',
b'\xf1\x00DN8HMFC AT USA LHD 1.00 1.01 99211-L1800 230512',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00DN8_ RDR ----- 1.00 1.00 99110-L1800 ',
],
},
CAR.KIA_SORENTO: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00UMP LKAS AT AUS RHD 1.00 1.00 96400-C6550 S30',
@@ -1069,6 +1129,16 @@ FW_VERSIONS = {
b'\xf1\x00NE1 MFC AT USA LHD 1.00 1.06 99211-GI010 230110',
],
},
CAR.HYUNDAI_IONIQ_5_N: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NE1N RDR ----- 1.00 1.00 99110-NI000 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.04 99211-NI000 231219',
b'\xf1\x00NE1NMFC AT KOR LHD 1.00 1.00 99211-NI010 240712',
b'\xf1\x00NE1NMFC AT USA LHD 1.00 1.04 99211-NI000 231219',
],
},
CAR.HYUNDAI_IONIQ_6: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ',
@@ -1107,6 +1177,37 @@ FW_VERSIONS = {
b'\xf1\x00NX4__ 1.01 1.02 99110-N9000 ',
],
},
CAR.HYUNDAI_TUCSON_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT GEN LHD 1.00 1.00 99211-N7030 C55',
b'\xf1\x00NX4 FR_CMR AT GEN LHD 1.00 1.00 99211-N7035 C5C',
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N7050 C5A',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ',
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
],
},
CAR.HYUNDAI_TUCSON_HEV_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT EUR LHD 1.00 1.00 99211-N7030 C55',
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7035 C5C',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NX4__ 1.00 1.02 99110N7000 ',
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
b'\xf1\x00NX4__ 1.00 1.03 99110N7100 ',
],
},
CAR.HYUNDAI_TUCSON_PHEV_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT CAN LHD 1.00 1.00 99211-N7030 C55',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NX4__ 1.00 1.02 99110N7100 ',
],
},
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW000 14M',
@@ -1118,6 +1219,14 @@ FW_VERSIONS = {
b'\xf1\x00NX4__ 1.01 1.00 99110-K5000 ',
],
},
CAR.HYUNDAI_SANTA_CRUZ_2025: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-N7030 C55',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00NX4__ 1.00 1.00 99110K5500 ',
],
},
CAR.KIA_SPORTAGE_5TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00NQ5 FR_CMR AT AUS RHD 1.00 1.00 99211-P1040 663',
@@ -1190,6 +1299,16 @@ FW_VERSIONS = {
b'\xf1\x00MQ4_ SCC FHCUP 1.00 1.08 99110-P2000 ',
],
},
CAR.KIA_SORENTO_2024: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00MQ4 MFC AT AUS RHD 1.01 1.04 99210-P2550 231127',
b'\xf1\x00MQ4 MFC AT USA LHD 1.01 1.04 99210-R5500 231127',
],
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-P2500 ',
b'\xf1\x00MQ4_ RDR ----- 1.00 1.01 99110-R5500 ',
],
},
CAR.KIA_SORENTO_HEV_4TH_GEN: {
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00MQ4HMFC AT KOR LHD 1.00 1.04 99210-P2000 200330',
@@ -1,5 +1,6 @@
import numpy as np
from opendbc.car import CanBusBase
from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.crc import CRC16_XMODEM
from opendbc.car.hyundai.values import HyundaiFlags
from opendbc.sunnypilot.car.hyundai.lead_data_ext import CanFdLeadData
@@ -125,8 +126,106 @@ def create_lfahda_cluster(packer, CAN, enabled, lfa_icon):
return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values)
def create_ccnc(packer, CAN, openpilotLongitudinalControl, enabled, hud, leftBlinker, rightBlinker, msg_161, msg_162, msg_1b5,
is_metric, out, main_cruise_enabled, lfa_icon):
for f in {"FAULT_LSS", "FAULT_HDA", "FAULT_DAS", "FAULT_LFA", "FAULT_DAW", "FAULT_ESS"}:
msg_162[f] = 0
if msg_161["ALERTS_2"] == 5:
msg_161.update({"ALERTS_2": 0, "SOUNDS_2": 0})
if msg_161["ALERTS_3"] == 17:
msg_161["ALERTS_3"] = 0
if msg_161["ALERTS_5"] in (2, 5):
msg_161["ALERTS_5"] = 0
if msg_161["SOUNDS_4"] == 2 and msg_161["LFA_ICON"] in (3, 0,):
msg_161["SOUNDS_4"] = 0
LANE_CHANGE_SPEED_MIN = 8.9408
anyBlinker = leftBlinker or rightBlinker
curvature = {i: (31 if i == -1 else 13 - abs(i + 15)) if i < 0 else 15 + i for i in range(-15, 16)}
msg_161.update({
"DAW_ICON": 0,
"LKA_ICON": 0,
"LFA_ICON": 2 if lfa_icon else 0,
"CENTERLINE": 1 if lfa_icon else 0,
"LANELINE_CURVATURE": curvature.get(max(-15, min(int(out.steeringAngleDeg / 4.5), 15)), 14) if lfa_icon and not anyBlinker else 15,
"LANELINE_LEFT": (0 if not lfa_icon else 1 if not hud.leftLaneVisible else 4 if hud.leftLaneDepart else 6 if anyBlinker else 2),
"LANELINE_RIGHT": (0 if not lfa_icon else 1 if not hud.rightLaneVisible else 4 if hud.rightLaneDepart else 6 if anyBlinker else 2),
"LCA_LEFT_ICON": (0 if not lfa_icon or out.vEgo < LANE_CHANGE_SPEED_MIN else 1 if out.leftBlindspot else 2 if anyBlinker else 4),
"LCA_RIGHT_ICON": (0 if not lfa_icon or out.vEgo < LANE_CHANGE_SPEED_MIN else 1 if out.rightBlindspot else 2 if anyBlinker else 4),
"LCA_LEFT_ARROW": 2 if leftBlinker else 0,
"LCA_RIGHT_ARROW": 2 if rightBlinker else 0,
})
if lfa_icon and (leftBlinker or rightBlinker):
leftlaneraw, rightlaneraw = msg_1b5["Info_LftLnPosVal"], msg_1b5["Info_RtLnPosVal"]
scale_per_m = 15 / 1.7
leftlane = abs(int(round(15 + (leftlaneraw - 1.7) * scale_per_m)))
rightlane = abs(int(round(15 + (rightlaneraw - 1.7) * scale_per_m)))
if msg_1b5["Info_LftLnQualSta"] not in (2, 3):
leftlane = 0
if msg_1b5["Info_RtLnQualSta"] not in (2, 3):
rightlane = 0
if leftlaneraw == -2.0248375:
leftlane = 30 - rightlane
if rightlaneraw == 2.0248375:
rightlane = 30 - leftlane
if leftlaneraw == rightlaneraw == 0:
leftlane = rightlane = 15
elif leftlaneraw == 0:
leftlane = 30 - rightlane
elif rightlaneraw == 0:
rightlane = 30 - leftlane
total = leftlane + rightlane
if total == 0:
leftlane = rightlane = 15
else:
leftlane = round((leftlane / total) * 30)
rightlane = 30 - leftlane
msg_161["LANELINE_LEFT_POSITION"] = leftlane
msg_161["LANELINE_RIGHT_POSITION"] = rightlane
if hud.leftLaneDepart or hud.rightLaneDepart:
msg_162["VIBRATE"] = 1
if openpilotLongitudinalControl:
if msg_161["ALERTS_3"] in (1, 2, 3, 4, 7, 8, 9, 10):
msg_161["ALERTS_3"] = 0
if msg_161["ALERTS_5"] == 4:
msg_161["ALERTS_5"] = 0
if msg_161["SOUNDS_3"] == 5:
msg_161["SOUNDS_3"] = 0
msg_161.update({
"SETSPEED": 3 if enabled else 1,
"SETSPEED_HUD": 0 if not main_cruise_enabled else 2 if enabled else 1,
"SETSPEED_SPEED": (
255 if not main_cruise_enabled else
(40 if is_metric else 25) if (s := round(out.vCruiseCluster * (1 if is_metric else CV.KPH_TO_MPH))) > (145 if is_metric else 90) else s
),
"DISTANCE": hud.leadDistanceBars,
"DISTANCE_SPACING": 0 if not main_cruise_enabled else 1 if enabled else 3,
"DISTANCE_LEAD": 0 if not main_cruise_enabled else 2 if enabled and hud.leadVisible else 1 if hud.leadVisible else 0,
"DISTANCE_CAR": 0 if not main_cruise_enabled else 2 if enabled else 1,
"SLA_ICON": 0,
"NAV_ICON": 0,
"TARGET": 0,
})
msg_162["LEAD"] = 0 if not main_cruise_enabled else 2 if enabled else 1
msg_162["LEAD_DISTANCE"] = msg_1b5["Longitudinal_Distance"]
return [packer.make_can_msg(msg, CAN.ECAN, data) for msg, data in [("CCNC_0x161", msg_161), ("CCNC_0x162", msg_162)]]
def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control,
lead_data: CanFdLeadData, main_cruise_enabled, tuning):
lead_data: CanFdLeadData, main_cruise_enabled, tuning, cruise_info=None):
jerk = 5
jn = jerk / 50
if not enabled or gas_override:
@@ -154,6 +253,8 @@ def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_ov
"SET_ME_TMP_64": 0x64,
"DISTANCE_SETTING": hud_control.leadDistanceBars,
}
if cruise_info:
values.update({s: cruise_info[s] for s in ["ACC_ObjDist", "ACC_ObjRelSpd"]})
return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values)
@@ -85,6 +85,8 @@ class CarInterface(CarInterfaceBase):
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
if ret.flags & HyundaiFlags.CCNC and not ret.flags & HyundaiFlags.CANFD_LKA_STEER_MSG:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CCNC.value
else:
# Shared configuration for non CAN-FD cars
@@ -23,7 +23,11 @@ NO_DATES_PLATFORMS = {
# CAN FD
CAR.KIA_SPORTAGE_5TH_GEN,
CAR.HYUNDAI_SANTA_CRUZ_1ST_GEN,
CAR.HYUNDAI_SANTA_CRUZ_2025,
CAR.HYUNDAI_TUCSON_4TH_GEN,
CAR.HYUNDAI_TUCSON_2025,
CAR.HYUNDAI_TUCSON_HEV_2025,
CAR.HYUNDAI_TUCSON_PHEV_2025,
# CAN
CAR.HYUNDAI_ELANTRA,
CAR.HYUNDAI_ELANTRA_GT_I30,
+72 -3
View File
@@ -68,6 +68,7 @@ class HyundaiSafetyFlags(IntFlag):
CANFD_LKA_STEER_MSG_ALT = 128
FCEV_GAS = 256
ALT_LIMITS_2 = 512
CCNC = 1024
# Hyundai/Kia/Genesis SCC (Smart Cruise Control) and steering architecture:
@@ -149,6 +150,8 @@ class HyundaiFlags(IntFlag):
ALT_LIMITS_2 = 2 ** 26
CCNC = 2 ** 27
@dataclass
class HyundaiCarDocs(CarDocs):
@@ -285,6 +288,16 @@ class CAR(Platforms):
CarSpecs(mass=1491, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.ALT_LIMITS_2,
)
HYUNDAI_KONA_2ND_GEN = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Kona (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_l]))],
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_KONA_HEV_2ND_GEN = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Kona Hybrid (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_l]))],
CarSpecs(mass=1590, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_KONA_EV = HyundaiPlatformConfig(
[HyundaiCarDocs("Hyundai Kona Electric 2018-21", car_parts=CarParts.common([CarHarness.hyundai_g]))],
CarSpecs(mass=1685, wheelbase=2.6, steerRatio=13.42, tireStiffnessFactor=0.385),
@@ -296,10 +309,13 @@ class CAR(Platforms):
flags=HyundaiFlags.CAMERA_SCC | HyundaiFlags.EV | HyundaiFlags.ALT_LIMITS,
)
HYUNDAI_KONA_EV_2ND_GEN = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
car_parts=CarParts.common([CarHarness.hyundai_r]))],
[
HyundaiCarDocs("Hyundai Kona Electric (with HDA II, Korea only) 2023", video="https://www.youtube.com/watch?v=U2fOCmcQ8hw",
car_parts=CarParts.common([CarHarness.hyundai_r])),
HyundaiCarDocs("Hyundai Kona Electric (without HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_a])),
],
CarSpecs(mass=1740, wheelbase=2.66, steerRatio=13.6, tireStiffnessFactor=0.385),
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE,
flags=HyundaiFlags.EV | HyundaiFlags.CANFD_NO_RADAR_DISABLE | HyundaiFlags.CCNC,
)
HYUNDAI_KONA_HEV = HyundaiPlatformConfig(
[HyundaiCarDocs("Hyundai Kona Hybrid 2020", car_parts=CarParts.common([CarHarness.hyundai_i]))], # TODO: check packages,
@@ -339,6 +355,11 @@ class CAR(Platforms):
CarSpecs(mass=1513, wheelbase=2.84, steerRatio=13.27 * 1.15, tireStiffnessFactor=0.65), # 15% higher at the center seems reasonable
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8,
)
HYUNDAI_SONATA_2024 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Sonata (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
CarSpecs(mass=1556, wheelbase=2.84, steerRatio=12.81),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_SONATA_LF = HyundaiPlatformConfig(
[HyundaiCarDocs("Hyundai Sonata 2018-19", car_parts=CarParts.common([CarHarness.hyundai_e]))],
CarSpecs(mass=1536, wheelbase=2.804, steerRatio=13.27 * 1.15), # 15% higher at the center seems reasonable
@@ -374,6 +395,11 @@ class CAR(Platforms):
HYUNDAI_SONATA.specs,
flags=HyundaiFlags.MANDO_RADAR | HyundaiFlags.CHECKSUM_CRC8 | HyundaiFlags.HYBRID,
)
HYUNDAI_SONATA_HEV_2024 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Sonata Hybrid (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
CarSpecs(mass=1616, wheelbase=2.84, steerRatio=13.27),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_IONIQ_5 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24", "All", car_parts=CarParts.common([CarHarness.hyundai_q])),
@@ -383,6 +409,11 @@ class CAR(Platforms):
CarSpecs(mass=1948, wheelbase=2.97, steerRatio=14.26, tireStiffnessFactor=0.65),
flags=HyundaiFlags.EV,
)
HYUNDAI_IONIQ_5_N = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Ioniq 5 N (with HDA II) 2024", car_parts=CarParts.common([CarHarness.hyundai_s]))],
CarSpecs(mass=2205, wheelbase=3.00, steerRatio=14.26, tireStiffnessFactor=1.3),
flags=HyundaiFlags.EV | HyundaiFlags.CCNC,
)
HYUNDAI_IONIQ_6 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Hyundai Ioniq 6 (without HDA II) 2023-24", "Highway Driving Assist", car_parts=CarParts.common([CarHarness.hyundai_l])),
@@ -400,11 +431,31 @@ class CAR(Platforms):
],
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
)
HYUNDAI_TUCSON_2025 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Tucson (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_TUCSON_HEV_2025 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Tucson Hybrid (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_n]))],
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_TUCSON_PHEV_2025 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Tucson Plug-in Hybrid (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
CarSpecs(mass=1630, wheelbase=2.756, steerRatio=13.7, tireStiffnessFactor=0.385),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_SANTA_CRUZ_1ST_GEN = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Santa Cruz 2022-24", car_parts=CarParts.common([CarHarness.hyundai_n]))],
# weight from Limited trim - the only supported trim, steering ratio according to Hyundai News https://www.hyundainews.com/assets/documents/original/48035-2022SantaCruzProductGuideSpecsv2081521.pdf
CarSpecs(mass=1870, wheelbase=3, steerRatio=14.2),
)
HYUNDAI_SANTA_CRUZ_2025 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Hyundai Santa Cruz (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_n]))],
CarSpecs(mass=1920, wheelbase=3, steerRatio=14.2),
flags=HyundaiFlags.CCNC,
)
HYUNDAI_CUSTIN_1ST_GEN = HyundaiPlatformConfig(
[HyundaiCarDocs("Hyundai Custin 2023", "All", car_parts=CarParts.common([CarHarness.hyundai_k]))],
CarSpecs(mass=1690, wheelbase=3.055, steerRatio=17), # mass: from https://www.hyundai-motor.com.tw/clicktobuy/custin#spec_0, steerRatio: from learner
@@ -419,11 +470,24 @@ class CAR(Platforms):
],
CarSpecs(mass=2878 * CV.LB_TO_KG, wheelbase=2.8, steerRatio=13.75, tireStiffnessFactor=0.5)
)
KIA_K4_2025 = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia K4 (without HDA II) 2025-26", car_parts=CarParts.common([CarHarness.hyundai_a])),
HyundaiCarDocs("Kia K4 (with HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_r])),
],
CarSpecs(mass=2987 * CV.LB_TO_KG, wheelbase=2.72, steerRatio=13.4),
flags=HyundaiFlags.CCNC,
)
KIA_K5_2021 = HyundaiPlatformConfig(
[HyundaiCarDocs("Kia K5 2021-24", car_parts=CarParts.common([CarHarness.hyundai_a]))],
CarSpecs(mass=3381 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27, tireStiffnessFactor=0.5), # 2021 Kia K5 Steering Ratio (all trims)
flags=HyundaiFlags.CHECKSUM_CRC8,
)
KIA_K5_2025 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Kia K5 (without HDA II) 2025", car_parts=CarParts.common([CarHarness.hyundai_m]))],
CarSpecs(mass=3230 * CV.LB_TO_KG, wheelbase=2.85, steerRatio=13.27),
flags=HyundaiFlags.CCNC,
)
KIA_K5_HEV_2020 = HyundaiPlatformConfig(
[HyundaiCarDocs("Kia K5 Hybrid 2020-22", car_parts=CarParts.common([CarHarness.hyundai_a]))],
KIA_K5_2021.specs,
@@ -534,6 +598,11 @@ class CAR(Platforms):
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5), # average of the platforms
flags=HyundaiFlags.CANFD_RADAR_SCC,
)
KIA_SORENTO_2024 = HyundaiCanFDPlatformConfig(
[HyundaiCarDocs("Kia Sorento (without HDA II) 2024-25", car_parts=CarParts.common([CarHarness.hyundai_a]))],
CarSpecs(mass=3957 * CV.LB_TO_KG, wheelbase=2.81, steerRatio=13.5),
flags=HyundaiFlags.CCNC,
)
KIA_SORENTO_HEV_4TH_GEN = HyundaiCanFDPlatformConfig(
[
HyundaiCarDocs("Kia Sorento Hybrid 2021-23", "All", car_parts=CarParts.common([CarHarness.hyundai_a])),
+12
View File
@@ -28,6 +28,9 @@ non_tested_cars = [
SUBARU.SUBARU_FORESTER_HYBRID,
VOLKSWAGEN.PORSCHE_MACAN_MK1,
HONDA.ACURA_TLX_2G,
HYUNDAI.KIA_SORENTO_2024,
HYUNDAI.HYUNDAI_IONIQ_5_N,
HYUNDAI.HYUNDAI_TUCSON_PHEV_2025,
# These had their DSUs unplugged, need new routes
# TOYOTA.LEXUS_ES # hybrid
@@ -166,6 +169,7 @@ routes = [
CarTestRoute("66eaa6c3b6b2afc6/00000009--3a5199aabe", HYUNDAI.GENESIS_G80_2ND_GEN_FL), # LKA steering
CarTestRoute("0bbe367c98fa1538/2023-09-16--00-16-49", HYUNDAI.HYUNDAI_CUSTIN_1ST_GEN),
CarTestRoute("f0709d2bc6ca451f/2022-10-15--08-13-54", HYUNDAI.HYUNDAI_SANTA_CRUZ_1ST_GEN),
CarTestRoute("6e7904b03a4aafc2/00000010--31034184b6", HYUNDAI.HYUNDAI_SANTA_CRUZ_2025),
CarTestRoute("4dbd55df87507948/2022-03-01--09-45-38", HYUNDAI.HYUNDAI_SANTA_FE),
CarTestRoute("bf43d9df2b660eb0/2021-09-23--14-16-37", HYUNDAI.HYUNDAI_SANTA_FE_2022),
CarTestRoute("37398f32561a23ad/2021-11-18--00-11-35", HYUNDAI.HYUNDAI_SANTA_FE_HEV_2022),
@@ -179,11 +183,14 @@ routes = [
CarTestRoute("6a42c1197b2a8179/2023-09-21--10-23-44", HYUNDAI.KIA_OPTIMA_H_G4_FL),
CarTestRoute("c75a59efa0ecd502/2021-03-11--20-52-55", HYUNDAI.KIA_SELTOS),
CarTestRoute("5b7c365c50084530/2020-04-15--16-13-24", HYUNDAI.HYUNDAI_SONATA),
CarTestRoute("4267ea8a353cdb36/00000262--8a427003c7", HYUNDAI.HYUNDAI_SONATA_2024, segment=34),
CarTestRoute("b2a38c712dcf90bd/2020-05-18--18-12-48", HYUNDAI.HYUNDAI_SONATA_LF),
CarTestRoute("c344fd2492c7a9d2/2023-12-11--09-03-23", HYUNDAI.HYUNDAI_STARIA_4TH_GEN),
CarTestRoute("fb3fd42f0baaa2f8/2022-03-30--15-25-05", HYUNDAI.HYUNDAI_TUCSON),
CarTestRoute("db68bbe12250812c/2022-12-05--00-54-12", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # 2023
CarTestRoute("36e10531feea61a4/2022-07-25--13-37-42", HYUNDAI.HYUNDAI_TUCSON_4TH_GEN), # hybrid
CarTestRoute("a01ca5d4f394c812/00000000--e98b7e4414", HYUNDAI.HYUNDAI_TUCSON_2025),
CarTestRoute("22f9090014364a87/00000002--4cc739c0b2", HYUNDAI.HYUNDAI_TUCSON_HEV_2025),
CarTestRoute("5875672fc1d4bf57/2020-07-23--21-33-28", HYUNDAI.KIA_SORENTO),
CarTestRoute("1d0d000db3370fd0/2023-01-04--22-28-42", HYUNDAI.KIA_SORENTO_4TH_GEN, segment=5),
CarTestRoute("fc19648042eb6896/2023-08-16--11-43-27", HYUNDAI.KIA_SORENTO_HEV_4TH_GEN, segment=14),
@@ -201,6 +208,8 @@ routes = [
CarTestRoute("ab59fe909f626921/2021-10-18--18-34-28", HYUNDAI.HYUNDAI_IONIQ_HEV_2022),
CarTestRoute("22d955b2cd499c22/2020-08-10--19-58-21", HYUNDAI.HYUNDAI_KONA),
CarTestRoute("0099bdb24d82951b/00000005--c38d940b04", HYUNDAI.HYUNDAI_KONA_2022),
CarTestRoute("32025f26789d8fab/00000022--a499e8ffa3", HYUNDAI.HYUNDAI_KONA_2ND_GEN),
CarTestRoute("97ca61196eb73e0d/00000052--4555329470", HYUNDAI.HYUNDAI_KONA_HEV_2ND_GEN),
CarTestRoute("efc48acf44b1e64d/2021-05-28--21-05-04", HYUNDAI.HYUNDAI_KONA_EV),
CarTestRoute("f90d3cd06caeb6fa/2023-09-06--17-15-47", HYUNDAI.HYUNDAI_KONA_EV), # openpilot longitudinal enabled
CarTestRoute("ff973b941a69366f/2022-07-28--22-01-19", HYUNDAI.HYUNDAI_KONA_EV_2022, segment=11),
@@ -214,7 +223,9 @@ routes = [
CarTestRoute("d545129f3ca90f28/2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # LKA steering
CarTestRoute("68d6a96e703c00c9/2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # LFA steering
CarTestRoute("9b25e8c1484a1b67/2023-04-13--10-41-45", HYUNDAI.KIA_EV6),
CarTestRoute("baf39eeaba1217ca/00000002--b36e3fa031", HYUNDAI.KIA_K4_2025),
CarTestRoute("007d5e4ad9f86d13/2021-09-30--15-09-23", HYUNDAI.KIA_K5_2021),
CarTestRoute("c4a804b067623789/0000007c--163f831540", HYUNDAI.KIA_K5_2025),
CarTestRoute("c58dfc9fc16590e0/2023-01-14--13-51-48", HYUNDAI.KIA_K5_HEV_2020),
CarTestRoute("74fbff45aa20fe9e/00000010--6f173d5799", HYUNDAI.KIA_K7_2017),
CarTestRoute("78ad5150de133637/2023-09-13--16-15-57", HYUNDAI.KIA_K8_HEV_1ST_GEN),
@@ -233,6 +244,7 @@ routes = [
CarTestRoute("82e9cdd3f43bf83e/2021-05-15--02-42-51", HYUNDAI.HYUNDAI_ELANTRA_2021),
CarTestRoute("715ac05b594e9c59/2021-06-20--16-21-07", HYUNDAI.HYUNDAI_ELANTRA_HEV_2021),
CarTestRoute("7120aa90bbc3add7/2021-08-02--07-12-31", HYUNDAI.HYUNDAI_SONATA_HYBRID),
CarTestRoute("bc40c72b728178f2/00000006--ee76ae8c42", HYUNDAI.HYUNDAI_SONATA_HEV_2024),
CarTestRoute("715ac05b594e9c59/2021-10-27--23-24-56", HYUNDAI.GENESIS_G70_2020),
CarTestRoute("6b0d44d22df18134/2023-05-06--10-36-55", HYUNDAI.GENESIS_GV80),
@@ -104,6 +104,13 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"JEEP_CHEROKEE_5TH_GEN" = [1.5, 1.5, 0.15]
"ACURA_MDX_4G" = [1.4, 1.4, 0.17]
"ACURA_RDX_3G_MMR" = [1.5, 1.5, 0.16]
"HYUNDAI_KONA_2ND_GEN" = [2.5, 2.5, 0.1]
"HYUNDAI_KONA_HEV_2ND_GEN" = [2.5, 2.5, 0.1]
"KIA_SORENTO_2024" = [2.5, 2.5, 0.1]
"KIA_K5_2025" = [2.5, 2.5, 0.1]
"KIA_K4_2025" = [2.5, 2.5, 0.1]
"HYUNDAI_SANTA_CRUZ_2025" = [2.5, 2.5, 0.1]
"HYUNDAI_IONIQ_5_N" = [2.5, 2.5, 0.005]
# Dashcam or fallback configured as ideal car
"MOCK" = [10.0, 10, 0.0]
@@ -45,6 +45,11 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"]
"GENESIS_G90" = "GENESIS_G70"
"GENESIS_G80" = "GENESIS_G70"
"GENESIS_G70_2020" = "HYUNDAI_SONATA"
"HYUNDAI_SONATA_2024" = "HYUNDAI_SONATA"
"HYUNDAI_SONATA_HEV_2024" = "HYUNDAI_SONATA_HYBRID"
"HYUNDAI_TUCSON_2025" = "HYUNDAI_TUCSON_4TH_GEN"
"HYUNDAI_TUCSON_HEV_2025" = "HYUNDAI_TUCSON_4TH_GEN"
"HYUNDAI_TUCSON_PHEV_2025" = "HYUNDAI_TUCSON_4TH_GEN"
"HONDA_FREED" = "HONDA_ODYSSEY"
"HONDA_CRV_EU" = "HONDA_CRV"
@@ -951,7 +951,7 @@ CM_ SG_ 1041 COUNTER_ALT "only increments on change";
CM_ BO_ 1043 "Lamp signals do not seem universal on cars that use LKAS_ALT, but stalk signals do.";
CM_ SG_ 1043 COUNTER_ALT "only increments on change";
CM_ SG_ 1043 USE_ALT_LAMP "likely 1 on cars that use alt lamp signals";
VAL_ 53 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 53 GEAR 0 "P" 4 "S" 5 "D" 6 "N" 7 "R";
VAL_ 64 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 69 GEAR 0 "P" 5 "D" 6 "N" 7 "R";
VAL_ 96 TRACTION_AND_STABILITY_CONTROL 0 "On" 5 "Limited" 1 "Off";
@@ -47,6 +47,11 @@
static bool hyundai_canfd_alt_buttons = false;
static bool hyundai_canfd_lka_steer_msg_alt = false;
static bool hyundai_ccnc = false;
static bool get_hyundai_ccnc(void) {
return hyundai_ccnc;
}
static unsigned int hyundai_canfd_get_lka_addr(void) {
return hyundai_canfd_lka_steer_msg_alt ? 0x110U : 0x50U;
@@ -227,6 +232,7 @@ 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_STEER_MSG_ALT = 128;
const uint16_t HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32;
const uint16_t HYUNDAI_PARAM_CCNC = 1024;
static const CanMsg HYUNDAI_CANFD_LKA_STEER_MSG_TX_MSGS[] = {
HYUNDAI_CANFD_LKA_STEER_MSG_COMMON_TX_MSGS(0, 1)
@@ -271,11 +277,21 @@ static safety_config hyundai_canfd_init(uint16_t param) {
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
{0x160, 0, 16, .check_relay = (longitudinal)}, /* ADRV_0x160 */ \
#define HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(longitudinal) \
HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) \
HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) \
HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(0, (longitudinal)) \
{0x161, 0, 32, .check_relay = true}, /* CCNC_0x161 */ \
{0x162, 0, 32, .check_relay = true}, /* CCNC_0x162 */ \
{0x7C4, 2, 8, .check_relay = true}, /* 0x7C4 */ \
{0xEA, 2, 24, .check_relay = true}, /* MDPS */ \
hyundai_common_init(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_steer_msg_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEER_MSG_ALT);
hyundai_ccnc = GET_FLAG(param, HYUNDAI_PARAM_CCNC);
safety_config ret;
if (hyundai_longitudinal) {
@@ -300,6 +316,10 @@ static safety_config hyundai_canfd_init(uint16_t param) {
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(true)
};
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(true)
};
if (hyundai_canfd_alt_buttons) {
SET_RX_CHECKS(hyundai_canfd_alt_buttons_long_rx_checks, ret);
} else {
@@ -307,7 +327,11 @@ static safety_config hyundai_canfd_init(uint16_t param) {
}
if (hyundai_camera_scc) {
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
if (get_hyundai_ccnc()) {
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
} else {
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
}
} else {
SET_TX_MSGS(HYUNDAI_CANFD_LFA_STEERING_LONG_TX_MSGS, ret);
}
@@ -368,7 +392,15 @@ static safety_config hyundai_canfd_init(uint16_t param) {
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_TX_MSGS(false)
};
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
static CanMsg hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs[] = {
HYUNDAI_CANFD_LFA_STEERING_CAMERA_SCC_CCNC_TX_MSGS(false)
};
if (get_hyundai_ccnc()) {
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_ccnc_tx_msgs, ret);
} else {
SET_TX_MSGS(hyundai_canfd_lfa_steering_camera_scc_tx_msgs, ret);
}
if (hyundai_canfd_alt_buttons) {
SET_RX_CHECKS(hyundai_canfd_alt_buttons_rx_checks, ret);
@@ -21,6 +21,13 @@ ALL_GAS_EV_HYBRID_COMBOS = [
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
]
ALL_GAS_EV_HYBRID_COMBOS_CCNC = [
# Camera SCC
{"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.CAMERA_SCC},
{"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CAMERA_SCC},
{"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiSafetyFlags.HYBRID_GAS | HyundaiSafetyFlags.CAMERA_SCC},
]
class TestHyundaiCanfdBase(HyundaiButtonBase, common.CarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest):
@@ -308,5 +315,73 @@ class TestHyundaiCanfdLFASteeringLongAltButtons(TestHyundaiCanfdLFASteeringLongB
pass
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS_CCNC)
class TestHyundaiCanfdLFASteeringCCNC(TestHyundaiCanfdLFASteeringBase):
TX_MSGS = [[0x12A, 0], [0x1E0, 0], [0x1CF, 2], [0x7C4, 2]]
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x161, 0x162), 2: (0x7C4, 0xEA)}
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0, 0x161, 0x162], 0: [0x7C4, 0xEA]}
@classmethod
def setUpClass(cls):
if cls.__name__ == "TestHyundaiCanfdLFASteeringCCNC":
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CCNC | self.SAFETY_PARAM)
self.safety.init_tests()
def test_ccnc(self):
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x161", self.STEER_BUS, {})))
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x162", self.STEER_BUS, {})))
def test_tx_hook_on_wrong_safety_mode(self):
from opendbc.safety.tests.common import make_msg
import importlib
for test_name in ["TestElm327"]:
mod = importlib.import_module("opendbc.safety.tests.test_" + test_name.replace("Test", "").lower())
tx_list = [m for m in getattr(mod, test_name).TX_MSGS if m[0] != 0x7C4] # skip overlapping 0x7C4 from Elm327
for addr, bus in tx_list:
if [addr, bus] not in self.TX_MSGS:
self.assertFalse(self._tx(make_msg(bus, addr)), f"allowed TX {addr=:#x} {bus=}")
@parameterized_class(ALL_GAS_EV_HYBRID_COMBOS_CCNC)
class TestHyundaiCanfdLFASteeringLongCCNC(TestHyundaiCanfdLFASteeringLongBase):
TX_MSGS = [[0x12A, 0], [0x1E0, 0], [0x1CF, 2], [0x7C4, 2], [0x1A0, 0]]
RELAY_MALFUNCTION_ADDRS = {0: (0x12A, 0x1E0, 0x161, 0x162, 0x1A0), 2: (0x7C4, 0xEA)}
FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0, 0x161, 0x162, 0x1A0], 0: [0x7C4, 0xEA]}
@classmethod
def setUpClass(cls):
if cls.__name__ == "TestHyundaiCanfdLFASteeringLongCCNC":
cls.safety = None
raise unittest.SkipTest
def setUp(self):
self.packer = CANPackerSafety("hyundai_canfd_generated")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, HyundaiSafetyFlags.CCNC | HyundaiSafetyFlags.LONG | self.SAFETY_PARAM)
self.safety.init_tests()
def test_ccnc(self):
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x161", self.STEER_BUS, {})))
self.assertTrue(self._tx(self.packer.make_can_msg_safety("CCNC_0x162", self.STEER_BUS, {})))
def test_tx_hook_on_wrong_safety_mode(self):
from opendbc.safety.tests.common import make_msg
import importlib
for test_name in ["TestElm327"]:
mod = importlib.import_module("opendbc.safety.tests.test_" + test_name.replace("Test", "").lower())
tx_list = [m for m in getattr(mod, test_name).TX_MSGS if m[0] != 0x7C4] # skip overlapping 0x7C4 from Elm327
for addr, bus in tx_list:
if [addr, bus] not in self.TX_MSGS:
self.assertFalse(self._tx(make_msg(bus, addr)), f"allowed TX {addr=:#x} {bus=}")
if __name__ == "__main__":
unittest.main()
@@ -1604,6 +1604,16 @@
],
"package": "Highway Driving Assist"
},
"Hyundai Ioniq 5 N (with HDA II) 2024": {
"platform": "HYUNDAI_IONIQ_5_N",
"make": "Hyundai",
"brand": "hyundai",
"model": "Ioniq 5 N (with HDA II)",
"year": [
"2024"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Ioniq 6 (with HDA II) 2023-24": {
"platform": "HYUNDAI_IONIQ_6",
"make": "Hyundai",
@@ -1713,6 +1723,17 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona (without HDA II) 2024-25": {
"platform": "HYUNDAI_KONA_2ND_GEN",
"make": "Hyundai",
"brand": "hyundai",
"model": "Kona (without HDA II)",
"year": [
"2024",
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona Electric 2018-21": {
"platform": "HYUNDAI_KONA_EV",
"make": "Hyundai",
@@ -1747,6 +1768,16 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona Electric (without HDA II) 2024": {
"platform": "HYUNDAI_KONA_EV_2ND_GEN",
"make": "Hyundai",
"brand": "hyundai",
"model": "Kona Electric (without HDA II)",
"year": [
"2024"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona Electric Non-SCC 2019": {
"platform": "HYUNDAI_KONA_EV_NON_SCC",
"make": "Hyundai",
@@ -1767,6 +1798,16 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona Hybrid (without HDA II) 2024": {
"platform": "HYUNDAI_KONA_HEV_2ND_GEN",
"make": "Hyundai",
"brand": "hyundai",
"model": "Kona Hybrid (without HDA II)",
"year": [
"2024"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Kona Non-SCC 2019": {
"platform": "HYUNDAI_KONA_NON_SCC",
"make": "Hyundai",
@@ -1811,6 +1852,16 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Santa Cruz (without HDA II) 2025": {
"platform": "HYUNDAI_SANTA_CRUZ_2025",
"make": "Hyundai",
"brand": "hyundai",
"model": "Santa Cruz (without HDA II)",
"year": [
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Santa Fe 2019-20": {
"platform": "HYUNDAI_SANTA_FE",
"make": "Hyundai",
@@ -1880,6 +1931,17 @@
],
"package": "All"
},
"Hyundai Sonata (without HDA II) 2024-25": {
"platform": "HYUNDAI_SONATA_2024",
"make": "Hyundai",
"brand": "hyundai",
"model": "Sonata (without HDA II)",
"year": [
"2024",
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Sonata Hybrid 2020-23": {
"platform": "HYUNDAI_SONATA_HYBRID",
"make": "Hyundai",
@@ -1893,6 +1955,17 @@
],
"package": "All"
},
"Hyundai Sonata Hybrid (without HDA II) 2024-25": {
"platform": "HYUNDAI_SONATA_HEV_2024",
"make": "Hyundai",
"brand": "hyundai",
"model": "Sonata Hybrid (without HDA II)",
"year": [
"2024",
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Staria 2023": {
"platform": "HYUNDAI_STARIA_4TH_GEN",
"make": "Hyundai",
@@ -1934,6 +2007,17 @@
],
"package": "All"
},
"Hyundai Tucson (without HDA II) 2025-26": {
"platform": "HYUNDAI_TUCSON_2025",
"make": "Hyundai",
"brand": "hyundai",
"model": "Tucson (without HDA II)",
"year": [
"2025",
"2026"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Tucson Diesel 2019": {
"platform": "HYUNDAI_TUCSON",
"make": "Hyundai",
@@ -1956,6 +2040,17 @@
],
"package": "All"
},
"Hyundai Tucson Hybrid (without HDA II) 2025-26": {
"platform": "HYUNDAI_TUCSON_HEV_2025",
"make": "Hyundai",
"brand": "hyundai",
"model": "Tucson Hybrid (without HDA II)",
"year": [
"2025",
"2026"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Tucson Plug-in Hybrid 2024": {
"platform": "HYUNDAI_TUCSON_4TH_GEN",
"make": "Hyundai",
@@ -1966,6 +2061,16 @@
],
"package": "All"
},
"Hyundai Tucson Plug-in Hybrid (without HDA II) 2025": {
"platform": "HYUNDAI_TUCSON_PHEV_2025",
"make": "Hyundai",
"brand": "hyundai",
"model": "Tucson Plug-in Hybrid (without HDA II)",
"year": [
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Hyundai Veloster 2019-20": {
"platform": "HYUNDAI_VELOSTER",
"make": "Hyundai",
@@ -2114,6 +2219,27 @@
],
"package": "No Smart Cruise Control (Non-SCC)"
},
"Kia K4 (with HDA II) 2025": {
"platform": "KIA_K4_2025",
"make": "Kia",
"brand": "hyundai",
"model": "K4 (with HDA II)",
"year": [
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia K4 (without HDA II) 2025-26": {
"platform": "KIA_K4_2025",
"make": "Kia",
"brand": "hyundai",
"model": "K4 (without HDA II)",
"year": [
"2025",
"2026"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia K5 2021-24": {
"platform": "KIA_K5_2021",
"make": "Kia",
@@ -2127,6 +2253,16 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Kia K5 (without HDA II) 2025": {
"platform": "KIA_K5_2025",
"make": "Kia",
"brand": "hyundai",
"model": "K5 (without HDA II)",
"year": [
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia K5 Hybrid 2020-22": {
"platform": "KIA_K5_HEV_2020",
"make": "Kia",
@@ -2377,6 +2513,17 @@
],
"package": "Smart Cruise Control (SCC)"
},
"Kia Sorento (without HDA II) 2024-25": {
"platform": "KIA_SORENTO_2024",
"make": "Kia",
"brand": "hyundai",
"model": "Sorento (without HDA II)",
"year": [
"2024",
"2025"
],
"package": "Smart Cruise Control (SCC)"
},
"Kia Sorento Hybrid 2021-23": {
"platform": "KIA_SORENTO_HEV_4TH_GEN",
"make": "Kia",
-2
View File
@@ -69,8 +69,6 @@ struct LeadData {
struct SelfdriveStateSP @0x81c2f05a394cf4af {
mads @0 :ModularAssistiveDrivingSystem;
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
buttonsPressed @2 :UInt16;
buttonsReleaseToggle @3 :UInt16;
enum AudibleAlert {
none @0;
+14 -47
View File
@@ -636,17 +636,17 @@ const ::capnp::_::RawSchema s_f488e435979fe1ff = {
0, 16, i_f488e435979fe1ff, nullptr, nullptr, { &s_f488e435979fe1ff, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
static const ::capnp::_::AlignedData<56> b_81c2f05a394cf4af = {
{ 0, 0, 0, 0, 5, 0, 6, 0,
175, 244, 76, 57, 90, 240, 194, 129,
13, 0, 0, 0, 1, 0, 1, 0,
13, 0, 0, 0, 1, 0, 0, 0,
89, 10, 85, 29, 102, 186, 38, 181,
2, 0, 7, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
21, 0, 0, 0, 242, 0, 0, 0,
33, 0, 0, 0, 23, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
45, 0, 0, 0, 231, 0, 0, 0,
45, 0, 0, 0, 119, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
99, 117, 115, 116, 111, 109, 46, 99,
@@ -658,35 +658,21 @@ static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
1, 0, 0, 0, 106, 0, 0, 0,
65, 117, 100, 105, 98, 108, 101, 65,
108, 101, 114, 116, 0, 0, 0, 0,
16, 0, 0, 0, 3, 0, 4, 0,
8, 0, 0, 0, 3, 0, 4, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
97, 0, 0, 0, 42, 0, 0, 0,
41, 0, 0, 0, 42, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
92, 0, 0, 0, 3, 0, 1, 0,
104, 0, 0, 0, 2, 0, 1, 0,
36, 0, 0, 0, 3, 0, 1, 0,
48, 0, 0, 0, 2, 0, 1, 0,
1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
101, 0, 0, 0, 18, 1, 0, 0,
45, 0, 0, 0, 18, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
112, 0, 0, 0, 3, 0, 1, 0,
124, 0, 0, 0, 2, 0, 1, 0,
2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
121, 0, 0, 0, 122, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
120, 0, 0, 0, 3, 0, 1, 0,
132, 0, 0, 0, 2, 0, 1, 0,
3, 0, 0, 0, 1, 0, 0, 0,
0, 0, 1, 0, 3, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
129, 0, 0, 0, 170, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
132, 0, 0, 0, 3, 0, 1, 0,
144, 0, 0, 0, 2, 0, 1, 0,
56, 0, 0, 0, 3, 0, 1, 0,
68, 0, 0, 0, 2, 0, 1, 0,
109, 97, 100, 115, 0, 0, 0, 0,
16, 0, 0, 0, 0, 0, 0, 0,
143, 147, 68, 238, 187, 112, 77, 205,
@@ -705,25 +691,6 @@ static const ::capnp::_::AlignedData<89> b_81c2f05a394cf4af = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
16, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
98, 117, 116, 116, 111, 110, 115, 80,
114, 101, 115, 115, 101, 100, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
98, 117, 116, 116, 111, 110, 115, 82,
101, 108, 101, 97, 115, 101, 84, 111,
103, 103, 108, 101, 0, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
7, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, }
};
@@ -733,11 +700,11 @@ static const ::capnp::_::RawSchema* const d_81c2f05a394cf4af[] = {
&s_90a324fe70479956,
&s_cd4d70bbee44938f,
};
static const uint16_t m_81c2f05a394cf4af[] = {2, 3, 1, 0};
static const uint16_t i_81c2f05a394cf4af[] = {0, 1, 2, 3};
static const uint16_t m_81c2f05a394cf4af[] = {1, 0};
static const uint16_t i_81c2f05a394cf4af[] = {0, 1};
const ::capnp::_::RawSchema s_81c2f05a394cf4af = {
0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 89, d_81c2f05a394cf4af, m_81c2f05a394cf4af,
2, 4, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false
0x81c2f05a394cf4af, b_81c2f05a394cf4af.words, 56, d_81c2f05a394cf4af, m_81c2f05a394cf4af,
2, 2, i_81c2f05a394cf4af, nullptr, nullptr, { &s_81c2f05a394cf4af, nullptr, nullptr, 0, 0, nullptr }, false
};
#endif // !CAPNP_LITE
static const ::capnp::_::AlignedData<184> b_878e32a6bc486e3f = {
+1 -39
View File
@@ -320,7 +320,7 @@ struct SelfdriveStateSP {
struct _capnpPrivate {
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 1, 2)
CAPNP_DECLARE_STRUCT_HEADER(81c2f05a394cf4af, 0, 2)
#if !CAPNP_LITE
static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; }
#endif // !CAPNP_LITE
@@ -1327,10 +1327,6 @@ public:
inline bool hasIntelligentCruiseButtonManagement() const;
inline ::cereal::IntelligentCruiseButtonManagement::Reader getIntelligentCruiseButtonManagement() const;
inline ::uint16_t getButtonsPressed() const;
inline ::uint16_t getButtonsReleaseToggle() const;
private:
::capnp::_::StructReader _reader;
template <typename, ::capnp::Kind>
@@ -1373,12 +1369,6 @@ public:
inline void adoptIntelligentCruiseButtonManagement(::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement>&& value);
inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> disownIntelligentCruiseButtonManagement();
inline ::uint16_t getButtonsPressed();
inline void setButtonsPressed( ::uint16_t value);
inline ::uint16_t getButtonsReleaseToggle();
inline void setButtonsReleaseToggle( ::uint16_t value);
private:
::capnp::_::StructBuilder _builder;
template <typename, ::capnp::Kind>
@@ -5607,34 +5597,6 @@ inline ::capnp::Orphan< ::cereal::IntelligentCruiseButtonManagement> SelfdriveSt
::capnp::bounded<1>() * ::capnp::POINTERS));
}
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsPressed() const {
return _reader.getDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsPressed() {
return _builder.getDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS);
}
inline void SelfdriveStateSP::Builder::setButtonsPressed( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
::capnp::bounded<0>() * ::capnp::ELEMENTS, value);
}
inline ::uint16_t SelfdriveStateSP::Reader::getButtonsReleaseToggle() const {
return _reader.getDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline ::uint16_t SelfdriveStateSP::Builder::getButtonsReleaseToggle() {
return _builder.getDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS);
}
inline void SelfdriveStateSP::Builder::setButtonsReleaseToggle( ::uint16_t value) {
_builder.setDataField< ::uint16_t>(
::capnp::bounded<1>() * ::capnp::ELEMENTS, value);
}
inline bool ModelManagerSP::Reader::hasActiveBundle() const {
return !_reader.getPointerField(
::capnp::bounded<0>() * ::capnp::POINTERS).isNull();
-1
View File
@@ -222,7 +222,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TeslaMadsScreenButton", {PERSISTENT | BACKUP, INT, "0"}},
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaStopAndGoHack", {PERSISTENT | BACKUP, BOOL, "0"}},
Binary file not shown.
@@ -158,7 +158,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
def publish(self, sm, pm):
plan_send = messaging.new_message('longitudinalPlan')
plan_send.valid = sm.all_checks()
plan_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'selfdriveState', 'radarState'])
longitudinalPlan = plan_send.longitudinalPlan
longitudinalPlan.modelMonoTime = sm.logMonoTime['modelV2']
+4 -4
View File
@@ -29,19 +29,19 @@ def main():
longitudinal_planner = LongitudinalPlanner(CP, CP_SP)
pm = messaging.PubMaster(['longitudinalPlan', 'driverAssistance', 'longitudinalPlanSP'])
sm = messaging.SubMaster(['carControl', 'carState', 'controlsState', 'liveParameters', 'radarState', 'modelV2', 'selfdriveState',
'liveMapDataSP', 'carStateSP', 'selfdriveStateSP', gps_location_service],
poll='modelV2', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
'liveMapDataSP', 'carStateSP', gps_location_service],
poll='carState', ignore_alive=ignore_services, ignore_avg_freq=ignore_services, ignore_valid=ignore_services)
while True:
sm.update()
longitudinal_planner.sla.update_buttons(sm['selfdriveStateSP'].buttonsReleaseToggle)
longitudinal_planner.sla.update_car_state(sm['carState'])
if sm.updated['modelV2']:
longitudinal_planner.update(sm)
longitudinal_planner.publish(sm, pm)
ldw.update(sm.frame, sm['modelV2'], sm['carState'], sm['carControl'])
msg = messaging.new_message('driverAssistance')
msg.valid = sm.all_checks()
msg.valid = sm.all_checks(['carState', 'carControl', 'modelV2', 'liveParameters'])
msg.driverAssistance.leftLaneDeparture = ldw.left
msg.driverAssistance.rightLaneDeparture = ldw.right
pm.send('driverAssistance', msg)
Binary file not shown.
@@ -30,7 +30,6 @@ from openpilot.sunnypilot import get_sanitize_int_param
from openpilot.sunnypilot.selfdrive.car.car_specific import CarSpecificEventsSP
from openpilot.sunnypilot.selfdrive.car.cruise_helpers import CruiseHelper
from openpilot.sunnypilot.selfdrive.car.intelligent_cruise_button_management.controller import IntelligentCruiseButtonManagement
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
REPLAY = "REPLAY" in os.environ
@@ -178,7 +177,6 @@ class SelfdriveD(CruiseHelper):
self.car_events_sp = CarSpecificEventsSP(self.CP, self.CP_SP)
CruiseHelper.__init__(self, self.CP)
self.button_state_tracker = ButtonStateTracker()
def update_events(self, CS):
"""Compute onroadEvents from carState"""
@@ -599,8 +597,6 @@ class SelfdriveD(CruiseHelper):
icbm.sendButton = self.icbm.cruise_button
icbm.vTarget = self.icbm.v_target
self.button_state_tracker.publish(ss_sp)
self.pm.send('selfdriveStateSP', ss_sp_msg)
# onroadEventsSP - logged every second or on change
@@ -620,7 +616,6 @@ class SelfdriveD(CruiseHelper):
self.mads.update(CS)
self.update_alerts(CS)
self.button_state_tracker.update(CS)
self.publish_selfdriveState(CS)
self.CS_prev = CS
@@ -7,7 +7,7 @@ See the LICENSE.md file in the root directory for more details.
from collections.abc import Callable
import pyray as rl
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake
from openpilot.system.ui.lib.multilang import tr, tr_noop
@@ -96,10 +96,7 @@ class MadsSettingsLayout(Widget):
if brand == "rivian":
return True
elif brand == "tesla":
if ui_state.CP_SP is None or not ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
return True
screen_button = int(ui_state.params.get("TeslaMadsScreenButton", return_default=True))
return screen_button == MadsScreenButtonType.OFF
return not (ui_state.CP_SP is not None and ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
return False
def _update_steering_mode_description(self, button_index: int):
@@ -4,11 +4,10 @@ Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
from openpilot.selfdrive.ui.sunnypilot.layouts.settings.vehicle.brands.base import BrandSettings
from openpilot.selfdrive.ui.ui_state import ui_state
from openpilot.system.ui.lib.multilang import tr
from openpilot.system.ui.sunnypilot.widgets.list_view import multiple_button_item_sp, toggle_item_sp
from openpilot.system.ui.sunnypilot.widgets.list_view import toggle_item_sp
COOP_STEERING_MIN_KMH = 23
OEM_STEERING_MIN_KMH = 48
@@ -19,14 +18,7 @@ class TeslaSettings(BrandSettings):
def __init__(self):
super().__init__()
self.coop_steering_toggle = toggle_item_sp(tr("Cooperative Steering (Beta)"), "", param="TeslaCoopSteering")
self.mads_screen_button = multiple_button_item_sp(
title=lambda: tr("MADS Screen Activation"),
description="",
buttons=[lambda: tr("Off"), lambda: tr("3-Finger"), lambda: tr("4-Finger"), lambda: tr("5-Finger")],
param="TeslaMadsScreenButton",
inline=False,
)
self.items = [self.coop_steering_toggle, self.mads_screen_button]
self.items = [self.coop_steering_toggle]
def update_settings(self):
is_metric = ui_state.is_metric
@@ -49,18 +41,3 @@ class TeslaSettings(BrandSettings):
self.coop_steering_toggle.set_description(coop_steering_desc)
self.coop_steering_toggle.action_item.set_enabled(ui_state.is_offroad())
has_vehicle_bus = ui_state.CP_SP is not None and bool(ui_state.CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS)
self.mads_screen_button.set_visible(has_vehicle_bus)
mads_screen_button_desc = (
f"{tr('Use a multi-finger press on the infotainment screen to toggle MADS.')} " +
f"{tr('This allows the use of full MADS functionality when enabled.')}<br><br>" +
f"{tr('Selecting a higher finger count may reduce accidental activations.')}<br><br>" +
f"<b>{tr('Note: Setting this to Off will reset your MADS settings to default.')}</b>"
)
if not ui_state.is_offroad():
mads_screen_button_disabled_msg = tr("Enable \"Always Offroad\" in Device panel, or turn vehicle off to change.")
mads_screen_button_desc = f"<b>{mads_screen_button_disabled_msg}</b><br><br>{mads_screen_button_desc}"
self.mads_screen_button.set_description(mads_screen_button_desc)
self.mads_screen_button.action_item.set_enabled(ui_state.is_offroad())
+1 -1
View File
@@ -1 +1 @@
#define SUNNYPILOT_VERSION "2026.08.02-4605"
#define SUNNYPILOT_VERSION "2026.07.27-4598"
+5 -8
View File
@@ -9,7 +9,7 @@ from openpilot.common.params import Params
from opendbc.car import structs
from opendbc.safety import ALTERNATIVE_EXPERIENCE
from opendbc.sunnypilot.car.hyundai.values import HyundaiFlagsSP, HyundaiSafetyFlagsSP
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
MADS_NO_ACC_MAIN_BUTTON = ("rivian", "tesla")
@@ -21,20 +21,17 @@ class MadsSteeringModeOnBrake:
DISENGAGE = 2
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params) -> bool:
def get_mads_limited_brands(CP: structs.CarParams, CP_SP: structs.CarParamsSP) -> bool:
if CP.brand == 'rivian':
return True
if CP.brand == 'tesla':
if not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS:
return True
screen_button = int(params.get("TeslaMadsScreenButton", return_default=True))
return screen_button == MadsScreenButtonType.OFF
return not CP_SP.flags & TeslaFlagsSP.HAS_VEHICLE_BUS
return False
def read_steering_mode_param(CP: structs.CarParams, CP_SP: structs.CarParamsSP, params: Params):
if get_mads_limited_brands(CP, CP_SP, params):
if get_mads_limited_brands(CP, CP_SP):
return MadsSteeringModeOnBrake.DISENGAGE
return params.get("MadsSteeringMode", return_default=True)
@@ -66,7 +63,7 @@ def set_car_specific_params(CP: structs.CarParams, CP_SP: structs.CarParamsSP, p
# MADS is currently partially supported for these platforms due to lack of consistent states to engage controls
# Only MadsSteeringModeOnBrake.DISENGAGE is supported for these platforms
# TODO-SP: To enable MADS full support for Rivian and most Tesla, identify consistent signals for MADS toggling
mads_partial_support = get_mads_limited_brands(CP, CP_SP, params)
mads_partial_support = get_mads_limited_brands(CP, CP_SP)
if mads_partial_support:
params.put("MadsSteeringMode", 2, block=True)
params.put_bool("MadsUnifiedEngagementMode", True, block=True)
@@ -13,7 +13,7 @@ from openpilot.selfdrive.selfdrived.events import Events
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
from openpilot.sunnypilot.mads.helpers import MadsSteeringModeOnBrake, read_steering_mode_param
from openpilot.sunnypilot.mads.mads import ModularAssistiveDrivingSystem
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType, TeslaFlagsSP
from opendbc.sunnypilot.car.tesla.values import TeslaFlagsSP
State = custom.ModularAssistiveDrivingSystem.ModularAssistiveDrivingSystemState
EventName = log.OnroadEvent.EventName
@@ -38,12 +38,6 @@ def make_panda_state(mocker, controls_allowed_lateral=True):
return ps
def make_params_mock(mocker, values):
params = mocker.MagicMock()
params.get = mocker.MagicMock(side_effect=lambda k, **kwargs: values[k])
return params
def make_mads(mocker, steering_mode):
sd = mocker.MagicMock()
sd.CP = structs.CarParams()
@@ -229,27 +223,15 @@ class TestBrandSteeringModeRestrictions:
params = mocker.MagicMock()
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
@pytest.mark.parametrize("screen_button", [MadsScreenButtonType.THREE_FINGER,
MadsScreenButtonType.FOUR_FINGER,
MadsScreenButtonType.FIVE_FINGER])
def test_tesla_with_vehicle_bus_uses_param(self, mocker, screen_button):
def test_tesla_with_vehicle_bus_uses_param(self, mocker):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
params = make_params_mock(mocker, {"TeslaMadsScreenButton": screen_button,
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
params = mocker.MagicMock()
params.get = mocker.MagicMock(return_value=MadsSteeringModeOnBrake.REMAIN_ACTIVE)
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.REMAIN_ACTIVE
def test_tesla_with_vehicle_bus_screen_button_off_forced_to_disengage(self, mocker):
CP = structs.CarParams()
CP.brand = "tesla"
CP_SP = structs.CarParamsSP()
CP_SP.flags = TeslaFlagsSP.HAS_VEHICLE_BUS
params = make_params_mock(mocker, {"TeslaMadsScreenButton": MadsScreenButtonType.OFF,
"MadsSteeringMode": MadsSteeringModeOnBrake.REMAIN_ACTIVE})
assert read_steering_mode_param(CP, CP_SP, params) == MadsSteeringModeOnBrake.DISENGAGE
@pytest.mark.parametrize("brand", ["hyundai", "toyota", "honda", "gm"])
def test_other_brands_use_param(self, mocker, brand):
CP = structs.CarParams()
@@ -123,7 +123,6 @@ def initialize_params(params) -> list[dict[str, Any]]:
# tesla
keys.extend([
"TeslaCoopSteering",
"TeslaMadsScreenButton",
])
# toyota
@@ -91,7 +91,7 @@ class SpeedLimitAssist:
self._plus_hold = 0.
self._minus_hold = 0.
self._release_toggle_prev = 0
self._last_carstate_ts = 0.
# TODO-SP: SLA's own output_a_target for planner
# Solution functions mapped to respective states
@@ -146,16 +146,16 @@ class SpeedLimitAssist:
set_speed_limit_assist_availability(self.CP, self.CP_SP, self.params)
self.enabled = self.params.get("SpeedLimitMode", return_default=True) == Mode.assist
def update_buttons(self, release_toggle: int) -> None:
released = self._release_toggle_prev ^ release_toggle
self._release_toggle_prev = release_toggle
if not released:
return
def update_car_state(self, CS: car.CarState) -> None:
now = time.monotonic()
if any((released >> b) & 1 for b in CRUISE_BUTTONS_PLUS):
self._plus_hold = max(self._plus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
if any((released >> b) & 1 for b in CRUISE_BUTTONS_MINUS):
self._minus_hold = max(self._minus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
self._last_carstate_ts = now
for b in CS.buttonEvents:
if not b.pressed:
if b.type in CRUISE_BUTTONS_PLUS:
self._plus_hold = max(self._plus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
elif b.type in CRUISE_BUTTONS_MINUS:
self._minus_hold = max(self._minus_hold, now + CRUISE_BUTTON_CONFIRM_HOLD)
def _get_button_release(self, req_plus: bool, req_minus: bool) -> bool:
now = time.monotonic()
@@ -5,14 +5,11 @@ This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import time
import pytest
from openpilot.cereal import custom
from opendbc.car.car_helpers import interfaces
from opendbc.car.rivian.values import CAR as RIVIAN
from opendbc.car.structs import car
from opendbc.car.tesla.values import CAR as TESLA
from opendbc.car.toyota.values import CAR as TOYOTA
from openpilot.common.constants import CV
@@ -24,13 +21,9 @@ from openpilot.sunnypilot.selfdrive.car import interfaces as sunnypilot_interfac
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit import PCM_LONG_REQUIRED_MAX_SET_SPEED
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.common import Mode
from openpilot.sunnypilot.selfdrive.controls.lib.speed_limit.speed_limit_assist import SpeedLimitAssist, \
PRE_ACTIVE_GUARD_PERIOD, ACTIVE_STATES, CRUISE_BUTTON_CONFIRM_HOLD
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
PRE_ACTIVE_GUARD_PERIOD, ACTIVE_STATES
from openpilot.sunnypilot.selfdrive.selfdrived.events import EventsSP
ButtonEvent = car.CarState.ButtonEvent
ButtonType = car.CarState.ButtonEvent.Type
SpeedLimitAssistState = custom.LongitudinalPlanSP.SpeedLimit.AssistState
ALL_STATES = tuple(SpeedLimitAssistState.schema.enumerants.values())
@@ -283,86 +276,3 @@ class TestSpeedLimitAssist:
assert self.sla.state in [SpeedLimitAssistState.preActive, SpeedLimitAssistState.active]
elif initial_state in ACTIVE_STATES:
assert self.sla.state in ACTIVE_STATES
class TestButtonStateTrackerSLAIntegration:
def setup_method(self, method):
self.tracker = ButtonStateTracker()
self.params = Params()
self.params.put("IsReleaseSpBranch", True, block=True)
self.params.put("SpeedLimitMode", int(Mode.assist), block=True)
self.params.put_bool("IsMetric", False, block=True)
self.params.put("SpeedLimitOffsetType", 0, block=True)
self.params.put("SpeedLimitValueOffset", 0, block=True)
CarInterface = interfaces[DEFAULT_CAR]
CP = CarInterface.get_non_essential_params(DEFAULT_CAR)
CP.openpilotLongitudinalControl = True
CP_SP = CarInterface.get_non_essential_params_sp(CP, DEFAULT_CAR)
self.sla = SpeedLimitAssist(CP, CP_SP)
def _make_cs(self, events=None) -> car.CarState:
CS = car.CarState()
CS.buttonEvents = events or []
return CS
def _run_ctrl_frames(self, frames: list[car.CarState]) -> None:
for cs in frames:
self.tracker.update(cs)
def test_button_confirm_via_tracker(self) -> None:
self._run_ctrl_frames([
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]),
self._make_cs(),
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]),
self._make_cs(),
self._make_cs(),
])
self.sla.update_buttons(self.tracker.release_toggle)
assert self.sla._get_button_release(req_plus=True, req_minus=False)
def test_rapid_press_release_between_polls(self) -> None:
self.sla.update_buttons(self.tracker.release_toggle)
self._run_ctrl_frames([
self._make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=True)]),
self._make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=False)]),
self._make_cs(),
self._make_cs(),
self._make_cs(),
])
self.sla.update_buttons(self.tracker.release_toggle)
assert self.sla._get_button_release(req_plus=False, req_minus=True)
def test_multiple_releases_between_polls(self) -> None:
self.sla.update_buttons(self.tracker.release_toggle)
self._run_ctrl_frames([
self._make_cs([
ButtonEvent(type=ButtonType.accelCruise, pressed=True),
ButtonEvent(type=ButtonType.decelCruise, pressed=True),
]),
self._make_cs([
ButtonEvent(type=ButtonType.accelCruise, pressed=False),
ButtonEvent(type=ButtonType.decelCruise, pressed=False),
]),
])
self.sla.update_buttons(self.tracker.release_toggle)
assert self.sla._get_button_release(req_plus=True, req_minus=False)
assert self.sla._get_button_release(req_plus=False, req_minus=True)
def test_no_false_positive_same_toggle(self) -> None:
self.sla.update_buttons(self.tracker.release_toggle)
self.sla.update_buttons(self.tracker.release_toggle)
assert not self.sla._get_button_release(req_plus=True, req_minus=False)
assert not self.sla._get_button_release(req_plus=False, req_minus=True)
def test_button_confirm_expires(self) -> None:
self._run_ctrl_frames([
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]),
self._make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]),
])
self.sla.update_buttons(self.tracker.release_toggle)
time.sleep(CRUISE_BUTTON_CONFIRM_HOLD + 0.1)
assert not self.sla._get_button_release(req_plus=True, req_minus=False)
Binary file not shown.
@@ -1,26 +0,0 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.car import structs
class ButtonStateTracker:
def __init__(self) -> None:
self.pressed: int = 0
self.release_toggle: int = 0
def update(self, CS: structs.CarState) -> None:
for b in CS.buttonEvents:
bit = 1 << b.type.raw
if b.pressed:
self.pressed |= bit
else:
self.pressed &= ~bit
self.release_toggle ^= bit
def publish(self, ss_sp) -> None:
ss_sp.buttonsPressed = self.pressed
ss_sp.buttonsReleaseToggle = self.release_toggle
@@ -1,67 +0,0 @@
"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
from opendbc.car.structs import car
from openpilot.sunnypilot.selfdrive.selfdrived.button_state_tracker import ButtonStateTracker
ButtonEvent = car.CarState.ButtonEvent
ButtonType = car.CarState.ButtonEvent.Type
class TestButtonStateTracker:
def setup_method(self) -> None:
self.tracker = ButtonStateTracker()
def make_cs(self, events: list) -> car.CarState:
CS = car.CarState()
CS.buttonEvents = events
return CS
def test_initial_state(self) -> None:
assert self.tracker.pressed == 0
assert self.tracker.release_toggle == 0
def test_press_sets_bit(self) -> None:
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
assert self.tracker.pressed == (1 << ButtonType.accelCruise)
assert self.tracker.release_toggle == 0
def test_release_clears_and_toggles(self) -> None:
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
assert self.tracker.pressed == 0
assert self.tracker.release_toggle == (1 << ButtonType.accelCruise)
def test_multiple_buttons(self) -> None:
self.tracker.update(self.make_cs([
ButtonEvent(type=ButtonType.accelCruise, pressed=True),
ButtonEvent(type=ButtonType.decelCruise, pressed=True),
]))
assert self.tracker.pressed == (1 << ButtonType.accelCruise) | (1 << ButtonType.decelCruise)
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
assert self.tracker.pressed == (1 << ButtonType.decelCruise)
assert self.tracker.release_toggle == (1 << ButtonType.accelCruise)
def test_release_toggle_flips(self) -> None:
for _ in range(2):
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.gapAdjustCruise, pressed=True)]))
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.gapAdjustCruise, pressed=False)]))
assert self.tracker.release_toggle == 0
def test_publish(self) -> None:
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=True)]))
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.decelCruise, pressed=True)]))
self.tracker.update(self.make_cs([ButtonEvent(type=ButtonType.accelCruise, pressed=False)]))
class MockSP:
buttonsPressed = 0
buttonsReleaseToggle = 0
sp = MockSP()
self.tracker.publish(sp)
assert sp.buttonsPressed == self.tracker.pressed
assert sp.buttonsReleaseToggle == self.tracker.release_toggle
@@ -2161,42 +2161,6 @@
"type": "offroad_only"
}
]
},
{
"key": "TeslaMadsScreenButton",
"widget": "multiple_button",
"title": "MADS Screen Activation",
"description": "Use a multi-finger press on the infotainment screen to toggle MADS. This allows the use of full MADS functionality when enabled. Selecting a higher finger count may reduce accidental activations. Note: Setting this to Off will reset your MADS settings to default.",
"options": [
{
"value": 0,
"label": "Off"
},
{
"value": 1,
"label": "3-Finger"
},
{
"value": 2,
"label": "4-Finger"
},
{
"value": 3,
"label": "5-Finger"
}
],
"visibility": [
{
"type": "capability",
"field": "tesla_has_vehicle_bus",
"equals": true
}
],
"enablement": [
{
"type": "offroad_only"
}
]
}
]
},
@@ -56,28 +56,6 @@ sections:
title: Cooperative Steering (Beta)
enablement:
- $ref: '#/macros/offroad'
- key: TeslaMadsScreenButton
widget: multiple_button
title: MADS Screen Activation
description: 'Use a multi-finger press on the infotainment screen to toggle MADS.
This allows the use of full MADS functionality when enabled. Selecting a higher
finger count may reduce accidental activations. Note: Setting this to Off will
reset your MADS settings to default.'
options:
- value: 0
label: 'Off'
- value: 1
label: 3-Finger
- value: 2
label: 4-Finger
- value: 3
label: 5-Finger
visibility:
- type: capability
field: tesla_has_vehicle_bus
equals: true
enablement:
- $ref: '#/macros/offroad'
- id: toyota
title: Toyota / Lexus Settings
description: ''
@@ -17,26 +17,6 @@ ONROAD_BRIGHTNESS_TIMER_VALUES = {0: 3, 1: 5, 2: 7, 3: 10, 4: 15, 5: 30, **{i: (
VALID_TIMER_VALUES = set(ONROAD_BRIGHTNESS_TIMER_VALUES.values())
def _resolve_brand(_params) -> str:
bundle = _params.get("CarPlatformBundle")
if isinstance(bundle, dict) and bundle.get("brand"):
return str(bundle["brand"])
# Auto-fingerprinted cars have no bundle, fall back to the last known CarParams.
CP_bytes = _params.get("CarParamsPersistent")
if CP_bytes is None:
return ""
# Never raises: callers rely on "" to mean "brand unknown, skip the migration".
try:
from openpilot.cereal import messaging # lazy: avoids heavy import at module level
from opendbc.car.structs import car
return str(messaging.log_from_bytes(CP_bytes, car.CarParams).brand)
except Exception as e:
cloudlog.exception(f"params_migration: failed to resolve brand from CarParamsPersistent: {e}")
return ""
def _migrate_car_platform_bundle(_params):
bundle = _params.get("CarPlatformBundle")
if bundle is None:
@@ -67,23 +47,6 @@ def _migrate_car_platform_bundle(_params):
cloudlog.info(f"params_migration: CarPlatformBundle migrated {old_platform!r} -> {new_platform!r}")
def _migrate_tesla_mads_screen_button(_params):
# TeslaMadsScreenButton defaults to Off for fresh installs, but the screen button was previously always
# active on Teslas with a vehicle bus. Seed existing Tesla installs with 3-finger to preserve that.
try:
if _params.get("TeslaMadsScreenButton") is not None:
return
if _resolve_brand(_params) != "tesla":
return
from opendbc.sunnypilot.car.tesla.values import MadsScreenButtonType # lazy: avoids heavy import at module level
_params.put("TeslaMadsScreenButton", MadsScreenButtonType.THREE_FINGER, block=True)
cloudlog.info("params_migration: seeded TeslaMadsScreenButton with 3-finger to preserve existing behavior")
except Exception as e:
cloudlog.exception(f"Error migrating TeslaMadsScreenButton: {e}")
def run_migration(_params):
# migrate OnroadScreenOffBrightness
if _params.get("OnroadScreenOffBrightnessMigrated") != ONROAD_BRIGHTNESS_MIGRATION_VERSION:
@@ -117,6 +80,3 @@ def run_migration(_params):
cloudlog.exception(f"Error migrating OnroadScreenOffTimer: {e}")
_migrate_car_platform_bundle(_params)
# seed TeslaMadsScreenButton for existing Tesla installs
_migrate_tesla_mads_screen_button(_params)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.