8000 Merge pull request #793 from sawyerbfuller/interconnect-tf · roryyorke/python-control@2dc409b · GitHub
[go: up one dir, main page]

Skip to content

Commit 2dc409b

Browse files
authored
Merge pull request python-control#793 from sawyerbfuller/interconnect-tf
fix error when an IOSystem is combined with a TransferFunction system
2 parents 5180c7b + 3729027 commit 2dc409b

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

control/iosys.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ def __init__(self, syslist, connections=None, inplist=None, outlist=None,
890890
kwargs, defaults, end=True)
891891

892892
# Initialize the system list and index
893-
self.syslist = syslist
893+
self.syslist = list(syslist) # insure modifications can be made
894894
self.syslist_index = {}
895895

896896
# Initialize the input, output, and state counts, indices
@@ -903,12 +903,12 @@ def __init__(self, syslist, connections=None, inplist=None, outlist=None,
903903
sysname_count_dct = {}
904904

905905
# Go through the system list and keep track of counts, offsets
906-
for sysidx, sys in enumerate(syslist):
906+
for sysidx, sys in enumerate(self.syslist):
907907
# If we were passed a SS or TF system, convert to LinearIOSystem
908908
if isinstance(sys, (StateSpace, TransferFunction)) and \
909909
not isinstance(sys, LinearIOSystem):
910-
sys = LinearIOSystem(sys)
911-
syslist[sysidx] = sys
910+
sys = LinearIOSystem(sys, name=sys.name)
911+
self.syslist[sysidx] = sys
912912

913913
# Make sure time bases are consistent
914914
dt = common_timebase(dt, sys.dt)
@@ -2850,12 +2850,12 @@ def interconnect(syslist, connections=None, inplist=None, outlist=None,
28502850
inputs=inputs, outputs=outputs, states=states,
28512851
params=params, dt=dt, name=name, warn_duplicate=warn_duplicate)
28522852

2853-
# check for implicity dropped signals
2853+
# check for implicitly dropped signals
28542854
if check_unused:
28552855
newsys.check_unused_signals(ignore_inputs, ignore_outputs)
28562856

28572857
# If all subsystems are linear systems, maintain linear structure
2858-
if all([isinstance(sys, LinearIOSystem) for sys in syslist]):
2858+
if all([isinstance(sys, LinearIOSystem) for sys in newsys.syslist]):
28592859
return LinearICSystem(newsys, None)
28602860

28612861
return newsys

control/tests/interconnect_test.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,25 @@ def test_string_inputoutput():
230230

231231
P_s2 = ct.interconnect([P1_iosys, P2_iosys], inputs=['u1'], output='y2')
232232
assert P_s2.output_index == {'y2' : 0}
233+
234+
def test_linear_interconnect():
235+
tf_ctrl = ct.tf(1, (10.1, 1), inputs='e', outputs='u')
236+
tf_plant = ct.tf(1, (10.1, 1), inputs='u', outputs='y')
237+
ss_ctrl = ct.ss(1, 2, 1, 2, inputs='e', outputs='u')
238+
ss_plant = ct.ss(1, 2, 1, 2, inputs='u', outputs='y')
239+
nl_ctrl = ct.NonlinearIOSystem(
240+
lambda t, x, u, params: x*x,
241+
lambda t, x, u, params: u*x, states=1, inputs='e', outputs='u')
242+
nl_plant = ct.NonlinearIOSystem(
243+
lambda t, x, u, params: x*x,
244+
lambda t, x, u, params: u*x, states=1, inputs='u', outputs='y')
245+
246+
assert isinstance(ct.interconnect((tf_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
247+
assert isinstance(ct.interconnect((ss_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
248+
assert isinstance(ct.interconnect((tf_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
249+
assert isinstance(ct.interconnect((ss_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
250+
251+
assert ~isinstance(ct.interconnect((nl_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
252+
assert ~isinstance(ct.interconnect((nl_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
253+
assert ~isinstance(ct.interconnect((ss_ctrl, nl_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
254+
assert ~isinstance(ct.interconnect((tf_ctrl, nl_plant), inputs='e', outputs='y'), ct.LinearIOSystem)

control/tests/iosys_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,11 @@ def test_linear_interconnection():
14541454
inputs = ('u[0]', 'u[1]'),
14551455
outputs = ('y[0]', 'y[1]'),
14561456
name = 'sys2')
1457+
tf_siso = ct.tf(1, [0.1, 1])
1458+
ss_siso = ct.ss(1, 2, 1, 1)
1459+
nl_siso = ios.NonlinearIOSystem(
1460+
lambda t, x, u, params: x*x,
1461+
lambda t, x, u, params: u*x, states=1, inputs=1, outputs=1)
14571462

14581463
# Create a "regular" InterconnectedSystem
14591464
nl_connect = ios.interconnect(
@@ -1500,6 +1505,18 @@ def test_linear_interconnection():
15001505
np.testing.assert_array_almost_equal(io_connect.C, ss_connect.C)
15011506
np.testing.assert_array_almost_equal(io_connect.D, ss_connect.D)
15021507

1508+
# make sure interconnections of linear systems are linear and
1509+
# if a nonlinear system is included then system is nonlinear
1510+
assert isinstance(ss_siso*ss_siso, ios.LinearIOSystem)
1511+
assert isinstance(tf_siso*ss_siso, ios.LinearIOSystem)
1512+
assert isinstance(ss_siso*tf_siso, ios.LinearIOSystem)
1513+
assert ~isinstance(ss_siso*nl_siso, ios.LinearIOSystem)
1514+
assert ~isinstance(nl_siso*ss_siso, ios.LinearIOSystem)
1515+
assert ~isinstance(nl_siso*nl_siso, ios.LinearIOSystem)
1516+
assert ~isinstance(tf_siso*nl_siso, ios.LinearIOSystem)
1517+
assert ~isinstance(nl_siso*tf_siso, ios.LinearIOSystem)
1518+
assert ~isinstance(nl_siso*nl_siso, ios.LinearIOSystem)
1519+
15031520

15041521
def predprey(t, x, u, params={}):
15051522
"""Predator prey dynamics"""

0 commit comments

Comments
 (0)
0