Steering Control¶
LQR steering control of autonomous vehicles in obstacle avoidance maneuvers.
This example requires the control package.
SteeringControl.m¶
First, we choose the tire model
TirePac = TirePacejka();
and define the tire parameters
Fz = 4e+03;
camber = 0;
TirePac.a0 = 1;
TirePac.a1 = 0;
TirePac.a2 = 800;
TirePac.a3 = 10000;
TirePac.a4 = 50;
TirePac.a5 = 0;
TirePac.a6 = 0;
TirePac.a7 = -1;
TirePac.a8 = 0;
TirePac.a9 = 0;
TirePac.a10 = 0;
TirePac.a11 = 0;
TirePac.a12 = 0;
TirePac.a13 = 0;
The plant model is defined with
VehiclePlant = VehicleSimpleNonlinear();
The vehicle parameters are
VehiclePlant.mF0 = 700;
VehiclePlant.mR0 = 600;
VehiclePlant.IT = 10000;
VehiclePlant.lT = 3.5;
VehiclePlant.nF = 1;
VehiclePlant.nR = 1;
VehiclePlant.wT = 1.8;
VehiclePlant.muy = 1;
Attributing the chosen tire model to the vehicle object we have
VehiclePlant.tire = TirePac;
The input steering angle is given by the control law within the ControlLaw.m function.
VehiclePlant.deltaf = @ControlLaw;
After this, we define the simulation time span
T = 12; % Total simulation time [s]
resol = 500; % Resolution
TSPAN = 0:T/resol:T; % Time span [s]
To define a simulation object (Simulator
) the arguments must be the vehicle object and the time span. This is,
simulator = Simulator(VehiclePlant, TSPAN);
The default parameters of the simulation object can be found in Simulator
. However, we are interested in changing the initial velocity of the vehicle. This can be done running
simulator.V0 = 16.7;
Now, we have everything needed to run the simulation. For this, we use
simulator.Simulate();
The resulting time response of each state is stored in separate variables:
XT = simulator.XT;
YT = simulator.YT;
PSI = simulator.PSI;
VEL = simulator.VEL;
ALPHAT = simulator.ALPHAT;
dPSI = simulator.dPSI;
x = [XT YT PSI VEL ALPHAT dPSI]; % ??
Preallocating the control input array
u = zeros(length(TSPAN),1); % ??
controlEffort = zeros(length(TSPAN),1);
Retrieving the control input of the system based on the simulation results
for ii = 1:length(TSPAN)
controlEffort(ii) = ControlLaw(x(ii,:));
end
The steering input can be plotted with
f1 = figure(1);
hold on; box on; grid on
plot(TSPAN,controlEffort*180/pi,'k')
xlabel('Time [s]');
ylabel('Steering input [deg]');
The resulting control input is
Frame and animation can be generated defining a graphic object (Graphics
). The only argument of the graphic object is the simulator object after the simulation.
g = Graphics(simulator);
To generate the frame/animation with a different horizontal and vertical scale run
g.Frame('scalefig',3);
The track limits can be added to the plot with the following code
carWidth = 2;
LaneOffset = 3.5;
section1width = 1.1*carWidth + 0.25;
section3width = 1.2*carWidth + 0.25;
section5width = 1.3*carWidth + 0.25;
section1Inf = -section1width/2;
section1Sup = section1width/2;
section3Inf = section1Inf+LaneOffset;
section3Sup = section3Inf+section3width;
section3Center = (section3Inf+section3Sup)/2;
section5Inf = -section5width/2;
section5Sup = section5width/2;
plot([0 15],[section1Inf section1Inf],'k') % linha inferior
plot([0 15],[section1Sup section1Sup],'k') % linha superior
plot([0 15],[0 0],'k--') % linha central
plot([15 45],[0 section3Center],'k--') % linha central
plot([45 70],[section3Inf section3Inf],'k') % linha inferior
plot([45 70],[section3Sup section3Sup],'k') % linha superior
plot([45 70],[section3Center section3Center],'k--') % linha central
plot([70 95],[section3Center 0],'k--')
plot([95 130],[section5Inf section5Inf],'k')
plot([95 130],[section5Sup section5Sup],'k')
plot([95 130],[0 0],'k--')
The resulting frame can be seen below.
The animation is generated with
g.Animation(‘scalefig’,3);
The resulting animation can be seen below.
ControlLaw.m¶
The vehicle model used in the control design is based on the Simple vehicle 4 DOF.
The state vector is given by
The state equation is
and the slip angles are
Thus, the linearized model can be written as
Neglecting equations of \(x\) and \(v_T\), using the linear tire model (Linear) and writting the state equation in the matrix form we have
Finally, the linearized slip angles are
The cornering stiffness of the chosen tire model for small values of slip angles is calculated as
muy0 = TirePac.a1 * Fz/1000 + TirePac.a2;
D = muy0 * Fz/1000;
BCD = TirePac.a3 * sin(2 * atan(Fz/1000/TirePac.a4))*(1-TirePac.a5 * abs(camber));
Ktire = BCD * 180/pi;
So, the parameters of equation (1) used for the design of the controller are
mT = 1300;
IT = 10000;
a = 1.6154;
b = 1.8846;
vT0 = 16.7;
KF = Ktire;
KR = Ktire;
The linear state space system (Equation (1)) is defined as
A = [ 0 vT0 vT0 0 ;...
0 0 0 1 ;...
0 0 -(KF+KR)/(mT*vT0) -(mT*vT0+(a*KF-b*KR)/(vT0))/(mT*vT0) ;...
0 0 -(a*KF-b*KR)/IT -(a^2*KF+b^2*KR)/(IT*vT0) ];
B = [ 0 ;...
0 ;...
KF/(mT*vT0) ;...
a*KF/IT ];
C = [1 0 0 0];
The design of the LQR controller can now be done.
Todo
Add illustration of the closed loop system.
The control law is given by
The double Lane change maneuver is achieved with a step reference point in the lateral position \(y\). Reference become \(r = 2 m\).
The maximum value of the steering angle is limited, i.e., the control input can be saturated.
The weight matrices for the LQR design are
Q = [ 3 0 0 0 ;...
0 1 0 0 ;...
0 0 1 0 ;...
0 0 0 1 ];
R = 1;
The control gains are calculated using the lqr function.
Klqr = lqr(A,B,Q,R);
The control law of the lateral dynamics is implemented in the code below.
function controlEffort = ControlLaw(sysData,~)
% sysData are the informations of the system necessary to generate the control effort
% controlEffort is the control input of the system
% In this case, the sysData contains the simple vehicle state variables
x = [sysData(2);sysData(3);sysData(5);sysData(6)];
% Vehicle longitudinal position
X = sysData(1);
% Lateral displacement
LateralDisp = 3.6;
% Reference signal (Double lane change)
if X <= 15
r = 0;
end
if X > 15 && X <= 70
r = LateralDisp;
end
if X > 70
r = 0;
end
% Control gains
K = [0.7936 6.6882 1.6107 0.5090];
u = - K*x + K(1)*r;
% Saturation of the control effort
if abs(u) < 42*pi/180
controlEffort = u;
else
controlEffort = sign(u)*42*pi/180;
end