Skip to content

Commit

Permalink
Merge pull request #145 from roryyorke/rory/static-ss-to-tf
Browse files Browse the repository at this point in the history
BUG: allow state-space to transfer function conversion of static gains
  • Loading branch information
slivingston committed Jun 27, 2017
2 parents 606d60e + d9aaa8f commit 05d6bc5
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 34 deletions.
23 changes: 23 additions & 0 deletions control/tests/convert_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,29 @@ def testTf2ssStaticMimo(self):
d = np.matrix([[0.5, 30, 0.0625], [-0.5, -1.25, 101.3]])
np.testing.assert_array_equal(d, gmimo.D)

def testSs2tfStaticSiso(self):
"""Regression: ss2tf for SISO static gain"""
import control
gsiso = control.ss2tf(control.ss([], [], [], 0.5))
np.testing.assert_array_equal([[[0.5]]], gsiso.num)
np.testing.assert_array_equal([[[1.]]], gsiso.den)

def testSs2tfStaticMimo(self):
"""Regression: ss2tf for MIMO static gain"""
import control
# 2x3 TFM
a = []
b = []
c = []
d = np.matrix([[0.5, 30, 0.0625], [-0.5, -1.25, 101.3]])
gtf = control.ss2tf(control.ss(a,b,c,d))

# we need a 3x2x1 array to compare with gtf.num
# np.testing.assert_array_equal doesn't seem to like a matrices
# with an extra dimension, so convert to ndarray
numref = np.asarray(d)[...,np.newaxis]
np.testing.assert_array_equal(numref, np.array(gtf.num) / np.array(gtf.den))


def suite():
return unittest.TestLoader().loadTestsFromTestCase(TestConvert)
Expand Down
76 changes: 42 additions & 34 deletions control/xferfcn.py
Original file line number Diff line number Diff line change
Expand Up @@ -1098,40 +1098,48 @@ def _convertToTransferFunction(sys, **kw):

return sys
elif isinstance(sys, StateSpace):
try:
from slycot import tb04ad
if len(kw):
raise TypeError(
"If sys is a StateSpace, " +
"_convertToTransferFunction cannot take keywords.")

# Use Slycot to make the transformation
# Make sure to convert system matrices to numpy arrays
tfout = tb04ad(sys.states, sys.inputs, sys.outputs, array(sys.A),
array(sys.B), array(sys.C), array(sys.D), tol1=0.0)

# Preallocate outputs.
num = [[[] for j in range(sys.inputs)] for i in range(sys.outputs)]
den = [[[] for j in range(sys.inputs)] for i in range(sys.outputs)]

for i in range(sys.outputs):
for j in range(sys.inputs):
num[i][j] = list(tfout[6][i, j, :])
# Each transfer function matrix row
# has a common denominator.
den[i][j] = list(tfout[5][i, :])
# print(num)
# print(den)
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")

lti_sys = lti(sys.A, sys.B, sys.C, sys.D)
num = squeeze(lti_sys.num)
den = squeeze(lti_sys.den)
# print(num)
# print(den)

if 0==sys.states:
# Slycot doesn't like static SS->TF conversion, so handle
# it first. Can't join this with the no-Slycot branch,
# since that doesn't handle general MIMO systems
num = [[[sys.D[i,j]] for j in range(sys.inputs)] for i in range(sys.outputs)]
den = [[[1.] for j in range(sys.inputs)] for i in range(sys.outputs)]
else:
try:
from slycot import tb04ad
if len(kw):
raise TypeError(
"If sys is a StateSpace, " +
"_convertToTransferFunction cannot take keywords.")

# Use Slycot to make the transformation
# Make sure to convert system matrices to numpy arrays
tfout = tb04ad(sys.states, sys.inputs, sys.outputs, array(sys.A),
array(sys.B), array(sys.C), array(sys.D), tol1=0.0)

# Preallocate outputs.
num = [[[] for j in range(sys.inputs)] for i in range(sys.outputs)]
den = [[[] for j in range(sys.inputs)] for i in range(sys.outputs)]

for i in range(sys.outputs):
for j in range(sys.inputs):
num[i][j] = list(tfout[6][i, j, :])
# Each transfer function matrix row
# has a common denominator.
den[i][j] = list(tfout[5][i, :])
# print(num)
# print(den)
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")

lti_sys = lti(sys.A, sys.B, sys.C, sys.D)
num = squeeze(lti_sys.num)
den = squeeze(lti_sys.den)
# print(num)
# print(den)

return TransferFunction(num, den, sys.dt)

Expand Down

0 comments on commit 05d6bc5

Please sign in to comment.