Skip to content

Commit d710dea

Browse files
authored
Merge pull request #996 from JuliaControl/margin_funs
add functions relating Ms peak to gain and phase margins
2 parents 20ed7ea + 3136191 commit d710dea

File tree

5 files changed

+44
-2
lines changed

5 files changed

+44
-2
lines changed

lib/ControlSystemsBase/src/ControlSystemsBase.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ export LTISystem,
8080
output_comp_sensitivity,
8181
G_PS,
8282
G_CS,
83+
margin_bounds,
84+
Ms_from_phase_margin,
85+
Ms_from_gain_margin,
8386
resolvent,
8487
input_resolvent,
8588
# Discrete

lib/ControlSystemsBase/src/analysis.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ end
7373
7474
Count the number of integrators in the system by finding the difference between the number of poles in the origin and the number of zeros in the origin. If the number of zeros in the origin is greater than the number of poles in the origin, the count is negative.
7575
76-
For discrete-tiem systems, the origin ``s = 0`` is replaced by the point ``z = 1``.
76+
For discrete-time systems, the origin ``s = 0`` is replaced by the point ``z = 1``.
7777
"""
7878
function integrator_excess(P::LTISystem)
7979
p = poles(P)

lib/ControlSystemsBase/src/plotting.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ Create a Nyquist plot of the `LTISystem`(s). A frequency vector `w` can be
416416
optionally provided.
417417
418418
- `unit_circle`: if the unit circle should be displayed. The Nyquist curve crosses the unit circle at the gain crossover frequency.
419-
- `Ms_circles`: draw circles corresponding to given levels of sensitivity (circles around -1 with radii `1/Ms`). `Ms_circles` can be supplied as a number or a vector of numbers. A design staying outside such a circle has a phase margin of at least `2asin(1/(2Ms))` rad and a gain margin of at least `Ms/(Ms-1)`.
419+
- `Ms_circles`: draw circles corresponding to given levels of sensitivity (circles around -1 with radii `1/Ms`). `Ms_circles` can be supplied as a number or a vector of numbers. A design staying outside such a circle has a phase margin of at least `2asin(1/(2Ms))` rad and a gain margin of at least `Ms/(Ms-1)`. See also [`margin_bounds`](@ref), [`Ms_from_phase_margin`](@ref) and [`Ms_from_gain_margin`](@ref).
420420
- `Mt_circles`: draw circles corresponding to given levels of complementary sensitivity. `Mt_circles` can be supplied as a number or a vector of numbers.
421421
- `critical_point`: point on real axis to mark as critical for encirclements
422422
- If `hz=true`, the hover information will be displayed in Hertz, the input frequency vector is still treated as rad/s.

lib/ControlSystemsBase/src/sensitivity_functions.jl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ The output [sensitivity function](https://en.wikipedia.org/wiki/Sensitivity_(con
2727
```math
2828
ϕ_m ≥ 2\\text{sin}^{-1}(\\frac{1}{2M_S}), g_m ≥ \\frac{M_S}{M_S-1}
2929
```
30+
(see [`margin_bounds`](@ref) for a function that computes these bounds, and [`Ms_from_phase_margin`](@ref) and [`Ms_from_gain_margin`](@ref) for the inverse functions.)
3031
Generally, bounding ``M_S`` is a better objective than looking at gain and phase margins due to the possibility of combined gain and pahse variations, which may lead to poor robustness despite large gain and pahse margins.
3132
3233
$sensdoc
@@ -35,6 +36,39 @@ function sensitivity(args...)# Sensitivity function
3536
return output_sensitivity(args...)
3637
end
3738

39+
40+
"""
41+
g_m, ϕ_m = margin_bounds(M_S)
42+
43+
Compute the phase margin lower bound ϕ_m (in radians) and gain margin lower bound g_m given a maximum sensitivity peak ``M_S = ||S||_∞``. These bounds are derived from the fact that the inverse of the sensitivity function is the distance from the open-loop Nyquist curve to the critical point -1.
44+
45+
See also [`Ms_from_phase_margin`](@ref) and [`Ms_from_gain_margin`](@ref) for the inverse functions. The circle corresponding to the maximum sensitivity peak ``M_S`` can be plotted in [`nyquistplot`](@ref) by passing the keyword argument `Ms_circles = [Ms]`.
46+
"""
47+
function margin_bounds(M_S)
48+
M_S < 1 && error("Maximum sensitivity peak M_S must be greater than or equal to 1, got $M_S")
49+
ϕ_m = 2 * asin(1 / (2 * M_S))
50+
g_m = M_S / (M_S - 1)
51+
return (; g_m, ϕ_m, ϕ_m_deg = rad2deg(ϕ_m))
52+
end
53+
54+
"""
55+
Ms_from_phase_margin(ϕ_m)
56+
57+
Compute the maximum sensitivity peak ``M_S = ||S||_∞`` such that if respected, gives a phase margin of at least ϕ_m (in radians).
58+
59+
See also [`Ms_from_gain_margin`](@ref) and [`margin_bounds`](@ref).
60+
"""
61+
Ms_from_phase_margin(ϕ_m) = 1 / (2 * sin(ϕ_m / 2))
62+
63+
"""
64+
Ms_from_gain_margin(g_m)
65+
66+
Compute the maximum sensitivity peak ``M_S = ||S||_∞`` such that if respected, gives a gain margin of at least g_m.
67+
68+
See also [`Ms_from_phase_margin`](@ref) and [`margin_bounds`](@ref).
69+
"""
70+
Ms_from_gain_margin(g_m) = g_m / (g_m - 1)
71+
3872
"""
3973
See [`output_comp_sensitivity`](@ref)
4074
$sensdoc

lib/ControlSystemsBase/test/test_analysis.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,11 @@ gof = gangoffour(P,C)
370370
F = ssrand(2,2,2,proper=true)
371371
@test_nowarn gangofseven(P, C, F)
372372

373+
## Test bound functions
374+
M_S = 1.3
375+
g_m, ϕ_m = margin_bounds(M_S)
376+
@test Ms_from_gain_margin(g_m) M_S
377+
@test Ms_from_phase_margin(ϕ_m) M_S
373378

374379
## Approximate double integrator
375380
P = let

0 commit comments

Comments
 (0)