From c5a8ad360dbfd580f315829ca34b29e066d292ed Mon Sep 17 00:00:00 2001 From: Rory Yorke Date: Mon, 2 Jan 2017 19:41:31 +0200 Subject: [PATCH] BugFix: tf2ss now handles static MIMO gains with no Slycot Check for static-gain (i.e., constant) transfer function matrix, and handle specially. Added unit tests for static SISO and MIMO plants. --- control/statesp.py | 33 +++++++++++++++++++++++---------- control/tests/convert_test.py | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/control/statesp.py b/control/statesp.py index fe2dc6643..13e662f03 100644 --- a/control/statesp.py +++ b/control/statesp.py @@ -10,6 +10,7 @@ # Python 3 compatibility (needs to go here) from __future__ import print_function +from __future__ import division # for _convertToStateSpace """Copyright (c) 2010 by California Institute of Technology All rights reserved. @@ -647,6 +648,7 @@ def _convertToStateSpace(sys, **kw): """ from .xferfcn import TransferFunction + import itertools if isinstance(sys, StateSpace): if len(kw): raise TypeError("If sys is a StateSpace, _convertToStateSpace \ @@ -679,16 +681,27 @@ def _convertToStateSpace(sys, **kw): ssout[3][:sys.outputs, :states], ssout[4], sys.dt) except ImportError: - # If slycot is not available, use signal.lti (SISO only) - if (sys.inputs != 1 or sys.outputs != 1): - raise TypeError("No support for MIMO without slycot") - - # TODO: do we want to squeeze first and check dimenations? - # I think this will fail if num and den aren't 1-D after - # the squeeze - lti_sys = lti(squeeze(sys.num), squeeze(sys.den)) - return StateSpace(lti_sys.A, lti_sys.B, lti_sys.C, lti_sys.D, - sys.dt) + # No Slycot. Scipy tf->ss can't handle MIMO, but static + # MIMO is an easy special case we can check for here + maxn = max(max(len(n) for n in nrow) + for nrow in sys.num) + maxd = max(max(len(d) for d in drow) + for drow in sys.den) + if 1==maxn and 1==maxd: + D = empty((sys.outputs,sys.inputs),dtype=float) + for i,j in itertools.product(range(sys.outputs),range(sys.inputs)): + D[i,j] = sys.num[i][j][0] / sys.den[i][j][0] + return StateSpace([], [], [], D, sys.dt) + else: + if (sys.inputs != 1 or sys.outputs != 1): + raise TypeError("No support for MIMO without slycot") + + # TODO: do we want to squeeze first and check dimenations? + # I think this will fail if num and den aren't 1-D after + # the squeeze + lti_sys = lti(squeeze(sys.num), squeeze(sys.den)) + return StateSpace(lti_sys.A, lti_sys.B, lti_sys.C, lti_sys.D, + sys.dt) elif isinstance(sys, (int, float, complex)): if "inputs" in kw: diff --git a/control/tests/convert_test.py b/control/tests/convert_test.py index 775118909..b395996e0 100644 --- a/control/tests/convert_test.py +++ b/control/tests/convert_test.py @@ -184,6 +184,28 @@ def testConvertMIMO(self): if (not slycot_check()): self.assertRaises(TypeError, control.tf2ss, tfcn) + def testTf2ssStaticSiso(self): + """Regression: tf2ss for SISO static gain""" + import control + gsiso = control.tf2ss(control.tf(23, 46)) + self.assertEqual(0, gsiso.states) + self.assertEqual(1, gsiso.inputs) + self.assertEqual(1, gsiso.outputs) + # in all cases ratios are exactly representable, so assert_array_equal is fine + np.testing.assert_array_equal([[0.5]], gsiso.D) + + def testTf2ssStaticMimo(self): + """Regression: tf2ss for MIMO static gain""" + import control + # 2x3 TFM + gmimo = control.tf2ss(control.tf([[ [23], [3], [5] ], [ [-1], [0.125], [101.3] ]], + [[ [46], [0.1], [80] ], [ [2], [-0.1], [1] ]])) + self.assertEqual(0, gmimo.states) + self.assertEqual(3, gmimo.inputs) + self.assertEqual(2, gmimo.outputs) + d = np.matrix([[0.5, 30, 0.0625], [-0.5, -1.25, 101.3]]) + np.testing.assert_array_equal(d, gmimo.D) + def suite(): return unittest.TestLoader().loadTestsFromTestCase(TestConvert) 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