Skip to content

Commit 8d62775

Browse files
committed
Change default value of dt to None, add equally spaced check for response time data
1 parent 7ac6ee0 commit 8d62775

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

control/modelsimp.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ def era(YY, m, n, nin, nout, r):
402402
raise NotImplementedError('This function is not implemented yet.')
403403

404404

405-
def markov(*args, m=None, transpose=False, dt=True, truncate=False):
405+
def markov(*args, m=None, transpose=False, dt=None, truncate=False):
406406
"""markov(Y, U, [, m])
407407
408408
Calculate the first `m` Markov parameters [D CB CAB ...] from data.
@@ -448,7 +448,9 @@ def markov(*args, m=None, transpose=False, dt=True, truncate=False):
448448
True indicates discrete time with unspecified sampling time and a
449449
positive float is discrete time with the specified sampling time.
450450
It can be used to scale the Markov parameters in order to match
451-
the unit-area impulse response of python-control. Default is True.
451+
the unit-area impulse response of python-control. Default is True
452+
for array_like and dt=data.time[1]-data.time[0] for
453+
TimeResponseData as input.
452454
truncate : bool, optional
453455
Do not use first m equation for least squares. Default is False.
454456
transpose : bool, optional
@@ -483,10 +485,16 @@ def markov(*args, m=None, transpose=False, dt=True, truncate=False):
483485
raise ControlArgument("not enough input arguments")
484486

485487
if isinstance(args[0], TimeResponseData):
486-
Umat = np.array(args[0].inputs, ndmin=2)
487-
Ymat = np.array(args[0].outputs, ndmin=2)
488-
transpose = args[0].transpose
489-
if args[0].transpose and not args[0].issiso:
488+
data = args[0]
489+
Umat = np.array(data.inputs, ndmin=2)
490+
Ymat = np.array(data.outputs, ndmin=2)
491+
if dt is None:
492+
dt = data.time[1] - data.time[0]
493+
if not np.allclose(np.diff(data.time), dt):
494+
raise ValueError("response time values must be equally "
495+
"spaced.")
496+
transpose = data.transpose
497+
if data.transpose and not data.issiso:
490498
Umat, Ymat = np.transpose(Umat), np.transpose(Ymat)
491499
if len(args) == 2:
492500
m = args[1]
@@ -497,6 +505,8 @@ def markov(*args, m=None, transpose=False, dt=True, truncate=False):
497505
raise ControlArgument("not enough input arguments")
498506
Umat = np.array(args[1], ndmin=2)
499507
Ymat = np.array(args[0], ndmin=2)
508+
if dt is None:
509+
dt = True
500510
if transpose:
501511
Umat, Ymat = np.transpose(Umat), np.transpose(Ymat)
502512
if len(args) == 3:

control/tests/modelsimp_test.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ def testMarkovSignature(self):
8181
T = np.linspace(0, 10, 100)
8282
U = np.ones((1, 100))
8383
T, Y = forced_response(tf([1], [1, 0.5], True), T, U)
84-
H = markov(Y, U, 4, transpose=False)
84+
H = markov(Y, U, 4, dt=True)
8585
np.testing.assert_array_almost_equal(H[:3], Htrue[:3])
8686

8787
response = forced_response(tf([1], [1, 0.5], True), T, U)
88-
H = markov(response, 4)
88+
H = markov(response, 4, dt=True)
8989
np.testing.assert_array_almost_equal(H[:3], Htrue[:3])
9090

9191
# Test example from issue #395
@@ -164,14 +164,28 @@ def testMarkovResults(self, k, m, n):
164164
# Generate input/output data
165165
T = np.array(range(n)) * Ts
166166
U = np.cos(T) + np.sin(T/np.pi)
167-
response = forced_response(Hd, T, U, squeeze=True)
168-
Mcomp = markov(response, m)
167+
168+
ir_true = impulse_response(Hd,T)
169+
Mtrue_scaled = ir_true[1][:m]
170+
171+
T, Y = forced_response(Hd, T, U, squeeze=True)
172+
Mcomp = markov(Y, U, m, dt=True)
173+
Mcomp_scaled = markov(Y, U, m, dt=Ts)
169174

170175
# Compare to results from markov()
171176
# experimentally determined probability to get non matching results
172177
# with rtot=1e-6 and atol=1e-8 due to numerical errors
173178
# for k=5, m=n=10: 0.015 %
174179
np.testing.assert_allclose(Mtrue, Mcomp, rtol=1e-6, atol=1e-8)
180+
np.testing.assert_allclose(Mtrue_scaled, Mcomp_scaled, rtol=1e-6, atol=1e-8)
181+
182+
response = forced_response(Hd, T, U, squeeze=True)
183+
Mcomp = markov(response, m, dt=True)
184+
Mcomp_scaled = markov(response, m, dt=Ts)
185+
186+
np.testing.assert_allclose(Mtrue, Mcomp, rtol=1e-6, atol=1e-8)
187+
np.testing.assert_allclose(Mtrue_scaled, Mcomp_scaled, rtol=1e-6, atol=1e-8)
188+
175189

176190
def testModredMatchDC(self):
177191
#balanced realization computed in matlab for the transfer function:

0 commit comments

Comments
 (0)