@@ -66,8 +66,8 @@ def siso_ss2(self, siso_ss1):
66
66
T .initial = siso_ss1 .yinitial - 9
67
67
T .yimpulse = np .array ([86. , 70.1808 , 57.3753 , 46.9975 , 38.5766 ,
68
68
31.7344 , 26.1668 , 21.6292 , 17.9245 , 14.8945 ])
69
- return T
70
69
70
+ return T
71
71
72
72
@pytest .fixture
73
73
def siso_tf1 (self ):
@@ -197,31 +197,98 @@ def no_pole_cancellation(self):
197
197
@pytest .fixture
198
198
def siso_tf_type1 (self ):
199
199
# System Type 1 - Step response not stationary: G(s)=1/s(s+1)
200
- return TransferFunction (1 , [1 , 1 , 0 ])
200
+ T = TSys (TransferFunction (1 , [1 , 1 , 0 ]))
201
+ T .step_info = {
202
+ 'RiseTime' : np .NaN ,
203
+ 'SettlingTime' : np .NaN ,
204
+ 'SettlingMin' : np .NaN ,
205
+ 'SettlingMax' : np .NaN ,
206
+ 'Overshoot' : np .NaN ,
207
+ 'Undershoot' : np .NaN ,
208
+ 'Peak' : np .Inf ,
209
+ 'PeakTime' : np .Inf ,
210
+ 'SteadyStateValue' : np .NaN }
211
+ return T
201
212
202
213
@pytest .fixture
203
214
def siso_tf_kpos (self ):
204
215
# SISO under shoot response and positive final value G(s)=(-s+1)/(s²+s+1)
205
- return TransferFunction ([- 1 , 1 ], [1 , 1 , 1 ])
216
+ T = TSys (TransferFunction ([- 1 , 1 ], [1 , 1 , 1 ]))
217
+ T .step_info = {
218
+ 'RiseTime' : 1.242 ,
219
+ 'SettlingTime' : 9.110 ,
220
+ 'SettlingMin' : 0.950 ,
221
+ 'SettlingMax' : 1.208 ,
222
+ 'Overshoot' : 20.840 ,
223
+ 'Undershoot' : 27.840 ,
224
+ 'Peak' : 1.208 ,
225
+ 'PeakTime' : 4.282 ,
226
+ 'SteadyStateValue' : 1.0 }
227
+ return T
206
228
207
229
@pytest .fixture
208
230
def siso_tf_kneg (self ):
209
231
# SISO under shoot response and negative final value k=-1 G(s)=-(-s+1)/(s²+s+1)
210
- return TransferFunction ([1 , - 1 ], [1 , 1 , 1 ])
232
+ T = TSys (TransferFunction ([1 , - 1 ], [1 , 1 , 1 ]))
233
+ T .step_info = {
234
+ 'RiseTime' : 1.242 ,
235
+ 'SettlingTime' : 9.110 ,
236
+ 'SettlingMin' : - 1.208 ,
237
+ 'SettlingMax' : - 0.950 ,
238
+ 'Overshoot' : 20.840 ,
239
+ 'Undershoot' : 27.840 ,
240
+ 'Peak' : 1.208 ,
241
+ 'PeakTime' : 4.282 ,
242
+ 'SteadyStateValue' : - 1.0 }
243
+ return T
211
244
212
245
@pytest .fixture
213
246
def tf1_matlab_help (self ):
214
247
# example from matlab online help https://www.mathworks.com/help/control/ref/stepinfo.html
215
- return TransferFunction ([1 , 5 , 5 ], [1 , 1.65 , 5 , 6.5 , 2 ])
248
+ T = TSys (TransferFunction ([1 , 5 , 5 ], [1 , 1.65 , 5 , 6.5 , 2 ]))
249
+ T .step_info = {
250
+ 'RiseTime' : 3.8456 ,
251
+ 'SettlingTime' : 27.9762 ,
252
+ 'SettlingMin' : 2.0689 ,
253
+ 'SettlingMax' : 2.6873 ,
254
+ 'Overshoot' : 7.4915 ,
255
+ 'Undershoot' : 0 ,
256
+ 'Peak' : 2.6873 ,
257
+ 'PeakTime' : 8.0530 ,
258
+ 'SteadyStateValue' : 2.5 }
259
+ return T
216
260
217
261
@pytest .fixture
218
- def tf2_matlab_help (self ):
262
+ def ss2_matlab_help (self ):
219
263
A = [[0.68 , - 0.34 ], [0.34 , 0.68 ]]
220
264
B = [[0.18 ], [0.04 ]]
221
265
C = [- 1.12 , - 1.10 ]
222
266
D = [0.06 ]
223
- sys = StateSpace (A , B , C , D , 0.2 )
224
- return sys
267
+ T = TSys (StateSpace (A , B , C , D , 0.2 ))
268
+ T .step_info = {
269
+ 'RiseTime' : 0.4000 ,
270
+ 'SettlingTime' : 2.8000 ,
271
+ 'SettlingMin' : - 0.6724 ,
272
+ 'SettlingMax' : - 0.5188 ,
273
+ 'Overshoot' : 24.6476 ,
274
+ 'Undershoot' : 11.1224 ,
275
+ 'Peak' : 0.6724 ,
276
+ 'PeakTime' : 1 ,
277
+ 'SteadyStateValue' : - 0.5394 }
278
+ return T
279
+
280
+ @pytest .fixture
281
+ def mimo_tf_step (self , tf1_matlab_help ,
282
+ siso_tf_kpos ,
283
+ siso_tf_kneg ,
284
+ siso_tf_type1 ):
285
+ Ta = [[tf1_matlab_help , tf1_matlab_help , siso_tf_kpos ],
286
+ [siso_tf_kneg , siso_tf_type1 , siso_tf_type1 ]]
287
+ T = TSys (TransferFunction (
288
+ [[Ti .sys .num [0 ][0 ] for Ti in Tr ] for Tr in Ta ],
289
+ [[Ti .sys .den [0 ][0 ] for Ti in Tr ] for Tr in Ta ]))
290
+ T .step_info = [[Ti .step_info for Ti in Tr ] for Tr in Ta ]
291
+ return T
225
292
226
293
@pytest .fixture
227
294
def tsystem (self ,
@@ -233,7 +300,7 @@ def tsystem(self,
233
300
mimo_dss1 , mimo_dss2 , mimo_dtf1 ,
234
301
pole_cancellation , no_pole_cancellation , siso_tf_type1 ,
235
302
siso_tf_kpos , siso_tf_kneg , tf1_matlab_help ,
236
- tf2_matlab_help ):
303
+ ss2_matlab_help , mimo_tf_step ):
237
304
systems = {"siso_ss1" : siso_ss1 ,
238
305
"siso_ss2" : siso_ss2 ,
239
306
"siso_tf1" : siso_tf1 ,
@@ -255,7 +322,8 @@ def tsystem(self,
255
322
"siso_tf_kpos" : siso_tf_kpos ,
256
323
"siso_tf_kneg" : siso_tf_kneg ,
257
324
"tf1_matlab_help" : tf1_matlab_help ,
258
- "tf2_matlab_help" : tf2_matlab_help ,
325
+ "ss2_matlab_help" : ss2_matlab_help ,
326
+ "mimo_tf_step" : mimo_tf_step ,
259
327
}
260
328
return systems [request .param ]
261
329
@@ -312,73 +380,43 @@ def test_step_nostates(self, dt):
312
380
# tolerance for all parameters could be wrong for some systems
313
381
# discrete systems time parameters tolerance could be +/-dt
314
382
@pytest .mark .parametrize (
315
- "tsystem, info_true, tolerance" ,
316
- [("tf1_matlab_help" , {
317
- 'RiseTime' : 3.8456 ,
318
- 'SettlingTime' : 27.9762 ,
319
- 'SettlingMin' : 2.0689 ,
320
- 'SettlingMax' : 2.6873 ,
321
- 'Overshoot' : 7.4915 ,
322
- 'Undershoot' : 0 ,
323
- 'Peak' : 2.6873 ,
324
- 'PeakTime' : 8.0530 ,
325
- 'SteadyStateValue' : 2.5 }, 2e-2 ),
326
- ("tf2_matlab_help" , {
327
- 'RiseTime' : 0.4000 ,
328
- 'SettlingTime' : 2.8000 ,
329
- 'SettlingMin' : - 0.6724 ,
330
- 'SettlingMax' : - 0.5188 ,
331
- 'Overshoot' : 24.6476 ,
332
- 'Undershoot' : 11.1224 ,
333
- 'Peak' : 0.6724 ,
334
- 'PeakTime' : 1 ,
335
- 'SteadyStateValue' : - 0.5394 }, .2 ),
336
- ("siso_tf_kpos" , {
337
- 'RiseTime' : 1.242 ,
338
- 'SettlingTime' : 9.110 ,
339
- 'SettlingMin' : 0.950 ,
340
- 'SettlingMax' : 1.208 ,
341
- 'Overshoot' : 20.840 ,
342
- 'Undershoot' : 27.840 ,
343
- 'Peak' : 1.208 ,
344
- 'PeakTime' : 4.282 ,
345
- 'SteadyStateValue' : 1.0 }, 2e-2 ),
346
- ("siso_tf_kneg" , {
347
- 'RiseTime' : 1.242 ,
348
- 'SettlingTime' : 9.110 ,
349
- 'SettlingMin' : - 1.208 ,
350
- 'SettlingMax' : - 0.950 ,
351
- 'Overshoot' : 20.840 ,
352
- 'Undershoot' : 27.840 ,
353
- 'Peak' : 1.208 ,
354
- 'PeakTime' : 4.282 ,
355
- 'SteadyStateValue' : - 1.0 }, 2e-2 ),
356
- ("siso_tf_type1" , {'RiseTime' : np .NaN ,
357
- 'SettlingTime' : np .NaN ,
358
- 'SettlingMin' : np .NaN ,
359
- 'SettlingMax' : np .NaN ,
360
- 'Overshoot' : np .NaN ,
361
- 'Undershoot' : np .NaN ,
362
- 'Peak' : np .Inf ,
363
- 'PeakTime' : np .Inf ,
364
- 'SteadyStateValue' : np .NaN }, 2e-2 )],
383
+ "tsystem, tolerance" ,
384
+ [("tf1_matlab_help" , 2e-2 ),
385
+ ("ss2_matlab_help" , .2 ),
386
+ ("siso_tf_kpos" , 2e-2 ),
387
+ ("siso_tf_kneg" , 2e-2 ),
388
+ ("siso_tf_type1" , 2e-2 )],
365
389
indirect = ["tsystem" ])
366
- def test_step_info (self , tsystem , info_true , tolerance ):
390
+ def test_step_info (self , tsystem , tolerance ):
367
391
"""Test step info for SISO systems"""
368
- info = step_info (tsystem )
392
+ info = step_info (tsystem . sys )
369
393
370
- info_true_sorted = sorted (info_true .keys ())
394
+ info_true_sorted = sorted (tsystem . step_info .keys ())
371
395
info_sorted = sorted (info .keys ())
372
396
assert info_sorted == info_true_sorted
373
397
374
398
for k in info :
375
- np .testing .assert_allclose (info [k ], info_true [k ], rtol = tolerance ,
376
- err_msg = f"key { k } does not match" )
399
+ np .testing .assert_allclose (info [k ], tsystem .step_info [k ],
400
+ rtol = tolerance ,
401
+ err_msg = f"{ k } does not match" )
377
402
378
- def test_step_info_mimo (self , tsystem , info_true , tolearance ):
403
+ @pytest .mark .parametrize (
404
+ "tsystem, tolerance" ,
405
+ [('mimo_tf_step' , 2e-2 )],
406
+ indirect = ["tsystem" ])
407
+ def test_step_info_mimo (self , tsystem , tolerance ):
379
408
"""Test step info for MIMO systems"""
380
- # TODO: implement
381
- pass
409
+ info_dict = step_info (tsystem .sys )
410
+ from pprint import pprint
411
+ pprint (info_dict )
412
+ for i , row in enumerate (info_dict ):
413
+ for j , info in enumerate (row ):
414
+ for k in info :
415
+ np .testing .assert_allclose (
416
+ info [k ], tsystem .step_info [i ][j ][k ],
417
+ rtol = tolerance ,
418
+ err_msg = f"{ k } for input { j } to output { i } "
419
+ "does not match" )
382
420
383
421
def test_step_pole_cancellation (self , pole_cancellation ,
384
422
no_pole_cancellation ):
0 commit comments