Skip to content

Commit 0758426

Browse files
committed
reorganize and clean up statesp.py
1 parent 9d426e9 commit 0758426

1 file changed

Lines changed: 28 additions & 45 deletions

File tree

control/statesp.py

Lines changed: 28 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -192,33 +192,32 @@ def __init__(self, *args, **kwargs):
192192
#
193193
# Process positional arguments
194194
#
195-
# TODO: Move all of this into the ss() factory function
196-
# TODO: Use standard processing order for I/O systems
195+
197196
if len(args) == 4:
198197
# The user provided A, B, C, and D matrices.
199-
(A, B, C, D) = args
198+
A, B, C, D = args
200199

201200
elif len(args) == 5:
202201
# Discrete time system
203-
(A, B, C, D, dt) = args
202+
A, B, C, D, dt = args
204203
if 'dt' in kwargs:
205204
warn("received multiple dt arguments, "
206205
"using positional arg dt = %s" % dt)
207206
kwargs['dt'] = dt
208207
args = args[:-1]
209208

210209
elif len(args) == 1:
211-
# Use the copy constructor.
210+
# Use the copy constructor
212211
if not isinstance(args[0], StateSpace):
213212
raise TypeError(
214-
"The one-argument constructor can only take in a "
215-
"StateSpace object. Received %s." % type(args[0]))
213+
"the one-argument constructor can only take in a "
214+
"StateSpace object; received %s" % type(args[0]))
216215
A = args[0].A
217216
B = args[0].B
218217
C = args[0].C
219218
D = args[0].D
220-
dt = args[0].dt
221-
# TODO: copy the remaining attributes
219+
if 'dt' not in kwargs:
220+
kwargs['dt'] = args[0].dt
222221

223222
else:
224223
raise TypeError(
@@ -691,7 +690,6 @@ def __mul__(self, other):
691690

692691
# Right multiplication of two state space systems (series interconnection)
693692
# Just need to convert LH argument to a state space object
694-
# TODO: __rmul__ only works for special cases (??)
695693
def __rmul__(self, other):
696694
"""Right multiply two LTI objects (serial connection)."""
697695
from .xferfcn import TransferFunction
@@ -720,7 +718,7 @@ def __rmul__(self, other):
720718

721719
# TODO: general __truediv__ requires descriptor system support
722720
def __truediv__(self, other):
723-
"""Division of state space systems byTFs, FRDs, scalars, and arrays"""
721+
"""Division of state space systems by TFs, FRDs, scalars, and arrays"""
724722
if not isinstance(other, (LTI, InputOutputSystem)):
725723
return self * (1/other)
726724
else:
@@ -1522,11 +1520,6 @@ def ss(*args, **kwargs):
15221520
Convert a linear system into space system form. Always creates a
15231521
new system, even if sys is already a state space system.
15241522
1525-
``ss(updfcn, outfcn)``
1526-
Create a nonlinear input/output system with update function ``updfcn``
1527-
and output function ``outfcn``. See :class:`NonlinearIOSystem` for
1528-
more information.
1529-
15301523
``ss(A, B, C, D)``
15311524
Create a state space system from the matrices of its state and
15321525
output equations:
@@ -1585,9 +1578,7 @@ def ss(*args, **kwargs):
15851578
15861579
See Also
15871580
--------
1588-
tf
1589-
ss2tf
1590-
tf2ss
1581+
tf, ss2tf, tf2ss
15911582
15921583
Examples
15931584
--------
@@ -1601,10 +1592,12 @@ def ss(*args, **kwargs):
16011592
>>> sys2 = ct.ss(sys_tf)
16021593
16031594
"""
1604-
# See if this is a nonlinear I/O system
1595+
# See if this is a nonlinear I/O system (legacy usage)
16051596
if len(args) > 0 and (hasattr(args[0], '__call__') or args[0] is None) \
16061597
and not isinstance(args[0], (InputOutputSystem, LTI)):
16071598
# Function as first (or second) argument => assume nonlinear IO system
1599+
warn("use nlsys() to create nonlinear I/O System",
1600+
PendingDeprecationWarning)
16081601
return NonlinearIOSystem(*args, **kwargs)
16091602

16101603
elif len(args) == 4 or len(args) == 5:
@@ -1644,8 +1637,8 @@ def tf2ss(*args, **kwargs):
16441637
The function accepts either 1 or 2 parameters:
16451638
16461639
``tf2ss(sys)``
1647-
Convert a linear system into space space form. Always creates
1648-
a new system, even if sys is already a StateSpace object.
1640+
Convert a transfer function into space space form. Equivalent to
1641+
`ss(sys)`.
16491642
16501643
``tf2ss(num, den)``
16511644
Create a state space system from its numerator and denominator
@@ -1710,15 +1703,8 @@ def tf2ss(*args, **kwargs):
17101703
_convert_to_statespace(TransferFunction(*args)), **kwargs)
17111704

17121705
elif len(args) == 1:
1713-
sys = args[0]
1714-
if not isinstance(sys, TransferFunction):
1715-
raise TypeError("tf2ss(sys): sys must be a TransferFunction "
1716-
"object.")
1717-
return StateSpace(
1718-
_convert_to_statespace(
1719-
sys,
1720-
use_prefix_suffix=not sys._generic_name_check()),
1721-
**kwargs)
1706+
return ss(*args, **kwargs)
1707+
17221708
else:
17231709
raise ValueError("Needs 1 or 2 arguments; received %i." % len(args))
17241710

@@ -1946,8 +1932,8 @@ def summing_junction(
19461932
19471933
Examples
19481934
--------
1949-
>>> P = ct.tf2io(1, [1, 0], inputs='u', outputs='y')
1950-
>>> C = ct.tf2io(10, [1, 1], inputs='e', outputs='u')
1935+
>>> P = ct.tf(1, [1, 0], inputs='u', outputs='y')
1936+
>>> C = ct.tf(10, [1, 1], inputs='e', outputs='u')
19511937
>>> sumblk = ct.summing_junction(inputs=['r', '-y'], output='e')
19521938
>>> T = ct.interconnect([P, C, sumblk], inputs='r', outputs='y')
19531939
>>> T.ninputs, T.noutputs, T.nstates
@@ -2031,6 +2017,9 @@ def _parse_list(signals, signame='input', prefix='u'):
20312017
return StateSpace(
20322018
ss_sys, inputs=input_names, outputs=output_names, name=name)
20332019

2020+
#
2021+
# Utility functions
2022+
#
20342023

20352024
def _ssmatrix(data, axis=1):
20362025
"""Convert argument to a (possibly empty) 2D state space matrix.
@@ -2104,7 +2093,6 @@ def _f2s(f):
21042093
return s
21052094

21062095

2107-
# TODO: add discrete time check
21082096
def _convert_to_statespace(sys, use_prefix_suffix=False):
21092097
"""Convert a system to state space form (if needed).
21102098
@@ -2126,8 +2114,8 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21262114
# Make sure the transfer function is proper
21272115
if any([[len(num) for num in col] for col in sys.num] >
21282116
[[len(num) for num in col] for col in sys.den]):
2129-
raise ValueError("Transfer function is non-proper; can't "
2130-
"convert to StateSpace system.")
2117+
raise ValueError("transfer function is non-proper; can't "
2118+
"convert to StateSpace system")
21312119

21322120
try:
21332121
from slycot import td04ad
@@ -2163,9 +2151,6 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21632151
if sys.ninputs != 1 or sys.noutputs != 1:
21642152
raise TypeError("No support for MIMO without slycot")
21652153

2166-
# TODO: do we want to squeeze first and check dimenations?
2167-
# I think this will fail if num and den aren't 1-D after
2168-
# the squeeze
21692154
A, B, C, D = \
21702155
sp.signal.tf2ss(squeeze(sys.num), squeeze(sys.den))
21712156
newsys = StateSpace(A, B, C, D, sys.dt)
@@ -2187,7 +2172,7 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
21872172
except Exception:
21882173
raise TypeError("Can't convert given type to StateSpace system.")
21892174

2190-
# TODO: add discrete time option
2175+
21912176
def _rss_generate(
21922177
states, inputs, outputs, cdtype, strictly_proper=False, name=None):
21932178
"""Generate a random state space.
@@ -2310,8 +2295,6 @@ def _rss_generate(
23102295
return StateSpace(*ss_args, name=name)
23112296

23122297

2313-
# Convert a MIMO system to a SISO system
2314-
# TODO: add discrete time check
23152298
def _mimo2siso(sys, input, output, warn_conversion=False):
23162299
# pylint: disable=W0622
23172300
"""
@@ -2416,8 +2399,8 @@ def _mimo2simo(sys, input, warn_conversion=False):
24162399
# Y = C*X + D*U
24172400
new_B = sys.B[:, input:input+1]
24182401
new_D = sys.D[:, input:input+1]
2419-
sys = StateSpace(sys.A, new_B, sys.C, new_D, sys.dt,
2420-
name=sys.name,
2421-
inputs=sys.input_labels[input], outputs=sys.output_labels)
2402+
sys = StateSpace(
2403+
sys.A, new_B, sys.C, new_D, sys.dt, name=sys.name,
2404+
inputs=sys.input_labels[input], outputs=sys.output_labels)
24222405

24232406
return sys

0 commit comments

Comments
 (0)