Skip to content

Commit 317d261

Browse files
committed
Change output to ndarray
1 parent 446a161 commit 317d261

File tree

3 files changed

+63
-43
lines changed

3 files changed

+63
-43
lines changed

control/modelsimp.py

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -438,21 +438,9 @@ def markov(data, m=None, dt=True, truncate=False):
438438
439439
Returns
440440
-------
441-
H : TimeResponseData
442-
Markov parameters / impulse response [D CB CAB ...] represented as
443-
a :class:`TimeResponseData` object containing the following properties:
444-
445-
* time (array): Time values of the output.
446-
447-
* outputs (array): Response of the system. If the system is SISO,
448-
the array is 1D (indexed by time). If the
449-
system is not SISO, the array is 3D (indexed
450-
by the output, trace, and time).
451-
452-
* inputs (array): Inputs of the system. If the system is SISO,
453-
the array is 1D (indexed by time). If the
454-
system is not SISO, the array is 3D (indexed
455-
by the output, trace, and time).
441+
H : ndarray
442+
First m Markov parameters, [D CB CAB ...]
443+
456444
457445
Notes
458446
-----
@@ -557,23 +545,8 @@ def markov(data, m=None, dt=True, truncate=False):
557545
H = H.reshape(q,m,p) # output, time*input -> output, time, input
558546
H = H.transpose(0,2,1) # output, input, time
559547

560-
# Create unit area impulse inputs
561-
inputs = np.zeros((p,p,m))
562-
trace_labels, trace_types = [], []
563-
for i in range(p):
564-
inputs[i,i,0] = 1/dt # unit area impulse
565-
trace_labels.append(f"From {data.input_labels[i]}")
566-
trace_types.append('impulse')
548+
if q == 1 and p == 1:
549+
H = np.squeeze(H)
567550

568-
# Markov parameters as TimeResponseData with unit area impulse inputs
569551
# Return the first m Markov parameters
570-
return TimeResponseData(time=data.time[:m],
571-
outputs=H,
572-
output_labels=data.output_labels,
573-
inputs=inputs,
574-
input_labels=data.input_labels,
575-
trace_labels=trace_labels,
576-
trace_types=trace_types,
577-
transpose=data.transpose,
578-
plot_inputs=False,
579-
issiso=data.issiso)
552+
return H if not data.transpose else np.transpose(H)

control/tests/modelsimp_test.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,17 @@ def testMarkovSignature(self):
4444
m = 3
4545
H = markov(response, m)
4646
Htrue = np.array([1., 0., 0.])
47-
np.testing.assert_array_almost_equal(H.outputs, Htrue)
47+
np.testing.assert_array_almost_equal(H, Htrue)
4848

4949
# Make sure that transposed data also works
5050
response.transpose=True
5151
H = markov(response, m)
52-
np.testing.assert_array_almost_equal(H.outputs, np.transpose(Htrue))
52+
np.testing.assert_array_almost_equal(H, np.transpose(Htrue))
5353

5454
# Generate Markov parameters without any arguments
5555
response.transpose=False
5656
H = markov(response, m)
57-
np.testing.assert_array_almost_equal(H.outputs, Htrue)
57+
np.testing.assert_array_almost_equal(H, Htrue)
5858

5959
# Test example from docstring
6060
T = np.linspace(0, 10, 100)
@@ -119,7 +119,7 @@ def testMarkovResults(self, k, m, n):
119119
# experimentally determined probability to get non matching results
120120
# with rtot=1e-6 and atol=1e-8 due to numerical errors
121121
# for k=5, m=n=10: 0.015 %
122-
np.testing.assert_allclose(Mtrue, Mcomp.outputs, rtol=1e-6, atol=1e-8)
122+
np.testing.assert_allclose(Mtrue, Mcomp, rtol=1e-6, atol=1e-8)
123123

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

examples/markov.py

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,43 @@
1010

1111
import control as ct
1212

13+
def create_impulse_response(H, time, transpose, dt):
14+
"""Helper function to use TimeResponseData type for plotting"""
15+
16+
H = np.array(H, ndmin=3)
17+
18+
if transpose:
19+
H = np.transpose(H)
20+
21+
q, p, m = H.shape
22+
inputs = np.zeros((p,p,m))
23+
24+
issiso = True if (q == 1 and p == 1) else False
25+
26+
input_labels = []
27+
trace_labels, trace_types = [], []
28+
for i in range(p):
29+
inputs[i,i,0] = 1/dt # unit area impulse
30+
input_labels.append(f"u{[i]}")
31+
trace_labels.append(f"From u{[i]}")
32+
trace_types.append('impulse')
33+
34+
output_labels = []
35+
for i in range(q):
36+
output_labels.append(f"y{[i]}")
37+
38+
return ct.TimeResponseData(time=time[:m],
39+
outputs=H,
40+
output_labels=output_labels,
41+
inputs=inputs,
42+
input_labels=input_labels,
43+
trace_labels=trace_labels,
44+
trace_types=trace_types,
45+
sysname="H_est",
46+
transpose=transpose,
47+
plot_inputs=False,
48+
issiso=issiso)
49+
1350
# set up a mass spring damper system (2dof, MIMO case)
1451
# m q_dd + c q_d + k q = u
1552
m1, k1, c1 = 1., 1., .1
@@ -41,19 +78,29 @@
4178

4279
dt = 0.5
4380
sysd = sys.sample(dt, method='zoh')
81+
sysd.name = "H_true"
4482

45-
t = np.arange(0,5000,dt)
46-
u = np.random.randn(sysd.B.shape[-1], len(t)) # random forcing input
83+
# random forcing input
84+
t = np.arange(0,500,dt)
85+
u = np.random.randn(sysd.B.shape[-1], len(t))
4786

4887
response = ct.forced_response(sysd, U=u)
4988
response.plot()
5089
plt.show()
5190

52-
markov_true = ct.impulse_response(sysd,T=dt*100)
53-
markov_est = ct.markov(response,m=100,dt=dt)
91+
m = 100
92+
ir_true = ct.impulse_response(sysd,T=dt*m)
93+
ir_true.tranpose = True
94+
95+
H_est = ct.markov(response,m=m,dt=dt)
96+
# Helper function for plotting only
97+
ir_est = create_impulse_response(H_est,
98+
ir_true.time,
99+
ir_true.transpose,
100+
dt)
54101

55-
markov_true.plot(title=xixo)
56-
markov_est.plot(color='orange',linestyle='dashed')
102+
ir_true.plot(title=xixo)
103+
ir_est.plot(color='orange',linestyle='dashed')
57104
plt.show()
58105

59106
if 'PYCONTROL_TEST_EXAMPLES' not in os.environ:

0 commit comments

Comments
 (0)