## Documentation Center |

This example shows how to create tunable models of control systems for use with `systune` or `looptune`.

On this page… |
---|

Using Pre-Defined Tunable Elements Interacting with the Tunable Parameters |

You can tune the gains and parameters of your control system with `systune` or `looptune`. To use these commands, you need to construct a tunable model of the control system that identifies and parameterizes its tunable elements. This is done by combining numeric LTI models of the fixed elements with parametric models of the tunable elements.

**Using Pre-Defined Tunable Elements**

You can use one of the following "parametric" blocks to model commonly encountered tunable elements:

**ltiblock.gain**: Tunable gain**ltiblock.pid**: Tunable PID controller**ltiblock.pid2**: Tunable two-degree-of-freedom PID controller**ltiblock.tf**: Tunable transfer function**ltiblock.ss**: Tunable state-space model.

For example, create a tunable model of the feedforward/feedback configuration of Figure 1 where is a tunable PID controller and is a tunable first-order transfer function.

**Figure 1: Control System with Feedforward and Feedback Paths**

First model each block in the block diagram, using suitable parametric blocks for and .

G = tf(1,[1 1]); C = ltiblock.pid('C','pid'); % tunable PID block F = ltiblock.tf('F',0,1); % tunable first-order transfer function

Then use `connect` to build a model of the overall block diagram. To specify how the blocks are connected, label the inputs and outputs of each block and model the summing junctions using `sumblk`.

G.u = 'u'; G.y = 'y'; C.u = 'e'; C.y = 'uC'; F.u = 'r'; F.y = 'uF'; % Summing junctions S1 = sumblk('e = r-y'); S2 = sumblk('u = uF + uC'); T = connect(G,C,F,S1,S2,'r','y')

T = Generalized continuous-time state-space model with 1 outputs, 1 inputs, 3 states, and the following blocks: C: Parametric PID controller, 1 occurrences. F: Parametric SISO transfer function, 0 zeros, 1 poles, 1 occurrences. Type "ss(T)" to see the current value, "get(T)" to see all properties, and "T.Blocks" to interact with the blocks.

This creates a generalized state-space model `T` of the closed-loop transfer function from `r` to `y`. This model depends on the tunable blocks `C` and `F`. You can use `systune` to automatically tune the PID gains and the feedforward coefficients `a,b` subject to your performance requirements. Use `showTunable` to see the current value of the tunable blocks.

showTunable(T)

C = 1 Ki * --- s with Ki = 0.001 Name: C Continuous-time I-only controller. ----------------------------------- F = 10 ------ s + 10 Name: F Continuous-time transfer function.

**Interacting with the Tunable Parameters**

You can adjust the parameterization of the tunable elements
and
by interacting with the objects `C` and `F`. Use `get` to see their list of properties.

get(C)

Kp: [1x1 param.Continuous] Ki: [1x1 param.Continuous] Kd: [1x1 param.Continuous] Tf: [1x1 param.Continuous] IFormula: '' DFormula: '' Ts: 0 TimeUnit: 'seconds' InputName: {'e'} InputUnit: {''} InputGroup: [1x1 struct] OutputName: {'uC'} OutputUnit: {''} OutputGroup: [1x1 struct] Name: 'C' Notes: {} UserData: []

A PID controller has four tunable parameters `Kp,Ki,Kd,Tf`. The tunable block `C` contains a description of each of these parameters. Parameter attributes include current value, minimum and maximum values, and whether the parameter is free or fixed.

C.Kp

ans = Name: 'Kp' Value: 0 Minimum: -Inf Maximum: Inf Free: 1 Scale: 1 Info: [1x1 struct] 1x1 param.Continuous

Set the corresponding attributes to override defaults. For example, you can fix the time constant `Tf` to the value 0.1 by

C.Tf.Value = 0.1; C.Tf.Free = false;

**Creating Custom Tunable Elements**

For tunable elements not covered by the pre-defined blocks listed above, you can create your own parameterization in terms of elementary real parameters (`realp`). Consider the low-pass filter

where the coefficient
is tunable. To model this tunable element, create a real parameter
and define
as a transfer function whose numerator and denominator are functions of
. This creates a generalized state-space model `F` of the low-pass filter parameterized by the tunable scalar `a`.

a = realp('a',1); % real tunable parameter, initial value 1 F = tf(a,[1 a])

F = Generalized continuous-time state-space model with 1 outputs, 1 inputs, 1 states, and the following blocks: a: Scalar parameter, 2 occurrences. Type "ss(F)" to see the current value, "get(F)" to see all properties, and "F.Blocks" to interact with the blocks.

Similarly, you can use real parameters to model the notch filter

with tunable coefficients .

wn = realp('wn',100); zeta1 = realp('zeta1',1); zeta1.Maximum = 1; % zeta1 <= 1 zeta2 = realp('zeta2',1); zeta2.Maximum = 1; % zeta2 <= 1 N = tf([1 2*zeta1*wn wn^2],[1 2*zeta2*wn wn^2]); % tunable notch filter

You can also create tunable elements with matrix-valued parameters. For example, model the observer-based controller with equations

and tunable gain matrices and .

% Plant with 6 states, 2 controls, 3 measurements [A,B,C] = ssdata(rss(6,3,2)); K = realp('K',zeros(2,6)); L = realp('L',zeros(6,3)); C = ss(A-B*K-L*C,L,-K,0)

C = Generalized continuous-time state-space model with 2 outputs, 3 inputs, 6 states, and the following blocks: K: Parametric 2x6 matrix, 2 occurrences. L: Parametric 6x3 matrix, 2 occurrences. Type "ss(C)" to see the current value, "get(C)" to see all properties, and "C.Blocks" to interact with the blocks.

**Enabling Open-Loop Requirements**

The `systune` command takes a closed-loop model of the overall control system, like the tunable model `T` built at the beginning of this example. Such models do not readily support open-loop analysis or open-loop specifications such as loop shapes and stability margins. To gain access to open-loop responses, insert a `loopswitch` block as shown in Figure 2.

**Figure 2: Loop Switch Block**

The `loopswitch` block is an open/closed switch that can be used to open feedback loops or to measure open-loop responses. For example, construct a closed-loop model `T` of the feedback loop of Figure 2 where
is a tunable PID.

G = tf(1,[1 1]); C = ltiblock.pid('C','pid'); LS = loopswitch('X'); T = feedback(G*C,LS);

By default the loop switch "X" is closed and `T` models the closed-loop transfer from
to
. However, you can now use `getLoopTransfer` to compute the (negative-feedback) loop transfer function measured at the location "X". Note that this loop transfer function is
for the feedback loop of Figure 2.

L = getLoopTransfer(T,'X',-1); % loop transfer at "X" clf, bode(L,'b',G*C,'r--')

You can also refer to the location "X" when specifying target loop shapes or stability margins for `systune`. The requirement then applies to the loop transfer measured at this location.

% Target loop shape for loop transfer at "X" Req1 = TuningGoal.LoopShape('X',tf(5,[1 0])); % Target stability margins for loop transfer at "X" Req2 = TuningGoal.Margins('X',6,40);

In general, loop opening locations are specified in the `Location` property of `loopswitch` blocks. For single-loop switches, the block name is used as default location name. For multi-loop switches, indices are appended to the block name to form the default location names.

LS = loopswitch('Y',2); % two-channel switch LS.Location

ans = 'Y(1)' 'Y(2)'

You can override the default location names and use more descriptive names by modifying the `Location` property.

% Rename loop opening locations to "InnerLoop" and "OuterLoop". LS.Location = {'InnerLoop' ; 'OuterLoop'}; LS.Location

ans = 'InnerLoop' 'OuterLoop'

Was this topic helpful?