pythonscipytransfer-function

Differing results in Scipy vs Matlab transfer functions


I can't understand why the scipy.signal.ss2tf() and scipy.signal.StateSpace().to_tf() give (the same) unexpected result.

Example:

A=[[0, 1, 0], [0, 0, 1], [-3, -4, -2]]
B=[[0], [0], [1]]
C=[[5, 1, 0]]
D=[[0]]

The result for scipy is

num = array([[0, 0, 0, 4]]),
den = array([1., 2., 4., 3.])

in Matlab the result is

num = [0,0,1,5],
den = [1,2,4,3]

It seems that the denominator is always right, I tried other examples, but the numerator of the transfer function doesn't correspond.

Am I using scipy in an incorrect way?

(another example)

A=[[0, 1, 0], [0, 0, 1], [-8, -14, -7]]
B=[[0], [0], [1]]
C=[[15, 5, 0]]
D=[[0]]

Solution

  • This is a bug in SciPy that was fixed in SciPy 1.6.0. When ss2tf creates an array to hold the numerator, it uses the data types of the inputs to determine the data type of the numerator array. In your case, the values are all integers, so the data type of the numerator is integer. However, the coefficients for the numerator are the result of a floating point calculation, and therefore are subject to loss of precision. When the computed values are copied into the numerator array, those values are truncated to integers. In your example, that results in a large error. When I reproduce the floating point calculation of the numerator, I get [0.0, 0.0, 0.9999999999999947, 4.999999999999995], and when those values are copied into the integer array, the result is [0, 0, 0, 4].

    A work-around is to ensure that your inputs (or at least A) contain floating point values. For example,

    In [33]: A = [[0., 1., 0.], [0., 0., 1.], [-8., -14., -7.]] 
        ...: B = [[0], [0], [1]] 
        ...: C = [[15, 5, 0]] 
        ...: D = [[0]]                                                              
    
    In [34]: num, den = ss2tf(A, B, C, D)                                           
    
    In [35]: num                                                                    
    Out[35]: array([[0.00000000e+00, 1.77635684e-15, 5.00000000e+00, 1.50000000e+01]])