Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
misc bugfixes: fixed prewarp not working in c2d and sample_system, in…
…correct order of return arguments in margin, typos and changed to ControlMIMONotImplemented error where needed.
  • Loading branch information
sawyerbfuller committed Nov 5, 2021
commit ca8e67025c1b429ef8fb57541eb449059eddd8a5
6 changes: 4 additions & 2 deletions control/dtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):
if not isctime(sysc):
raise ValueError("First argument must be continuous time system")

return sysc.sample(Ts, method, alpha, prewarp_frequency)
return sysc.sample(Ts,
method=method, alpha=alpha, prewarp_frequency=prewarp_frequency)
Comment thread
sawyerbfuller marked this conversation as resolved.


def c2d(sysc, Ts, method='zoh', prewarp_frequency=None):
Expand Down Expand Up @@ -126,6 +127,7 @@ def c2d(sysc, Ts, method='zoh', prewarp_frequency=None):
"""

# Call the sample_system() function to do the work
sysd = sample_system(sysc, Ts, method, prewarp_frequency)
sysd = sample_system(sysc, Ts,
method=method, prewarp_frequency=prewarp_frequency)
Comment thread
sawyerbfuller marked this conversation as resolved.

return sysd
8 changes: 4 additions & 4 deletions control/margins.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ def stability_margins(sysdata, returnall=False, epsw=0.0, method='best'):
-------
gm : float or array_like
Gain margin
pm : float or array_loke
pm : float or array_like
Phase margin
sm : float or array_like
Stability margin, the minimum distance from the Nyquist plot to -1
Expand Down Expand Up @@ -522,10 +522,10 @@ def margin(*args):
Gain margin
pm : float
Phase margin (in degrees)
wpc : float or array_like
Phase crossover frequency (where phase crosses -180 degrees)
wgc : float or array_like
Gain crossover frequency (where gain crosses 1)
wpc : float or array_like
Phase crossover frequency (where phase crosses -180 degrees)
Comment thread
bnavigator marked this conversation as resolved.
Outdated

Margins are calculated for a SISO open-loop system.

Expand All @@ -548,4 +548,4 @@ def margin(*args):
raise ValueError("Margin needs 1 or 3 arguments; received %i."
% len(args))

return margin[0], margin[1], margin[3], margin[4]
return margin[0], margin[1], margin[4], margin[3]
20 changes: 10 additions & 10 deletions control/tests/margin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ def test_margin_sys(tsys):
sys, refout, refoutall = tsys
"""Test margin() function with system input"""
out = margin(sys)
assert_allclose(out, np.array(refout)[[0, 1, 3, 4]], atol=1.5e-3)
assert_allclose(out, np.array(refout)[[0, 1, 4, 3]], atol=1.5e-3)

def test_margin_3input(tsys):
sys, refout, refoutall = tsys
"""Test margin() function with mag, phase, omega input"""
omega = np.logspace(-2, 2, 2000)
mag, phase, omega_ = sys.frequency_response(omega)
out = margin((mag, phase*180/np.pi, omega_))
assert_allclose(out, np.array(refout)[[0, 1, 3, 4]], atol=1.5e-3)
assert_allclose(out, np.array(refout)[[0, 1, 4, 3]], atol=1.5e-3)


@pytest.mark.parametrize(
Expand Down Expand Up @@ -276,23 +276,23 @@ def tsys_zmore(request, tsys_zmoresystems):
@pytest.mark.parametrize(
'tsys_zmore',
[dict(sysname='typem1', K=2.0, atol=1.5e-3,
result=(float('Inf'), -120.0007, float('NaN'), 0.5774)),
result=(float('Inf'), -120.0007, 0.5774, float('NaN'))),
dict(sysname='type0', K=0.8, atol=1.5e-3,
result=(10.0014, float('inf'), 1.7322, float('nan'))),
result=(10.0014, float('inf'), float('nan'), 1.7322)),
dict(sysname='type0', K=2.0, atol=1e-2,
result=(4.000, 67.6058, 1.7322, 0.7663)),
result=(4.000, 67.6058, 0.7663, 1.7322)),
dict(sysname='type1', K=1.0, atol=1e-4,
result=(float('Inf'), 144.9032, float('NaN'), 0.3162)),
result=(float('Inf'), 144.9032, 0.3162, float('NaN'))),
dict(sysname='type2', K=1.0, atol=1e-4,
result=(float('Inf'), 44.4594, float('NaN'), 0.7907)),
result=(float('Inf'), 44.4594, 0.7907, float('NaN'))),
dict(sysname='type3', K=1.0, atol=1.5e-3,
result=(0.0626, 37.1748, 0.1119, 0.7951)),
result=(0.0626, 37.1748, 0.7951, 0.1119)),
dict(sysname='example21', K=1.0, atol=1e-2,
result=(0.0100, -14.5640, 0, 0.0022)),
dict(sysname='example21', K=1000.0, atol=1e-2,
result=(0.1793, 22.5215, 0.0243, 0.0630)),
result=(0.1793, 22.5215, 0.0630, 0.0243)),
dict(sysname='example21', K=5000.0, atol=1.5e-3,
result=(4.5596, 21.2101, 0.4385, 0.1868)),
result=(4.5596, 21.2101, 0.1868, 0.4385)),
],
indirect=True)
def test_zmore_margin(tsys_zmore):
Expand Down
6 changes: 3 additions & 3 deletions control/tests/matlab_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ def testMargin(self, siso):
gm, pm, wg, wp = margin(siso.ss2)
gm, pm, wg, wp = margin(siso.ss2 * siso.ss2 * 2)
np.testing.assert_array_almost_equal(
[gm, pm, wg, wp], [1.5451, 75.9933, 1.2720, 0.6559], decimal=3)
[gm, pm, wg, wp], [1.5451, 75.9933, 0.6559, 1.2720], decimal=3)

def testDcgain(self, siso):
"""Test dcgain() for SISO system"""
Expand Down Expand Up @@ -785,8 +785,8 @@ def testCombi01(self):
# print("%f %f %f %f" % (gm, pm, wg, wp))
np.testing.assert_allclose(gm, 3.32065569155)
np.testing.assert_allclose(pm, 46.9740430224)
np.testing.assert_allclose(wg, 0.176469728448)
np.testing.assert_allclose(wp, 0.0616288455466)
np.testing.assert_allclose(wg, 0.0616288455466)
np.testing.assert_allclose(wp, 0.176469728448)

def test_tf_string_args(self):
"""Make sure s and z are defined properly"""
Expand Down
12 changes: 7 additions & 5 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
from itertools import chain
from re import sub
from .lti import LTI, common_timebase, isdtime, _process_frequency_response
from .exception import ControlMIMONotImplemented
from . import config

__all__ = ['TransferFunction', 'tf', 'ss2tf', 'tfdata']
Expand Down Expand Up @@ -793,9 +794,9 @@ def feedback(self, other=1, sign=-1):
if (self.ninputs > 1 or self.noutputs > 1 or
other.ninputs > 1 or other.noutputs > 1):
# TODO: MIMO feedback
raise NotImplementedError(
"TransferFunction.feedback is currently only implemented "
"for SISO functions.")
raise ControlMIMONotImplemented(
"TransferFunction.feedback is currently not implemented for "
"MIMO systems.")
dt = common_timebase(self.dt, other.dt)

num1 = self.num[0][0]
Expand Down Expand Up @@ -1117,7 +1118,7 @@ def sample(self, Ts, method='zoh', alpha=None, prewarp_frequency=None):
if not self.isctime():
raise ValueError("System must be continuous time system")
if not self.issiso():
raise NotImplementedError("MIMO implementation not available")
raise ControlMIMONotImplemented("Not implemented for MIMO systems")
if method == "matched":
return _c2d_matched(self, Ts)
sys = (self.num[0][0], self.den[0][0])
Expand Down Expand Up @@ -1373,7 +1374,8 @@ def _convert_to_transfer_function(sys, **kw):
except ImportError:
# If slycot is not available, use signal.lti (SISO only)
if sys.ninputs != 1 or sys.noutputs != 1:
raise TypeError("No support for MIMO without slycot.")
raise ControlMIMONotImplemented("Not implemented for " +
"MIMO systems without slycot.")

# Do the conversion using sp.signal.ss2tf
# Note that this returns a 2D array for the numerator
Expand Down