8000 add zpk() function · python-control/python-control@91466d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 91466d1

Browse files
committed
add zpk() function
1 parent b4cd96b commit 91466d1

File tree

5 files changed

+92
-4
lines changed

5 files changed

+92
-4
lines changed

control/matlab/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@
115115
116116
== ========================== ============================================
117117
\* :func:`tf` create transfer function (TF) models
118-
\ zpk create zero/pole/gain (ZPK) models.
118+
\* :func:`zpk` create zero/pole/gain (ZPK) models.
119119
\* :func:`ss` create state-space (SS) models
120120
\ dss create descriptor state-space models
121121
\ delayss create state-space models with delayed terms

control/tests/kwargs_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def test_kwarg_search(module, prefix):
9696
(control.tf, 0, 0, ([1], [1, 1]), {}),
9797
(control.tf2io, 0, 1, (), {}),
9898
(control.tf2ss, 0, 1, (), {}),
99+
(control.zpk, 0, 0, ([1], [2, 3], 4), {}),
99100
(control.InputOutputSystem, 0, 0, (),
100101
{'inputs': 1, 'outputs': 1, 'states': 1}),
101102
(control.InputOutputSystem.linearize, 1, 0, (0, 0), {}),
@@ -184,6 +185,7 @@ def test_matplotlib_kwargs(function, nsysargs, moreargs, kwargs, mplcleanup):
184185
'tf2io' : test_unrecognized_kwargs,
185186
'tf2ss' : test_unrecognized_kwargs,
186187
'sample_system' : test_unrecognized_kwargs,
188+
'zpk': test_unrecognized_kwargs,
187189
'flatsys.point_to_point':
188190
flatsys_test.TestFlatSys.test_point_to_point_errors,
189191
'flatsys.solve_flat_ocp':

control/tests/xferfcn_test.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ def test_repr(self, Hargs, ref):
986986
np.testing.assert_array_almost_equal(H.num[p][m], H2.num[p][m])
987987
np.testing.assert_array_almost_equal(H.den[p][m], H2.den[p][m])
988988
assert H.dt == H2.dt
989-
989+
990990
def test_sample_named_signals(self):
991991
sysc = ct.TransferFunction(1.1, (1, 2), inputs='u', outputs='y')
992992

@@ -1073,3 +1073,41 @@ def test_xferfcn_ndarray_precedence(op, tf, arr):
10731073
# Apply the operator to the array and transfer function
10741074
result = op(arr, tf)
10751075
assert isinstance(result, ct.TransferFunction)
1076+
1077+
1078+
@pytest.mark.parametrize(
1079+
"zeros, poles, gain, args, kwargs", [
1080+
([], [-1], 1, [], {}),
1081+
([1, 2], [-1, -2, -3], 5, [], {}),
1082+
([1, 2], [-1, -2, -3], 5, [], {'name': "sys"}),
1083+
([1, 2], [-1, -2, -3], 5, [], {'inputs': ["in"], 'outputs': ["out"]}),
1084+
([1, 2], [-1, -2, -3], 5, [0.1], {}),
1085+
(np.array([1, 2]), np.array([-1, -2, -3]), 5, [], {}),
1086+
])
1087+
def test_zpk(zeros, poles, gain, args, kwargs):
1088+
# Create the transfer function
1089+
sys = ct.zpk(zeros, poles, gain, *args, **kwargs)
1090+
1091+
# Make sure the poles and zeros match
1092+
np.testing.assert_equal(sys.zeros().sort(), zeros.sort())
1093+
np.testing.assert_equal(sys.poles().sort(), poles.sort())
1094+
1095+
# Check to make sure the gain is OK
1096+
np.testing.assert_almost_equal(
1097+
gain, sys(0) * np.prod(-sys.poles()) / np.prod(-sys.zeros()))
1098+
1099+
# Check time base
1100+
if args:
1101+
assert sys.dt == args[0]
1102+
1103+
# Check inputs, outputs, name
1104+
input_labels = kwargs.get('inputs', [])
1105+
for i, label in enumerate(input_labels):
1106+
assert sys.input_labels[i] == label
1107+
1108+
output_labels = kwargs.get('outputs', [])
1109+
for i, label in enumerate(output_labels):
1110+
assert sys.output_labels[i] == label
1111+
1112+
if kwargs.get('name'):
1113+
assert sys.name == kwargs.get('name')

control/xferfcn.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
from .frdata import FrequencyResponseData
6666
from . import config
6767

68-
__all__ = ['TransferFunction', 'tf', 'ss2tf', 'tfdata']
68+
__all__ = ['TransferFunction', 'tf', 'zpk', 'ss2tf', 'tfdata']
6969

7070

7171
# Define module default parameter values
@@ -796,7 +796,7 @@ def zeros(self):
796796
"""Compute the zeros of a transfer function."""
797797
if self.ninputs > B41A 1 or self.noutputs > 1:
798798
raise NotImplementedError(
799-
"TransferFunction.zero is currently only implemented "
799+
"TransferFunction.zeros is currently only implemented "
800800
"for SISO systems.")
801801
else:
802802
# for now, just give zeros of a SISO tf
@@ -1577,8 +1577,55 @@ def tf(*args, **kwargs):
15771577
else:
15781578
raise ValueError("Needs 1 or 2 arguments; received %i." % len(args))
15791579

1580+
1581+
def zpk(zeros, poles, gain, *args, **kwargs):
1582+
"""zpk(zeros, poles, gain[, dt])
1583+
1584+
Create a transfer function from zeros, poles, gain.
1585+
1586+
Given a list of zeros z_i, poles p_j, and gain k, return the transfer
1587+
function:
1588+
1589+
.. math::
1590+
H(s) = k \\frac{(s - z_1) (s - z_2) \\cdots (s - z_m)}
1591+
{(s - p_1) (s - p_2) \\cdots (s - p_n)}
1592+
1593+
Parameters
1594+
----------
1595+
zeros : array_like
1596+
Array containing the location of zeros.
1597+
poles : array_like
1598+
Array containing the location of zeros.
1599+
gain : float
1600+
System gain
1601+
dt : None, True or float, optional
1602+
System timebase. 0 (default) indicates continuous
1603+
time, True indicates discrete time with unspecified sampling
1604+
time, positive number is discrete time with specified
1605+
sampling time, None indicates unspecified timebase (either
1606+
continuous or discrete time).
1607+
inputs, outputs, states : str, or list of str, optional
1608+
List of strings that name the individual signals. If this parameter
1609+
is not given or given as `None`, the signal names will be of the
1610+
form `s[i]` (where `s` is one of `u`, `y`, or `x`). See
1611+
:class:`InputOutputSystem` for more information.
1612+
name : string, optional
1613+
System name (used for specifying signals). If unspecified, a generic
1614+
name <sys[id]> is generated with a unique integer id.
1615+
1616+
Returns
1617+
-------
1618+
out: :class:`TransferFunction`
1619+
Transfer function with given zeros, poles, and gain.
1620+
1621+
"""
1622+
num, den = zpk2tf(zeros, poles, gain)
1623+
return TransferFunction(num, den, *args, **kwargs)
1624+
1625+
15801626
# TODO: copy signal names
15811627
def ss2tf(*args, **kwargs):
1628+
15821629
"""ss2tf(sys)
15831630
15841631
Transform a state space system to a transfer function.

doc/control.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ System creation
1818
ss
1919
tf
2020
frd
21+
zpk
2122
rss
2223
drss
2324
NonlinearIOSystem

0 commit comments

Comments
 (0)
0