from cereal import car
from panda import Panda
from panda . python import uds
from openpilot . selfdrive . car . toyota . values import Ecu , CAR , DBC , ToyotaFlags , CarControllerParams , TSS2_CAR , RADAR_ACC_CAR , NO_DSU_CAR , \
MIN_ACC_SPEED , EPS_SCALE , UNSUPPORTED_DSU_CAR , NO_STOP_TIMER_CAR , ANGLE_CONTROL_CAR
from openpilot . selfdrive . car import create_button_events , get_safety_config
from openpilot . selfdrive . car . disable_ecu import disable_ecu
from openpilot . selfdrive . car . interfaces import CarInterfaceBase
ButtonType = car . CarState . ButtonEvent . Type
EventName = car . CarEvent . EventName
SteerControlType = car . CarParams . SteerControlType
class CarInterface ( CarInterfaceBase ) :
@staticmethod
def get_pid_accel_limits ( CP , current_speed , cruise_speed ) :
return CarControllerParams . ACCEL_MIN , CarControllerParams . ACCEL_MAX
@staticmethod
def _get_params ( ret , candidate , fingerprint , car_fw , experimental_long , docs ) :
ret . carName = " toyota "
ret . safetyConfigs = [ get_safety_config ( car . CarParams . SafetyModel . toyota ) ]
ret . safetyConfigs [ 0 ] . safetyParam = EPS_SCALE [ candidate ]
# BRAKE_MODULE is on a different address for these cars
if DBC [ candidate ] [ " pt " ] == " toyota_new_mc_pt_generated " :
ret . safetyConfigs [ 0 ] . safetyParam | = Panda . FLAG_TOYOTA_ALT_BRAKE
if candidate in ANGLE_CONTROL_CAR :
ret . steerControlType = SteerControlType . angle
ret . safetyConfigs [ 0 ] . safetyParam | = Panda . FLAG_TOYOTA_LTA
# LTA control can be more delayed and winds up more often
ret . steerActuatorDelay = 0.18
ret . steerLimitTimer = 0.8
else :
CarInterfaceBase . configure_torque_tune ( candidate , ret . lateralTuning )
ret . steerActuatorDelay = 0.12 # Default delay, Prius has larger delay
ret . steerLimitTimer = 0.4
ret . stoppingControl = False # Toyota starts braking more when it thinks you want to stop
stop_and_go = candidate in TSS2_CAR
# In TSS2 cars, the camera does long control
found_ecus = [ fw . ecu for fw in car_fw ]
ret . enableDsu = len ( found_ecus ) > 0 and Ecu . dsu not in found_ecus and candidate not in ( NO_DSU_CAR | UNSUPPORTED_DSU_CAR )
if candidate == CAR . TOYOTA_PRIUS :
stop_and_go = True
# Only give steer angle deadzone to for bad angle sensor prius
for fw in car_fw :
if fw . ecu == " eps " and not fw . fwVersion == b ' 8965B47060 \x00 \x00 \x00 \x00 \x00 \x00 ' :
ret . steerActuatorDelay = 0.25
CarInterfaceBase . configure_torque_tune ( candidate , ret . lateralTuning , steering_angle_deadzone_deg = 0.2 )
elif candidate in ( CAR . LEXUS_RX , CAR . LEXUS_RX_TSS2 ) :
stop_and_go = True
ret . wheelSpeedFactor = 1.035
elif candidate in ( CAR . TOYOTA_AVALON , CAR . TOYOTA_AVALON_2019 , CAR . TOYOTA_AVALON_TSS2 ) :
# starting from 2019, all Avalon variants have stop and go
# https://engage.toyota.com/static/images/toyota_safety_sense/TSS_Applicability_Chart.pdf
stop_and_go = candidate != CAR . TOYOTA_AVALON
elif candidate in ( CAR . TOYOTA_RAV4_TSS2 , CAR . TOYOTA_RAV4_TSS2_2022 , CAR . TOYOTA_RAV4_TSS2_2023 ) :
ret . lateralTuning . init ( ' pid ' )
ret . lateralTuning . pid . kiBP = [ 0.0 ]
ret . lateralTuning . pid . kpBP = [ 0.0 ]
ret . lateralTuning . pid . kpV = [ 0.6 ]
ret . lateralTuning . pid . kiV = [ 0.1 ]
ret . lateralTuning . pid . kf = 0.00007818594
# 2019+ RAV4 TSS2 uses two different steering racks and specific tuning seems to be necessary.
# See https://github.com/commaai/openpilot/pull/21429#issuecomment-873652891
for fw in car_fw :
if fw . ecu == " eps " and ( fw . fwVersion . startswith ( b ' \x02 ' ) or fw . fwVersion in [ b ' 8965B42181 \x00 \x00 \x00 \x00 \x00 \x00 ' ] ) :
ret . lateralTuning . pid . kpV = [ 0.15 ]
ret . lateralTuning . pid . kiV = [ 0.05 ]
ret . lateralTuning . pid . kf = 0.00004
break
elif candidate in ( CAR . TOYOTA_CHR , CAR . TOYOTA_CAMRY , CAR . TOYOTA_SIENNA , CAR . LEXUS_CTH , CAR . LEXUS_NX ) :
# TODO: Some of these platforms are not advertised to have full range ACC, are they similar to SNG_WITHOUT_DSU cars?
stop_and_go = True
# TODO: these models can do stop and go, but unclear if it requires sDSU or unplugging DSU.
# For now, don't list stop and go functionality in the docs
if ret . flags & ToyotaFlags . SNG_WITHOUT_DSU :
stop_and_go = stop_and_go or ( ret . enableDsu and not docs )
ret . centerToFront = ret . wheelbase * 0.44
# TODO: Some TSS-P platforms have BSM, but are flipped based on region or driving direction.
# Detect flipped signals and enable for C-HR and others
ret . enableBsm = 0x3F6 in fingerprint [ 0 ] and candidate in TSS2_CAR
# No radar dbc for cars without DSU which are not TSS 2.0
# TODO: make an adas dbc file for dsu-less models
ret . radarUnavailable = DBC [ candidate ] [ ' radar ' ] is None or candidate in ( NO_DSU_CAR - TSS2_CAR )
# since we don't yet parse radar on TSS2/TSS-P radar-based ACC cars, gate longitudinal behind experimental toggle
if candidate in ( RADAR_ACC_CAR | NO_DSU_CAR ) :
ret . experimentalLongitudinalAvailable = candidate in RADAR_ACC_CAR
# Disabling radar is only supported on TSS2 radar-ACC cars
if experimental_long and candidate in RADAR_ACC_CAR :
ret . flags | = ToyotaFlags . DISABLE_RADAR . value
# openpilot longitudinal enabled by default:
# - cars w/ DSU disconnected
# - TSS2 cars with camera sending ACC_CONTROL where we can block it
# openpilot longitudinal behind experimental long toggle:
# - TSS2 radar ACC cars (disables radar)
ret . openpilotLongitudinalControl = ret . enableDsu or candidate in ( TSS2_CAR - RADAR_ACC_CAR ) or bool ( ret . flags & ToyotaFlags . DISABLE_RADAR . value )
ret . autoResumeSng = ret . openpilotLongitudinalControl and candidate in NO_STOP_TIMER_CAR
if not ret . openpilotLongitudinalControl :
ret . safetyConfigs [ 0 ] . safetyParam | = Panda . FLAG_TOYOTA_STOCK_LONGITUDINAL
# min speed to enable ACC. if car can do stop and go, then set enabling speed
# to a negative value, so it won't matter.
ret . minEnableSpeed = - 1. if stop_and_go else MIN_ACC_SPEED
tune = ret . longitudinalTuning
if candidate in TSS2_CAR :
tune . kpV = [ 0.0 ]
tune . kiV = [ 0.5 ]
ret . vEgoStopping = 0.25
ret . vEgoStarting = 0.25
ret . stoppingDecelRate = 0.3 # reach stopping target smoothly
else :
tune . kiBP = [ 0. , 5. , 35. ]
tune . kiV = [ 3.6 , 2.4 , 1.5 ]
return ret
@staticmethod
def init ( CP , logcan , sendcan ) :
# disable radar if alpha longitudinal toggled on radar-ACC car
if CP . flags & ToyotaFlags . DISABLE_RADAR . value :
communication_control = bytes ( [ uds . SERVICE_TYPE . COMMUNICATION_CONTROL , uds . CONTROL_TYPE . ENABLE_RX_DISABLE_TX , uds . MESSAGE_TYPE . NORMAL ] )
disable_ecu ( logcan , sendcan , bus = 0 , addr = 0x750 , sub_addr = 0xf , com_cont_req = communication_control )
# returns a car.CarState
def _update ( self , c ) :
ret = self . CS . update ( self . cp , self . cp_cam )
if self . CP . carFingerprint in ( TSS2_CAR - RADAR_ACC_CAR ) :
ret . buttonEvents = create_button_events ( self . CS . distance_button , self . CS . prev_distance_button , { 1 : ButtonType . gapAdjustCruise } )
# events
events = self . create_common_events ( ret )
# Lane Tracing Assist control is unavailable (EPS_STATUS->LTA_STATE=0) until
# the more accurate angle sensor signal is initialized
if self . CP . steerControlType == SteerControlType . angle and not self . CS . accurate_steer_angle_seen :
events . add ( EventName . vehicleSensorsInvalid )
if self . CP . openpilotLongitudinalControl :
if ret . cruiseState . standstill and not ret . brakePressed :
events . add ( EventName . resumeRequired )
if self . CS . low_speed_lockout :
events . add ( EventName . lowSpeedLockout )
if ret . vEgo < self . CP . minEnableSpeed :
events . add ( EventName . belowEngageSpeed )
if c . actuators . accel > 0.3 :
# some margin on the actuator to not false trigger cancellation while stopping
events . add ( EventName . speedTooLow )
if ret . vEgo < 0.001 :
# while in standstill, send a user alert
events . add ( EventName . manualRestart )
ret . events = events . to_msg ( )
return ret