|
|
|
@ -1,5 +1,6 @@ |
|
|
|
|
#!/usr/bin/env python3 |
|
|
|
|
import os |
|
|
|
|
import math |
|
|
|
|
from cereal import car, log |
|
|
|
|
from common.numpy_fast import clip |
|
|
|
|
from common.realtime import sec_since_boot, config_realtime_process, Priority, Ratekeeper, DT_CTRL |
|
|
|
@ -16,6 +17,7 @@ from selfdrive.controls.lib.longcontrol import LongControl, STARTING_TARGET_SPEE |
|
|
|
|
from selfdrive.controls.lib.latcontrol_pid import LatControlPID |
|
|
|
|
from selfdrive.controls.lib.latcontrol_indi import LatControlINDI |
|
|
|
|
from selfdrive.controls.lib.latcontrol_lqr import LatControlLQR |
|
|
|
|
from selfdrive.controls.lib.latcontrol_angle import LatControlAngle |
|
|
|
|
from selfdrive.controls.lib.events import Events, ET |
|
|
|
|
from selfdrive.controls.lib.alertmanager import AlertManager |
|
|
|
|
from selfdrive.controls.lib.vehicle_model import VehicleModel |
|
|
|
@ -102,7 +104,9 @@ class Controls: |
|
|
|
|
self.LoC = LongControl(self.CP, self.CI.compute_gb) |
|
|
|
|
self.VM = VehicleModel(self.CP) |
|
|
|
|
|
|
|
|
|
if self.CP.lateralTuning.which() == 'pid': |
|
|
|
|
if self.CP.steerControlType == car.CarParams.SteerControlType.angle: |
|
|
|
|
self.LaC = LatControlAngle(self.CP) |
|
|
|
|
elif self.CP.lateralTuning.which() == 'pid': |
|
|
|
|
self.LaC = LatControlPID(self.CP) |
|
|
|
|
elif self.CP.lateralTuning.which() == 'indi': |
|
|
|
|
self.LaC = LatControlINDI(self.CP) |
|
|
|
@ -363,6 +367,12 @@ class Controls: |
|
|
|
|
def state_control(self, CS): |
|
|
|
|
"""Given the state, this function returns an actuators packet""" |
|
|
|
|
|
|
|
|
|
# Update VehicleModel |
|
|
|
|
params = self.sm['liveParameters'] |
|
|
|
|
x = max(params.stiffnessFactor, 0.1) |
|
|
|
|
sr = max(params.steerRatio, 0.1) |
|
|
|
|
self.VM.update_params(x, sr) |
|
|
|
|
|
|
|
|
|
lat_plan = self.sm['lateralPlan'] |
|
|
|
|
long_plan = self.sm['longitudinalPlan'] |
|
|
|
|
|
|
|
|
@ -386,8 +396,9 @@ class Controls: |
|
|
|
|
|
|
|
|
|
# Gas/Brake PID loop |
|
|
|
|
actuators.gas, actuators.brake = self.LoC.update(self.active, CS, v_acc_sol, long_plan.vTargetFuture, a_acc_sol, self.CP) |
|
|
|
|
|
|
|
|
|
# Steering PID loop and lateral MPC |
|
|
|
|
actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(self.active, CS, self.CP, lat_plan) |
|
|
|
|
actuators.steer, actuators.steeringAngleDeg, lac_log = self.LaC.update(self.active, CS, self.CP, self.VM, params, lat_plan) |
|
|
|
|
|
|
|
|
|
# Check for difference between desired angle and angle for angle based control |
|
|
|
|
angle_control_saturated = self.CP.steerControlType == car.CarParams.SteerControlType.angle and \ |
|
|
|
@ -401,12 +412,14 @@ class Controls: |
|
|
|
|
# Send a "steering required alert" if saturation count has reached the limit |
|
|
|
|
if (lac_log.saturated and not CS.steeringPressed) or \ |
|
|
|
|
(self.saturated_count > STEER_ANGLE_SATURATION_TIMEOUT): |
|
|
|
|
# Check if we deviated from the path |
|
|
|
|
left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[0] < -0.1 |
|
|
|
|
right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[0] > 0.1 |
|
|
|
|
|
|
|
|
|
if left_deviation or right_deviation: |
|
|
|
|
self.events.add(EventName.steerSaturated) |
|
|
|
|
if len(lat_plan.dPathPoints): |
|
|
|
|
# Check if we deviated from the path |
|
|
|
|
left_deviation = actuators.steer > 0 and lat_plan.dPathPoints[0] < -0.1 |
|
|
|
|
right_deviation = actuators.steer < 0 and lat_plan.dPathPoints[0] > 0.1 |
|
|
|
|
|
|
|
|
|
if left_deviation or right_deviation: |
|
|
|
|
self.events.add(EventName.steerSaturated) |
|
|
|
|
|
|
|
|
|
return actuators, v_acc_sol, a_acc_sol, lac_log |
|
|
|
|
|
|
|
|
@ -468,7 +481,14 @@ class Controls: |
|
|
|
|
force_decel = (self.sm['driverMonitoringState'].awarenessStatus < 0.) or \ |
|
|
|
|
(self.state == State.softDisabling) |
|
|
|
|
|
|
|
|
|
steer_angle_rad = (CS.steeringAngleDeg - self.sm['lateralPlan'].angleOffsetDeg) * CV.DEG_TO_RAD |
|
|
|
|
# Curvature & Steering angle |
|
|
|
|
params = self.sm['liveParameters'] |
|
|
|
|
lat_plan = self.sm['lateralPlan'] |
|
|
|
|
|
|
|
|
|
steer_angle_without_offset = math.radians(CS.steeringAngleDeg - params.angleOffsetAverageDeg) |
|
|
|
|
curvature = -self.VM.calc_curvature(steer_angle_without_offset, CS.vEgo) |
|
|
|
|
angle_steers_des = math.degrees(self.VM.get_steer_from_curvature(-lat_plan.curvature, CS.vEgo)) |
|
|
|
|
angle_steers_des += params.angleOffsetDeg |
|
|
|
|
|
|
|
|
|
# controlsState |
|
|
|
|
dat = messaging.new_message('controlsState') |
|
|
|
@ -486,7 +506,8 @@ class Controls: |
|
|
|
|
controlsState.lateralPlanMonoTime = self.sm.logMonoTime['lateralPlan'] |
|
|
|
|
controlsState.enabled = self.enabled |
|
|
|
|
controlsState.active = self.active |
|
|
|
|
controlsState.curvature = self.VM.calc_curvature(steer_angle_rad, CS.vEgo) |
|
|
|
|
controlsState.curvature = curvature |
|
|
|
|
controlsState.steeringAngleDesiredDeg = angle_steers_des |
|
|
|
|
controlsState.state = self.state |
|
|
|
|
controlsState.engageable = not self.events.any(ET.NO_ENTRY) |
|
|
|
|
controlsState.longControlState = self.LoC.long_control_state |
|
|
|
@ -495,7 +516,6 @@ class Controls: |
|
|
|
|
controlsState.upAccelCmd = float(self.LoC.pid.p) |
|
|
|
|
controlsState.uiAccelCmd = float(self.LoC.pid.i) |
|
|
|
|
controlsState.ufAccelCmd = float(self.LoC.pid.f) |
|
|
|
|
controlsState.steeringAngleDesiredDeg = float(self.LaC.angle_steers_des) |
|
|
|
|
controlsState.vTargetLead = float(v_acc) |
|
|
|
|
controlsState.aTarget = float(a_acc) |
|
|
|
|
controlsState.cumLagMs = -self.rk.remaining * 1000. |
|
|
|
@ -503,7 +523,9 @@ class Controls: |
|
|
|
|
controlsState.forceDecel = bool(force_decel) |
|
|
|
|
controlsState.canErrorCounter = self.can_error_counter |
|
|
|
|
|
|
|
|
|
if self.CP.lateralTuning.which() == 'pid': |
|
|
|
|
if self.CP.steerControlType == car.CarParams.SteerControlType.angle: |
|
|
|
|
controlsState.lateralControlState.angleState = lac_log |
|
|
|
|
elif self.CP.lateralTuning.which() == 'pid': |
|
|
|
|
controlsState.lateralControlState.pidState = lac_log |
|
|
|
|
elif self.CP.lateralTuning.which() == 'lqr': |
|
|
|
|
controlsState.lateralControlState.lqrState = lac_log |
|
|
|
|