|
|
|
@ -4,7 +4,6 @@ from cereal import log |
|
|
|
|
from common.numpy_fast import interp |
|
|
|
|
from selfdrive.controls.lib.latcontrol import LatControl, MIN_STEER_SPEED |
|
|
|
|
from selfdrive.controls.lib.pid import PIDController |
|
|
|
|
from selfdrive.controls.lib.drive_helpers import apply_deadzone |
|
|
|
|
from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY |
|
|
|
|
|
|
|
|
|
# At higher speeds (25+mph) we can assume: |
|
|
|
@ -19,19 +18,20 @@ from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY |
|
|
|
|
# move it at all, this is compensated for too. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FRICTION_THRESHOLD = 0.2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LatControlTorque(LatControl): |
|
|
|
|
def __init__(self, CP, CI): |
|
|
|
|
super().__init__(CP, CI) |
|
|
|
|
self.pid = PIDController(CP.lateralTuning.torque.kp, CP.lateralTuning.torque.ki, |
|
|
|
|
k_f=CP.lateralTuning.torque.kf, pos_limit=self.steer_max, neg_limit=-self.steer_max) |
|
|
|
|
self.get_steer_feedforward = CI.get_steer_feedforward_function() |
|
|
|
|
self.use_steering_angle = CP.lateralTuning.torque.useSteeringAngle |
|
|
|
|
self.friction = CP.lateralTuning.torque.friction |
|
|
|
|
self.kf = CP.lateralTuning.torque.kf |
|
|
|
|
self.steering_angle_deadzone_deg = CP.lateralTuning.torque.steeringAngleDeadzoneDeg |
|
|
|
|
self.torque_params = CP.lateralTuning.torque |
|
|
|
|
self.pid = PIDController(self.torque_params.kp, self.torque_params.ki, |
|
|
|
|
k_f=self.torque_params.kf, pos_limit=self.steer_max, neg_limit=-self.steer_max) |
|
|
|
|
self.torque_from_lateral_accel = CI.torque_from_lateral_accel() |
|
|
|
|
self.use_steering_angle = self.torque_params.useSteeringAngle |
|
|
|
|
self.steering_angle_deadzone_deg = self.torque_params.steeringAngleDeadzoneDeg |
|
|
|
|
|
|
|
|
|
def update_live_torque_params(self, latAccelFactor, latAccelOffset, friction): |
|
|
|
|
self.torque_params.latAccelFactor = latAccelFactor |
|
|
|
|
self.torque_params.latAccelOffset = latAccelOffset |
|
|
|
|
self.torque_params.friction = friction |
|
|
|
|
|
|
|
|
|
def update(self, active, CS, VM, params, last_actuators, steer_limited, desired_curvature, desired_curvature_rate, llk): |
|
|
|
|
pid_log = log.ControlsState.LateralTorqueState.new_message() |
|
|
|
@ -55,19 +55,16 @@ class LatControlTorque(LatControl): |
|
|
|
|
actual_lateral_accel = actual_curvature * CS.vEgo ** 2 |
|
|
|
|
lateral_accel_deadzone = curvature_deadzone * CS.vEgo ** 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
low_speed_factor = interp(CS.vEgo, [0, 10, 20], [500, 500, 200]) |
|
|
|
|
setpoint = desired_lateral_accel + low_speed_factor * desired_curvature |
|
|
|
|
measurement = actual_lateral_accel + low_speed_factor * actual_curvature |
|
|
|
|
error = setpoint - measurement |
|
|
|
|
pid_log.error = error |
|
|
|
|
gravity_adjusted_lateral_accel = desired_lateral_accel - params.roll * ACCELERATION_DUE_TO_GRAVITY |
|
|
|
|
pid_log.error = self.torque_from_lateral_accel(error, self.torque_params, error, lateral_accel_deadzone, friction_compensation=False) |
|
|
|
|
ff = self.torque_from_lateral_accel(gravity_adjusted_lateral_accel, self.torque_params, error, lateral_accel_deadzone, friction_compensation=True) |
|
|
|
|
|
|
|
|
|
ff = desired_lateral_accel - params.roll * ACCELERATION_DUE_TO_GRAVITY |
|
|
|
|
# convert friction into lateral accel units for feedforward |
|
|
|
|
friction_compensation = interp(apply_deadzone(error, lateral_accel_deadzone), [-FRICTION_THRESHOLD, FRICTION_THRESHOLD], [-self.friction, self.friction]) |
|
|
|
|
ff += friction_compensation / self.kf |
|
|
|
|
freeze_integrator = steer_limited or CS.steeringPressed or CS.vEgo < 5 |
|
|
|
|
output_torque = self.pid.update(error, |
|
|
|
|
output_torque = self.pid.update(pid_log.error, |
|
|
|
|
feedforward=ff, |
|
|
|
|
speed=CS.vEgo, |
|
|
|
|
freeze_integrator=freeze_integrator) |
|
|
|
@ -78,9 +75,9 @@ class LatControlTorque(LatControl): |
|
|
|
|
pid_log.d = self.pid.d |
|
|
|
|
pid_log.f = self.pid.f |
|
|
|
|
pid_log.output = -output_torque |
|
|
|
|
pid_log.saturated = self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited) |
|
|
|
|
pid_log.actualLateralAccel = actual_lateral_accel |
|
|
|
|
pid_log.desiredLateralAccel = desired_lateral_accel |
|
|
|
|
pid_log.saturated = self._check_saturation(self.steer_max - abs(output_torque) < 1e-3, CS, steer_limited) |
|
|
|
|
|
|
|
|
|
# TODO left is positive in this convention |
|
|
|
|
return -output_torque, 0.0, pid_log |
|
|
|
|