|
|
|
@ -4,10 +4,12 @@ from common.realtime import DT_CTRL |
|
|
|
|
from selfdrive.car.body import bodycan |
|
|
|
|
from opendbc.can.packer import CANPacker |
|
|
|
|
from selfdrive.car.body.values import SPEED_FROM_RPM |
|
|
|
|
from selfdrive.controls.lib.pid import PIDController |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MAX_TORQUE = 500 |
|
|
|
|
MAX_TORQUE_RATE = 50 |
|
|
|
|
MAX_ANGLE_ERROR = 7 |
|
|
|
|
MAX_ANGLE_ERROR = np.radians(7) |
|
|
|
|
MAX_POS_INTEGRATOR = 0.2 # meters |
|
|
|
|
MAX_TURN_INTEGRATOR = 0.1 # meters |
|
|
|
|
|
|
|
|
@ -17,11 +19,10 @@ class CarController(): |
|
|
|
|
self.frame = 0 |
|
|
|
|
self.packer = CANPacker(dbc_name) |
|
|
|
|
|
|
|
|
|
self.i_speed = 0 |
|
|
|
|
self.i_speed_diff = 0 |
|
|
|
|
|
|
|
|
|
self.i_balance = 0 |
|
|
|
|
self.d_balance = 0 |
|
|
|
|
# Speed, balance and turn PIDs |
|
|
|
|
self.speed_pid = PIDController(0.115, k_i=0.23, rate=1/DT_CTRL) |
|
|
|
|
self.balance_pid = PIDController(1300, k_i=0, k_d=280, rate=1/DT_CTRL) |
|
|
|
|
self.turn_pid = PIDController(110, k_i=11.5, rate=1/DT_CTRL) |
|
|
|
|
|
|
|
|
|
self.torque_r_filtered = 0. |
|
|
|
|
self.torque_l_filtered = 0. |
|
|
|
@ -46,37 +47,23 @@ class CarController(): |
|
|
|
|
speed_desired = CC.actuators.accel / 5. |
|
|
|
|
speed_diff_desired = -CC.actuators.steer |
|
|
|
|
|
|
|
|
|
# Setpoint speed PID |
|
|
|
|
kp_speed = 0.001 / SPEED_FROM_RPM |
|
|
|
|
ki_speed = 0.002 / SPEED_FROM_RPM |
|
|
|
|
|
|
|
|
|
speed_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr) / 2. |
|
|
|
|
speed_error = speed_desired - speed_measured |
|
|
|
|
|
|
|
|
|
self.i_speed += speed_error * DT_CTRL |
|
|
|
|
self.i_speed = np.clip(self.i_speed, -MAX_POS_INTEGRATOR, MAX_POS_INTEGRATOR) |
|
|
|
|
set_point = kp_speed * speed_error + ki_speed * self.i_speed |
|
|
|
|
|
|
|
|
|
# Balancing PID |
|
|
|
|
kp_balance = 1300 |
|
|
|
|
ki_balance = 0 |
|
|
|
|
kd_balance = 280 |
|
|
|
|
freeze_integrator = ((speed_error < 0 and self.speed_pid.error_integral <= -MAX_POS_INTEGRATOR) or |
|
|
|
|
(speed_error > 0 and self.speed_pid.error_integral >= MAX_POS_INTEGRATOR)) |
|
|
|
|
angle_setpoint = self.speed_pid.update(speed_error, freeze_integrator=freeze_integrator) |
|
|
|
|
|
|
|
|
|
# Clip angle error, this is enough to get up from stands |
|
|
|
|
p_balance = np.clip((-CC.orientationNED[1]) - set_point, np.radians(-MAX_ANGLE_ERROR), np.radians(MAX_ANGLE_ERROR)) |
|
|
|
|
self.i_balance += CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr |
|
|
|
|
self.d_balance = np.clip(-CC.angularVelocity[1], -1., 1.) |
|
|
|
|
torque = int(np.clip((p_balance*kp_balance + self.i_balance*ki_balance + self.d_balance*kd_balance), -1000, 1000)) |
|
|
|
|
|
|
|
|
|
# yaw recovery PID |
|
|
|
|
kp_turn = 0.95 / SPEED_FROM_RPM |
|
|
|
|
ki_turn = 0.1 / SPEED_FROM_RPM |
|
|
|
|
angle_error = np.clip((-CC.orientationNED[1]) - angle_setpoint, -MAX_ANGLE_ERROR, MAX_ANGLE_ERROR) |
|
|
|
|
angle_error_rate = np.clip(-CC.angularVelocity[1], -1., 1.) |
|
|
|
|
torque = self.balance_pid.update(angle_error, error_rate=angle_error_rate) |
|
|
|
|
|
|
|
|
|
speed_diff_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr) |
|
|
|
|
speed_diff_error = speed_diff_measured - speed_diff_desired |
|
|
|
|
self.i_speed_diff += speed_diff_error * DT_CTRL |
|
|
|
|
self.i_speed_diff = np.clip(self.i_speed_diff, -MAX_TURN_INTEGRATOR, MAX_TURN_INTEGRATOR) |
|
|
|
|
torque_diff = int(np.clip(kp_turn * speed_diff_error + ki_turn * self.i_speed_diff, -100, 100)) |
|
|
|
|
turn_error = speed_diff_measured - speed_diff_desired |
|
|
|
|
freeze_integrator = ((turn_error < 0 and self.turn_pid.error_integral <= -MAX_POS_INTEGRATOR) or |
|
|
|
|
(turn_error > 0 and self.turn_pid.error_integral >= MAX_POS_INTEGRATOR)) |
|
|
|
|
torque_diff = self.turn_pid.update(turn_error, freeze_integrator=freeze_integrator) |
|
|
|
|
|
|
|
|
|
# Combine 2 PIDs outputs |
|
|
|
|
torque_r = torque + torque_diff |
|
|
|
|