Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit67d6ef0

Browse files
committed
Add unit tests, change okid output for siso
1 parent23c0a44 commit67d6ef0

File tree

2 files changed

+142
-2
lines changed

2 files changed

+142
-2
lines changed

‎control/modelsimp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,5 +764,9 @@ def okid(*args, m=None, transpose=False, dt=True, truncate=False):
764764
H[:,:,1:]=Y[:,:,:]
765765
H=H/dt# scaling
766766

767+
# for siso return a 1D array instead of a 3D array
768+
ifq==1andp==1:
769+
H=np.squeeze(H)
770+
767771
# Return the first m Markov parameters
768772
returnHifnottransposeelsenp.transpose(H)

‎control/tests/modelsimp_test.py

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
importpytest
88

99

10-
fromcontrolimportStateSpace,forced_response,tf,rss,c2d
10+
fromcontrolimportStateSpace,impulse_response,forced_response,tf,rss,c2d
1111
fromcontrol.exceptionimportControlMIMONotImplemented
1212
fromcontrol.tests.conftestimportslycotonly
13-
fromcontrol.modelsimpimportbalred,hsvd,markov,modred
13+
fromcontrol.modelsimpimportbalred,hsvd,markov,okid,modred
1414

1515

1616
classTestModelsimp:
@@ -111,6 +111,142 @@ def testMarkovResults(self, k, m, n):
111111
# for k=5, m=n=10: 0.015 %
112112
np.testing.assert_allclose(Mtrue,Mcomp,rtol=1e-6,atol=1e-8)
113113

114+
deftestOKIDSignature(self):
115+
116+
# Example 6.1, Applied System Identification
117+
m1,k1,c1=1.,1.,0.01
118+
A=np.array([
119+
[0.,1.],
120+
[-k1/m1,-c1/m1],
121+
])
122+
B=np.array([[0.],[1./m1]])
123+
C=np.array([[-k1/m1,-c1/m1]])
124+
D=np.array([[1.]])
125+
sys=StateSpace(A,B,C,D)
126+
dt=0.1
127+
sysd=sys.sample(dt,method='zoh')
128+
129+
T=np.arange(0,200,dt)
130+
U=np.random.randn(sysd.B.shape[-1],len(T))
131+
response=forced_response(sysd,U=U)
132+
Y=response.outputs
133+
134+
m=5
135+
ir_true=impulse_response(sysd,T=T)
136+
Htrue=ir_true.outputs[:m+1]*dt
137+
H=okid(Y,U,m,dt=True)
138+
139+
np.testing.assert_allclose(Htrue,H,atol=1e-1)
140+
141+
# Test mimo example
142+
# Mechanical Vibrations: Theory and Application, SI Edition, 1st ed.
143+
# Figure 6.5 / Example 6.7
144+
m1,k1,c1=1.,4.,1.
145+
m2,k2,c2=2.,2.,1.
146+
k3,c3=6.,2.
147+
148+
A=np.array([
149+
[0.,0.,1.,0.],
150+
[0.,0.,0.,1.],
151+
[-(k1+k2)/m1, (k2)/m1,-(c1+c2)/m1,c2/m1],
152+
[(k2)/m2,-(k2+k3)/m2,c2/m2,-(c2+c3)/m2]
153+
])
154+
B=np.array([[0.,0.],[0.,0.],[1/m1,0.],[0.,1/m2]])
155+
C=np.array([[1.0,0.0,0.0,0.0],[0.0,1.0,0.0,0.0]])
156+
D=np.zeros((2,2))
157+
158+
sys=StateSpace(A,B,C,D)
159+
dt=0.25
160+
sysd=sys.sample(dt,method='zoh')
161+
162+
T=np.arange(0,100,dt)
163+
U=np.random.randn(sysd.B.shape[-1],len(T))
164+
response=forced_response(sysd,U=U)
165+
Y=response.outputs
166+
167+
m=100
168+
_,Htrue=impulse_response(sysd,T=dt*(m))
169+
170+
171+
# test array_like
172+
atol=1e-1
173+
H=okid(Y,U,m,dt=dt)
174+
np.testing.assert_allclose(H,Htrue,atol=atol)
175+
176+
# test array_like, truncate
177+
H=okid(Y,U,m,dt=dt,truncate=True)
178+
np.testing.assert_allclose(H,Htrue,atol=atol)
179+
180+
# test array_like, transpose
181+
HT=okid(Y.T,U.T,m,dt=dt,transpose=True)
182+
np.testing.assert_allclose(HT,np.transpose(Htrue),atol=atol)
183+
184+
# test response data
185+
H=okid(response,m,dt=dt)
186+
np.testing.assert_allclose(H,Htrue,atol=atol)
187+
188+
# test response data
189+
H=okid(response,m,dt=dt,truncate=True)
190+
np.testing.assert_allclose(H,Htrue,atol=atol)
191+
192+
# test response data, transpose
193+
response.transpose=True
194+
HT=okid(response,m,dt=dt)
195+
np.testing.assert_allclose(HT,np.transpose(Htrue),atol=atol)
196+
197+
# Make sure markov() returns the right answer
198+
@pytest.mark.parametrize("k, m, n",
199+
[(2,2,2),
200+
(2,5,5),
201+
(5,2,2),
202+
(5,5,5),
203+
(5,10,10)])
204+
deftestOkidResults(self,k,m,n):
205+
#
206+
# Test over a range of parameters
207+
#
208+
# k = order of the system
209+
# m = number of Markov parameters
210+
# n = size of the data vector
211+
#
212+
# Values *should* match exactly for n = m, otherewise you get a
213+
# close match but errors due to the assumption that C A^k B =
214+
# 0 for k > m-2 (see modelsimp.py).
215+
#
216+
217+
# Generate stable continuous time system
218+
Hc=rss(k,1,1)
219+
220+
# Choose sampling time based on fastest time constant / 10
221+
w,_=np.linalg.eig(Hc.A)
222+
Ts=np.min(-np.real(w))/10.
223+
224+
# Convert to a discrete time system via sampling
225+
Hd=c2d(Hc,Ts,'zoh')
226+
227+
# Compute the Markov parameters from state space
228+
Mtrue=np.hstack([Hd.D]+ [
229+
Hd.C @np.linalg.matrix_power(Hd.A,i) @Hd.B
230+
foriinrange(m-1)])
231+
232+
Mtrue=np.squeeze(Mtrue)
233+
234+
# Generate input/output data
235+
T=np.array(range(n))*Ts
236+
U=np.cos(T)+np.sin(T/np.pi)
237+
_,Y=forced_response(Hd,T,U,squeeze=True)
238+
Mcomp=okid(Y,U,m-1)
239+
240+
241+
# TODO: Check tol
242+
# Compare to results from markov()
243+
# experimentally determined probability to get non matching results
244+
# with rtot=1e-6 and atol=1e-8 due to numerical errors
245+
# for k=5, m=n=10: 0.015 %
246+
np.testing.assert_allclose(Mtrue,Mcomp,atol=1e-1)
247+
248+
249+
114250
deftestModredMatchDC(self):
115251
#balanced realization computed in matlab for the transfer function:
116252
# num = [1 11 45 32], den = [1 15 60 200 60]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp