Skip to content

Commit 2dc409b

Browse files
authored
Merge pull request #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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy