text: from common.numpy_fast import clip, interp
  from opendbc.can.packer import CANPacker
  from selfdrive.car.tesla.teslacan import TeslaCAN
  from selfdrive.car.tesla.values import DBC, CANBUS, CarControllerParams
  
  
  class CarController:
    def __init__(self, dbc_name, CP, VM):
      self.CP = CP
      self.frame = 0
      self.last_angle = 0
      self.long_control_counter = 0
      self.packer = CANPacker(dbc_name)
      self.pt_packer = CANPacker(DBC[CP.carFingerprint]['pt'])
      self.tesla_can = TeslaCAN(self.packer, self.pt_packer)
  
    def update(self, CC, CS):
      actuators = CC.actuators
      pcm_cancel_cmd = CC.cruiseControl.cancel
  
      can_sends = []
  
      # Temp disable steering on a hands_on_fault, and allow for user override
      hands_on_fault = CS.steer_warning == "EAC_ERROR_HANDS_ON" and CS.hands_on_level >= 3
      lkas_enabled = CC.latActive and not hands_on_fault
  
      if lkas_enabled:
        apply_angle = actuators.steeringAngleDeg
  
        # Angular rate limit based on speed
        steer_up = self.last_angle * apply_angle > 0. and abs(apply_angle) > abs(self.last_angle)
        rate_limit = CarControllerParams.RATE_LIMIT_UP if steer_up else CarControllerParams.RATE_LIMIT_DOWN
        max_angle_diff = interp(CS.out.vEgo, rate_limit.speed_points, rate_limit.max_angle_diff_points)
        apply_angle = clip(apply_angle, self.last_angle - max_angle_diff, self.last_angle + max_angle_diff)
  
        # To not fault the EPS
        apply_angle = clip(apply_angle, CS.out.steeringAngleDeg - 20, CS.out.steeringAngleDeg + 20)
      else:
        apply_angle = CS.out.steeringAngleDeg
  
      self.last_angle = apply_angle
      can_sends.append(self.tesla_can.create_steering_control(apply_angle, lkas_enabled, self.frame))
  
      # Longitudinal control (40Hz)
      if self.CP.openpilotLongitudinalControl and self.frame % 5 in (0, 2):
        target_accel = actuators.accel
        target_speed = max(CS.out.vEgo + (target_accel * CarControllerParams.ACCEL_TO_SPEED_MULTIPLIER), 0)
        max_accel = 0 if target_accel < 0 else target_accel
        min_accel = 0 if target_accel > 0 else target_accel
  
        can_sends.extend(self.tesla_can.create_longitudinal_commands(CS.acc_state, target_speed, min_accel, max_accel, self.long_control_counter))
        self.long_control_counter += 1
  
      # Cancel on user steering override, since there is no steering torque blending
      if hands_on_fault:
        pcm_cancel_cmd = True
  
      if self.frame % 10 == 0 and pcm_cancel_cmd:
        # Spam every possible counter value, otherwise it might not be accepted
        for counter in range(16):
          can_sends.append(self.tesla_can.create_action_request(CS.msg_stw_actn_req, pcm_cancel_cmd, CANBUS.chassis, counter))
          can_sends.append(self.tesla_can.create_action_request(CS.msg_stw_actn_req, pcm_cancel_cmd, CANBUS.autopilot_chassis, counter))
  
      # TODO: HUD control
  
      new_actuators = actuators.copy()
      new_actuators.steeringAngleDeg = apply_angle
  
      self.frame += 1
      return new_actuators, can_sends
  