Thanks to visit codestin.com
Credit goes to github.com

Skip to content

scipy-based implementation of ss2tf #1108

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 0 additions & 5 deletions control/tests/frd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ def testNyquist(self, frd_fcn):
freqplot.nyquist(f1)
# plt.savefig('/dev/null', format='svg')

@slycotonly
@pytest.mark.parametrize(
"frd_fcn", [ct.frd, ct.FRD, ct.FrequencyResponseData])
def testMIMO(self, frd_fcn):
Expand All @@ -276,7 +275,6 @@ def testMIMO(self, frd_fcn):
sys.frequency_response(chkpts)[1],
f1.frequency_response(chkpts)[1])

@slycotonly
@pytest.mark.parametrize(
"frd_fcn", [ct.frd, ct.FRD, ct.FrequencyResponseData])
def testMIMOfb(self, frd_fcn):
Expand All @@ -295,7 +293,6 @@ def testMIMOfb(self, frd_fcn):
f1.frequency_response(chkpts)[1],
f2.frequency_response(chkpts)[1])

@slycotonly
@pytest.mark.parametrize(
"frd_fcn", [ct.frd, ct.FRD, ct.FrequencyResponseData])
def testMIMOfb2(self, frd_fcn):
Expand All @@ -316,7 +313,6 @@ def testMIMOfb2(self, frd_fcn):
f1.frequency_response(chkpts)[1],
f2.frequency_response(chkpts)[1])

@slycotonly
@pytest.mark.parametrize(
"frd_fcn", [ct.frd, ct.FRD, ct.FrequencyResponseData])
def testMIMOMult(self, frd_fcn):
Expand All @@ -335,7 +331,6 @@ def testMIMOMult(self, frd_fcn):
(f1*f2).frequency_response(chkpts)[1],
(sys*sys).frequency_response(chkpts)[1])

@slycotonly
@pytest.mark.parametrize(
"frd_fcn", [ct.frd, ct.FRD, ct.FrequencyResponseData])
def testMIMOSmooth(self, frd_fcn):
Expand Down
1 change: 0 additions & 1 deletion control/tests/iosys_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2288,7 +2288,6 @@ def test_signal_indexing():
resp.outputs['y[0]', 'u[0]']


@slycotonly
@pytest.mark.parametrize("fcn, spec, expected, missing", [
(ct.ss, {}, "states=4, outputs=3, inputs=2", r"dt|name"),
(ct.tf, {}, "outputs=3, inputs=2", r"dt|states|name"),
Expand Down
2 changes: 0 additions & 2 deletions control/tests/lti_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,6 @@ def test_squeeze_exceptions(self, fcn):
evalfr(sys, [[0.1j, 1j], [1j, 10j]])


@slycotonly
@pytest.mark.parametrize(
"outdx, inpdx, key",
[('y[0]', 'u[1]', (0, 1)),
Expand Down Expand Up @@ -356,7 +355,6 @@ def test_subsys_indexing(fcn, outdx, inpdx, key):
subsys_chk.frequency_response(omega).response)


@slycotonly
@pytest.mark.parametrize("op", [
'__mul__', '__rmul__', '__add__', '__radd__', '__sub__', '__rsub__'])
@pytest.mark.parametrize("fcn", [ct.ss, ct.tf, ct.frd])
Expand Down
1 change: 0 additions & 1 deletion control/tests/matlab2_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ def MIMO_mats(self):
D = zeros((2, 2))
return A, B, C, D

@slycotonly
def test_dcgain_mimo(self, MIMO_mats):
"""Test function dcgain with MIMO systems"""
#Test MIMO systems
Expand Down
5 changes: 0 additions & 5 deletions control/tests/statesp_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,13 @@ def test_zero_siso(self, sys222):

np.testing.assert_almost_equal(true_z, z)

@slycotonly
def test_zero_mimo_sys322_square(self, sys322):
"""Evaluate the zeros of a square MIMO system."""

z = np.sort(sys322.zeros())
true_z = np.sort([44.41465, -0.490252, -5.924398])
np.testing.assert_array_almost_equal(z, true_z)

@slycotonly
def test_zero_mimo_sys222_square(self, sys222):
"""Evaluate the zeros of a square MIMO system."""

Expand Down Expand Up @@ -320,7 +318,6 @@ def test_multiply_ss(self, sys222, sys322):
np.testing.assert_array_almost_equal(sys.C, C)
np.testing.assert_array_almost_equal(sys.D, D)

@slycotonly
def test_add_sub_mimo_siso(self):
# Test SS with SS
ss_siso = StateSpace(
Expand Down Expand Up @@ -702,8 +699,6 @@ def test_call(self, dt, omega, resp):
with pytest.raises(AttributeError):
sys.evalfr(omega)


@slycotonly
def test_freq_resp(self):
"""Evaluate the frequency response at multiple frequencies."""

Expand Down
17 changes: 3 additions & 14 deletions control/tests/xferfcn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import pytest

import control as ct
from control import (StateSpace, TransferFunction, defaults, evalfr, isctime,
isdtime, reset_defaults, rss, sample_system, set_defaults,
ss, ss2tf, tf, tf2ss, zpk)
from control import StateSpace, TransferFunction, defaults, evalfr, isctime, \
isdtime, reset_defaults, rss, sample_system, set_defaults, ss, ss2tf, tf, \
tf2ss, zpk
from control.statesp import _convert_to_statespace
from control.tests.conftest import slycotonly
from control.xferfcn import _convert_to_transfer_function, _tf_close_coeff
Expand Down Expand Up @@ -186,7 +186,6 @@ def test_reverse_sign_siso(self):
np.testing.assert_allclose(sys2.num, [[[-1., -3., -5.]]])
np.testing.assert_allclose(sys2.den, [[[1., 6., 2., -1.]]])

@slycotonly
def test_reverse_sign_mimo(self):
"""Negate a MIMO system."""
num1 = [[[1., 2.], [0., 3.], [2., -1.]],
Expand Down Expand Up @@ -228,7 +227,6 @@ def test_add_siso(self):
np.testing.assert_allclose(sys3.num, [[[20., 4., -8]]])
np.testing.assert_allclose(sys3.den, [[[1., 6., 1., -7., -2., 1.]]])

@slycotonly
def test_add_mimo(self):
"""Add two MIMO systems."""
num1 = [[[1., 2.], [0., 3.], [2., -1.]],
Expand Down Expand Up @@ -276,7 +274,6 @@ def test_subtract_siso(self):
np.testing.assert_allclose(sys4.num, [[[-2., -6., 12., 10., 2.]]])
np.testing.assert_allclose(sys4.den, [[[1., 6., 1., -7., -2., 1.]]])

@slycotonly
def test_subtract_mimo(self):
"""Subtract two MIMO systems."""
num1 = [[[1., 2.], [0., 3.], [2., -1.]],
Expand Down Expand Up @@ -327,7 +324,6 @@ def test_multiply_siso(self):
np.testing.assert_allclose(sys3.num, sys4.num)
np.testing.assert_allclose(sys3.den, sys4.den)

@slycotonly
def test_multiply_mimo(self):
"""Multiply two MIMO systems."""
num1 = [[[1., 2.], [0., 3.], [2., -1.]],
Expand Down Expand Up @@ -714,7 +710,6 @@ def test_call_dtime(self):
sys = TransferFunction([1., 3., 5], [1., 6., 2., -1], 0.1)
np.testing.assert_array_almost_equal(sys(1j), -0.5 - 0.5j)

@slycotonly
def test_call_mimo(self):
"""Evaluate the frequency response of a MIMO system at one frequency."""

Expand Down Expand Up @@ -755,7 +750,6 @@ def test_frequency_response_siso(self):
np.testing.assert_array_almost_equal(phase, truephase)
np.testing.assert_array_almost_equal(omega, trueomega)

@slycotonly
def test_freqresp_mimo(self):
"""Evaluate the MIMO magnitude and phase at multiple frequencies."""
num = [[[1., 2.], [0., 3.], [2., -1.]],
Expand Down Expand Up @@ -852,7 +846,6 @@ def test_common_den_nonproper(self):
_, den2, _ = tf2._common_den(allow_nonproper=True)
np.testing.assert_array_almost_equal(den2, common_den_ref)

@slycotonly
def test_pole_mimo(self):
"""Test for correct MIMO poles."""
sys = TransferFunction(
Expand Down Expand Up @@ -936,7 +929,6 @@ def test_append(self):
tf_appended_2 = tf1.append(tf2).append(tf3)
assert _tf_close_coeff(tf_exp_2, tf_appended_2)

@slycotonly
def test_convert_to_transfer_function(self):
"""Test for correct state space to transfer function conversion."""
A = [[1., -2.], [-3., 4.]]
Expand Down Expand Up @@ -1023,7 +1015,6 @@ def test_state_space_conversion_mimo(self):
np.testing.assert_array_almost_equal(H.num[1][0], H2.num[1][0])
np.testing.assert_array_almost_equal(H.den[1][0], H2.den[1][0])

@slycotonly
def test_indexing(self):
"""Test TF scalar indexing and slice"""
tm = ss2tf(rss(5, 3, 3))
Expand Down Expand Up @@ -1213,7 +1204,6 @@ def test_printing_polynomial(self, args, outputfmt, var, dt, dtstring):
assert len(polystr[0].split('\n')) == 4
assert polystr[2] == outputfmt.format(var=var)

@slycotonly
def test_printing_mimo(self):
"""Print MIMO, continuous time"""
sys = ss2tf(rss(4, 2, 3))
Expand Down Expand Up @@ -1332,7 +1322,6 @@ def test_printing_zpk_mimo(self, num, den, output):
res = str(G)
assert res.partition('\n\n')[2] == output

@slycotonly
def test_size_mismatch(self):
"""Test size mismacht"""
sys1 = ss2tf(rss(2, 2, 2))
Expand Down
29 changes: 13 additions & 16 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,12 @@ def _convert_to_transfer_function(
den = [[[1.] for j in range(sys.ninputs)]
for i in range(sys.noutputs)]
else:
# Preallocate numerator and denominator arrays
num = [[[] for j in range(sys.ninputs)]
for i in range(sys.noutputs)]
den = [[[] for j in range(sys.ninputs)]
for i in range(sys.noutputs)]

try:
# Use Slycot to make the transformation
# Make sure to convert system matrices to numpy arrays
Expand All @@ -1524,12 +1530,6 @@ def _convert_to_transfer_function(
sys.nstates, sys.ninputs, sys.noutputs, array(sys.A),
array(sys.B), array(sys.C), array(sys.D), tol1=0.0)

# Preallocate outputs.
num = [[[] for j in range(sys.ninputs)]
for i in range(sys.noutputs)]
den = [[[] for j in range(sys.ninputs)]
for i in range(sys.noutputs)]

for i in range(sys.noutputs):
for j in range(sys.ninputs):
num[i][j] = list(tfout[6][i, j, :])
Expand All @@ -1538,16 +1538,13 @@ def _convert_to_transfer_function(
den[i][j] = list(tfout[5][i, :])

except ImportError:
# If slycot is not available, use signal.lti (SISO only)
if sys.ninputs != 1 or sys.noutputs != 1:
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
num, den = sp.signal.ss2tf(sys.A, sys.B, sys.C, sys.D)
num = squeeze(num) # Convert to 1D array
den = squeeze(den) # Probably not needed
# If slycot not available, do conversion using sp.signal.ss2tf
for j in range(sys.ninputs):
num_j, den_j = sp.signal.ss2tf(
sys.A, sys.B, sys.C, sys.D, input=j)
for i in range(sys.noutputs):
num[i][j] = num_j[i]
den[i][j] = den_j

newsys = TransferFunction(num, den, sys.dt)
if use_prefix_suffix:
Expand Down
Loading