60
60
from scipy .signal import StateSpace as signalStateSpace
61
61
from warnings import warn
62
62
63
- from .exception import ControlSlycot
63
+ from .exception import ControlSlycot , slycot_check
64
64
from .frdata import FrequencyResponseData
65
65
from .lti import LTI , _process_frequency_response
66
66
from .iosys import InputOutputSystem , common_timebase , isdtime , \
@@ -1615,10 +1615,13 @@ def ss(*args, **kwargs):
1615
1615
warn ("state labels specified for "
1616
1616
"non-unique state space realization" )
1617
1617
1618
+ # Allow method to be specified (eg, tf2ss)
1619
+ method = kwargs .pop ('method' , None )
1620
+
1618
1621
# Create a state space system from an LTI system
1619
1622
sys = StateSpace (
1620
1623
_convert_to_statespace (
1621
- sys ,
1624
+ sys , method = method ,
1622
1625
use_prefix_suffix = not sys ._generic_name_check ()),
1623
1626
** kwargs )
1624
1627
@@ -2189,7 +2192,7 @@ def _f2s(f):
2189
2192
return s
2190
2193
2191
2194
2192
- def _convert_to_statespace (sys , use_prefix_suffix = False ):
2195
+ def _convert_to_statespace (sys , use_prefix_suffix = False , method = None ):
2193
2196
"""Convert a system to state space form (if needed).
2194
2197
2195
2198
If sys is already a state space, then it is returned. If sys is a
@@ -2213,13 +2216,17 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
2213
2216
raise ValueError ("transfer function is non-proper; can't "
2214
2217
"convert to StateSpace system" )
2215
2218
2216
- try :
2219
+ if method is None and slycot_check () or method == 'slycot' :
2220
+ if not slycot_check ():
2221
+ raise ValueError ("method='slycot' requires slycot" )
2222
+
2217
2223
from slycot import td04ad
2218
2224
2219
2225
# Change the numerator and denominator arrays so that the transfer
2220
2226
# function matrix has a common denominator.
2221
2227
# matrices are also sized/padded to fit td04ad
2222
2228
num , den , denorder = sys .minreal ()._common_den ()
2229
+ num , den , denorder = sys ._common_den ()
2223
2230
2224
2231
# transfer function to state space conversion now should work!
2225
2232
ssout = td04ad ('C' , sys .ninputs , sys .noutputs ,
@@ -2230,9 +2237,8 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
2230
2237
ssout [1 ][:states , :states ], ssout [2 ][:states , :sys .ninputs ],
2231
2238
ssout [3 ][:sys .noutputs , :states ], ssout [4 ], sys .dt )
2232
2239
2233
- except ImportError :
2234
- # No Slycot. Scipy tf->ss can't handle MIMO, but static
2235
- # MIMO is an easy special case we can check for here
2240
+ elif method in [None , 'scipy' ]:
2241
+ # Scipy tf->ss can't handle MIMO, but SISO is OK
2236
2242
maxn = max (max (len (n ) for n in nrow )
2237
2243
for nrow in sys .num )
2238
2244
maxd = max (max (len (d ) for d in drow )
@@ -2250,6 +2256,8 @@ def _convert_to_statespace(sys, use_prefix_suffix=False):
2250
2256
A , B , C , D = \
2251
2257
sp .signal .tf2ss (squeeze (sys .num ), squeeze (sys .den ))
2252
2258
newsys = StateSpace (A , B , C , D , sys .dt )
2259
+ else :
2260
+ raise ValueError (f"unknown { method = } " )
2253
2261
2254
2262
# Copy over the signal (and system) names
2255
2263
newsys ._copy_names (
0 commit comments