# Tuning Control Systems with SYSTUNE

The `systune` command can jointly tune the gains of your control system regardless of its architecture and number of feedback loops. This example outlines the `systune` workflow on a simple application.

This example uses a 9th-order model of the head-disk assembly (HDA) in a hard-disk drive. This model captures the first few flexible modes in the HDA.

```load rctExamples 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 low-pass 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 steady-state error.

Figure 1: Control Structure

You can use `systune` to directly tune the PI gains and filter coefficient $a$ subject to a variety of time- and frequency-domain requirements.

### Specifying the Tunable Elements

There are two tunable elements in the control structure of Figure 1: the PI controller $C\left(s\right)$ and the low-pass filter

`$F\left(s\right)=\frac{a}{s+a}.$`

You can use the `tunablePID` object to parameterize the PI block:

`C0 = tunablePID('C','pi'); % tunable PI`

To parameterize the lowpass filter $F\left(s\right)$, create a tunable real parameter $a$ and construct a first-order transfer function with numerator $a$ and denominator $s+a$:

```a = realp('a',1); % filter coefficient F0 = tf(a,[1 a]); % filter parameterized by a```

See the "Building Tunable Models" example for an overview of available tunable elements.

### Building a Tunable Closed-Loop Model

Next build a closed-loop model of the feedback loop in Figure 1. To facilitate open-loop analysis and specify open-loop requirements such as desired stability margins, add an analysis point at the plant input `u`:

`AP = AnalysisPoint('u');`

Figure 2: Analysis Point Block

Use `feedback` to build a model of the closed-loop transfer from reference `r` to head position `y`:

```T0 = feedback(G*AP*C0,F0); % closed-loop transfer from r to y T0.InputName = 'r'; T0.OutputName = 'y';```

The result `T0` is a generalized state-space model (`genss`) that depends on the tunable elements $C$ and $F$.

### Specifying the Design Requirements

The `TuningGoal` package contains a variety of control design requirements for specifying the desired behavior of the control system. These include requirements on the response time, deterministic and stochastic gains, loop shape, stability margins, and pole locations. Here we use two requirements to capture the control objectives:

• Tracking requirement : The position `y` should track the reference `r` with a 1 millisecond response time

• Stability margin requirement : The feedback loop should have 6dB of gain margin and 45 degrees of phase margin

Use the `TuningGoal.Tracking` and `TuningGoal.Margins` objects to capture these requirements. Note that the margins requirement applies to the open-loop response measured at the plant input `u` (location marked by the analysis point `AP`).

```Req1 = TuningGoal.Tracking('r','y',0.001); Req2 = TuningGoal.Margins('u',6,45);```

### Tuning the Controller Parameters

You can now use `systune` to tune the PI gain and filter coefficient $a$. This function takes the tunable closed-loop model `T0` and the requirements `Req1,Req2`. Use a few randomized starting points to improve the chances of getting a globally optimal design.

```rng('default') Options = systuneOptions('RandomStart',3); [T,fSoft] = systune(T0,[Req1,Req2],Options);```
```Final: Soft = 1.35, Hard = -Inf, Iterations = 69 Final: Soft = 1.35, Hard = -Inf, Iterations = 101 Final: Soft = 2.78e+03, Hard = -Inf, Iterations = 187 Some closed-loop poles are marginally stable (decay rate near 1e-07) Final: Soft = 1.35, Hard = -Inf, Iterations = 65 ```

All requirements are normalized so a requirement is satisfied when its value is less than 1. Here the final value is slightly greater than 1, indicating that the requirements are nearly satisfied. Use the output `fSoft` to see the tuned value of each requirement. Here we see that the first requirement (tracking) is slightly violated while the second requirement (margins) is satisfied.

`fSoft`
```fSoft = 1×2 1.3483 0.6356 ```

The first output `T` of `systune` is the "tuned" closed-loop model. Use `showTunable` or `getBlockValue` to access the tuned values of the PI gains and filter coefficient:

`getBlockValue(T,'C') % tuned value of PI controller`
```ans = 1 Kp + Ki * --- s with Kp = 0.00104, Ki = 0.0208 Name: C Continuous-time PI controller in parallel form. ```
`showTunable(T) % tuned values of all tunable elements`
```C = 1 Kp + Ki * --- s with Kp = 0.00104, Ki = 0.0208 Name: C Continuous-time PI controller in parallel form. ----------------------------------- a = 3.2e+03 ```

### Validating Results

First use `viewGoal` to inspect how the tuned system does against each requirement. The first plot shows the tracking error as a function of frequency, and the second plot shows the normalized disk margins as a function of frequency (see `diskmargin`). See the "Creating Design Requirements" example for details.

`clf, viewGoal([Req1 Req2],T)`

Next plot the closed-loop step response from reference `r` to head position `y`. The response has no overshoot but wobbles a little.

`clf, step(T)`

To investigate further, use `getLoopTransfer` to get the open-loop response at the plant input.

```L = getLoopTransfer(T,'u'); bode(L,{1e3,1e6}), grid title('Open-loop response')```

The wobble is due to the first resonance after the gain crossover. To eliminate it, you could add a notch filter to the feedback loop and tune its coefficients along with the lowpass coefficient and PI gains using `systune`.