#!/usr/bin/env python3
from cereal import car
from selfdrive . config import Conversions as CV
from selfdrive . controls . lib . drive_helpers import EventTypes as ET , create_event
from selfdrive . car . hyundai . values import Ecu , ECU_FINGERPRINT , CAR , get_hud_alerts , FINGERPRINTS
from selfdrive . car import STD_CARGO_KG , scale_rot_inertia , scale_tire_stiffness , is_ecu_disconnected , gen_empty_fingerprint
from selfdrive . car . interfaces import CarInterfaceBase
GearShifter = car . CarState . GearShifter
ButtonType = car . CarState . ButtonEvent . Type
class CarInterface ( CarInterfaceBase ) :
def __init__ ( self , CP , CarController , CarState ) :
super ( ) . __init__ ( CP , CarController , CarState )
self . idx = 0
self . lanes = 0
self . lkas_request = 0
self . low_speed_alert = False
@staticmethod
def compute_gb ( accel , speed ) :
return float ( accel ) / 3.0
@staticmethod
def get_params ( candidate , fingerprint = gen_empty_fingerprint ( ) , has_relay = False , car_fw = [ ] ) :
ret = car . CarParams . new_message ( )
ret . carName = " hyundai "
ret . carFingerprint = candidate
ret . isPandaBlack = has_relay
ret . radarOffCan = True
ret . safetyModel = car . CarParams . SafetyModel . hyundai
ret . enableCruise = True # stock acc
ret . steerActuatorDelay = 0.1 # Default delay
ret . steerRateCost = 0.5
ret . steerLimitTimer = 0.4
tire_stiffness_factor = 1.
if candidate == CAR . SANTA_FE :
ret . lateralTuning . pid . kf = 0.00005
ret . mass = 3982. * CV . LB_TO_KG + STD_CARGO_KG
ret . wheelbase = 2.766
# Values from optimizer
ret . steerRatio = 16.55 # 13.8 is spec end-to-end
tire_stiffness_factor = 0.82
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 9. , 22. ] , [ 9. , 22. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.2 , 0.35 ] , [ 0.05 , 0.09 ] ]
ret . minSteerSpeed = 0.
elif candidate == CAR . KIA_SORENTO :
ret . lateralTuning . pid . kf = 0.00005
ret . mass = 1985. + STD_CARGO_KG
ret . wheelbase = 2.78
ret . steerRatio = 14.4 * 1.1 # 10% higher at the center seems reasonable
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 0. ] , [ 0. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.25 ] , [ 0.05 ] ]
ret . minSteerSpeed = 0.
elif candidate == CAR . ELANTRA :
ret . lateralTuning . pid . kf = 0.00006
ret . mass = 1275. + STD_CARGO_KG
ret . wheelbase = 2.7
ret . steerRatio = 13.73 #Spec
tire_stiffness_factor = 0.385
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 0. ] , [ 0. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.25 ] , [ 0.05 ] ]
ret . minSteerSpeed = 32 * CV . MPH_TO_MS
elif candidate == CAR . GENESIS :
ret . lateralTuning . pid . kf = 0.00005
ret . mass = 2060. + STD_CARGO_KG
ret . wheelbase = 3.01
ret . steerRatio = 16.5
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 0. ] , [ 0. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.16 ] , [ 0.01 ] ]
ret . minSteerSpeed = 35 * CV . MPH_TO_MS
elif candidate == CAR . KIA_OPTIMA :
ret . lateralTuning . pid . kf = 0.00005
ret . mass = 3558. * CV . LB_TO_KG
ret . wheelbase = 2.80
ret . steerRatio = 13.75
tire_stiffness_factor = 0.5
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 0. ] , [ 0. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.25 ] , [ 0.05 ] ]
elif candidate == CAR . KIA_STINGER :
ret . lateralTuning . pid . kf = 0.00005
ret . mass = 1825. + STD_CARGO_KG
ret . wheelbase = 2.78
ret . steerRatio = 14.4 * 1.15 # 15% higher at the center seems reasonable
ret . lateralTuning . pid . kiBP , ret . lateralTuning . pid . kpBP = [ [ 0. ] , [ 0. ] ]
ret . lateralTuning . pid . kpV , ret . lateralTuning . pid . kiV = [ [ 0.25 ] , [ 0.05 ] ]
ret . minSteerSpeed = 0.
ret . minEnableSpeed = - 1. # enable is done by stock ACC, so ignore this
ret . longitudinalTuning . kpBP = [ 0. ]
ret . longitudinalTuning . kpV = [ 0. ]
ret . longitudinalTuning . kiBP = [ 0. ]
ret . longitudinalTuning . kiV = [ 0. ]
ret . longitudinalTuning . deadzoneBP = [ 0. ]
ret . longitudinalTuning . deadzoneV = [ 0. ]
ret . centerToFront = ret . wheelbase * 0.4
# TODO: get actual value, for now starting with reasonable value for
# civic and scaling by mass and wheelbase
ret . rotationalInertia = scale_rot_inertia ( ret . mass , ret . wheelbase )
# TODO: start from empirically derived lateral slip stiffness for the civic and scale by
# mass and CG position, so all cars will have approximately similar dyn behaviors
ret . tireStiffnessFront , ret . tireStiffnessRear = scale_tire_stiffness ( ret . mass , ret . wheelbase , ret . centerToFront ,
tire_stiffness_factor = tire_stiffness_factor )
# no rear steering, at least on the listed cars above
ret . steerRatioRear = 0.
ret . steerControlType = car . CarParams . SteerControlType . torque
# steer, gas, brake limitations VS speed
ret . steerMaxBP = [ 0. ]
ret . steerMaxV = [ 1.0 ]
ret . gasMaxBP = [ 0. ]
ret . gasMaxV = [ 1. ]
ret . brakeMaxBP = [ 0. ]
ret . brakeMaxV = [ 1. ]
ret . enableCamera = is_ecu_disconnected ( fingerprint [ 0 ] , FINGERPRINTS , ECU_FINGERPRINT , candidate , Ecu . fwdCamera ) or has_relay
ret . openpilotLongitudinalControl = False
ret . stoppingControl = False
ret . startAccel = 0.0
return ret
def update ( self , c , can_strings ) :
self . cp . update_strings ( can_strings )
self . cp_cam . update_strings ( can_strings )
ret = self . CS . update ( self . cp , self . cp_cam )
ret . canValid = self . cp . can_valid and self . cp_cam . can_valid
# TODO: button presses
ret . buttonEvents = [ ]
# low speed steer alert hysteresis logic (only for cars with steer cut off above 10 m/s)
if ret . vEgo < ( self . CP . minSteerSpeed + 2. ) and self . CP . minSteerSpeed > 10. :
self . low_speed_alert = True
if ret . vEgo > ( self . CP . minSteerSpeed + 4. ) :
self . low_speed_alert = False
events = [ ]
if not ret . gearShifter == GearShifter . drive :
events . append ( create_event ( ' wrongGear ' , [ ET . NO_ENTRY , ET . SOFT_DISABLE ] ) )
if ret . doorOpen :
events . append ( create_event ( ' doorOpen ' , [ ET . NO_ENTRY , ET . SOFT_DISABLE ] ) )
if ret . seatbeltUnlatched :
events . append ( create_event ( ' seatbeltNotLatched ' , [ ET . NO_ENTRY , ET . SOFT_DISABLE ] ) )
if self . CS . esp_disabled :
events . append ( create_event ( ' espDisabled ' , [ ET . NO_ENTRY , ET . SOFT_DISABLE ] ) )
if not ret . cruiseState . available :
events . append ( create_event ( ' wrongCarMode ' , [ ET . NO_ENTRY , ET . USER_DISABLE ] ) )
if ret . gearShifter == GearShifter . reverse :
events . append ( create_event ( ' reverseGear ' , [ ET . NO_ENTRY , ET . IMMEDIATE_DISABLE ] ) )
if self . CS . steer_error :
events . append ( create_event ( ' steerTempUnavailable ' , [ ET . NO_ENTRY , ET . WARNING ] ) )
if ret . cruiseState . enabled and not self . cruise_enabled_prev :
events . append ( create_event ( ' pcmEnable ' , [ ET . ENABLE ] ) )
elif not ret . cruiseState . enabled :
events . append ( create_event ( ' pcmDisable ' , [ ET . USER_DISABLE ] ) )
# disable on pedals rising edge or when brake is pressed and speed isn't zero
if ( ret . gasPressed and not self . gas_pressed_prev ) or \
( ret . brakePressed and ( not self . brake_pressed_prev or ret . vEgoRaw > 0.1 ) ) :
events . append ( create_event ( ' pedalPressed ' , [ ET . NO_ENTRY , ET . USER_DISABLE ] ) )
if ret . gasPressed :
events . append ( create_event ( ' pedalPressed ' , [ ET . PRE_ENABLE ] ) )
if self . low_speed_alert :
events . append ( create_event ( ' belowSteerSpeed ' , [ ET . WARNING ] ) )
ret . events = events
self . gas_pressed_prev = ret . gasPressed
self . brake_pressed_prev = ret . brakePressed
self . cruise_enabled_prev = ret . cruiseState . enabled
self . CS . out = ret . as_reader ( )
return self . CS . out
def apply ( self , c ) :
hud_alert = get_hud_alerts ( c . hudControl . visualAlert )
can_sends = self . CC . update ( c . enabled , self . CS , c . actuators ,
c . cruiseControl . cancel , hud_alert )
return can_sends