# Tuning Feedback Loops with LOOPTUNE

This example shows the basic workflow of tuning feedback loops with the `looptune` command. `looptune` is similar to `systune` and meant to facilitate loop shaping design by automatically generating the tuning requirements.

### Engine Speed Control

This example uses a simple engine speed control application as illustration. The control system consists of a single PID loop and the PID controller gains must be tuned to adequately respond to step changes in the desired speed. Specifically, we want the response to settle in less than 5 seconds with little or no overshoot.

Figure 1: Engine Speed Control Loop

We use the following fourth-order model of the engine dynamics.

```load rctExamples Engine bode(Engine), grid```

### Specifying the Tunable Elements

We need to tune the four PID gains to achieve the desired performance. Use the `tunablePID` class to parameterize the PID controller.

`PID0 = tunablePID('SpeedController','pid')`
```PID0 = Parametric continuous-time PID controller "SpeedController" with formula: 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 and tunable parameters Kp, Ki, Kd, Tf. Type "pid(PID0)" to see the current value and "get(PID0)" to see all properties. ```

### Building a Tunable Model of the Feedback Loop

`looptune` tunes the generic SISO or MIMO feedback loop of Figure 2. This feedback loop models the interaction between the plant and the controller. Note that this is a positive feedback interconnection.

Figure 2: Generic Feedback Loop

For the speed control loop, the plant $G$ is the engine model and the controller $C$ consists of the PID and the prefilter $F$.

Figure 3: Feedback Loop for Engine Speed Control

To use `looptune`, create models for $G$ and $C$ in Figure 3. Assign names to the inputs and outputs of each model to specify the feedback paths between plant and controller. Note that the controller $C$ has two inputs: the speed reference "r" and the speed measurement "speed".

```F = tf(10,[1 10]); % prefilter G = Engine; G.InputName = 'throttle'; G.OutputName = 'speed'; C0 = PID0 * [F , -1]; C0.InputName = {'r','speed'}; C0.OutputName = 'throttle';```

Here `C0` is a generalized state-space model (`genss`) that depends on the tunable PID block `PID0`.

### Tuning the Controller Parameters

You can now use `looptune` to tune the PID gains subject to a simple control bandwidth requirement. To achieve the 5-second settling time, the gain crossover frequency of the open-loop response should be approximately 1 rad/s. Given this basic requirement, `looptune` automatically shapes the open-loop response to provide integral action, high-frequency roll-off, and adequate stability margins. Note that you could specify additional requirements to further constrain the design, see "Decoupling Controller for a Distillation Column" for an example.

```wc = 1; % target gain crossover frequency [~,C,~,Info] = looptune(G,C0,wc);```
```Final: Peak gain = 0.965, Iterations = 5 Achieved target gain value TargetGain=1. ```

The final value is less than 1, indicating that the desired bandwidth was achieved with adequate roll-off and stability margins. `looptune` returns the tuned controller `C`. Use `getBlockValue` to retrieve the tuned value of the PID block.

`PIDT = getBlockValue(C,'SpeedController')`
```PIDT = 1 s Kp + Ki * --- + Kd * -------- s Tf*s+1 with Kp = 0.00111, Ki = 0.00253, Kd = 0.000359, Tf = 1 Name: SpeedController Continuous-time PIDF controller in parallel form. ```

### Validating Results

Use `loopview` to validate the design and visualize the loop shaping requirements implicitly enforced by `looptune`.

`clf, loopview(G,C,Info)`

Next plot the closed-loop response to a step command in engine speed. The tuned response satisfies our requirements.

```T = connect(G,C,'r','speed'); % closed-loop transfer from r to speed clf, step(T)```
{"extraction_info": {"found_math": true, "script_math_tex": 0, "script_math_asciimath": 0, "math_annotations": 0, "math_alttext": 0, "mathml": 6, "mathjax_tag": 0, "mathjax_inline_tex": 0, "mathjax_display_tex": 0, "mathjax_asciimath": 0, "img_math": 0, "codecogs_latex": 0, "wp_latex": 0, "mimetex.cgi": 0, "/images/math/codecogs": 0, "mathtex.cgi": 0, "katex": 0, "math-container": 0, "wp-katex-eq": 0, "align": 0, "equation": 0, "x-ck12": 0, "texerror": 0, "math_score": 0.6388831734657288, "perplexity": 1744.222610979344}, "config": {"markdown_headings": true, "markdown_code": true, "boilerplate_config": {"ratio_threshold": 0.18, "absolute_threshold": 10, "end_threshold": 15, "enable": true}, "remove_buttons": true, "remove_image_figures": true, "remove_link_clusters": true, "table_config": {"min_rows": 2, "min_cols": 3, "format": "plain"}, "remove_chinese": true, "remove_edit_buttons": true, "extract_latex": true}, "warc_path": "s3://commoncrawl/crawl-data/CC-MAIN-2020-29/segments/1593655891884.11/warc/CC-MAIN-20200707080206-20200707110206-00450.warc.gz"}