Skip to content

Commit c653069

Browse files
committed
lighter plots
1 parent 19f7a74 commit c653069

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
[deps]
22
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"
3+
DisplayAs = "0b91fe84-8a4c-11e9-3e1d-67c38462b6d6"
34
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
45
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
56
MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca"
67
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
8+
RobustAndOptimalControl = "21fd56a4-db03-40ee-82ee-a87907bee541"

docs/make.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
ENV["GKSwstype"] = 322 # workaround for gr segfault on GH actions
22
# ENV["GKS_WSTYPE"]=100 # try this if above does not work
33
using Documenter, RobustAndOptimalControl, ControlSystemsBase
4-
4+
# using DisplayAs
5+
ENV["JULIA_DEBUG"]=Documenter # Enable this for debugging
56
using Plots
67
gr()
78

docs/src/uncertainty.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ We will create uncertain parameters using the [`δr`](@ref) constructor from thi
3434
### Basic example
3535
This example shows how to use MonteCarloMeasurements directly to build uncertain systems.
3636
```@example BASIC_MCM
37+
using DisplayAs # hide
3738
using ControlSystemsBase, MonteCarloMeasurements, Plots
3839
gr(fmt=:png) # hide
3940
ω = 1 ± 0.1 # Create an uncertain Gaussian parameter
@@ -50,14 +51,17 @@ G = tf(ω^2, [1, 2ζ*ω, ω^2]) # systems accept uncertain parameters
5051
```@example BASIC_MCM
5152
w = exp10.(-2:0.02:2)
5253
bodeplot(G, w)
54+
DisplayAs.PNG(Plots.current()) # hide
5355
```
5456

5557
```@example BASIC_MCM
5658
plot(step(G, 0:0.1:20))
59+
DisplayAs.PNG(Plots.current()) # hide
5760
```
5861
### Example: Spinning satellite
5962
This example makes use of real-valued uncertain parameters created using [`δr`](@ref), it comes from section 3.7.1 of Skogestad's book.
6063
```@example satellite
64+
using DisplayAs # hide
6165
using RobustAndOptimalControl, ControlSystemsBase, MonteCarloMeasurements, Plots, LinearAlgebra
6266
gr(fmt=:png, size=(640,480)) # hide
6367
unsafe_comparisons(true)
@@ -82,11 +86,13 @@ P = ss([0 a; -a 0], I(2), [1 a; -a 1], 0)
8286
Sp, PSp, CSp, Tp = gangoffour(P, K)
8387
sigmaplot(Sp, w, lab="S")
8488
sigmaplot!(Tp, w, c=2, lab="T", ylims=(0.01, 100))
89+
DisplayAs.PNG(Plots.current()) # hide
8590
```
8691

8792
Not only are sensitivity functions large, they vary a lot under the considered uncertainty. We can also plot a step response of one of the sensitivity functions to check how the system behaves
8893
```@example satellite
8994
plot(step(c2d(Tp, 0.01), 10))
95+
DisplayAs.PNG(Plots.current()) # hide
9096
```
9197
This kind of plot is quite useful, it immediately tells you that this transfer function appears stable, and that there is uncertainty in the static gain etc.
9298

@@ -103,6 +109,7 @@ Ps = P*W
103109
Ss, PSs, CSs, Ts = gangoffour(Ps, K)
104110
sigmaplot(Ss, w, lab="S")
105111
sigmaplot!(Ts, w, c=2, lab="T", ylims=(0.01, 100))
112+
DisplayAs.PNG(Plots.current()) # hide
106113
```
107114

108115
Under this uncertainty, the sensitivity could potentially be sky high., note how some of the 100 realizations peak much higher than the others. This is an indication that the system might be unstable.
@@ -111,13 +118,15 @@ With complex entries in the system model, we can't really plot the step response
111118
```@example satellite
112119
res = step(c2d(Ts, 0.01), 10)
113120
plot(res.t, [abs.(res.y)[1,:,1] abs.(res.y)[2,:,2]]) # plot only the diagonal response
121+
DisplayAs.PNG(Plots.current()) # hide
114122
```
115123
Looks unstable to me. The analysis using $M\Delta$ methodology below will also reach this conclusion.
116124

117125

118126
### Example: Distillation Process
119127
This example comes from section 3.7.2 of Skogestad's book. In this example, we'll explore also complex uncertainties, created using [`δc`](@ref).
120128
```@example distill
129+
using DisplayAs # hide
121130
using RobustAndOptimalControl, ControlSystemsBase, MonteCarloMeasurements, Plots, LinearAlgebra
122131
gr(fmt=:png, size=(640,480)) # hide
123132
unsafe_comparisons(true)
@@ -168,6 +177,7 @@ plot!(step(feedback(G′*Kinv)*F, 20), l=:dash)
168177
res = step(c2d(feedback(Gs*Kinv)*F, 0.01), 20)
169178
mcplot!(res.t, abs.(res.y[:, :, 1]'), alpha=0.3)
170179
mcplot!(res.t, abs.(res.y[:, :, 2]'), alpha=0.3)
180+
DisplayAs.PNG(Plots.current()) # hide
171181
```
172182

173183
The system is very sensitive to real input uncertainty!
@@ -179,6 +189,7 @@ Gs = G*W
179189
res = step(c2d(feedback(Gs*Kinv)*F, 0.01), 20)
180190
mcplot!(res.t, abs.(res.y[:, :, 1]'), alpha=0.3)
181191
mcplot!(res.t, abs.(res.y[:, :, 2]'), alpha=0.3)
192+
DisplayAs.PNG(Plots.current()) # hide
182193
```
183194

184195
How about the sensitivity functions?
@@ -187,14 +198,16 @@ Si = input_sensitivity(Gs, Kinv)
187198
sigmaplot(Si, w, c=1, lab="Si")
188199
So = output_sensitivity(Gs, Kinv)
189200
sigmaplot!(So, w, c=2, lab="So")
201+
DisplayAs.PNG(Plots.current()) # hide
190202
```
191203

192204
The sensitivity at the plant output is enormous. A low sensitivity with the nominal system does not guarantee robustness!
193205

194206
## Model-order reduction for uncertain models
195207
The ``\nu``-gap metric is a measure of distance between models when they are used in a feedback loop. This metric has the nice property that a controller designed for a process ``P`` that achieves a normalized coprime factor margin ([`ncfmargin`](@ref)) of ``m``, will stabilize all models that are within a ``\nu``-gap distance of ``m`` from ``P``. This can be used to reduce the number of uncertain realizations for a model represented with `Particles` like above in a smart way. Say that we have a plant model ``P``
196208
```@example MCM_NUGAP
197-
using RobustAndOptimalControl, ControlSystemsBase, MonteCarloMeasurements
209+
using DisplayAs # hide
210+
using RobustAndOptimalControl, ControlSystemsBase, MonteCarloMeasurements, Plots
198211
ω = with_nominal(0.9 .. 1.1, 1)
199212
ζ = with_nominal(0.5 ± 0.01, 0.5)
200213
P = tf([ω^2], [1, 2*ζ*ω, ω^2]) |> ss
@@ -205,6 +218,7 @@ If we plot ``P``, it looks something like this:
205218
w = exp10.(LinRange(-1, 0.5, 150))
206219
# nyquistplot(P, w, lab="Original P", xlims=(-1.1,1.1), ylims=(-1.5,0.7), points=true, format=:png, dpi=80)
207220
bodeplot(P, w, lab="Original P", plotphase = false, format=:png, dpi=80, ri=false, c=1, legend=true)
221+
DisplayAs.PNG(Plots.current()) # hide
208222
```
209223

210224
We can compute the ``\nu``-gap metric between each realization in ``P`` and the nominal value (encoded using `with_nominal` above):
@@ -225,6 +239,7 @@ here, all realizations that were within a ``\nu``-gap distance of 0.1 from the n
225239
```@example MCM_NUGAP
226240
# nyquistplot(Pr, lab="Reduced P", xlims=(-1.1,1.1), ylims=(-1.5,0.7), points=true, format=:png, dpi=80)
227241
bodeplot!(Pr, w, lab="Reduced P", plotphase = false, format=:png, dpi=80, ri=false, c=2, l=2)
242+
DisplayAs.PNG(Plots.current()) # hide
228243
```
229244
we see that the reduction kept the realizations that were furthest away from the nominal value.
230245

@@ -235,6 +250,7 @@ Prr = nu_reduction_recursive(P, 0.1)
235250
```@example MCM_NUGAP
236251
# nyquistplot(Prr, lab="Recursively reduced P", xlims=(-1.1,1.1), ylims=(-1.5,0.7), points=true, format=:png, dpi=80)
237252
bodeplot!(Prr, w, lab="Recursively reduced P", plotphase = false, format=:png, dpi=80, ri=false, c=3, l=3)
253+
DisplayAs.PNG(Plots.current()) # hide
238254
```
239255
We now have only three realizations left, the nominal one and the two extreme cases (in the ``\nu``-gap sense).
240256

@@ -362,6 +378,7 @@ We can draw samples from this uncertainty representation (sampling of $\Delta$ a
362378
```@example satellite
363379
Psamples = rand(Ps, 100)
364380
sigmaplot(Psamples, w)
381+
DisplayAs.PNG(Plots.current()) # hide
365382
```
366383

367384
We can extract the nominal model using
@@ -410,6 +427,7 @@ TODO
410427

411428
Modeling uncertain time delays can be done in several ways, one approach is to make use of a multiplicative uncertainty weight created using [`neglected_delay`](@ref) multiplied by an uncertain element created using [`δc`](@ref), example:
412429
```@example uncertain_delay
430+
using DisplayAs # hide
413431
using RobustAndOptimalControl, ControlSystemsBase, MonteCarloMeasurements, Plots, LinearAlgebra
414432
gr(fmt=:png, size=(640,480)) # hide
415433
a = 10
@@ -421,6 +439,7 @@ Psamples = rand(Ps, 1000) # Sample the uncertain plant for plotting
421439
w = exp10.(LinRange(-1, 3, 300)) # Frequency vector
422440
bodeplot(Psamples, w, legend=false, N=0, quantile=0)
423441
bodeplot!(P*[delay(0.005) tf(0); tf(0) delay(0.005)], w) # Compare to the plant with a model of the delay
442+
DisplayAs.PNG(Plots.current()) # hide
424443
```
425444
We see that the uncertain model set includes the model with the delay. Note how this approximation approach imparts some uncertainty also in the gain.
426445

@@ -440,6 +459,7 @@ plot(
440459
# plot(step(feedback(P, C), 0:0.0001:0.05), lab="L = " .* string.(P.Tau[].particles'), title="Disturbance response"), # This simulation requires using ControlSystems
441460
nyquistplot(P*C, w[1:10:end], points=true, xlims=(-3.5, 2.5), ylims=(-5, 1.5), Ms_circles=[1.5, 2], alpha=1) # Note, the nyquistplot with uncertain coefficients requires manual selection of plot limits
442461
)
462+
DisplayAs.PNG(Plots.current()) # hide
443463
```
444464
Notice how the gain is completely certain, while the phase starts becoming very uncertain for high frequencies.
445465

@@ -591,6 +611,7 @@ For any of the uncertainty descriptions above, we may plot the total loop gain e
591611
##### Example: Bode plot
592612
Below, we perform this procedure for an multiplicative (relative) uncertainty model at the plant output. The uncertainty weight ``W(s)`` is chosen to give 10% uncertainty at low frequencies and 10x uncertainty at high frequencies, indicating that we are absolutely oblivious to the behavior of the plant at high frequencies. This is often the case, either because identification experiments did not contain excitation for high frequencies, or because the plant had nonlinear behavior at higher frequencies.
593613
```@example UNCERTAIN_VIZ
614+
using DisplayAs # hide
594615
using ControlSystemsBase, RobustAndOptimalControl, Plots
595616
gr(fmt=:png, size=(640,480)) # hide
596617
P = tf(1, [1, 2, 1]) # Plant model
@@ -608,6 +629,7 @@ centers = freqrespv(P*C, w)
608629
radii = abs.(freqrespv(W*P*C, w))
609630
nyquistplot(P*C, w, xlims=(-4,0.1), ylims=(-4,0.1))
610631
nyquistcircles!(w, centers, radii)
632+
DisplayAs.PNG(Plots.current()) # hide
611633
```
612634
If the plots above are created using the `plotly()` backend, each circle is associated with hover information that is accessible by hovering the mouse over the plot. This indicates that the circle that touches the critical point is the one at ``\omega \approx 4.5``, which coincides exactly with the point at thich the Bode plot above touches the inverse weight``W^{-1}``.
613635

0 commit comments

Comments
 (0)