@@ -519,6 +519,46 @@ function loopshapingPI(P0, ωp; ϕl=0, rl=0, phasemargin=0, form::Symbol=:standa
519519 (; C, kp, ki, fig, CF)
520520end
521521
522+ function loopshapingPD(P0, ωp; ϕl= 0 , rl= 0 , phasemargin= 0 , form:: Symbol = :standard, doplot= false , Tf = nothing , F= nothing )
523+ issiso(P0) || throw(ArgumentError(" P must be SISO" ))
524+ if F === nothing && Tf != = nothing
525+ F = tf(1 , [Tf^ 2 , 2 * Tf/ sqrt(2 ), 1 ])
526+ end
527+ if F != = nothing
528+ P = P0* F
529+ else
530+ P = P0
531+ end
532+ Pw = freqresp(P, ωp)[]
533+ ϕp = angle(Pw)
534+ rp = abs.(Pw)
535+
536+ if phasemargin > 0
537+ ϕl == 0 || @warn " Both phasemargin and ϕl provided, the provided value for ϕl will be ignored."
538+ ϕl = deg2rad(- 180 + phasemargin)
539+ else
540+ ϕl = ϕl == 0 ? ϕp : ϕl
541+ end
542+ rl = rl == 0 ? rp : rl
543+
544+ kp = rl/ rp* cos(ϕp- ϕl)
545+ kd = rl/ (rp* ωp)* sin(ϕl- ϕp)
546+ C = pid(kp, 0 , kd, form= :parallel)
547+ CF = F === nothing ? C : C* F
548+
549+ fig = if doplot
550+ w = exp10.(LinRange(log10(ωp)- 2 , log10(ωp)+ 2 , 500 ))
551+ f1 = gangoffourplot(P0,CF, w)
552+ f2 = nyquistplot([P0 * CF, P0], w, ylims= (- 4 ,2 ), xlims= (- 4 ,1.2 ), unit_circle= true , show= false , lab= [" PC" " P" ])
553+ RecipesBase. plot!([rl* cos(ϕl)], [rl* sin(ϕl)], lab= " Specification point" , seriestype= :scatter)
554+ RecipesBase. plot(f1, f2)
555+ else
556+ nothing
557+ end
558+ kp, _, kd = convert_pidparams_from_parallel(kp, 0 , kd, form)
559+ (; C, kp, kd, fig, CF)
560+ end
561+
522562
523563"""
524564 C, kp, ki = placePI(P, ω₀, ζ; form=:standard)
0 commit comments