## Documentation Center |

This example shows how to use robust control
techniques to design an active suspension system for a quarter car
body and wheel assembly model. In this example, you use *H*_{∞} design
techniques to design a controller for a nominal quarter-car model.
Then, you use *μ* synthesis to design a robust
controller that accounts for uncertainty in the model.

Conventional *passive suspensions* use
a spring and damper between the car body and wheel assembly. The spring-damper
characteristics are adjusted to emphasize one of several conflicting
objectives such as passenger comfort, road holding, and suspension
deflection. *Active suspensions* use a feedback-controller
hydraulic actuator between the chassis and wheel assembly, which allows
the designer to better balance these objectives.

On this page… |
---|

**Quarter-Car Suspension Model**

This example uses the quarter-car model of the following illustration to design active suspension control laws.

The mass, *m _{b}*, represents
the car chassis (body) and the mass,

The following state-space equations describe the quarter-car dynamics.

The state variables in the system are defined as , , , and .

Define the physical parameters of the system.

mb = 300; % kg mw = 60; % kg bs = 1000; % N/m/s ks = 16000 ; % N/m kt = 190000; % N/m

Use these equations and parameter values to construct
a state-space model, `qcar`, of the quarter-car suspension
system.

A = [ 0 1 0 0; [-ks -bs ks bs]/mb ; ... 0 0 0 1; [ks bs -ks-kt -bs]/mw]; B = [0 0; 0 10000/mb ; 0 0; [kt -10000]/mw]; C = [1 0 0 0; 1 0 -1 0; A(2,:)]; D = [0 0; 0 0; B(2,:)]; qcar = ss(A,B,C,D); qcar.StateName = {'body travel xb (m)';'body vel (m/s)';... 'wheel travel xw (m)';'wheel vel (m/s)'}; qcar.InputName = {'r';'fs'}; qcar.OutputName = {'xb';'sd';'ab'};

The model inputs are the road disturbance, *r*,
and actuator force, *f _{s}*.
The model outputs are the car body travel,
,
suspension deflection
,
and car body acceleration
.

The transfer function from actuator to body travel and acceleration has an imaginary-axis zero. Examine the zero of this transfer function.

tzero(qcar({'xb','ab'},'fs'))

ans = -0.0000 +56.2731i -0.0000 -56.2731i

The natural frequency of this zero, 56.27 rad/s, is called the *tire-hop
frequency*.

The transfer function from the actuator to suspension deflection also has an imaginary-axis zero. Examine this zero.

zero(qcar('sd','fs'))

ans = 0.0000 +22.9734i 0.0000 -22.9734i

The natural frequency of this zero, 22.97 rad/s, is called the *rattlespace
frequency*.

Plot the frequency response of the quarter-car model from
inputs, (*r*,*f _{s}*),
to outputs, (

bodemag(qcar({'ab','sd'},'r'),'b',qcar({'ab','sd'},'fs'),'r',{1 100}); legend('Road disturbance (r)','Actuator force (fs)','location','SouthWest') title(['Gain from road dist (r) and actuator force (fs) '... 'to body accel (ab) and suspension travel (sd)'])

Road disturbances influence the motion of the car and suspension:

Small body acceleration influences passenger comfort.

Small suspension travel contributes to good road handling. Further, limits on the actuator displacement constrain the allowable travel.

Because of the imaginary axis zeros, feedback control cannot
improve the response from road disturbance (*r*)
to body acceleration (*a _{b}*)
at the tire-hop frequency. Similarly, feedback control cannot improve
the response from

**Hydraulic Actuator Model**

The hydraulic actuator used for active suspension control is
connected between the body mass, *m _{b}*,
and the wheel assembly mass,

The maximum displacement is 0.05 m.

The nominal actuator model approximates the physical actuator dynamics. You can model variations between the actuator model and the physical device as a family of actuator models. You can also use this approach to model variations between the passive quarter-car model and actual vehicle dynamics. The resulting family of models comprises a nominal model with a frequency-dependent amount of uncertainty.

Create an uncertain model that represents this family of models.

ActNom = tf(1,[1/60 1]); Wunc = makeweight(0.40,15,3); unc = ultidyn('unc',[1 1],'SampleStateDim',5); Act = ActNom*(1 + Wunc*unc); Act.InputName = 'u'; Act.OutputName = 'fs';

At low frequency, below 3 rad/s, the model can vary up to 40%
from its nominal value. Around 3 rad/s, the percentage variation starts
to increase. The uncertainty crosses 100% at 15 rad/s, and reaches
2000% at approximately 1000 rad/sec. The weighting function, `Wunc`,
reflects this profile and is used to modulate the amount of uncertainty
as a function of frequency. The result `Act` is an
uncertain state-space model of the actuator.

Examine the uncertain actuator model by plotting the frequency
response of 20 randomly sampled models from `Act`.

bode(Act,'b',Act.NominalValue,'r+',logspace(-1,3,120)) title('Nominal and 20 random actuator models')

The plus (+) marker denotes the nominal actuator model. The blue solid lines represent the randomly sampled models.

**Design Objectives for H-Infinity Synthesis**

To use *H*_{∞} synthesis
algorithms, you must express your design objectives as a single cost
function to be minimized. For the quarter-car model, the main control
objectives are formulated in terms of passenger comfort and road handling.
These objectives relate to body acceleration, *a _{b},* and
suspension travel,

Characteristics of the road disturbance

Quality of the sensor measurements for feedback

Limits on the available control force

Use weights to model external disturbances and quantify the design objectives, as shown in the following diagram.

The feedback controller uses the measurements *y*_{1} and *y*_{2} of
the suspension travel, *s _{d}*,
and body acceleration,

The road disturbance,

*r*, which is modeled as a normalized signal,*d*_{1}, which is shaped by a weighting function*W*._{road}Sensor noise on both measurements. This noise is modeled as normalized signals,

*d*_{2}and*d*_{3}, which are shaped by weighting functions*W*_{d2}and*W*_{d3}.

You can reinterpret the control objectives as a disturbance
rejection goal. The goal is to minimize the impact of the disturbances, *d*_{1}, *d*_{2},
and *d*_{3}, on a weighted combination
of suspension travel (*s _{d}*),
body acceleration (

Create the weighting functions that model the design objectives.

Wroad = ss(0.07); Wroad.u = 'd1'; Wroad.y = 'r'; Wact = 8*tf([1 50],[1 500]); Wact.u = 'u'; Wact.y = 'e1'; Wd2 = ss(0.01); Wd2.u = 'd2'; Wd2.y = 'Wd2'; Wd3 = ss(0.5); Wd3.u = 'd3'; Wd3.y = 'Wd3';

The constant weight `Wroad = 0.07` models broadband
road deflections of magnitude 7 cm. `Wact` is a highpass
filter. This filter penalizes high-frequency content in the control
signal, and thus limits control bandwidth. `Wd2` and `Wd3` model
broadband sensor noise of intensity 0.01 and 0.5, respectively. In
a more realistic design, `Wd2` and `Wd3` would
be frequency dependent to model the noise spectrum of the displacement
and acceleration sensors. The inputs and outputs of all weighting
functions are named to facilitate interconnection. The notation `u` and `y` are
shorthand for the `InputName` and `OutputName` properties,
respectively.

Specify target functions for the closed-loop response
of the system from the road disturbance, *r*, to
the suspension deflection, *s _{d}*,
and body acceleration,

HandlingTarget = 0.04 * tf([1/8 1],[1/80 1]); ComfortTarget = 0.4 * tf([1/0.45 1],[1/150 1]); Targets = [HandlingTarget;ComfortTarget];

Because of the actuator uncertainty and imaginary-axis zeros, the targets attenuate disturbances only below 10 rad/s. These targets represent the goals of passenger comfort (small car body acceleration) and adequate road handling (small suspension deflection).

Plot the closed-loop targets and compare to the open-loop response.

bodemag(qcar({'sd','ab'},'r')*Wroad,'b',Targets,'r--',{1,1000}) grid, title('Response to road disturbance') legend('Open-loop','Closed-loop target')

The corresponding performance weights *W _{sd}* and

beta = reshape([0.01 0.5 0.99],[1 1 3]); Wsd = beta/HandlingTarget; Wsd.u = 'sd'; Wsd.y = 'e3'; Wab = (1-beta)/ComfortTarget; Wab.u = 'ab'; Wab.y = 'e2';

`Wsd` and `Wab` are arrays
of weighting functions that correspond to three different trade-offs:
emphasizing comfort (*β* = 0.01), balancing
comfort and handling (*β* = 0.5), and emphasizing
handling (*β* = 0.99).

Connect the quarter-car plant model, actuator model, and weighting functions to construct the block diagram of the plant model weighted by the objectives.

sdmeas = sumblk('y1 = sd+Wd2'); abmeas = sumblk('y2 = ab+Wd3'); ICinputs = {'d1';'d2';'d3';'u'}; ICoutputs = {'e1';'e2';'e3';'y1';'y2'}; qcaric = connect(qcar(2:3,:),Act,Wroad,Wact,Wab,Wsd,Wd2,Wd3,... sdmeas,abmeas,ICinputs,ICoutputs);

`qcaric` is an array of three models, one for
each value of the blending parameter, *β*.
Also, the models in `qcaric` are uncertain, because
they contain the uncertain actuator model Act.

**Nominal H-Infinity Synthesis**

Use `hinfsyn` to compute an *H*_{∞} controller
for each value of the blending parameter, *β*. `hinfsyn` ignores
the uncertainty in the plant models and synthesizes a controller for
the nominal value of each model.

ncont = 1; nmeas = 2; K = ss(zeros(ncont,nmeas,3)); gamma = zeros(3,1); for i=1:3 [K(:,:,i),~,gamma(i)] = hinfsyn(qcaric(:,:,i),nmeas,ncont); end

The weighted plant model has one control input (`ncont`),
the hydraulic actuator force. The model also has two measurement outputs
(`nmeas`), which give the suspension deflection and
body acceleration.

Examine the resulting closed-loop *H*_{∞} norms, `gamma`.

gamma

gamma = 0.9410 0.6724 0.8877

The three *H*_{∞} controllers
achieve closed-loop *H*_{∞} norms
of 0.94 (emphasizing comfort), 0.67 (balancing comfort and handling),
and 0.89 (emphasizing handling).

Construct closed-loop models of the quarter-car plant
with the synthesized controller, corresponding to each of the three
blending parameter values. Compare the frequency response from the
road disturbance to *x _{b}*,

K.u = {'sd','ab'}; K.y = 'u'; CL = connect(qcar,Act.Nominal,K,'r',{'xb';'sd';'ab'}); clf bodemag(qcar(:,'r'),'b', CL(:,:,1),'r-.', ... CL(:,:,2),'m-.', CL(:,:,3),'k:',{1,140}) grid legend('Open-loop','Comfort','Balanced','Handling','location','SouthEast') title('Body travel, suspension deflection, and body acceleration due to road')

The solid blue line corresponds to the open-loop response. The other lines are the closed-loop frequency responses for the different comfort and handling blends. All three controllers reduce suspension deflection and body acceleration below the rattlespace frequency (23 rad/s).

**Time-Domain Evaluation**

To further evaluate the three designs, perform time-domain simulations
using the following road disturbance signal *r*(*t*):

This signal corresponds to a road bump of height 5 cm.

Create a vector that represents the road disturbance.

t = 0:0.005:1; roaddist = zeros(size(t)); roaddist(1:51) = 0.025*(1-cos(8*pi*t(1:51)));

Build the closed-loop model using the synthesized controller.

SIMK = connect(qcar,Act.Nominal,K,'r',{'xb';'sd';'ab';'fs'});

`SIMK` is a model array containing three closed-loop
models, one for each of the three blending parameter values. Each
model in the array represents a closed loop that is built from the
original quarter-car plant model, the nominal actuator model, and
the corresponding synthesized controller.

Simulate and plot the time-domain response of the closed-loop models to the road disturbance signal.

p1 = lsim(qcar(:,1),roaddist,t); y1 = lsim(SIMK(1:4,1,1),roaddist,t); y2 = lsim(SIMK(1:4,1,2),roaddist,t); y3 = lsim(SIMK(1:4,1,3),roaddist,t); clf subplot(221) plot(t,p1(:,1),'b',t,y1(:,1),'r.',t,y2(:,1),'m.',t,y3(:,1),'k.',t,roaddist,'g') title('Body travel') ylabel('x_b (m)') subplot(222) plot(t,p1(:,3),'b',t,y1(:,3),'r.',t,y2(:,3),'m.',t,y3(:,3),'k.',t,roaddist,'g') title('Body acceleration') ylabel('a_b (m/s^2)') subplot(223) plot(t,p1(:,2),'b',t,y1(:,2),'r.',t,y2(:,2),'m.',t,y3(:,2),'k.',t,roaddist,'g') title('Suspension deflection') xlabel('Time (s)') ylabel('s_d (m)') subplot(224) plot(t,zeros(size(t)),'b',t,y1(:,4),'r.',t,y2(:,4),'m.',t,y3(:,4),'k.',t,roaddist,'g') title('Control force') xlabel('Time (s)') ylabel('f_s (N)') legend('Open-loop','Comfort','Balanced','Suspension','Road Disturbance','location','SouthEast')

The simulations show that the body acceleration is smallest for the controller emphasizing passenger comfort. Body acceleration is largest for the controller emphasizing suspension deflection. The balanced design achieves a good tradeoff between body acceleration and suspension deflection.

**Robust μ Design**

So far you designed *H*_{∞} controllers
that meet the performance objectives for the nominal actuator model.
However, this model is only an approximation of the true actuator.
To make sure that controller performance is maintained even with model
error and uncertainty, you must design the model to have *robust
performance*. In this part of the example, you use *μ*-synthesis
to design a controller that achieves robust performance for the entire
family of actuator models that takes uncertainty into account.

Use D-K iteration to synthesize a controller for the quarter-car model with actuator uncertainty.

[Krob,~,RPmuval] = dksyn(qcaric(:,:,2),nmeas,ncont);

The model `qcaric(:,:,2)` is the weighted quarter-car
model for the uncertain model that corresponds to the blending variable *β* =
0.5.

Examine the resulting *μ*-synthesis
controller.

size(Krob)

State-space model with 1 outputs, 2 inputs, and 11 states.

Build the closed-loop model using the robust controller, `Krob`.

Krob.u = {'sd','ab'}; Krob.y = 'u'; SIMKrob = connect(qcar,Act.Nominal,Krob,'r',{'xb';'sd';'ab';'fs'});

Simulate and plot the nominal time-domain response to a road bump with the robust controller.

p1 = lsim(qcar(:,1),roaddist,t); y1 = lsim(SIMKrob(1:4,1),roaddist,t); clf subplot(221) plot(t,p1(:,1),'b',t,y1(:,1),'r',t,roaddist,'g') title('Body travel'), ylabel('x_b (m)') subplot(222) plot(t,p1(:,3),'b',t,y1(:,3),'r') title('Body acceleration'), ylabel('a_b (m/s^2)') subplot(223) plot(t,p1(:,2),'b',t,y1(:,2),'r') title('Suspension deflection'), xlabel('Time (s)'), ylabel('s_d (m)') subplot(224) plot(t,zeros(size(t)),'b',t,y1(:,4),'r') title('Control force'), xlabel('Time (s)'), ylabel('f_s (N)') legend('Open-loop','Robust design','location','SouthEast')

These responses are similar to those obtained with the balanced *H*_{∞} controller.

Examine the effect of the robust controller on variability
caused by model uncertainty. To do so, simulate the response to a
road bump for 120 actuator models randomly sampled from the uncertain
model, `Act`. Perform this simulation for both the *H*_{∞} and
the robust controllers, to compare the results.

Compute an uncertain closed-loop model with the balanced *H*_{∞} controller, `K`.
Sample this model, simulate the sampled models, and plot the results.

CLU = connect(qcar,Act,K(:,:,2),'r',{'xb','sd','ab'}); nsamp = 120; rng('default'); figure(1) clf lsim(usample(CLU,nsamp),'b',CLU.Nominal,'r+',roaddist,t) title('Nominal "balanced" design')

Compute an uncertain closed-loop model with the balanced
robust controller, `Krob`. Sample this model, simulate
the sampled models, and plot the results.

CLU = connect(qcar,Act,Krob,'r',{'xb','sd','ab'}); figure(2) clf lsim(usample(CLU,nsamp),'b',CLU.Nominal,'r+',roaddist,t) title('Robust "balanced" design')

The robust controller reduces variability caused by model uncertainty, and delivers more consistent performance.

**Controller Simplification**

The robust controller `Krob` has eleven states.
It is often the case that controllers synthesized with `dksyn` have
high order. You can use the model reduction functions to find a lower-order
controller that achieves the same level of robust performance. Use `reduce` to
generate approximations of various orders. Then, use `robustperf` to
compute the robust performance margin for each reduced-order approximation.

Create an array of reduced-order controllers.

NS = order(Krob); StateOrders = 1:NS; Kred = reduce(Krob,StateOrders);

`Krob` is a model array containing a reduced-order
controller of every order from 1 up to the original 11 states.

Compute the robust performance margin for each reduced controller.

CLP = lft(qcaric(:,:,2),Kred); ropt = robustperfOptions('Sensitivity','off','Display','off','Mussv','a'); PM = robustperf(CLP,ropt);

Compare the robust performance of the reduced- and full-order controllers.

plot(StateOrders,[PM.LowerBound],'b-o',... StateOrders,repmat(1/RPmuval,[1 NS]),'r'); title('Robust performance as a function of controller order') legend('Reduced order','Full order')

There is no significant difference in robust performance between
the 8th- and 11th-order controllers. Therefore, you can safely replace `Krob` by
its 8th-order approximation.

Krob8 = Kred(:,:,8);

You now have a simplified controller, `Krob8`,
that provides robust control with a balance between passenger comfort
and handling.

Was this topic helpful?