Skip to content

Commit 57b5307

Browse files
authored
Merge pull request #1064 from murrayrm/fix_frd_timebase-20Nov2024
fix timebase processing in frd, zpk
2 parents 20a73de + 8b29e45 commit 57b5307

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

control/frdata.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,24 @@ def __init__(self, *args, **kwargs):
124124
To construct frequency response data for an existing LTI
125125
object, other than an FRD, call FRD(sys, omega).
126126
127+
The timebase for the frequency response can be provided using an
128+
optional third argument or the 'dt' keyword.
129+
127130
"""
128-
# TODO: discrete-time FRD systems?
129131
smooth = kwargs.pop('smooth', False)
130132

131133
#
132134
# Process positional arguments
133135
#
136+
if len(args) == 3:
137+
# Discrete time transfer function
138+
dt = args[-1]
139+
if 'dt' in kwargs:
140+
warn("received multiple dt arguments, "
141+
"using positional arg dt = %s" % dt)
142+
kwargs['dt'] = dt
143+
args = args[:-1]
144+
134145
if len(args) == 2:
135146
if not isinstance(args[0], FRD) and isinstance(args[0], LTI):
136147
# not an FRD, but still a system, second argument should be
@@ -200,11 +211,11 @@ def __init__(self, *args, **kwargs):
200211

201212
# Process iosys keywords
202213
defaults = {
203-
'inputs': self.fresp.shape[1], 'outputs': self.fresp.shape[0],
204-
'dt': None}
214+
'inputs': self.fresp.shape[1], 'outputs': self.fresp.shape[0]}
215+
if arg_dt is not None:
216+
defaults['dt'] = arg_dt # choose compatible timebase
205217
name, inputs, outputs, states, dt = _process_iosys_keywords(
206218
kwargs, defaults, end=True)
207-
dt = common_timebase(dt, arg_dt) # choose compatible timebase
208219

209220
# Process signal names
210221
InputOutputSystem.__init__(

control/tests/docstrings_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
control.bode_plot: ['sharex', 'sharey', 'margin_info'], # deprecated
5555
control.eigensys_realization: ['arg'], # quasi-positional
5656
control.find_operating_point: ['method'], # internal use
57+
control.zpk: ['args'] # 'dt' (manual)
5758
}
5859

5960
# Decide on the level of verbosity (use -rP when running pytest)

control/tests/timebase_test.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,34 @@ def test_composition_override(dt):
9797
with pytest.raises(ValueError, match="incompatible timebases"):
9898
sys3 = ct.interconnect(
9999
[sys1, sys2], inputs='u1', outputs='y2', dt=dt)
100+
101+
102+
# Make sure all system creation functions treat timebases uniformly
103+
@pytest.mark.parametrize(
104+
"fcn, args", [
105+
(ct.ss, [-1, 1, 1, 1]),
106+
(ct.tf, [[1, 2], [3, 4, 5]]),
107+
(ct.zpk, [[-1], [-2, -3], 1]),
108+
(ct.frd, [[1, 1, 1], [1, 2, 3]]),
109+
(ct.nlsys, [lambda t, x, u, params: -x, None]),
110+
])
111+
@pytest.mark.parametrize(
112+
"kwargs, expected", [
113+
({}, 0),
114+
({'dt': 0}, 0),
115+
({'dt': 0.1}, 0.1),
116+
({'dt': True}, True),
117+
({'dt': None}, None),
118+
])
119+
def test_default(fcn, args, kwargs, expected):
120+
sys = fcn(*args, **kwargs)
121+
assert sys.dt == expected
122+
123+
# Some commands allow dt via extra argument
124+
if fcn in [ct.ss, ct.tf, ct.zpk, ct.frd] and kwargs.get('dt'):
125+
sys = fcn(*args, kwargs['dt'])
126+
assert sys.dt == expected
127+
128+
# Make sure an error is generated if dt is redundant
129+
with pytest.warns(UserWarning, match="received multiple dt"):
130+
sys = fcn(*args, kwargs['dt'], **kwargs)

control/xferfcn.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,7 +1677,7 @@ def tf(*args, **kwargs):
16771677
raise ValueError("Needs 1 or 2 arguments; received %i." % len(args))
16781678

16791679

1680-
def zpk(zeros, poles, gain, dt=None, **kwargs):
1680+
def zpk(zeros, poles, gain, *args, **kwargs):
16811681
"""zpk(zeros, poles, gain[, dt])
16821682
16831683
Create a transfer function from zeros, poles, gain.
@@ -1732,7 +1732,7 @@ def zpk(zeros, poles, gain, dt=None, **kwargs):
17321732
17331733
"""
17341734
num, den = zpk2tf(zeros, poles, gain)
1735-
return TransferFunction(num, den, dt=dt, **kwargs)
1735+
return TransferFunction(num, den, *args, **kwargs)
17361736

17371737

17381738
def ss2tf(*args, **kwargs):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy