from openpilot.common.numpy_fast import clip from openpilot.selfdrive.car import CanBusBase from openpilot.selfdrive.car.hyundai.values import HyundaiFlags from openpilot.common.params import Params class CanBus(CanBusBase): def __init__(self, CP, hda2=None, fingerprint=None) -> None: super().__init__(CP, fingerprint) if hda2 is None: assert CP is not None hda2 = CP.flags & HyundaiFlags.CANFD_HDA2.value # On the CAN-FD platforms, the LKAS camera is on both A-CAN and E-CAN. HDA2 cars # have a different harness than the HDA1 and non-HDA variants in order to split # a different bus, since the steering is done by different ECUs. self._a, self._e = 1, 0 if hda2: self._a, self._e = 0, 1 self._a += self.offset self._e += self.offset self._cam = 2 + self.offset @property def ECAN(self): return self._e @property def ACAN(self): return self._a @property def CAM(self): return self._cam def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_steer): # Im sure there is a better way to do this params_memory = Params("/dev/shm/params") no_lat_lane_change = params_memory.get_int("no_lat_lane_change", 1) ret = [] values = { "LKA_MODE": 2, "LKA_ICON": 0 if no_lat_lane_change else 2 if enabled else 1 if lat_active else 0, # right mode icon "TORQUE_REQUEST": apply_steer, "LKA_ASSIST": 0, "STEER_REQ": 1 if lat_active else 0, "STEER_MODE": 0, "HAS_LANE_SAFETY": 0, # hide LKAS settings "NEW_SIGNAL_1": 0, "NEW_SIGNAL_2": 0, } if CP.flags & HyundaiFlags.CANFD_HDA2: hda2_lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_HDA2_ALT_STEERING else "LKAS" if CP.openpilotLongitudinalControl: ret.append(packer.make_can_msg("LFA", CAN.ECAN, values)) ret.append(packer.make_can_msg(hda2_lkas_msg, CAN.ACAN, values)) else: ret.append(packer.make_can_msg("LFA", CAN.ECAN, values)) return ret def create_suppress_lfa(packer, CAN, hda2_lfa_block_msg, hda2_alt_steering): suppress_msg = "CAM_0x362" if hda2_alt_steering else "CAM_0x2a4" msg_bytes = 32 if hda2_alt_steering else 24 values = {f"BYTE{i}": hda2_lfa_block_msg[f"BYTE{i}"] for i in range(3, msg_bytes) if i != 7} values["COUNTER"] = hda2_lfa_block_msg["COUNTER"] values["SET_ME_0"] = 0 values["SET_ME_0_2"] = 0 values["LEFT_LANE_LINE"] = 0 values["RIGHT_LANE_LINE"] = 0 return packer.make_can_msg(suppress_msg, CAN.ACAN, values) def create_buttons(packer, CP, CAN, cnt, btn): values = { "COUNTER": cnt, "SET_ME_1": 1, "CRUISE_BUTTONS": btn, } bus = CAN.ECAN if CP.flags & HyundaiFlags.CANFD_HDA2 else CAN.CAM return packer.make_can_msg("CRUISE_BUTTONS", bus, values) # null # {'CHECKSUM': [], 'COUNTER': [], 'NEW_SIGNAL_1': [], 'SET_ME_1': [], 'DISTANCE_UNIT': [], # 'NEW_SIGNAL_2': [], 'ADAPT # IVE_CRUISE_MAIN_BTN': [], 'NEW_SIGNAL_3': [], 'LFA_BTN': [], 'CRUISE_BUTTONS': [], # 'NEW_SIGNAL_4': [], 'NORMAL_CRUI # SE_MAIN_BTN': [], 'NEW_SIGNAL_5': [], 'SET_ME_2': [], 'NEW_SIGNAL_6': [], 'BYTE6': [], # 'BYTE7': [], 'BYTE8': [], 'B # YTE9': [], 'BYTE10': [], 'BYTE11': [], 'BYTE12': [], 'BYTE13': [], 'BYTE14': [], # 'BYTE15': []} # holding down up button # {'CHECKSUM': [5774.0], 'COUNTER': [63.0], 'NEW_SIGNAL_1': [0.0], 'SET_ME_1': # [0.0], 'DISTANCE_UNIT': [1.0], 'NEW_SIGNAL_2': [4.0], 'ADAPTIVE_CRUISE_MAIN_BTN': # [0.0], 'NEW_SIGNAL_3': [0.0], 'LFA_BTN': [0.0], 'CRUISE_BUTTONS': [1.0], # 'NEW_SIGNAL_4': [0.0], 'NORMAL_CRUISE_MAIN_BTN': [0.0], 'NEW_SIGNAL_5': [0.0], # 'SET_ME_2': [2.0], 'NEW_SIGNAL_6': [1.0], 'BYTE6': [32.0], 'BYTE7': [0.0], # 'BYTE8': [26.0], 'BYTE9': [0.0], 'BYTE10': [0.0], 'BYTE11': [0.0], 'BYTE12': # [0.0], 'BYTE13': [0.0], 'BYTE14': [0.0], 'BYTE15': [0.0]} # {'CHECKSUM': [14783.0], 'COUNTER': [150.0], 'NEW_SIGNAL_1': [0.0], # 'SET_ME_1': [0.0], 'DISTANCE_UNIT': [1.0], 'NEW_ # SIGNAL_2': [6.0], 'ADAPTIVE_CRUISE_MAIN_BTN': [0.0], 'NEW_SIGNAL_3': [0.0], # 'LFA_BTN': [0.0], 'CRUISE_BUTTONS': [1. # 0], 'NEW_SIGNAL_4': [0.0], 'NORMAL_CRUISE_MAIN_BTN': [0.0], 'NEW_SIGNAL_5': # [0.0], 'SET_ME_2': [2.0], 'NEW_SIGNAL_6 # ': [1.0], 'BYTE6': [37.0], 'BYTE7': [0.0], 'BYTE8': [30.0], 'BYTE9': [0.0], # 'BYTE10': [0.0], 'BYTE11': [0.0], 'BYTE # 12': [0.0], 'BYTE13': [0.0], 'BYTE14': [0.0], 'BYTE15': [0.0]} # {'CHECKSUM': [61602.0], 'COUNTER': [153.0], 'NEW_SIGNAL_1': [0.0], 'SET_ME_1': # [0.0], 'DISTANCE_UNIT': [1.0], 'NEW_ # SIGNAL_2': [0.0], 'ADAPTIVE_CRUISE_MAIN_BTN': [0.0], 'NEW_SIGNAL_3': [0.0], # 'LFA_BTN': [1.0], 'CRUISE_BUTTONS': [1. # 0], 'NEW_SIGNAL_4': [0.0], 'NORMAL_CRUISE_MAIN_BTN': [0.0], 'NEW_SIGNAL_5': # [0.0], 'SET_ME_2': [2.0], 'NEW_SIGNAL_6 # ': [1.0], 'BYTE6': [38.0], 'BYTE7': [0.0], 'BYTE8': [31.0], 'BYTE9': [0.0], # 'BYTE10': [0.0], 'BYTE11': [0.0], 'BYTE # 12': [0.0], 'BYTE13': [0.0], 'BYTE14': [0.0], 'BYTE15': [0.0]} def create_buttons_alt(packer, CP, CAN, cnt, btn, template): params_memory = Params("/dev/shm/params") self.params_memory.get_float("CarCruiseDisplayActual") values = { "COUNTER": cnt, "NEW_SIGNAL_1": 0.0, "DISTANCE_UNIT": 1.0, "SET_ME_1": 0.0, "NEW_SIGNAL_2": 0.0, "ADAPTIVE_CRUISE_MAIN_BTN": 0.0, "NEW_SIGNAL_3": 0.0, "CRUISE_BUTTONS": 1.0, #btn * 1.0, "NEW_SIGNAL_4": 0.0, "NORMAL_CRUISE_MAIN_BTN": 0.0, "NEW_SIGNAL_5": 0.0, "SET_ME_2": 2.0, "NEW_SIGNAL_5": 1.0, "BYTE_6": CarCruiseDisplayActual+1, # Target "BYTE_7": 0.0, "BYTE_8": CarCruiseDisplayActual, # Current cruise sets "BYTE_9": 0.0, "BYTE_10": 0.0, "BYTE_11": 0.0, "BYTE_12": 0.0, "BYTE_13": 0.0, "BYTE_14": 0.0, "BYTE_15": 0.0, } bus = CAN.ECAN # if CP.flags & HyundaiFlags.CANFD_HDA2 else CAN.CAM return packer.make_can_msg("CRUISE_BUTTONS_ALT", bus, values) # def create_buttons_alt(packer, CP, CAN, cnt, btn, template): # template.update({ # "CRUISE_BUTTONS": btn # }) # bus = CAN.ECAN # if CP.flags & HyundaiFlags.CANFD_HDA2 else CAN.CAM # return packer.make_can_msg("CRUISE_BUTTONS_ALT", bus, template) def create_acc_set_speed(packer, CP, CAN, cruise_info_copy, speed): # why are we executing this at all? # TODO: why do we copy different values here? if CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value: values = {s: cruise_info_copy[s] for s in [ "COUNTER", "CHECKSUM", "NEW_SIGNAL_1", "MainMode_ACC", "ACCMode", "ZEROS_9", "CRUISE_STANDSTILL", "ZEROS_5", "DISTANCE_SETTING", "VSetDis", ]} else: values = {s: cruise_info_copy[s] for s in [ "COUNTER", "CHECKSUM", "ACCMode", "VSetDis", "CRUISE_STANDSTILL", ]} values.update({ "ACCMode": 1, # testing 1 instead of 4 "VSetDis": speed }) return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) def create_acc_cancel(packer, CP, CAN, cruise_info_copy): # This does nothing on the tucson # TODO: why do we copy different values here? if CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value: values = {s: cruise_info_copy[s] for s in [ "COUNTER", "CHECKSUM", "NEW_SIGNAL_1", "MainMode_ACC", "ACCMode", "ZEROS_9", "CRUISE_STANDSTILL", "ZEROS_5", "DISTANCE_SETTING", "VSetDis", ]} else: values = {s: cruise_info_copy[s] for s in [ "COUNTER", "CHECKSUM", "ACCMode", "VSetDis", "CRUISE_STANDSTILL", ]} values.update({ "ACCMode": 4, # testing 1 instead of 4 "aReqRaw": 0.0, "aReqValue": 0.0, }) return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) # CLEARPILOT changed HDA icons # This doesn't appear to do anything on my tucson def create_lfahda_cluster(packer, CAN, enabled, lat_active): values = { "HDA_ICON": 0, # Literally shows HDA. Maybe we use this to indicate experimental mode "LFA_ICON": 2 if enabled else 1 if lat_active else 0 } return packer.make_can_msg("LFAHDA_CLUSTER", CAN.ECAN, values) def create_acc_control(packer, CAN, enabled, accel_last, accel, stopping, gas_override, set_speed, hud_control): jerk = 5 jn = jerk / 50 if not enabled or gas_override: a_val, a_raw = 0, 0 else: a_raw = accel a_val = clip(accel, accel_last - jn, accel_last + jn) values = { "ACCMode": 0 if not enabled else (2 if gas_override else 1), "MainMode_ACC": 1, "StopReq": 1 if stopping else 0, "aReqValue": a_val, "aReqRaw": a_raw, "VSetDis": set_speed, "JerkLowerLimit": jerk if enabled else 1, "JerkUpperLimit": 3.0, "ACC_ObjDist": 1, "ObjValid": 0, "OBJ_STATUS": 2, "SET_ME_2": 0x4, "SET_ME_3": 0x3, "SET_ME_TMP_64": 0x64, "DISTANCE_SETTING": hud_control.leadDistanceBars, } return packer.make_can_msg("SCC_CONTROL", CAN.ECAN, values) # Disabled blinker messages def create_spas_messages(packer, CAN, frame, left_blink, right_blink): ret = [] return ret values = { } ret.append(packer.make_can_msg("SPAS1", CAN.ECAN, values)) blink = 0 if left_blink: blink = 3 elif right_blink: blink = 4 values = { "BLINKER_CONTROL": blink, } ret.append(packer.make_can_msg("SPAS2", CAN.ECAN, values)) return ret def create_adrv_messages(packer, CAN, frame): # messages needed to car happy after disabling # the ADAS Driving ECU to do longitudinal control ret = [] values = { } ret.append(packer.make_can_msg("ADRV_0x51", CAN.ACAN, values)) if frame % 2 == 0: values = { 'AEB_SETTING': 0x1, # show AEB disabled icon 'SET_ME_2': 0x2, 'SET_ME_FF': 0xff, 'SET_ME_FC': 0xfc, 'SET_ME_9': 0x9, } ret.append(packer.make_can_msg("ADRV_0x160", CAN.ECAN, values)) if frame % 5 == 0: values = { 'SET_ME_1C': 0x1c, 'SET_ME_FF': 0xff, 'SET_ME_TMP_F': 0xf, 'SET_ME_TMP_F_2': 0xf, } ret.append(packer.make_can_msg("ADRV_0x1ea", CAN.ECAN, values)) values = { 'SET_ME_E1': 0xe1, 'SET_ME_3A': 0x3a, } ret.append(packer.make_can_msg("ADRV_0x200", CAN.ECAN, values)) if frame % 20 == 0: values = { 'SET_ME_15': 0x15, } ret.append(packer.make_can_msg("ADRV_0x345", CAN.ECAN, values)) if frame % 100 == 0: values = { 'SET_ME_22': 0x22, 'SET_ME_41': 0x41, } ret.append(packer.make_can_msg("ADRV_0x1da", CAN.ECAN, values)) return ret