# Smith predictor

This example designs a controller for a plant with a time delay using the internal-model principle, which in this case implies the use of a Smith predictor. The plant is given by $ \dfrac{1}{s + 1}e^{-s\tau} = P_0 e^{-s\tau}$

and the control architecture looks like this

```
┌──────┐ ┌─────────────┐
r │ │ u │ │
───+──+────────►│ C0 ├───────────┬─►│ P0*exp(-st) ├─┐y
▲ ▲ │ │ │ │ │ │
-│ │- └──────┘ │ └─────────────┘ │
│ │ │ │
│ │ ┌──────────┐ ┌──────┐ │ │
│ │ │ │ │ │ │ │
│ └─┤1-exp(-st)│◄───┤ P0 │◄──┘ │
│ │ │ │ │ │
│ └──────────┘ └──────┘ │
│ │
└──────────────────────────────────────────────────┘
```

The benefit of this approach is that the controller $C_0$ can be designed for the nominal plant $P_0$ without time delay, and still behave well in the presence of the delay. We also see why we refer to such a controller as using an "internal model", due to the presence of a model of $P_0$ in the inner feedback path.

We now set up the nominal system and PI controller

```
using ControlSystemsBase, Plots
P0 = ss(-1, 1, 1, 0) # Nominal system
```

```
StateSpace{Continuous, Int64}
A =
-1
B =
1
C =
1
D =
0
Continuous-time state-space model
```

We design a PI controller for nominal system using `placePI`

. To verify the pole placement, use, e.g., `dampreport(feedback(P0, C0))`

```
ω0 = 2
ζ = 0.7
C0, _ = placePI(P0, ω0, ζ)
```

```
(TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
1.7999999999999998s + 4.0
-------------------------
1.0s
Continuous-time transfer function model, 1.7999999999999998, 0.44999999999999996)
```

We then setup delayed plant + Smith predictor-based controller

```
τ = 8
P = delay(τ) * P0
C = feedback(C0, (1.0 - delay(τ))*P0) # form the inner feedback connection in the diagram above
```

```
DelayLtiSystem{Float64, Float64}
P: StateSpace{Continuous, Float64}
A =
0.0 -2.0
2.0 -2.8
B =
2.0 -2.0
1.7999999999999998 -1.7999999999999998
C =
2.0 -1.7999999999999998
0.0 -1.0
D =
1.7999999999999998 -1.7999999999999998
0.0 0.0
Continuous-time state-space model
Delays: [8.0]
```

We now plot the closed loop responses. The transfer function from $r$ to $y$ is given by $PC_r/(1+PC_r)$ = `feedback(P*C,1)`

, and from a load disturbance entering at $u$ the transfer function is $P/(1+PC_r)$ = `feedback(P, C)`

```
using ControlSystems # Load full ControlSystems for delay-system simulation
G = [feedback(P*C, 1) feedback(P, C)] # Reference step at t = 0 and load disturbance step at t = 15
fig_timeresp = plot(lsim(G, (_,t) -> [1; t >= 15], 0:0.1:40), title="τ = $τ")
```

Plot the frequency response of the predictor part and compare to a negative delay, which would be an ideal controller that can (typically) not be realized in practice (a negative delay implies foresight).

```
C_pred = feedback(1, C0*(ss(1.0) - delay(τ))*P0)
fig_bode = bodeplot([C_pred, delay(-τ)], exp10.(-1:0.002:0.4), ls=[:solid :solid :dash :dash], title="", lab=["Smith predictor" "" "Ideal predictor" ""])
plot!(yticks=[0.1, 1, 10], sp=1)
plot!(yticks=0:180:1080, sp=2)
```

Check the Nyquist plot. Note that the Nyquist curve encircles -1 for τ > 2.99

`fig_nyquist = nyquistplot(C * P, exp10.(-1:1e-4:2), title="τ = $τ")`

A video tutorial on delay systems is available here:

## Additional design methods for delay systems

Many standard control-design methods fail for delay systems, or any system not represented as a rational function. In addition to using the Smith predictor outlined above, there are however several common tricks that can be applied to make use of these methods.

- Approximate the delay using a
`pade`

approximation, this will result in a standard rational model. The drawbacks include zeros in the right half plane and a failure to capture the extreme phase loss of the delay for high frequencies. - Discretize the system with a sample time that fits an integer multiple in the delay time. A delay can be represented exactly in discrete time, but if the sample time is chosen small in relation to the delay time, a large number of extra states will be introduced.
- Neglect the delay and design the controller with large phase and delay margins. This is perhaps not a terribly sophisticated method, but nevertheless useful in practice.
- Neglect the delay, but model it as uncertainty. See Modeling uncertain time delays in the RobustAndOptimalControl.jl extension package. This can help you get a feeling for the margin with which you must design your controller when you have neglected to model the delay.
- Frequency-domain methods such as manual loop shaping, and some forms of optimization-based tuning, handle time delays natively.

Whatever method is used to design in the presence of delays, the robustness and performance of the design should preferably be verified using a model of the plant where the delay is included, uncertain or not.