import numpy as np
from opendbc . can . packer import CANPacker
from opendbc . car import Bus , apply_std_steer_angle_limits
from opendbc . car . interfaces import CarControllerBase
from opendbc . car . tesla . teslacan import TeslaCAN
from opendbc . car . tesla . values import CarControllerParams
class CarController ( CarControllerBase ) :
def __init__ ( self , dbc_names , CP ) :
super ( ) . __init__ ( dbc_names , CP )
self . apply_angle_last = 0
self . packer = CANPacker ( dbc_names [ Bus . party ] )
self . tesla_can = TeslaCAN ( self . packer )
def update ( self , CC , CS , now_nanos ) :
actuators = CC . actuators
can_sends = [ ]
# Tesla EPS enforces disabling steering on heavy lateral override force.
# When enabling in a tight curve, we wait until user reduces steering force to start steering.
# Canceling is done on rising edge and is handled generically with CC.cruiseControl.cancel
lat_active = CC . latActive and CS . hands_on_level < 3
if self . frame % 2 == 0 :
# Angular rate limit based on speed
self . apply_angle_last = apply_std_steer_angle_limits ( actuators . steeringAngleDeg , self . apply_angle_last , CS . out . vEgo ,
CS . out . steeringAngleDeg , lat_active , CarControllerParams . ANGLE_LIMITS )
can_sends . append ( self . tesla_can . create_steering_control ( self . apply_angle_last , lat_active , ( self . frame / / 2 ) % 16 ) )
if self . frame % 10 == 0 :
can_sends . append ( self . tesla_can . create_steering_allowed ( ( self . frame / / 10 ) % 16 ) )
# Longitudinal control
if self . CP . openpilotLongitudinalControl :
if self . frame % 4 == 0 :
state = 13 if CC . cruiseControl . cancel else 4 # 4=ACC_ON, 13=ACC_CANCEL_GENERIC_SILENT
accel = float ( np . clip ( actuators . accel , CarControllerParams . ACCEL_MIN , CarControllerParams . ACCEL_MAX ) )
cntr = ( self . frame / / 4 ) % 8
can_sends . append ( self . tesla_can . create_longitudinal_command ( state , accel , cntr , CS . out . vEgo , CC . longActive ) )
else :
# Increment counter so cancel is prioritized even without openpilot longitudinal
if CC . cruiseControl . cancel :
cntr = ( CS . das_control [ " DAS_controlCounter " ] + 1 ) % 8
can_sends . append ( self . tesla_can . create_longitudinal_command ( 13 , 0 , cntr , CS . out . vEgo , False ) )
# TODO: HUD control
new_actuators = actuators . as_builder ( )
new_actuators . steeringAngleDeg = self . apply_angle_last
self . frame + = 1
return new_actuators , can_sends