Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
from slycot import td04ad
if len(kw):
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.
# 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], ssout[2][:states, :sys.inputs],
ssout[3][:sys.outputs, :states], ssout[4], sys.dt)
except ImportError:
# 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")
--------
>>> A = [[1., -2], [3, -4]]
>>> B = [[5.], [7]]
>>> C = [[6., 8]]
>>> D = [[9.]]
>>> sys1 = ss2tf(A, B, C, D)
>>> sys_ss = ss(A, B, C, D)
>>> sys2 = ss2tf(sys_ss)
"""
from .statesp import StateSpace
if len(args) == 4 or len(args) == 5:
# Assume we were given the A, B, C, D matrix and (optional) dt
return _convert_to_transfer_function(StateSpace(*args))
elif len(args) == 1:
sys = args[0]
if isinstance(sys, StateSpace):
return _convert_to_transfer_function(sys)
else:
raise TypeError(
"ss2tf(sys): sys must be a StateSpace object. It is %s."
% type(sys))
else:
raise ValueError("Needs 1 or 4 arguments; received %i." % len(args))
def issys(object):
# Check for a member of one of the classes that we define here
#! TODO: this should probably look for an LTI object instead??
if (isinstance(object, (statesp.StateSpace, xferfcn.TransferFunction))):
return True
# Didn't find anything that matched
return False
Returns
-------
iosys : LinearIOSystem
Linear system represented as an input/output system
"""
if not isinstance(linsys, StateSpace):
raise TypeError("Linear I/O system must be a state space object")
# Create the I/O system object
super(LinearIOSystem, self).__init__(
inputs=linsys.inputs, outputs=linsys.outputs,
states=linsys.states, params={}, dt=linsys.dt, name=name)
# Initalize additional state space variables
StateSpace.__init__(self, linsys, remove_useless=False)
# Process input, output, state lists, if given
# Make sure they match the size of the linear system
ninputs, self.input_index = self._process_signal_list(
inputs if inputs is not None else linsys.inputs, prefix='u')
if ninputs is not None and linsys.inputs != ninputs:
raise ValueError("Wrong number/type of inputs given.")
noutputs, self.output_index = self._process_signal_list(
outputs if outputs is not None else linsys.outputs, prefix='y')
if noutputs is not None and linsys.outputs != noutputs:
raise ValueError("Wrong number/type of outputs given.")
nstates, self.state_index = self._process_signal_list(
states if states is not None else linsys.states, prefix='x')
if nstates is not None and linsys.states != nstates:
raise ValueError("Wrong number/type of states given.")
raise ValueError("Selected output does not exist. "
"Selected output: {sel}, "
"number of system outputs: {ext}."
.format(sel=output, ext=sys.outputs))
#Convert sys to SISO if necessary
if sys.inputs > 1 or sys.outputs > 1:
if warn_conversion:
warn("Converting MIMO system to SISO system. "
"Only input {i} and output {o} are used."
.format(i=input, o=output))
# $X = A*X + B*U
# Y = C*X + D*U
new_B = sys.B[:, input]
new_C = sys.C[output, :]
new_D = sys.D[output, input]
sys = StateSpace(sys.A, new_B, new_C, new_D, sys.dt)
return sys
np_ = np.size(P.C, 0)
gamma = 1.e100
out = sb10ad(n, m, np_, ncon, nmeas, gamma, P.A, P.B, P.C, P.D)
gam = out[0]
Ak = out[1]
Bk = out[2]
Ck = out[3]
Dk = out[4]
Ac = out[5]
Bc = out[6]
Cc = out[7]
Dc = out[8]
rcond = out[9]
K = StateSpace(Ak, Bk, Ck, Dk)
CL = StateSpace(Ac, Bc, Cc, Dc)
return K, CL, gam, rcond
inputs = 1
if "outputs" in kw:
outputs = kw["outputs"]
else:
outputs = 1
# Generate a simple state space system of the desired dimension
# The following Doesn't work due to inconsistencies in ltisys:
# return StateSpace([[]], [[]], [[]], eye(outputs, inputs))
return StateSpace(0., zeros((1, inputs)), zeros((outputs, 1)),
sys * ones((outputs, inputs)))
# If this is a matrix, try to create a constant feedthrough
try:
D = _ssmatrix(sys)
return StateSpace([], [], [], D)
except Exception as e:
print("Failure to assume argument is matrix-like in" \
" _convertToStateSpace, result %s" % e)
raise TypeError("Can't convert given type to StateSpace system.")
uncontrollable states"""
if self.states:
try:
from slycot import tb01pd
B = empty((self.states, max(self.inputs, self.outputs)))
B[:,:self.inputs] = self.B
C = empty((max(self.outputs, self.inputs), self.states))
C[:self.outputs,:] = self.C
A, B, C, nr = tb01pd(self.states, self.inputs, self.outputs,
self.A, B, C, tol=tol)
return StateSpace(A[:nr,:nr], B[:nr,:self.inputs],
C[:self.outputs,:nr], self.D)
except ImportError:
raise TypeError("minreal requires slycot tb01pd")
else:
return StateSpace(self)
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
A, B, C, D = sp.signal.tf2ss(squeeze(sys.num), squeeze(sys.den))
return StateSpace(A, B, C, D, sys.dt)
elif isinstance(sys, (int, float, complex, np.number)):
if "inputs" in kw:
inputs = kw["inputs"]
else:
inputs = 1
if "outputs" in kw:
outputs = kw["outputs"]
else:
outputs = 1
# Generate a simple state space system of the desired dimension
# The following Doesn't work due to inconsistencies in ltisys:
# return StateSpace([[]], [[]], [[]], eye(outputs, inputs))
return StateSpace(0., zeros((1, inputs)), zeros((outputs, 1)),
sys * ones((outputs, inputs)))
* if system is not instance of StateSpace class
* if `type` is not 'c' or 'o'
* if system is unstable (sys.A has eigenvalues not in left half plane)
ImportError
if slycot routin sb03md cannot be found
Examples
--------
>>> Wc = gram(sys,'c')
>>> Wo = gram(sys,'o')
"""
#Check for ss system object
if not isinstance(sys,statesp.StateSpace):
raise ValueError("System must be StateSpace!")
#TODO: Check for continous or discrete, only continuous supported right now
# if isCont():
# dico = 'C'
# elif isDisc():
# dico = 'D'
# else:
dico = 'C'
#TODO: Check system is stable, perhaps a utility in ctrlutil.py
# or a method of the StateSpace class?
D,V = np.linalg.eig(sys.A)
for e in D:
if e.real >= 0:
raise ValueError("Oops, the system is unstable!")