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

Fix bdalg.connect#474

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
bnavigator merged 3 commits intopython-control:masterfromsawyerbfuller:fix-connect
Dec 21, 2020
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
39 changes: 30 additions & 9 deletionscontrol/bdalg.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -302,14 +302,16 @@ def connect(sys, Q, inputv, outputv):
sys : StateSpace Transferfunction
System to be connected
Q : 2D array
Interconnection matrix. First column gives the input to be connected
second column gives the output to be fed into this input. Negative
values for the second column mean the feedback is negative, 0 means
no connection is made. Inputs and outputs are indexed starting at 1.
Interconnection matrix. First column gives the input to be connected.
The second column gives the index of an output that is to be fed into
that input. Each additional column gives the index of an additional
input that may be optionally added to that input. Negative
values mean the feedback is negative. A zero value is ignored. Inputs
and outputs are indexed starting at 1 to communicate sign information.
inputv : 1D array
list of final external inputs
list of final external inputs, indexed starting at 1
outputv : 1D array
list of final external outputs
list of final external outputs, indexed starting at 1

Returns
-------
Expand All@@ -325,15 +327,34 @@ def connect(sys, Q, inputv, outputv):
>>> sysc = connect(sys, Q, [2], [1, 2])

"""
inputv, outputv, Q = np.asarray(inputv), np.asarray(outputv), np.asarray(Q)
# check indices
index_errors = (inputv - 1 > sys.inputs) | (inputv < 1)
if np.any(index_errors):
raise IndexError(
"inputv index %s out of bounds" % inputv[np.where(index_errors)])
index_errors = (outputv - 1 > sys.outputs) | (outputv < 1)
if np.any(index_errors):
raise IndexError(
"outputv index %s out of bounds" % outputv[np.where(index_errors)])
index_errors = (Q[:,0:1] - 1 > sys.inputs) | (Q[:,0:1] < 1)
if np.any(index_errors):
raise IndexError(
"Q input index %s out of bounds" % Q[np.where(index_errors)])
index_errors = (np.abs(Q[:,1:]) - 1 > sys.outputs)
if np.any(index_errors):
raise IndexError(
"Q output index %s out of bounds" % Q[np.where(index_errors)])

# first connect
K = np.zeros((sys.inputs, sys.outputs))
for r in np.array(Q).astype(int):
inp = r[0]-1
for outp in r[1:]:
if outp > 0 and outp <= sys.outputs:
K[inp,outp-1] = 1.
elif outp < 0 and -outp >= -sys.outputs:
if outp < 0:
K[inp,-outp-1] = -1.
elif outp > 0:
K[inp,outp-1] = 1.
sys = sys.feedback(np.array(K), sign=1)

# now trim
Expand Down
84 changes: 68 additions & 16 deletionscontrol/tests/bdalg_test.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,7 +9,7 @@
import control as ctrl
from control.xferfcn import TransferFunction
from control.statesp import StateSpace
from control.bdalg import feedback
from control.bdalg import feedback, append, connect
from control.lti import zero, pole

class TestFeedback(unittest.TestCase):
Expand All@@ -23,7 +23,9 @@ def setUp(self):
# Two random SISO systems.
self.sys1 = TransferFunction([1, 2], [1, 2, 3])
self.sys2 = StateSpace([[1., 4.], [3., 2.]], [[1.], [-4.]],
[[1., 0.]], [[0.]])
[[1., 0.]], [[0.]]) # 2 states, SISO
self.sys3 = StateSpace([[-1.]], [[1.]], [[1.]], [[0.]]) # 1 state, SISO

# Two random scalars.
self.x1 = 2.5
self.x2 = -3.
Expand DownExpand Up@@ -192,50 +194,50 @@ def testLists(self):
sys1_2 = ctrl.series(sys1, sys2)
np.testing.assert_array_almost_equal(sort(pole(sys1_2)), [-4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_2)), [-3., -1.])

sys1_3 = ctrl.series(sys1, sys2, sys3);
np.testing.assert_array_almost_equal(sort(pole(sys1_3)),
[-6., -4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_3)),
np.testing.assert_array_almost_equal(sort(zero(sys1_3)),
[-5., -3., -1.])

sys1_4 = ctrl.series(sys1, sys2, sys3, sys4);
np.testing.assert_array_almost_equal(sort(pole(sys1_4)),
[-8., -6., -4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_4)),
[-7., -5., -3., -1.])

sys1_5 = ctrl.series(sys1, sys2, sys3, sys4, sys5);
np.testing.assert_array_almost_equal(sort(pole(sys1_5)),
[-8., -6., -4., -2., -0.])
np.testing.assert_array_almost_equal(sort(zero(sys1_5)),
np.testing.assert_array_almost_equal(sort(zero(sys1_5)),
[-9., -7., -5., -3., -1.])

# Parallel
# Parallel
sys1_2 = ctrl.parallel(sys1, sys2)
np.testing.assert_array_almost_equal(sort(pole(sys1_2)), [-4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_2)),
sort(zero(sys1 + sys2)))

sys1_3 = ctrl.parallel(sys1, sys2, sys3);
np.testing.assert_array_almost_equal(sort(pole(sys1_3)),
[-6., -4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_3)),
np.testing.assert_array_almost_equal(sort(zero(sys1_3)),
sort(zero(sys1 + sys2 + sys3)))

sys1_4 = ctrl.parallel(sys1, sys2, sys3, sys4);
np.testing.assert_array_almost_equal(sort(pole(sys1_4)),
[-8., -6., -4., -2.])
np.testing.assert_array_almost_equal(sort(zero(sys1_4)),
sort(zero(sys1 + sys2 +
np.testing.assert_array_almost_equal(sort(zero(sys1_4)),
sort(zero(sys1 + sys2 +
sys3 + sys4)))


sys1_5 = ctrl.parallel(sys1, sys2, sys3, sys4, sys5);
np.testing.assert_array_almost_equal(sort(pole(sys1_5)),
[-8., -6., -4., -2., -0.])
np.testing.assert_array_almost_equal(sort(zero(sys1_5)),
sort(zero(sys1 + sys2 +
np.testing.assert_array_almost_equal(sort(zero(sys1_5)),
sort(zero(sys1 + sys2 +
sys3 + sys4 + sys5)))
def testMimoSeries(self):
"""regression: bdalg.series reverses order of arguments"""
Expand DownExpand Up@@ -270,6 +272,56 @@ def test_feedback_args(self):
sys = ctrl.feedback(1, frd)
self.assertTrue(isinstance(sys, ctrl.FRD))

def testConnect(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

These tests only look for failures. What about tests that successfully connect systems?

Obviously I will pytest.parametrize this for#438

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

These tests only look for failures. What about tests that successfully connect systems?

good idea; added.

Obviously I will pytest.parametrize this for#438

thx!

sys = append(self.sys2, self.sys3) # two siso systems

# should not raise error
connect(sys, [[1, 2], [2, -2]], [2], [1, 2])
connect(sys, [[1, 2], [2, 0]], [2], [1, 2])
connect(sys, [[1, 2, 0], [2, -2, 1]], [2], [1, 2])
connect(sys, [[1, 2], [2, -2]], [2, 1], [1])
sys3x3 = append(sys, self.sys3) # 3x3 mimo
connect(sys3x3, [[1, 2, 0], [2, -2, 1], [3, -3, 0]], [2], [1, 2])
connect(sys3x3, [[1, 2, 0], [2, -2, 1], [3, -3, 0]], [1, 2, 3], [3])
connect(sys3x3, [[1, 2, 0], [2, -2, 1], [3, -3, 0]], [2, 3], [2, 1])

# feedback interconnection out of bounds: input too high
Q = [[1, 3], [2, -2]]
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 2])
# feedback interconnection out of bounds: input too low
Q = [[0, 2], [2, -2]]
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 2])

# feedback interconnection out of bounds: output too high
Q = [[1, 2], [2, -3]]
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 2])
Q = [[1, 2], [2, 4]]
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 2])

# input/output index testing
Q = [[1, 2], [2, -2]] # OK interconnection

# input index is out of bounds: too high
with self.assertRaises(IndexError):
connect(sys, Q, [3], [1, 2])
# input index is out of bounds: too low
with self.assertRaises(IndexError):
connect(sys, Q, [0], [1, 2])
with self.assertRaises(IndexError):
connect(sys, Q, [-2], [1, 2])
# output index is out of bounds: too high
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 3])
# output index is out of bounds: too low
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, 0])
with self.assertRaises(IndexError):
connect(sys, Q, [2], [1, -1])


if __name__ == "__main__":
unittest.main()

[8]ページ先頭

©2009-2025 Movatter.jp