Continuous and discrete state-space model conversions

Continuous and discrete state-space model conversions.

class pyyeti.ssmodel.SSModel(A, B, C, D, h=None, method=None, prewarp=None)[source]

Bases: object

Simple class for storing information about a continuous or discrete state-space model with tools for converting from one to another.

A, B, C, D

These are the continuous or discrete state-space matrices (see below).

Type:

2d ndarrays

h

None for continuous models, the time step for discete models.

Type:

scalar or None

method

For discrete models, this can specify the method used to convert from continuous.

Type:

string, optional

prewarp

For discrete systems, this can specify the prewarp frequency (rad/sec) used in the Tustin transformation.

Type:

scalar or None, optional

Notes

The continuous (s-domain) state-space equations are:

xdot = A*x + B*u
y    = C*x + D*u

The discrete (z-domain) state-space equations are:

x[k+1] = A*x[k] + B*u[k]
y[k]   = C*x[k] + D*u[k]
__repr__()[source]

Return representation of the SSModel system.

c2d(h, method='foh', prewarp=0)[source]

Compute a discrete state-space model (z-plane) from continuous state-space model (s-plane).

Parameters:
  • h (scalar) – The time step for discretization

  • method (string, optional) – Conversion method: ‘zoh’, ‘zoha’, ‘foh’, or ‘tustin’:

    method

    Transformation method

    ‘zoh’

    zero order hold, use input at start of time step used for time step

    ‘zoha’

    zero order hold, use average of start and end input values for time step

    ‘foh’

    first order hold, input ramps linearly across time step

    ‘tustin’

    uses the Tustin (or bilinear) transform

  • prewarp (scalar or None, optional) – Prewarp frequency used for the Tustin transform (rad/sec)

Returns:

cls (instance of SSModel) – Has attributes set for a discrete (z-plane) state-space model.

Notes

If self is already a discrete model, this routine quietly returns itself. To convert to a different time-step, call d2c() first.

The conversion is based on the matrix exponential (see pyyeti.expmint.expmint()). Letting z and s represent the discrete and continuous versions of the SSModel, the following equations show the conversion methods. First (noting that E, I1, and I2 can be calculated by pyyeti.expmint.expmint()):

lambda, phi = eig(z.A)
E = exp(s.A*h)
I1 = integral (exp(s.A*t) dt) from 0 to h
I2 = integral (exp(s.A*t)*t dt) from 0 to h
I = identity

For method='zoh', the conversion is:

z.A = E
z.B = I1*s.B
z.C = s.C
z.D = s.D

For method='zoha', the conversion is:

z.A = E
P = I1/2
z.B = (P+E*P)*s.B
z.C = s.C
z.D = s.C*P*s.B + s.D

For method='foh', the conversion is:

z.A = E
Q = I1 - I2/h
P = I1 - Q
z.B = (P+E*Q)*s.B
z.C = s.C
z.D = s.C*Q*s.B + s.D

For method='tustin', the conversion is:

if prewarp == 0:
    k = 2/h     # standard Tustin method
else:
    k = prewarp/tan(prewarp*h/2)
Q = inv(k*I-s.A)
z.A = Q*(k*I+s.A)
z.B = (I+s.A)*Q*s.B
z.C = s.C
z.D = s.C*Q*s.B + s.D
d2c(method='foh', prewarp=0)[source]

Compute a continuous state-space model (s-plane) from discrete state-space model (z-plane).

Parameters:
  • method (string, optional) – Conversion method: ‘zoh’, ‘zoha’, ‘foh’, or ‘tustin’:

    method

    Transformation method

    ‘zoh’

    zero order hold, use input at start of time step used for time step

    ‘zoha’

    zero order hold, use average of start and end input values for time step

    ‘foh’

    first order hold, input ramps linearly across time step

    ‘tustin’

    uses the Tustin (or bilinear) transform

  • prewarp (scalar or None, optional) – Prewarp frequency used for the Tustin transform (rad/sec)

Returns:

cls (instance of SSModel) – Has attributes set for a continuous (s-plane) state-space model.

Notes

If self is already a continuous model, this routine quietly returns itself.

The conversion is based on the matrix exponential (see pyyeti.expmint.expmint()). Letting z and s represent the discrete and continuous versions of the SSModel the following equations show the conversion methods. First (noting that E, I1, and I2 can be calculated by pyyeti.expmint.expmint() once s.A has been computed):

lambda, phi = eig(z.A)
E = exp(s.A*h)
I1 = integral (exp(s.A*t) dt) from 0 to h
I2 = integral (exp(s.A*t)*t dt) from 0 to h
I = identity

For method='zoh', the conversion is:

s.A = phi * diag(log(lambda)/h) * inv(phi)
s.B = inv(z.A - I) * s.A * z.B
s.C = z.C
s.D = z.D

For method='zoha', the conversion is:

s.A = phi * diag(log(lambda)/h) * inv(phi)
P = I1/2
s.B = inv(P + z.A*P) * z.B
s.C = z.C
s.D = z.D - s.C*P*s.B

For method='foh', the conversion is:

s.A = phi * diag(log(lambda)/h) * inv(phi)
Q = (I1 - I2/h)
P = I1 - Q
s.B = inv(P + z.A*Q) * z.B
s.C = z.C
s.D = z.D - s.C*Q*s.B

For method='tustin', the conversion is:

if prewarp == 0:
    k = 2/h     # standard Tustin method
else:
    k = prewarp/tan(prewarp*h/2)
Q = inv(I+z.A)
s.A = k*(z.A-I)*Q
s.B = (k*I-s.A)*Q*z.B
s.C = z.C
s.D = z.D - z.C*Q*z.B
getlti()[source]

Return scipy.signal.lti instance of continuous model. If model is discrete, d2c() is called (with defaults) to convert to continuous before calling scipy.signal.lti.