Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TransferFunction _common_den rewrite - issue #194 #206

Merged
merged 13 commits into from
Jul 2, 2018
20 changes: 8 additions & 12 deletions control/statesp.py
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,6 @@ def _convertToStateSpace(sys, **kw):
[1., 1., 1.]].

"""

from .xferfcn import TransferFunction
import itertools
if isinstance(sys, StateSpace):
Expand All @@ -771,20 +770,17 @@ def _convertToStateSpace(sys, **kw):
try:
from slycot import td04ad
if len(kw):
raise TypeError("If sys is a TransferFunction, _convertToStateSpace \
cannot take keywords.")
raise TypeError("If sys is a TransferFunction, "
"_convertToStateSpace cannot take keywords.")

# Change the numerator and denominator arrays so that the transfer
# function matrix has a common denominator.
num, den = sys._common_den()
# Make a list of the orders of the denominator polynomials.
index = [len(den) - 1 for i in range(sys.outputs)]
# Repeat the common denominator along the rows.
den = array([den for i in range(sys.outputs)])
#! TODO: transfer function to state space conversion is still buggy!
#print num
#print shape(num)
ssout = td04ad('R',sys.inputs, sys.outputs, index, den, num,tol=0.0)
# matrices are also sized/padded to fit td04ad
num, den, denorder = sys.minreal()._common_den()

# transfer function to state space conversion now should work!
ssout = td04ad('C', sys.inputs, sys.outputs,
denorder, den, num, tol=0)

states = ssout[0]
return StateSpace(ssout[1][:states, :states],
Expand Down
27 changes: 21 additions & 6 deletions control/tests/convert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def setUp(self):
# Set to True to print systems to the output.
self.debug = False
# get consistent results
np.random.seed(9)
np.random.seed(7)

def printSys(self, sys, ind):
"""Print system to the standard output."""
Expand Down Expand Up @@ -141,10 +141,9 @@ def testConvert(self):
ssxfrm_real = ssxfrm_mag * np.cos(ssxfrm_phase)
ssxfrm_imag = ssxfrm_mag * np.sin(ssxfrm_phase)
np.testing.assert_array_almost_equal( \
ssorig_real, ssxfrm_real)
ssorig_real, ssxfrm_real)
np.testing.assert_array_almost_equal( \
ssorig_imag, ssxfrm_imag)

ssorig_imag, ssxfrm_imag)
#
# Make sure xform'd TF has same frequency response
#
Expand Down Expand Up @@ -198,8 +197,9 @@ 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] ]]))
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)
Expand Down Expand Up @@ -229,6 +229,21 @@ def testSs2tfStaticMimo(self):
numref = np.asarray(d)[...,np.newaxis]
np.testing.assert_array_equal(numref, np.array(gtf.num) / np.array(gtf.den))

def testTf2SsDuplicatePoles(self):
"""Tests for "too few poles for MIMO tf #111" """
import control
try:
import slycot
num = [ [ [1], [0] ],
[ [0], [1] ] ]

den = [ [ [1,0], [1] ],
[ [1], [1,0] ] ]
g = control.tf(num, den)
s = control.ss(g)
np.testing.assert_array_equal(g.pole(), s.pole())
except ImportError:
print("Slycot not present, skipping")

def suite():
return unittest.TestLoader().loadTestsFromTestCase(TestConvert)
Expand Down
1 change: 1 addition & 0 deletions control/tests/discrete_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import unittest
import numpy as np
from control import *
from control import matlab

class TestDiscrete(unittest.TestCase):
"""Tests for the DiscreteStateSpace class."""
Expand Down
12 changes: 9 additions & 3 deletions control/tests/xferfcn_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,16 @@ def testPoleMIMO(self):
[[[1., 2.], [1., 3.]], [[1., 4., 4.], [1., 9., 14.]]])
p = sys.pole()

np.testing.assert_array_almost_equal(p, [-7., -3., -2., -2.])

# Tests for TransferFunction.feedback.
np.testing.assert_array_almost_equal(p, [-2., -2., -7., -3., -2.])

@unittest.skipIf(not slycot_check(), "slycot not installed")
def testDoubleCancelingPoleSiso(self):

H = TransferFunction([1,1],[1,2,1])
p = H.pole()
np.testing.assert_array_almost_equal(p, [-1, -1])

# Tests for TransferFunction.feedback
def testFeedbackSISO(self):
"""Test for correct SISO transfer function feedback."""

Expand Down