from cereal import car from common.numpy_fast import clip, interp from selfdrive.car.nissan import nissancan from opendbc.can.packer import CANPacker # Steer angle limits ANGLE_MAX_BP = [1.3, 10., 30.] ANGLE_MAX_V = [540., 120., 23.] ANGLE_DELTA_BP = [0., 5., 15.] ANGLE_DELTA_V = [5., .8, .15] # windup limit ANGLE_DELTA_VU = [5., 3.5, 0.4] # unwind limit LKAS_MAX_TORQUE = 100 # A value of 100 is easy to overpower VisualAlert = car.CarControl.HUDControl.VisualAlert class CarController(): def __init__(self, dbc_name, CP, VM): self.car_fingerprint = CP.carFingerprint self.lkas_max_torque = 0 self.last_angle = 0 self.packer = CANPacker(dbc_name) def update(self, enabled, CS, frame, actuators, cruise_cancel, hud_alert, left_line, right_line, left_lane_depart, right_lane_depart): """ Controls thread """ # Send CAN commands. can_sends = [] ### STEER ### acc_active = bool(CS.out.cruiseState.enabled) cruise_throttle_msg = CS.cruise_throttle_msg lkas_hud_msg = CS.lkas_hud_msg lkas_hud_info_msg = CS.lkas_hud_info_msg apply_angle = actuators.steerAngle steer_hud_alert = 1 if hud_alert == VisualAlert.steerRequired else 0 if enabled: # # windup slower if self.last_angle * apply_angle > 0. and abs(apply_angle) > abs(self.last_angle): angle_rate_lim = interp(CS.out.vEgo, ANGLE_DELTA_BP, ANGLE_DELTA_V) else: angle_rate_lim = interp(CS.out.vEgo, ANGLE_DELTA_BP, ANGLE_DELTA_VU) apply_angle = clip(apply_angle, self.last_angle - angle_rate_lim, self.last_angle + angle_rate_lim) # steer angle angle_lim = interp(CS.out.vEgo, ANGLE_MAX_BP, ANGLE_MAX_V) apply_angle = clip(apply_angle, -angle_lim, angle_lim) # Max torque from driver before EPS will give up and not apply torque if not bool(CS.out.steeringPressed): self.lkas_max_torque = LKAS_MAX_TORQUE else: # Scale max torque based on how much torque the driver is applying to the wheel self.lkas_max_torque = max( 0, LKAS_MAX_TORQUE - 0.4 * abs(CS.out.steeringTorque)) else: apply_angle = CS.out.steeringAngle self.lkas_max_torque = 0 self.last_angle = apply_angle if not enabled and acc_active: # send acc cancel cmd if drive is disabled but pcm is still on, or if the system can't be activated cruise_cancel = 1 if cruise_cancel: can_sends.append(nissancan.create_acc_cancel_cmd( self.packer, cruise_throttle_msg, frame)) can_sends.append(nissancan.create_steering_control( self.packer, self.car_fingerprint, apply_angle, frame, acc_active, self.lkas_max_torque)) if frame % 2 == 0: can_sends.append(nissancan.create_lkas_hud_msg( self.packer, lkas_hud_msg, enabled, left_line, right_line, left_lane_depart, right_lane_depart)) if frame % 50 == 0: can_sends.append(nissancan.create_lkas_hud_info_msg( self.packer, lkas_hud_info_msg, steer_hud_alert )) return can_sends