Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

make _convert_to_statespace properly pass signal and system names#884

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes fromall 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
13 changes: 8 additions & 5 deletionscontrol/statesp.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -170,9 +170,9 @@ class StateSpace(LTI):

The StateSpace class is used to represent state-space realizations of
linear time-invariant (LTI) systems:

.. math::

dx/dt &= A x + B u \\
y &= C x + D u

Expand DownExpand Up@@ -1561,7 +1561,8 @@ def _convert_to_statespace(sys):
return StateSpace(
ssout[1][:states, :states], ssout[2][:states, :sys.ninputs],
ssout[3][:sys.noutputs, :states], ssout[4], sys.dt,
inputs=sys.input_labels, outputs=sys.output_labels)
inputs=sys.input_labels, outputs=sys.output_labels,
name=sys.name)
except ImportError:
# No Slycot. Scipy tf->ss can't handle MIMO, but static
# MIMO is an easy special case we can check for here
Expand All@@ -1574,7 +1575,9 @@ def _convert_to_statespace(sys):
for i, j in itertools.product(range(sys.noutputs),
range(sys.ninputs)):
D[i, j] = sys.num[i][j][0] / sys.den[i][j][0]
return StateSpace([], [], [], D, sys.dt)
return StateSpace([], [], [], D, sys.dt,
inputs=sys.input_labels, outputs=sys.output_labels,
name=sys.name)
else:
if sys.ninputs != 1 or sys.noutputs != 1:
raise TypeError("No support for MIMO without slycot")
Expand All@@ -1586,7 +1589,7 @@ def _convert_to_statespace(sys):
sp.signal.tf2ss(squeeze(sys.num), squeeze(sys.den))
return StateSpace(
A, B, C, D, sys.dt, inputs=sys.input_labels,
outputs=sys.output_labels)
outputs=sys.output_labels, name=sys.name)

elif isinstance(sys, FrequencyResponseData):
raise TypeError("Can't convert FRD to StateSpace system.")
Expand Down
20 changes: 17 additions & 3 deletionscontrol/tests/interconnect_test.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -68,8 +68,13 @@ def test_interconnect_implicit():
ki = ct.tf(random.uniform(1, 10), [1, 0])
C = ct.tf2io(kp + ki, inputs='e', outputs='u', name='C')

# same but static C2
C2 = ct.tf(random.uniform(1, 10), 1,
inputs='e', outputs='u', name='C2')

# Block diagram computation
Tss = ct.feedback(P * C, 1)
Tss2 = ct.feedback(P * C2, 1)

# Construct the interconnection explicitly
Tio_exp = ct.interconnect(
Expand All@@ -93,6 +98,15 @@ def test_interconnect_implicit():
np.testing.assert_almost_equal(Tio_sum.C, Tss.C)
np.testing.assert_almost_equal(Tio_sum.D, Tss.D)

# test whether signal names work for static system C2
Tio_sum2 = ct.interconnect(
[C2, P, sumblk], inputs='r', outputs='y')

np.testing.assert_almost_equal(Tio_sum2.A, Tss2.A)
np.testing.assert_almost_equal(Tio_sum2.B, Tss2.B)
np.testing.assert_almost_equal(Tio_sum2.C, Tss2.C)
np.testing.assert_almost_equal(Tio_sum2.D, Tss2.D)

# Setting connections to False should lead to an empty connection map
empty = ct.interconnect(
(C, P, sumblk), connections=False, inplist=['r'], outlist=['y'])
Expand DownExpand Up@@ -237,17 +251,17 @@ def test_linear_interconnect():
ss_ctrl = ct.ss(1, 2, 1, 2, inputs='e', outputs='u')
ss_plant = ct.ss(1, 2, 1, 2, inputs='u', outputs='y')
nl_ctrl = ct.NonlinearIOSystem(
lambda t, x, u, params: x*x,
lambda t, x, u, params: x*x,
lambda t, x, u, params: u*x, states=1, inputs='e', outputs='u')
nl_plant = ct.NonlinearIOSystem(
lambda t, x, u, params: x*x,
lambda t, x, u, params: x*x,
lambda t, x, u, params: u*x, states=1, inputs='u', outputs='y')

assert isinstance(ct.interconnect((tf_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
assert isinstance(ct.interconnect((ss_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
assert isinstance(ct.interconnect((tf_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
assert isinstance(ct.interconnect((ss_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)

assert ~isinstance(ct.interconnect((nl_ctrl, ss_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
assert ~isinstance(ct.interconnect((nl_ctrl, tf_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
assert ~isinstance(ct.interconnect((ss_ctrl, nl_plant), inputs='e', outputs='y'), ct.LinearIOSystem)
Expand Down
47 changes: 41 additions & 6 deletionscontrol/tests/namedio_test.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -90,8 +90,10 @@ def test_named_ss():
(lambda t, x, u, params: -x, None),
{'inputs': 2, 'outputs':2, 'states':2}],
[ct.ss, ([[1, 2], [3, 4]], [[0], [1]], [[1, 0]], 0), {}],
[ct.ss, ([], [], [], 3), {}], # static system
[ct.StateSpace, ([[1, 2], [3, 4]], [[0], [1]], [[1, 0]], 0), {}],
[ct.tf, ([1, 2], [3, 4, 5]), {}],
[ct.tf, (2, 3), {}], # static system
[ct.TransferFunction, ([1, 2], [3, 4, 5]), {}],
])
def test_io_naming(fun, args, kwargs):
Expand All@@ -112,7 +114,7 @@ def test_io_naming(fun, args, kwargs):
assert sys_g.name == 'sys[0]'
assert sys_g.input_labels == [f'u[{i}]' for i in range(sys_g.ninputs)]
assert sys_g.output_labels == [f'y[{i}]' for i in range(sys_g.noutputs)]
if sys_g.nstates:
if sys_g.nstates is not None:
assert sys_g.state_labels == [f'x[{i}]' for i in range(sys_g.nstates)]

#
Expand All@@ -128,7 +130,7 @@ def test_io_naming(fun, args, kwargs):
sys_r.set_outputs(output_labels)
assert sys_r.output_labels == output_labels

if sys_g.nstates:
if sys_g.nstates is not None:
state_labels = [f'x{i}' for i in range(sys_g.nstates)]
sys_r.set_states(state_labels)
assert sys_r.state_labels == state_labels
Expand All@@ -143,7 +145,7 @@ def test_io_naming(fun, args, kwargs):
sys_k = fun(state_labels, output_labels, input_labels, name='mysys')

elif sys_g.nstates is None:
# Don't pass state labels
# Don't pass state labels if TransferFunction
sys_k = fun(
*args, inputs=input_labels, outputs=output_labels, name='mysys')

Expand All@@ -155,7 +157,7 @@ def test_io_naming(fun, args, kwargs):
assert sys_k.name == 'mysys'
assert sys_k.input_labels == input_labels
assert sys_k.output_labels == output_labels
if sys_g.nstates:
if sys_g.nstates is not None:
assert sys_k.state_labels == state_labels

#
Expand DownExpand Up@@ -193,6 +195,24 @@ def test_io_naming(fun, args, kwargs):
assert sys_tf.input_labels == input_labels
assert sys_tf.output_labels == output_labels

#
# Convert the system to a LinearIOSystem and make sure labels transfer
#
if not isinstance(
sys_r, (ct.FrequencyResponseData, ct.NonlinearIOSystem)) and \
ct.slycot_check():
sys_lio = ct.LinearIOSystem(sys_r)
assert sys_lio != sys_r
assert sys_lio.input_labels == input_labels
assert sys_lio.output_labels == output_labels

# Reassign system and signal names
sys_lio = ct.LinearIOSystem(
sys_g, inputs=input_labels, outputs=output_labels, name='new')
assert sys_lio.name == 'new'
assert sys_lio.input_labels == input_labels
assert sys_lio.output_labels == output_labels


# Internal testing of StateSpace initialization
def test_init_namedif():
Expand DownExpand Up@@ -221,14 +241,29 @@ def test_init_namedif():

# Test state space conversion
def test_convert_to_statespace():
# Set up the initial system
sys = ct.tf(ct.rss(2, 1, 1))
# Set up the initial systems
sys = ct.tf(ct.rss(2, 1, 1), inputs='u', outputs='y', name='sys')
sys_static = ct.tf(1, 2, inputs='u', outputs='y', name='sys_static')

# check that name, inputs, and outputs passed through
sys_new = ct.ss(sys)
assert sys_new.name == 'sys'
assert sys_new.input_labels == ['u']
assert sys_new.output_labels == ['y']
sys_new = ct.ss(sys_static)
assert sys_new.name == 'sys_static'
assert sys_new.input_labels == ['u']
assert sys_new.output_labels == ['y']

# Make sure we can rename system name, inputs, outputs
sys_new = ct.ss(sys, inputs='u', outputs='y', name='new')
assert sys_new.name == 'new'
assert sys_new.input_labels == ['u']
assert sys_new.output_labels == ['y']
sys_new = ct.ss(sys_static, inputs='u', outputs='y', name='new')
assert sys_new.name == 'new'
assert sys_new.input_labels == ['u']
assert sys_new.output_labels == ['y']

# Try specifying the state names (via low level test)
with pytest.warns(UserWarning, match="non-unique state space realization"):
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp