Compare commits

...

19 Commits

Author SHA1 Message Date
Jonathan Frey 8bd8fc36bb lat_control_steer_model: use model without memory
of the form

    steering_angle = B * u + R * p

    with ['can_cmds_squared', 'cmds_by_vsquared', 'cmds_squared_by_vsquared']
    p = ['roll', 'roll_squared', 'roll_by_speed', 'roll_by_vsquared']

Note: coefficients in B must be positive
2022-02-28 19:58:00 +01:00
Jonathan Frey 97b6678d8d lat_control_steer_model: use model without memory
of the form

steering_angle = B * u + R * p

with u = ['can_cmds', 'can_cmds_squared', 'cmds_by_speed',
                 'cmds_by_vsquared', 'cmds_squared_by_vsquared', 'cmds_squared_by_v']

p = ['roll', 'roll_squared', 'roll_by_speed', 'roll_by_vsquared']
2022-02-28 17:38:54 +01:00
Jonathan Frey f1b9b4799e update cereal 2022-02-24 17:17:24 +01:00
Jonathan Frey 319ffdcedc lat_control_steer_model: penalize delta_torque:
optain torque as the solution of:

      min_(\delta_torque) norm(angle - desired_angle, dangle - desired_angle_rate, torque_current+\delta_torque, delta_torque)_W

with torque_next = torque_current + delta_torque
angle, dangle = euler forward simulation with model and (torque_next)
2022-02-24 17:17:24 +01:00
Jonathan Frey 749078d4d9 lat_control_steer_model: back to tracking angle and rate and penalize torque 2022-02-24 17:17:24 +01:00
Jonathan Frey 68cb798722 lat_control_steer_model: back to hacky but practical approach 2022-02-24 17:17:24 +01:00
Jonathan Frey d369cb024e lat_control_steer_model: no roll for angle rate 2022-02-24 17:17:24 +01:00
Jonathan Frey 107a47cce5 lat_control_steer_model: don't clip and use last_actuators 2022-02-24 17:17:24 +01:00
Jonathan Frey 20a29378d0 set new parameters 2022-02-24 17:17:24 +01:00
Jonathan Frey 57c3c36ddb lat_control_steer_model: comments 2022-02-24 17:17:24 +01:00
Jonathan Frey fc3343788f adapt lat_control_steer_model to use controls_list = ['can_cmds', 'can_cmds_squared', 'cmds_by_vsquared'], live_param_list = ['roll', 'speed_times_roll', 'roll_squared', 'roll_by_speed'] 2022-02-24 17:17:23 +01:00
Jonathan Frey bf2406b2e3 latcontrol_steer_model: variant with u*abs(u) 2022-02-24 17:17:23 +01:00
Jonathan Frey 094018cf62 latcontrol_steer_model: some cleanup 2022-02-24 17:17:23 +01:00
Jonathan Frey 705d4f48ad latcontrol_steer_model: get torque as torque = argmin norm(xcurrent + DT_CTRL * (A*xcurrent + R*live_param + B*u) - [desired_angle, desired_angle_rate])_W 2022-02-24 17:17:23 +01:00
Jonathan Frey 0df3a8c265 latcontrol_steer_model: apply limits, use only roll as parameter for now 2022-02-24 17:17:23 +01:00
Jonathan Frey 96a57f2690 work on LatControlSteerModel 2022-02-24 17:17:23 +01:00
Jonathan Frey 7b9668db9f test LatControlSteerModel 2022-02-24 17:17:23 +01:00
Jonathan Frey 0ab4f0618e use steer_model as lateral control for COROLLA_TSS2 2022-02-24 17:17:23 +01:00
Jonathan Frey 194cc7a8b9 add latcontrol_steer_model 2022-02-24 17:17:23 +01:00
7 changed files with 77 additions and 3 deletions

2
cereal

@ -1 +1 @@
Subproject commit 28d458a9af49b38bd0a9052f09fbe927324320fb
Subproject commit 2336d872a7b18c614f33bcb5802a73b4dcd6c1ae

View File

@ -130,7 +130,8 @@ class CarInterface(CarInterfaceBase):
ret.steerRatio = 13.9
tire_stiffness_factor = 0.444 # not optimized yet
ret.mass = 3060. * CV.LB_TO_KG + STD_CARGO_KG
set_lat_tune(ret.lateralTuning, LatTunes.PID_D)
# set_lat_tune(ret.lateralTuning, LatTunes.PID_D)
set_lat_tune(ret.lateralTuning, LatTunes.STEER_MODEL)
elif candidate in (CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.LEXUS_ESH):
stop_and_go = True

View File

@ -24,6 +24,7 @@ class LatTunes(Enum):
PID_L = 13
PID_M = 14
PID_N = 15
STEER_MODEL = 16
###### LONG ######
@ -72,6 +73,9 @@ def set_lat_tune(tune, name):
tune.lqr.l = [0.3233671, 0.3185757]
tune.lqr.dcGain = 0.002237852961363602
elif name == LatTunes.STEER_MODEL:
tune.init('steerModel')
tune.steerModel.modelparam = [ 1.71925238e+01, 1.41763391e+03, 9.77812550e+02, 1.88123015e-01, -9.82756467e-02, -1.26513806e+00, -1.68255566e+02]
elif 'PID' in str(name):
tune.init('pid')
tune.pid.kiBP = [0.0]

View File

@ -21,6 +21,7 @@ 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.latcontrol_steer_model import LatControlSteerModel
from selfdrive.controls.lib.events import Events, ET
from selfdrive.controls.lib.alertmanager import AlertManager, set_offroad_alert
from selfdrive.controls.lib.vehicle_model import VehicleModel
@ -133,6 +134,8 @@ class Controls:
self.LaC = LatControlINDI(self.CP, self.CI)
elif self.CP.lateralTuning.which() == 'lqr':
self.LaC = LatControlLQR(self.CP, self.CI)
elif self.CP.lateralTuning.which() == 'steerModel':
self.LaC = LatControlSteerModel(self.CP, self.CI)
self.initialized = False
self.state = State.disabled
@ -669,6 +672,8 @@ class Controls:
controlsState.lateralControlState.lqrState = lac_log
elif lat_tuning == 'indi':
controlsState.lateralControlState.indiState = lac_log
elif lat_tuning == 'steerModel':
controlsState.lateralControlState.steerModelState = lac_log
self.pm.send('controlsState', dat)

View File

@ -0,0 +1,60 @@
import math
import numpy as np
from selfdrive.controls.lib.drive_helpers import get_steer_max
from cereal import log
from selfdrive.controls.lib.latcontrol import LatControl, MIN_STEER_SPEED
controls_list = ['can_cmds_squared', 'cmds_by_vsquared', 'cmds_squared_by_vsquared']
NU = len(controls_list)
live_param_list = ['roll', 'roll_squared', 'roll_by_speed', 'roll_by_vsquared']
N_live_param = len(live_param_list)
class LatControlSteerModel(LatControl):
def __init__(self, CP, CI):
super().__init__(CP, CI)
model_param = np.asarray(list(CP.lateralTuning.steerModel.modelparam))
self.B = model_param[0:NU]
self.R = model_param[NU:NU+N_live_param]
assert(NU+N_live_param == len(model_param))
def update(self, active, CS, CP, VM, params, last_actuators, desired_curvature, desired_curvature_rate):
model_log = log.ControlsState.LateralSteerModelState.new_message()
steers_max = get_steer_max(CP, CS.vEgo)
# offset does not contribute to resistive torque
angle_steers_des_no_offset = math.degrees(VM.get_steer_from_curvature(-desired_curvature, CS.vEgo, params.roll))
angle_steers_des = angle_steers_des_no_offset + params.angleOffsetDeg
model_log.steeringAngleDesiredDeg = angle_steers_des
if CS.vEgo < MIN_STEER_SPEED or not active:
output_steer = 0.0
model_log.active = False
self.reset()
else:
# NOTE: live_param_list dependent.
# live_param_list = ['roll', 'roll_squared', 'roll_by_speed', 'roll_by_vsquared']
torque_prev = last_actuators.steer
roll_deg = np.degrees(params.roll)
live_param = np.array([roll_deg, roll_deg * abs(roll_deg), roll_deg / CS.vEgo, roll_deg/(CS.vEgo**2)])
Rp = self.R @ live_param
# NOTE: controls_list dependent.
# controls_list = ['can_cmds_squared', 'cmds_by_vsquared', 'cmds_squared_by_vsquared']
du_dtorque = np.array([2*abs(torque_prev), 1/(CS.vEgo**2), 2*abs(torque_prev)/(CS.vEgo**2) ])
B_tilde = self.B @ du_dtorque
output_steer = float( (1/B_tilde) * (angle_steers_des_no_offset - Rp) )
model_log.active = True
# model_log.steeringAngleDeg = float(self.xcurrent[0])
model_log.output = output_steer
model_log.saturated = self._check_saturation(steers_max - abs(output_steer) < 1e-3, CS)
return output_steer, angle_steers_des, model_log

View File

@ -12,12 +12,14 @@ from selfdrive.controls.lib.latcontrol_pid import LatControlPID
from selfdrive.controls.lib.latcontrol_lqr import LatControlLQR
from selfdrive.controls.lib.latcontrol_indi import LatControlINDI
from selfdrive.controls.lib.latcontrol_angle import LatControlAngle
from selfdrive.controls.lib.latcontrol_steer_model import LatControlSteerModel
from selfdrive.controls.lib.vehicle_model import VehicleModel
class TestLatControl(unittest.TestCase):
@parameterized.expand([(HONDA.CIVIC, LatControlPID), (TOYOTA.RAV4, LatControlLQR), (TOYOTA.PRIUS, LatControlINDI), (NISSAN.LEAF, LatControlAngle)])
@parameterized.expand([(HONDA.CIVIC, LatControlPID), (TOYOTA.RAV4, LatControlLQR), (TOYOTA.PRIUS, LatControlINDI),
(NISSAN.LEAF, LatControlAngle), (TOYOTA.COROLLA_TSS2, LatControlSteerModel)])
def test_saturation(self, car_name, controller):
CarInterface, CarController, CarState = interfaces[car_name]
CP = CarInterface.get_params(car_name)

View File

@ -120,6 +120,8 @@ class TestCarModel(unittest.TestCase):
self.assertTrue(len(self.CP.lateralTuning.lqr.a))
elif tuning == 'indi':
self.assertTrue(len(self.CP.lateralTuning.indi.outerLoopGainV))
elif tuning == 'steerModel':
self.assertTrue(len(self.CP.lateralTuning.steerModel.modelparam))
else:
raise Exception("unkown tuning")