Robust Control Toolbox 

This example uses the hinfstruct command to tune a fixedstructure controller subject to constraints.
On this page… 

The hinfstruct command extends classical synthesis (see hinfsyn) to fixedstructure control systems. This command is meant for users already comfortable with the hinfsyn workflow. If you are unfamiliar with synthesis or find augmented plants and weighting functions intimidating, use systune and looptune instead. See "Tuning Control Systems with SYSTUNE" for the systune counterpart of this example.
This example uses a 9thorder model of the headdisk assembly (HDA) in a harddisk drive. This model captures the first few flexible modes in the HDA.
load hinfstruct_demo G bode(G), grid
We use the feedback loop shown below to position the head on the correct track. This control structure consists of a PI controller and a lowpass filter in the return path. The head position y should track a step change r with a response time of about one millisecond, little or no overshoot, and no steadystate error.
Figure 1: Control Structure
There are two tunable elements in the control structure of Figure 1: the PI controller and the lowpass filter
Use the ltiblock.pid class to parameterize the PI block and specify the filter as a transfer function depending on a tunable real parameter .
C0 = ltiblock.pid('C','pi'); % tunable PI a = realp('a',1); % filter coefficient F0 = tf(a,[1 a]); % filter parameterized by a
Loop shaping is a frequencydomain technique for enforcing requirements on response speed, control bandwidth, rolloff, and steady state error. The idea is to specify a target gain profile or "loop shape" for the openloop response . A reasonable loop shape for this application should have integral action and a crossover frequency of about 1000 rad/s (the reciprocal of the desired response time of 0.001 seconds). This suggests the following loop shape:
wc = 1000; % target crossover s = tf('s'); LS = (1+0.001*s/wc)/(0.001+s/wc); bodemag(LS,{1e1,1e5}), grid, title('Target loop shape')
Note that we chose a biproper, bistable realization to avoid technical difficulties with marginally stable poles and improper inverses. In order to tune and with hinfstruct, we must turn this target loop shape into constraints on the closedloop gains. A systematic way to go about this is to instrument the feedback loop as follows:
Add a measurement noise signal n
Use the target loop shape LS and its reciprocal to filter the error signal e and the white noise source nw.
Figure 2: ClosedLoop Formulation
If denotes the closedloop transfer function from (r,nw) to (y,ew), the gain constraint
secures the following desirable properties:
At low frequency (w<wc), the openloop gain stays above the gain specified by the target loop shape LS
At high frequency (w>wc), the openloop gain stays below the gain specified by LS
The closedloop system has adequate stability margins
The closedloop step response has small overshoot.
We can therefore focus on tuning and to enforce .
Specifying the Control Structure in MATLAB
In MATLAB, you can use the connect command to model by connecting the fixed and tunable components according to the block diagram of Figure 2:
% Label the block I/Os Wn = 1/LS; Wn.u = 'nw'; Wn.y = 'n'; We = LS; We.u = 'e'; We.y = 'ew'; C0.u = 'e'; C0.y = 'u'; F0.u = 'yn'; F0.y = 'yf'; % Specify summing junctions Sum1 = sumblk('e = r  yf'); Sum2 = sumblk('yn = y + n'); % Connect the blocks together T0 = connect(G,Wn,We,C0,F0,Sum1,Sum2,{'r','nw'},{'y','ew'});
These commands construct a generalized statespace model T0 of . This model depends on the tunable blocks C and a:
T0.Blocks
ans = C: [1x1 ltiblock.pid] a: [1x1 realp]
Note that T0 captures the following "Standard Form" of the block diagram of Figure 2 where the tunable components are separated from the fixed dynamics.
Figure 3: Standard Form for DiskDrive Loop Shaping
We are now ready to use hinfstruct to tune the PI controller and filter for the control architecture of Figure 1. To mitigate the risk of local minima, run three optimizations, two of which are started from randomized initial values for C0 and F0:
rng('default') opt = hinfstructOptions('Display','final','RandomStart',5); T = hinfstruct(T0,opt);
Final: Peak gain = 3.88, Iterations = 103 Final: Peak gain = 1.56, Iterations = 115 Final: Peak gain = 597, Iterations = 188 Some closedloop poles are marginally stable (decay rate near 1e07) Final: Peak gain = 1.56, Iterations = 128 Final: Peak gain = 1.56, Iterations = 92 Final: Peak gain = 3.88, Iterations = 56
The best closedloop gain is 1.56, so the constraint is nearly satisfied. The hinfstruct command returns the tuned closedloop transfer . Use showTunable to see the tuned values of and the filter coefficient :
showTunable(T)
C = 1 Kp + Ki *  s with Kp = 0.000846, Ki = 0.0103 Name: C Continuoustime PI controller in parallel form.  a = 5.49e+03
Use getBlockValue to get the tuned value of and use getValue to evaluate the filter for the tuned value of :
C = getBlockValue(T,'C'); F = getValue(F0,T.Blocks); % propagate tuned parameters from T to F tf(F)
ans = From input "yn" to output "yf": 5486  s + 5486 Continuoustime transfer function.
To validate the design, plot the openloop response L=F*G*C and compare with the target loop shape LS:
bode(LS,'r',G*C*F,'b',{1e1,1e6}), grid, title('Openloop response'), legend('Target','Actual')
The 0dB crossover frequency and overall loop shape are as expected. The stability margins can be read off the plot by rightclicking and selecting the Characteristics menu. This design has 24dB gain margin and 81 degrees phase margin. Plot the closedloop step response from reference r to position y:
step(feedback(G*C,F)), grid, title('Closedloop response')
While the response has no overshoot, there is some residual wobble due to the first resonant peaks in G. You might consider adding a notch filter in the forward path to remove the influence of these modes.
Tuning the Controller Gains from Simulink
Suppose you used this Simulink modelSimulink model to represent the control structure. If you have Simulink Control Design installed, you can tune the controller gains from this Simulink model as follows. First mark the signals r,e,y,n as Linear Analysis points in the Simulink model.
Then create an instance of the slTuner interface and mark the Simulink blocks C and F as tunable:
ST0 = slTuner('rct_diskdrive',{'C','F'});
Since the filter has a special structure, explicitly specify how to parameterize the F block:
a = realp('a',1); % filter coefficient setBlockParam(ST0,'F',tf(a,[1 a]));
Finally, use getIOTransfer to derive a tunable model of the closedloop transfer function (see Figure 2)
% Compute tunable model of closedloop transfer (r,n) > (y,e) T0 = getIOTransfer(ST0,{'r','n'},{'y','e'}); % Add weighting functions in n and e channels T0 = blkdiag(1,LS) * T0 * blkdiag(1,1/LS);
You are now ready to tune the controller gains with hinfstruct:
rng(0) opt = hinfstructOptions('Display','final','RandomStart',5); T = hinfstruct(T0,opt);
Final: Peak gain = 3.93, Iterations = 120 Final: Peak gain = 1.56, Iterations = 100 Final: Peak gain = 597, Iterations = 192 Some closedloop poles are marginally stable (decay rate near 1e07) Final: Peak gain = 3.9, Iterations = 108 Final: Peak gain = 1.56, Iterations = 103 Final: Peak gain = 3.88, Iterations = 75
Verify that you obtain the same tuned values as with the MATLAB approach:
showTunable(T)
C = 1 Kp + Ki *  s with Kp = 0.000846, Ki = 0.0103 Name: C Continuoustime PI controller in parallel form.  a = 5.49e+03