Skip to content

Commit fae3595

Browse files
committed
Fix bug in stability_margins
Fixes #58. The documentation is also updated to specify the units of the inputs and outputs. Also, previously there was an optional argument `deg` which the docstring claimed was used to specify the units of the input/output phases, but this was never actually used in the implementation. This commit removes that optional argument.
1 parent c1c35d1 commit fae3595

1 file changed

Lines changed: 29 additions & 25 deletions

File tree

control/margins.py

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -82,38 +82,41 @@ def _polysqr(pol):
8282
#
8383
# RvP, July 8, 2014, corrected to exclude phase=0 crossing for the gain
8484
# margin polynomial
85-
def stability_margins(sysdata, deg=True, returnall=False, epsw=1e-10):
86-
"""Calculate gain, phase and stability margins and associated
87-
crossover frequencies.
85+
def stability_margins(sysdata, returnall=False, epsw=1e-10):
86+
"""Calculate stability margins and associated crossover frequencies.
8887
8988
Parameters
9089
----------
91-
sysdata: linsys or (mag, phase, omega) sequence
92-
sys : linsys
90+
sysdata: LTI system or (mag, phase, omega) sequence
91+
sys : LTI system
9392
Linear SISO system
9493
mag, phase, omega : sequence of array_like
95-
Input magnitude, phase, and frequencies (rad/sec) sequence from
96-
bode frequency response data
97-
deg=True: boolean
98-
If true, all input and output phases in degrees, else in radians
99-
returnall=False: boolean
100-
If true, return all margins found. Note that for frequency data or
101-
FRD systems, only one margin is found and returned.
102-
epsw=1e-10: float
103-
frequencies below this value are considered static gain, and not
104-
returned as margin.
94+
Arrays of magnitudes (absolute values, not dB), phases (degrees),
95+
and corresponding frequencies. Crossover frequencies returned are
96+
in the same units as those in `omega` (e.g., rad/sec or Hz).
97+
returnall: bool, optional
98+
If true, return all margins found. If false (default), return only the
99+
minimum stability margins. For frequency data or FRD systems, only one
100+
margin is found and returned.
101+
epsw: float, optional
102+
Frequencies below this value (default 1e-10) are considered static gain,
103+
and not returned as margin.
105104
106105
Returns
107106
-------
108-
gm, pm, sm, wg, wp, ws: float or array_like
109-
Gain margin gm, phase margin pm, stability margin sm, and
110-
associated crossover
111-
frequencies wg, wp, and ws of SISO open-loop. If more than
112-
one crossover frequency is detected, returns the lowest corresponding
113-
margin.
114-
When requesting all margins, the return values are array_like,
115-
and all margins are returns for linear systems not equal to FRD
116-
"""
107+
gm: float or array_like
108+
Gain margin
109+
pm: float or array_loke
110+
Phase margin
111+
sm: float or array_like
112+
Stability margin, the minimum distance from the Nyquist plot to -1
113+
wg: float or array_like
114+
Gain margin crossover frequency (where phase crosses -180 degrees)
115+
wp: float or array_like
116+
Phase margin crossover frequency (where gain crosses 0 dB)
117+
ws: float or array_like
118+
Stability margin frequency (where Nyquist plot is closest to -1)
119+
"""
117120

118121
try:
119122
if isinstance(sysdata, frdata.FRD):
@@ -122,7 +125,8 @@ def stability_margins(sysdata, deg=True, returnall=False, epsw=1e-10):
122125
sys = sysdata
123126
elif getattr(sysdata, '__iter__', False) and len(sysdata) == 3:
124127
mag, phase, omega = sysdata
125-
sys = frdata.FRD(mag*np.exp((1j/360.)*phase), omega, smooth=True)
128+
sys = frdata.FRD(mag * np.exp(1j * phase * np.pi/180), omega,
129+
smooth=True)
126130
else:
127131
sys = xferfcn._convertToTransferFunction(sysdata)
128132
except Exception as e:

0 commit comments

Comments
 (0)