Skip to content

Commit 8bb2312

Browse files
authored
add options and more docstring to loopshapingPI (#745)
* add options and more docstring to loopshapingPI * convert to correct output form
1 parent e9460ef commit 8bb2312

2 files changed

Lines changed: 27 additions & 10 deletions

File tree

src/pid_design.jl

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ end
382382

383383

384384
"""
385-
C, kp, ki, fig = loopshapingPI(P, ωp; ϕl, rl, phasemargin, form=:standard, doplot=false)
385+
C, kp, ki, fig, CF = loopshapingPI(P, ωp; ϕl, rl, phasemargin, form=:standard, doplot=false, Tf, F)
386386
387387
Selects the parameters of a PI-controller (on parallel form) such that the Nyquist curve of `P` at the frequency `ωp` is moved to `rl exp(i ϕl)`
388388
@@ -396,12 +396,22 @@ If `phasemargin` is supplied (in degrees), `ϕl` is selected such that the curve
396396
397397
If no `rl` is given, the magnitude of the curve at `ωp` is kept the same and only the phase is affected, the same goes for `ϕl` if no phasemargin is given.
398398
399-
Set `doplot = true` to plot the `gangoffourplot` and `nyquistplot` of the system.
399+
- `Tf`: An optional time constant for second-order measurement noise filter on the form `tf(1, [Tf^2, 2*Tf/sqrt(2), 1])` to make the controller strictly proper.
400+
- `F`: A pre-designed filter to use instead of the default second-order filter that is used if `Tf` is given.
401+
- `doplot` plot the `gangoffourplot` and `nyquistplot` of the system.
400402
401403
See also [`loopshapingPID`](@ref), [`pidplots`](@ref), [`stabregionPID`](@ref) and [`placePI`](@ref).
402404
"""
403-
function loopshapingPI(P, ωp; ϕl=0, rl=0, phasemargin=0, form::Symbol=:standard, doplot=false)
404-
issiso(P) || throw(ArgumentError("P must be SISO"))
405+
function loopshapingPI(P0, ωp; ϕl=0, rl=0, phasemargin=0, form::Symbol=:standard, doplot=false, Tf = nothing, F=nothing)
406+
issiso(P0) || throw(ArgumentError("P must be SISO"))
407+
if F === nothing && Tf !== nothing
408+
F = tf(1, [Tf^2, 2*Tf/sqrt(2), 1])
409+
end
410+
if F !== nothing
411+
P = P0*F
412+
else
413+
P = P0
414+
end
405415
Pw = freqresp(P, ωp)[]
406416
ϕp = angle(Pw)
407417
rp = abs.(Pw)
@@ -416,18 +426,20 @@ function loopshapingPI(P, ωp; ϕl=0, rl=0, phasemargin=0, form::Symbol=:standar
416426

417427
kp = rl/rp*cos(ϕp-ϕl)
418428
ki = rl*ωp/rp*sin(ϕp-ϕl)
419-
420-
Kp, Ti, Td = convert_pidparams_to_standard(kp, ki, 0, :parallel)
421-
C = pid(Kp, Ti, Td)
429+
C = pid(kp, ki, 0, form=:parallel)
430+
CF = F === nothing ? C : C*F
422431

423432
fig = if doplot
424-
f1 = gangoffourplot(P,[tf(1),C])
425-
f2 = nyquistplot([P, P*C])
433+
w = exp10.(LinRange(log10(ωp)-2, log10(ωp)+2, 500))
434+
f1 = gangoffourplot(P0,CF, w)
435+
f2 = nyquistplot([P0 * CF, P0], w, ylims=(-4,2), xlims=(-4,1.2), unit_circle=true, show=false, lab=["PC" "P"])
436+
RecipesBase.plot!([rl*cos(ϕl)], [rl*sin(ϕl)], lab="Specification point", seriestype=:scatter)
426437
RecipesBase.plot(f1, f2)
427438
else
428439
nothing
429440
end
430-
C, convert_pidparams_from_standard(Kp, Ti, Td, form)[1:2]..., fig
441+
kp, ki = convert_pidparams_from_to(kp, ki, 0, :parallel, form)
442+
(; C, kp, ki, fig, CF)
431443
end
432444

433445

test/test_pid_design.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ C, kp, ki = loopshapingPI(P,10; phasemargin = 30, doplot = false)
4646
_,_,_,pm = margin(P*C)
4747
@test pm[] > 30
4848

49+
C, kp, ki, fig, CF = loopshapingPI(P,1; phasemargin = 45, doplot = true, Tf = 0.1)
50+
_,_,_,pm = margin(P*CF)
51+
@test pm[] > 45*0.99
52+
53+
4954
# Test placePI
5055
P = tf(1,[1, 1])
5156
C, Kp, Ti = placePI(P, 2, 0.7; form=:standard)

0 commit comments

Comments
 (0)