2021-03-12 06:08:51 +01:00
|
|
|
import math
|
2021-12-03 21:35:34 +01:00
|
|
|
|
2021-03-12 06:08:51 +01:00
|
|
|
from cereal import log
|
2023-08-20 20:49:55 -07:00
|
|
|
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
|
2021-03-12 06:08:51 +01:00
|
|
|
|
2025-08-11 14:25:29 -07:00
|
|
|
# TODO This is speed dependent
|
2022-01-26 08:10:41 -08:00
|
|
|
STEER_ANGLE_SATURATION_THRESHOLD = 2.5 # Degrees
|
2021-03-12 06:08:51 +01:00
|
|
|
|
|
|
|
|
|
2022-01-26 08:10:41 -08:00
|
|
|
class LatControlAngle(LatControl):
|
2025-11-16 02:00:29 -05:00
|
|
|
def __init__(self, CP, CP_SP, CI, dt):
|
|
|
|
|
super().__init__(CP, CP_SP, CI, dt)
|
2022-12-09 23:29:56 -08:00
|
|
|
self.sat_check_min_speed = 5.
|
2025-08-11 14:25:29 -07:00
|
|
|
self.use_steer_limited_by_safety = CP.brand == "tesla"
|
2022-12-09 21:43:55 -08:00
|
|
|
|
2025-11-16 02:00:29 -05:00
|
|
|
def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, calibrated_pose, curvature_limited, lat_delay):
|
2021-03-12 06:08:51 +01:00
|
|
|
angle_log = log.ControlsState.LateralAngleState.new_message()
|
|
|
|
|
|
2023-01-10 23:51:10 -05:00
|
|
|
if not active:
|
2021-03-12 06:08:51 +01:00
|
|
|
angle_log.active = False
|
|
|
|
|
angle_steers_des = float(CS.steeringAngleDeg)
|
|
|
|
|
else:
|
|
|
|
|
angle_log.active = True
|
2021-12-16 17:34:12 -08:00
|
|
|
angle_steers_des = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo, params.roll))
|
2021-03-12 06:08:51 +01:00
|
|
|
angle_steers_des += params.angleOffsetDeg
|
|
|
|
|
|
2025-08-11 14:25:29 -07:00
|
|
|
if self.use_steer_limited_by_safety:
|
2025-05-17 22:54:01 -07:00
|
|
|
# these cars' carcontrollers calculate max lateral accel and jerk, so we can rely on carOutput for saturation
|
2025-08-11 14:25:29 -07:00
|
|
|
angle_control_saturated = steer_limited_by_safety
|
2025-05-16 21:29:16 -07:00
|
|
|
else:
|
|
|
|
|
# for cars which use a method of limiting torque such as a torque signal (Nissan and Toyota)
|
|
|
|
|
# or relying on EPS (Ford Q3), carOutput does not capture maxing out torque # TODO: this can be improved
|
|
|
|
|
angle_control_saturated = abs(angle_steers_des - CS.steeringAngleDeg) > STEER_ANGLE_SATURATION_THRESHOLD
|
2025-03-03 21:47:52 -06:00
|
|
|
angle_log.saturated = bool(self._check_saturation(angle_control_saturated, CS, False, curvature_limited))
|
2021-12-03 21:35:34 +01:00
|
|
|
angle_log.steeringAngleDeg = float(CS.steeringAngleDeg)
|
2021-12-16 13:08:20 +01:00
|
|
|
angle_log.steeringAngleDesiredDeg = angle_steers_des
|
2021-03-12 06:08:51 +01:00
|
|
|
return 0, float(angle_steers_des), angle_log
|