from opendbc . car import Bus , get_safety_config , structs
from opendbc . car . hyundai . hyundaicanfd import CanBus
from opendbc . car . hyundai . values import HyundaiFlags , CAR , DBC , \
CANFD_UNSUPPORTED_LONGITUDINAL_CAR , \
UNSUPPORTED_LONGITUDINAL_CAR , HyundaiSafetyFlags
from opendbc . car . hyundai . radar_interface import RADAR_START_ADDR
from opendbc . car . interfaces import CarInterfaceBase
from opendbc . car . disable_ecu import disable_ecu
from opendbc . car . hyundai . carcontroller import CarController
from opendbc . car . hyundai . carstate import CarState
from opendbc . car . hyundai . radar_interface import RadarInterface
ButtonType = structs . CarState . ButtonEvent . Type
Ecu = structs . CarParams . Ecu
# Cancel button can sometimes be ACC pause/resume button, main button can also enable on some cars
ENABLE_BUTTONS = ( ButtonType . accelCruise , ButtonType . decelCruise , ButtonType . cancel , ButtonType . mainCruise )
class CarInterface ( CarInterfaceBase ) :
CarState = CarState
CarController = CarController
RadarInterface = RadarInterface
@staticmethod
def _get_params ( ret : structs . CarParams , candidate , fingerprint , car_fw , alpha_long , docs ) - > structs . CarParams :
ret . brand = " hyundai "
cam_can = CanBus ( None , fingerprint ) . CAM
lka_steering = 0x50 in fingerprint [ cam_can ] or 0x110 in fingerprint [ cam_can ]
CAN = CanBus ( None , fingerprint , lka_steering )
if ret . flags & HyundaiFlags . CANFD :
# Shared configuration for CAN-FD cars
ret . alphaLongitudinalAvailable = candidate not in CANFD_UNSUPPORTED_LONGITUDINAL_CAR
if lka_steering and Ecu . adas not in [ fw . ecu for fw in car_fw ] :
# this needs to be figured out for cars without an ADAS ECU
ret . alphaLongitudinalAvailable = False
ret . enableBsm = 0x1e5 in fingerprint [ CAN . ECAN ]
# Check if the car is hybrid. Only HEV/PHEV cars have 0xFA on E-CAN.
if 0xFA in fingerprint [ CAN . ECAN ] :
ret . flags | = HyundaiFlags . HYBRID . value
if lka_steering :
# detect LKA steering
ret . flags | = HyundaiFlags . CANFD_LKA_STEERING . value
if 0x110 in fingerprint [ CAN . CAM ] :
ret . flags | = HyundaiFlags . CANFD_LKA_STEERING_ALT . value
else :
# no LKA steering
if 0x1cf not in fingerprint [ CAN . ECAN ] :
ret . flags | = HyundaiFlags . CANFD_ALT_BUTTONS . value
if not ret . flags & HyundaiFlags . RADAR_SCC :
ret . flags | = HyundaiFlags . CANFD_CAMERA_SCC . value
# Some LKA steering cars have alternative messages for gear checks
# ICE cars do not have 0x130; GEARS message on 0x40 or 0x70 instead
if 0x130 not in fingerprint [ CAN . ECAN ] :
if 0x40 not in fingerprint [ CAN . ECAN ] :
ret . flags | = HyundaiFlags . CANFD_ALT_GEARS_2 . value
else :
ret . flags | = HyundaiFlags . CANFD_ALT_GEARS . value
cfgs = [ get_safety_config ( structs . CarParams . SafetyModel . hyundaiCanfd ) , ]
if CAN . ECAN > = 4 :
cfgs . insert ( 0 , get_safety_config ( structs . CarParams . SafetyModel . noOutput ) )
ret . safetyConfigs = cfgs
if ret . flags & HyundaiFlags . CANFD_LKA_STEERING :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . CANFD_LKA_STEERING . value
if ret . flags & HyundaiFlags . CANFD_LKA_STEERING_ALT :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . CANFD_LKA_STEERING_ALT . value
if ret . flags & HyundaiFlags . CANFD_ALT_BUTTONS :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . CANFD_ALT_BUTTONS . value
if ret . flags & HyundaiFlags . CANFD_CAMERA_SCC :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . CAMERA_SCC . value
else :
# Shared configuration for non CAN-FD cars
ret . alphaLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR
ret . enableBsm = 0x58b in fingerprint [ 0 ]
# Send LFA message on cars with HDA
if 0x485 in fingerprint [ 2 ] :
ret . flags | = HyundaiFlags . SEND_LFA . value
# These cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
if 0x38d in fingerprint [ 0 ] or 0x38d in fingerprint [ 2 ] :
ret . flags | = HyundaiFlags . USE_FCA . value
if ret . flags & HyundaiFlags . LEGACY :
# these cars require a special panda safety mode due to missing counters and checksums in the messages
ret . safetyConfigs = [ get_safety_config ( structs . CarParams . SafetyModel . hyundaiLegacy ) ]
else :
ret . safetyConfigs = [ get_safety_config ( structs . CarParams . SafetyModel . hyundai , 0 ) ]
if ret . flags & HyundaiFlags . CAMERA_SCC :
ret . safetyConfigs [ 0 ] . safetyParam | = HyundaiSafetyFlags . CAMERA_SCC . value
# These cars have the LFA button on the steering wheel
if 0x391 in fingerprint [ 0 ] :
ret . flags | = HyundaiFlags . HAS_LDA_BUTTON . value
# Common lateral control setup
ret . centerToFront = ret . wheelbase * 0.4
ret . steerActuatorDelay = 0.1
ret . steerLimitTimer = 0.4
CarInterfaceBase . configure_torque_tune ( candidate , ret . lateralTuning )
if ret . flags & HyundaiFlags . ALT_LIMITS :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . ALT_LIMITS . value
if ret . flags & HyundaiFlags . ALT_LIMITS_2 :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . ALT_LIMITS_2 . value
# see https://github.com/commaai/opendbc/pull/1137/
ret . dashcamOnly = True
# Common longitudinal control setup
ret . radarUnavailable = RADAR_START_ADDR not in fingerprint [ 1 ] or Bus . radar not in DBC [ ret . carFingerprint ]
ret . openpilotLongitudinalControl = alpha_long and ret . alphaLongitudinalAvailable
ret . pcmCruise = not ret . openpilotLongitudinalControl
ret . startingState = True
ret . vEgoStarting = 0.1
ret . startAccel = 1.0
ret . longitudinalActuatorDelay = 0.5
if ret . openpilotLongitudinalControl :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . LONG . value
if ret . flags & HyundaiFlags . HYBRID :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . HYBRID_GAS . value
elif ret . flags & HyundaiFlags . EV :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . EV_GAS . value
elif ret . flags & HyundaiFlags . FCEV :
ret . safetyConfigs [ - 1 ] . safetyParam | = HyundaiSafetyFlags . FCEV_GAS . value
# Car specific configuration overrides
if candidate == CAR . KIA_OPTIMA_G4_FL :
ret . steerActuatorDelay = 0.2
# Dashcam cars are missing a test route, or otherwise need validation
# TODO: Optima Hybrid 2017 uses a different SCC12 checksum
ret . dashcamOnly = candidate in { CAR . KIA_OPTIMA_H , }
return ret
@staticmethod
def init ( CP , can_recv , can_send ) :
if CP . openpilotLongitudinalControl and not ( CP . flags & ( HyundaiFlags . CANFD_CAMERA_SCC | HyundaiFlags . CAMERA_SCC ) ) :
addr , bus = 0x7d0 , CanBus ( CP ) . ECAN if CP . flags & HyundaiFlags . CANFD else 0
if CP . flags & HyundaiFlags . CANFD_LKA_STEERING . value :
addr , bus = 0x730 , CanBus ( CP ) . ECAN
disable_ecu ( can_recv , can_send , bus = bus , addr = addr , com_cont_req = b ' \x28 \x83 \x01 ' )
# for blinkers
if CP . flags & HyundaiFlags . ENABLE_BLINKERS :
disable_ecu ( can_recv , can_send , bus = CanBus ( CP ) . ECAN , addr = 0x7B1 , com_cont_req = b ' \x28 \x83 \x01 ' )