Skip to content

Commit ca8e670

Browse files
committed
misc bugfixes: fixed prewarp not working in c2d and sample_system, incorrect order of return arguments in margin, typos and changed to ControlMIMONotImplemented error where needed.
1 parent e9c224c commit ca8e670

5 files changed

Lines changed: 28 additions & 24 deletions

File tree

control/dtime.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ def sample_system(sysc, Ts, method='zoh', alpha=None, prewarp_frequency=None):
8989
if not isctime(sysc):
9090
raise ValueError("First argument must be continuous time system")
9191

92-
return sysc.sample(Ts, method, alpha, prewarp_frequency)
92+
return sysc.sample(Ts,
93+
method=method, alpha=alpha, prewarp_frequency=prewarp_frequency)
9394

9495

9596
def c2d(sysc, Ts, method='zoh', prewarp_frequency=None):
@@ -126,6 +127,7 @@ def c2d(sysc, Ts, method='zoh', prewarp_frequency=None):
126127
"""
127128

128129
# Call the sample_system() function to do the work
129-
sysd = sample_system(sysc, Ts, method, prewarp_frequency)
130+
sysd = sample_system(sysc, Ts,
131+
method=method, prewarp_frequency=prewarp_frequency)
130132

131133
return sysd

control/margins.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def stability_margins(sysdata, returnall=False, epsw=0.0, method='best'):
283283
-------
284284
gm : float or array_like
285285
Gain margin
286-
pm : float or array_loke
286+
pm : float or array_like
287287
Phase margin
288288
sm : float or array_like
289289
Stability margin, the minimum distance from the Nyquist plot to -1
@@ -522,10 +522,10 @@ def margin(*args):
522522
Gain margin
523523
pm : float
524524
Phase margin (in degrees)
525-
wpc : float or array_like
526-
Phase crossover frequency (where phase crosses -180 degrees)
527525
wgc : float or array_like
528526
Gain crossover frequency (where gain crosses 1)
527+
wpc : float or array_like
528+
Phase crossover frequency (where phase crosses -180 degrees)
529529
530530
Margins are calculated for a SISO open-loop system.
531531
@@ -548,4 +548,4 @@ def margin(*args):
548548
raise ValueError("Margin needs 1 or 3 arguments; received %i."
549549
% len(args))
550550

551-
return margin[0], margin[1], margin[3], margin[4]
551+
return margin[0], margin[1], margin[4], margin[3]

control/tests/margin_test.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,15 +102,15 @@ def test_margin_sys(tsys):
102102
sys, refout, refoutall = tsys
103103
"""Test margin() function with system input"""
104104
out = margin(sys)
105-
assert_allclose(out, np.array(refout)[[0, 1, 3, 4]], atol=1.5e-3)
105+
assert_allclose(out, np.array(refout)[[0, 1, 4, 3]], atol=1.5e-3)
106106

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

115115

116116
@pytest.mark.parametrize(
@@ -276,23 +276,23 @@ def tsys_zmore(request, tsys_zmoresystems):
276276
@pytest.mark.parametrize(
277277
'tsys_zmore',
278278
[dict(sysname='typem1', K=2.0, atol=1.5e-3,
279-
result=(float('Inf'), -120.0007, float('NaN'), 0.5774)),
279+
result=(float('Inf'), -120.0007, 0.5774, float('NaN'))),
280280
dict(sysname='type0', K=0.8, atol=1.5e-3,
281-
result=(10.0014, float('inf'), 1.7322, float('nan'))),
281+
result=(10.0014, float('inf'), float('nan'), 1.7322)),
282282
dict(sysname='type0', K=2.0, atol=1e-2,
283-
result=(4.000, 67.6058, 1.7322, 0.7663)),
283+
result=(4.000, 67.6058, 0.7663, 1.7322)),
284284
dict(sysname='type1', K=1.0, atol=1e-4,
285-
result=(float('Inf'), 144.9032, float('NaN'), 0.3162)),
285+
result=(float('Inf'), 144.9032, 0.3162, float('NaN'))),
286286
dict(sysname='type2', K=1.0, atol=1e-4,
287-
result=(float('Inf'), 44.4594, float('NaN'), 0.7907)),
287+
result=(float('Inf'), 44.4594, 0.7907, float('NaN'))),
288288
dict(sysname='type3', K=1.0, atol=1.5e-3,
289-
result=(0.0626, 37.1748, 0.1119, 0.7951)),
289+
result=(0.0626, 37.1748, 0.7951, 0.1119)),
290290
dict(sysname='example21', K=1.0, atol=1e-2,
291291
result=(0.0100, -14.5640, 0, 0.0022)),
292292
dict(sysname='example21', K=1000.0, atol=1e-2,
293-
result=(0.1793, 22.5215, 0.0243, 0.0630)),
293+
result=(0.1793, 22.5215, 0.0630, 0.0243)),
294294
dict(sysname='example21', K=5000.0, atol=1.5e-3,
295-
result=(4.5596, 21.2101, 0.4385, 0.1868)),
295+
result=(4.5596, 21.2101, 0.1868, 0.4385)),
296296
],
297297
indirect=True)
298298
def test_zmore_margin(tsys_zmore):

control/tests/matlab_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ def testMargin(self, siso):
361361
gm, pm, wg, wp = margin(siso.ss2)
362362
gm, pm, wg, wp = margin(siso.ss2 * siso.ss2 * 2)
363363
np.testing.assert_array_almost_equal(
364-
[gm, pm, wg, wp], [1.5451, 75.9933, 1.2720, 0.6559], decimal=3)
364+
[gm, pm, wg, wp], [1.5451, 75.9933, 0.6559, 1.2720], decimal=3)
365365

366366
def testDcgain(self, siso):
367367
"""Test dcgain() for SISO system"""
@@ -785,8 +785,8 @@ def testCombi01(self):
785785
# print("%f %f %f %f" % (gm, pm, wg, wp))
786786
np.testing.assert_allclose(gm, 3.32065569155)
787787
np.testing.assert_allclose(pm, 46.9740430224)
788-
np.testing.assert_allclose(wg, 0.176469728448)
789-
np.testing.assert_allclose(wp, 0.0616288455466)
788+
np.testing.assert_allclose(wg, 0.0616288455466)
789+
np.testing.assert_allclose(wp, 0.176469728448)
790790

791791
def test_tf_string_args(self):
792792
"""Make sure s and z are defined properly"""

control/xferfcn.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
from itertools import chain
6565
from re import sub
6666
from .lti import LTI, common_timebase, isdtime, _process_frequency_response
67+
from .exception import ControlMIMONotImplemented
6768
from . import config
6869

6970
__all__ = ['TransferFunction', 'tf', 'ss2tf', 'tfdata']
@@ -793,9 +794,9 @@ def feedback(self, other=1, sign=-1):
793794
if (self.ninputs > 1 or self.noutputs > 1 or
794795
other.ninputs > 1 or other.noutputs > 1):
795796
# TODO: MIMO feedback
796-
raise NotImplementedError(
797-
"TransferFunction.feedback is currently only implemented "
798-
"for SISO functions.")
797+
raise ControlMIMONotImplemented(
798+
"TransferFunction.feedback is currently not implemented for "
799+
"MIMO systems.")
799800
dt = common_timebase(self.dt, other.dt)
800801

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

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

0 commit comments

Comments
 (0)