SERIES
This function builds the equivalent transfer function for two linear time-invariant systems connected in cascade. In a series interconnection, the output of the first block drives the input of the second block.
For transfer functions G_1(s) and G_2(s), the combined system is
G(s) = G_2(s)G_1(s)
The wrapper accepts each system as a 2-row coefficient array of the form [[numerator], [denominator]], converts them to python-control transfer functions, and returns the formatted string representation of the cascaded result.
Excel Usage
=SERIES(sys_a, sys_b)
sys_a(list[list], required): Numerator and denominator of the first system G1.sys_b(list[list], required): Numerator and denominator of the second system G2.
Returns (str): String representation of the resulting series-connected system.
Example 1: Two first order systems in series
Inputs:
| sys_a | sys_b |
|---|---|
| 1 | 1 |
| 1 | 1 |
Excel formula:
=SERIES({1;1,1}, {1;1,2})
Expected output:
"<TransferFunction>: sys[2]\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\n\n 1\n -------------\n s^2 + 3 s + 2"
Example 2: Static gain cascaded with a first-order lag
Inputs:
| sys_a | sys_b |
|---|---|
| 4 | 1 |
| 1 | 1 |
Excel formula:
=SERIES({4;1}, {1;1,3})
Expected output:
"<TransferFunction>: sys[5]\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\n\n 4\n -----\n s + 3"
Example 3: Integrator cascaded with a first-order lag
Inputs:
| sys_a | sys_b |
|---|---|
| 1 | 2 |
| 1 | 1 |
Excel formula:
=SERIES({1;1,0}, {2;1,5})
Expected output:
"<TransferFunction>: sys[8]\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\n\n 2\n ---------\n s^2 + 5 s"
Example 4: Second-order plant followed by a static gain
Inputs:
| sys_a | sys_b |
|---|---|
| 1 | 3 |
| 1 | 1 |
Excel formula:
=SERIES({1;1,2,2}, {3;1})
Expected output:
"<TransferFunction>: sys[11]\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\n\n 3\n -------------\n s^2 + 2 s + 2"
Python Code
Show Code
import control as ct
def series(sys_a, sys_b):
"""
Series interconnection of two LTI systems.
See: https://python-control.readthedocs.io/en/latest/generated/control.series.html
This example function is provided as-is without any representation of accuracy.
Args:
sys_a (list[list]): Numerator and denominator of the first system G1.
sys_b (list[list]): Numerator and denominator of the second system G2.
Returns:
str: String representation of the resulting series-connected system.
"""
try:
def to2d(value):
return [[value]] if not isinstance(value, list) else value
def parse_coefficients(row, label):
if not isinstance(row, list):
return None, f"Error: {label} must be a list of coefficients"
coefficients = []
for item in row:
if item is None or str(item).strip() == "":
continue
try:
coefficients.append(float(item))
except (TypeError, ValueError):
return None, f"Error: {label} contains a non-numeric coefficient"
if not coefficients:
return None, f"Error: {label} must contain at least one numeric coefficient"
return coefficients, None
def to_tf(data, label):
matrix = to2d(data)
if not isinstance(matrix, list) or len(matrix) < 2:
return None, f"Error: {label} must be provided as [[numerator], [denominator]]"
numerator, error = parse_coefficients(matrix[0], f"{label} numerator")
if error:
return None, error
denominator, error = parse_coefficients(matrix[1], f"{label} denominator")
if error:
return None, error
return ct.tf(numerator, denominator), None
g1, error = to_tf(sys_a, "sys_a")
if error:
return error
g2, error = to_tf(sys_b, "sys_b")
if error:
return error
res = ct.series(g1, g2)
return str(res)
except Exception as e:
return f"Error: {str(e)}"