System Dynamics

Transfer Functions in Python

In Python, there are two common transfer function representations:

  • SymPy symbolic expressions, which are used for symbolic manipulation and analysis
  • Control Systems Library transfer function objects (control.xferfcn.TransferFunction), which are used for numerical simulation and analysis

We will use both representations and introduce the DySys package’s dysys.transferfunctionsymbolic.tfs() function for convenient symbolic transfer function creation, manipulation, and conversion to a control.xferfcn.TransferFunction object. ## Define a Symbolic Transfer Function

Load Python packages as follows:

import numpy as np
import sympy as sp
import dysys
import control

Consider the transfer function \[ H(s) = \frac{b_1 s + b_0}{a_2 s^2 + a_1 s + a_0}, \] where \(b_i\) and \(a_i\) are real-valued coefficients. We could define the transfer function as a symbolic expression as follows:

s = sp.symbols("s", complex=True)
a0, a1, a2, b0, b1 = sp.symbols("a0, a1, a2, b0, b1")
H_sp = (b1 * s + b0) / (a2 * s**2 + a1 * s + a0)

We can also use the DySys package to create a symbolic transfer function as follows:

H_dysys = dysys.tfs(H_sp, s)

Use DySys Methods

Something nice about the DySys representation created by tfs is that several methods are available. For instance, the poles and zeros can be computed as follows:

print(H_dysys.poles())
print(H_dysys.zeros())
{-a1/(2*a2) - sqrt(-4*a0*a2 + a1**2)/(2*a2): 1, -a1/(2*a2) + sqrt(-4*a0*a2 + a1**2)/(2*a2): 1}
{-b0/b1: 1}

Note that the multiplicity of the poles and zeros are the dictionary values. The DC gain can be computed as follows:

print(H_dysys.dc_gain())
b0/a0

Convert to Control Systems Library Transfer Function

The DySys representation can be converted to a control.xferfcn.TransferFunction object as follows:

params = {"a0": 1, "a1": 2, "a2": 3, "b0": 4, "b1": 5}
H_control = H_dysys.to_control(params)
print(H_control)
<TransferFunction>: sys[0]
Inputs (1): ['u[0]']
Outputs (1): ['y[0]']


    5 s + 4
---------------
3 s^2 + 2 s + 1

Note that the params dictionary is used to substitute the symbolic parameters with numerical values, which is required if there are any nonnumerical parameters remaining in the symbolic transfer function.

Constructing Control Systems Library Transfer Functions from Scratch

The control.xferfcn.TransferFunction object can be constructed from scratch in two primary ways. The first way is to use the numerator and denominator coefficients as follows:

num = [5, 4]  # 5 s + 4
den = [3, 2, 1]  # 3 s^2 + 2 s + 1
H_control_2 = control.tf(num, den)
print(H_control_2)
<TransferFunction>: sys[1]
Inputs (1): ['u[0]']
Outputs (1): ['y[0]']


    5 s + 4
---------------
3 s^2 + 2 s + 1

The second way is to use the zero-pole-gain representation as follows:

zeros = [3, 4]
poles = [0, 1, 2]
gain = 3
H_control_3 = control.zpk(zeros, poles, gain)
print(H_control_3)
<TransferFunction>: sys[2]
Inputs (1): ['u[0]']
Outputs (1): ['y[0]']


3 s^2 - 21 s + 36
-----------------
s^3 - 3 s^2 + 2 s

Online Resources for Section 11.3

No online resources.