2020# Additionally, there is friction in the steering wheel that needs
2121# to be overcome to move it at all, this is compensated for too.
2222
23- KP = 1.0
24- KI = 0.3
25- KD = 0.0
23+ KP = 0.8
24+ KI = 0.15
25+
2626INTERP_SPEEDS = [1 , 1.5 , 2.0 , 3.0 , 5 , 7.5 , 10 , 15 , 30 ]
2727KP_INTERP = [250 , 120 , 65 , 30 , 11.5 , 5.5 , 3.5 , 2.0 , KP ]
2828
2929LP_FILTER_CUTOFF_HZ = 1.2
30+ JERK_LOOKAHEAD_SECONDS = 0.19
31+ JERK_GAIN = 0.3
3032LAT_ACCEL_REQUEST_BUFFER_SECONDS = 1.0
31- VERSION = 0
33+ VERSION = 1
3234
3335class LatControlTorque (LatControl ):
3436 def __init__ (self , CP , CI , dt ):
3537 super ().__init__ (CP , CI , dt )
3638 self .torque_params = CP .lateralTuning .torque .as_builder ()
3739 self .torque_from_lateral_accel = CI .torque_from_lateral_accel ()
3840 self .lateral_accel_from_torque = CI .lateral_accel_from_torque ()
39- self .pid = PIDController ([INTERP_SPEEDS , KP_INTERP ], KI , KD , rate = 1 / self .dt )
41+ self .pid = PIDController ([INTERP_SPEEDS , KP_INTERP ], KI , rate = 1 / self .dt )
4042 self .update_limits ()
4143 self .steering_angle_deadzone_deg = self .torque_params .steeringAngleDeadzoneDeg
4244 self .lat_accel_request_buffer_len = int (LAT_ACCEL_REQUEST_BUFFER_SECONDS / self .dt )
4345 self .lat_accel_request_buffer = deque ([0. ] * self .lat_accel_request_buffer_len , maxlen = self .lat_accel_request_buffer_len )
44- self .previous_measurement = 0.0
45- self .measurement_rate_filter = FirstOrderFilter (0.0 , 1 / (2 * np .pi * LP_FILTER_CUTOFF_HZ ), self .dt )
46+ self .lookahead_frames = int ( JERK_LOOKAHEAD_SECONDS / self . dt )
47+ self .jerk_filter = FirstOrderFilter (0.0 , 1 / (2 * np .pi * LP_FILTER_CUTOFF_HZ ), self .dt )
4648
4749 def update_live_torque_params (self , latAccelFactor , latAccelOffset , friction ):
4850 self .torque_params .latAccelFactor = latAccelFactor
@@ -68,33 +70,26 @@ def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvat
6870
6971 delay_frames = int (np .clip (lat_delay / self .dt , 1 , self .lat_accel_request_buffer_len ))
7072 expected_lateral_accel = self .lat_accel_request_buffer [- delay_frames ]
71- # TODO factor out lateral jerk from error to later replace it with delay independent alternative
73+ lookahead_idx = int (np .clip (- delay_frames + self .lookahead_frames , - self .lat_accel_request_buffer_len + 1 , - 2 ))
74+ raw_lateral_jerk = (self .lat_accel_request_buffer [lookahead_idx + 1 ] - self .lat_accel_request_buffer [lookahead_idx - 1 ]) / (2 * self .dt )
75+ desired_lateral_jerk = self .jerk_filter .update (raw_lateral_jerk )
7276 future_desired_lateral_accel = desired_curvature * CS .vEgo ** 2
7377 self .lat_accel_request_buffer .append (future_desired_lateral_accel )
7478 gravity_adjusted_future_lateral_accel = future_desired_lateral_accel - roll_compensation
75- desired_lateral_jerk = ( future_desired_lateral_accel - expected_lateral_accel ) / lat_delay
79+ setpoint = expected_lateral_accel
7680
7781 measurement = measured_curvature * CS .vEgo ** 2
78- measurement_rate = self .measurement_rate_filter .update ((measurement - self .previous_measurement ) / self .dt )
79- self .previous_measurement = measurement
80-
81- setpoint = lat_delay * desired_lateral_jerk + expected_lateral_accel
8282 error = setpoint - measurement
8383
8484 # do error correction in lateral acceleration space, convert at end to handle non-linear torque responses correctly
8585 pid_log .error = float (error )
8686 ff = gravity_adjusted_future_lateral_accel
8787 # latAccelOffset corrects roll compensation bias from device roll misalignment relative to car roll
8888 ff -= self .torque_params .latAccelOffset
89- # TODO jerk is weighted by lat_delay for legacy reasons, but should be made independent of it
90- ff += get_friction (error , lateral_accel_deadzone , FRICTION_THRESHOLD , self .torque_params )
89+ ff += get_friction (error + JERK_GAIN * desired_lateral_jerk , lateral_accel_deadzone , FRICTION_THRESHOLD , self .torque_params )
9190
9291 freeze_integrator = steer_limited_by_safety or CS .steeringPressed or CS .vEgo < 5
93- output_lataccel = self .pid .update (pid_log .error ,
94- - measurement_rate ,
95- feedforward = ff ,
96- speed = CS .vEgo ,
97- freeze_integrator = freeze_integrator )
92+ output_lataccel = self .pid .update (pid_log .error , speed = CS .vEgo , feedforward = ff , freeze_integrator = freeze_integrator )
9893 output_torque = self .torque_from_lateral_accel (output_lataccel , self .torque_params )
9994
10095 pid_log .active = True
0 commit comments