@@ -17,7 +17,8 @@ an integrator with a constant input is often used together with the system under
17
17
sys = structural_simplify (iosys)
18
18
prob = ODEProblem (sys, Pair[int. x=> 1.0 ], (0.0 , 1.0 ))
19
19
sol = solve (prob, Rodas4 ())
20
- @test sol[int. output. u][end ] ≈ 2
20
+ @test all (sol[c. output. u] .≈ 1 )
21
+ @test sol[int. output. u][end ] .≈ 2 # expected solution
21
22
end
22
23
23
24
@testset " Derivative" begin
34
35
sys = structural_simplify (iosys)
35
36
prob = ODEProblem (sys, Pair[int. x=> 0.0 ], (0.0 , 10.0 ))
36
37
sol = solve (prob, Rodas4 ())
37
- @test isapprox (sol[source. output. u], sol[int. output. u], atol= 1e-1 )
38
+ @test all ( isapprox . (sol[source. output. u], sol[int. output. u], atol= 1e-1 ) )
38
39
end
39
40
40
41
@testset " PT1" begin
88
89
sys = structural_simplify (model)
89
90
prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
90
91
sol = solve (prob, Rodas4 ())
92
+ # initial condition
93
+ @test sol[ss. x[1 ]][1 ] ≈ 0 atol= 1e-3
94
+ @test sol[ss. x[2 ]][1 ] ≈ 0 atol= 1e-3
91
95
# equilibrium point is at [1, 0]
92
96
@test sol[ss. x[1 ]][end ] ≈ 1 atol= 1e-3
93
97
@test sol[ss. x[2 ]][end ] ≈ 0 atol= 1e-3
@@ -108,7 +112,8 @@ function Plant(;name, x_start=zeros(2))
108
112
end
109
113
110
114
@testset " PI" begin
111
- @named ref = Constant (; k= 2 )
115
+ re_val = 2
116
+ @named ref = Constant (; k= re_val)
112
117
@named pi_controller = PI (k= 1 , T= 1 )
113
118
@named plant = Plant ()
114
119
@named fb = Feedback ()
@@ -125,11 +130,13 @@ end
125
130
sys = structural_simplify (model)
126
131
prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
127
132
sol = solve (prob, Rodas4 ())
128
- @test sol[ref. output. u - plant. output. u][end ] ≈ 0 atol= 1e-3 # zero control error after 100s
133
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
134
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
129
135
end
130
136
131
137
@testset " PID" begin
132
- @named ref = Constant (; k= 2 )
138
+ re_val = 2
139
+ @named ref = Constant (; k= re_val)
133
140
@named pid_controller = PID (k= 3 , Ti= 0.5 , Td= 100 )
134
141
@named plant = Plant ()
135
142
@named fb = Feedback ()
146
153
sys = structural_simplify (model)
147
154
prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
148
155
sol = solve (prob, Rodas4 ())
149
- @test sol[ref. output. u - plant. output. u][end ] ≈ 0 atol= 1e-3 # zero control error after 100s
156
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
157
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
158
+
159
+ @testset " PI" begin
160
+ @named pid_controller = PID (k= 3 , Ti= 0.5 , Td= false )
161
+ @named model = ODESystem (
162
+ [
163
+ connect (ref. output, fb. input1),
164
+ connect (plant. output, fb. input2),
165
+ connect (fb. output, pid_controller. err_input),
166
+ connect (pid_controller. ctr_output, plant. input),
167
+ ],
168
+ t,
169
+ systems= [pid_controller, plant, ref, fb]
170
+ )
171
+ sys = structural_simplify (model)
172
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
173
+ sol = solve (prob, Rodas4 ())
174
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
175
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
176
+ end
177
+
178
+ @testset " PD" begin
179
+ @named pid_controller = PID (k= 10 , Ti= false , Td= 1 )
180
+ @named model = ODESystem (
181
+ [
182
+ connect (ref. output, fb. input1),
183
+ connect (plant. output, fb. input2),
184
+ connect (fb. output, pid_controller. err_input),
185
+ connect (pid_controller. ctr_output, plant. input),
186
+ ],
187
+ t,
188
+ systems= [pid_controller, plant, ref, fb]
189
+ )
190
+ sys = structural_simplify (model)
191
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
192
+ sol = solve (prob, Rodas4 ())
193
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
194
+ @test sol[plant. output. u][end ] > 1 # without I there will be a steady-state error
195
+ end
150
196
end
151
197
152
198
@test_skip begin
236
282
end
237
283
238
284
@testset " LimPI" begin
239
- @named ref = Constant (; k= 1 )
285
+ re_val = 1
286
+ @named ref = Constant (; k= re_val)
240
287
@named pi_controller_lim = LimPI (k= 3 , T= 0.5 , u_max= 1.5 , u_min= - 1.5 , Ta= 0.1 )
241
288
@named pi_controller = PI (k= 3 , T= 0.5 )
242
289
@named sat = Limiter (y_max= 1.5 , y_min= - 1.5 )
@@ -279,15 +326,19 @@ end
279
326
sol = solve (prob, Rodas4 ())
280
327
end
281
328
282
- @test sol[ref. output. u - plant. output. u][end ] ≈ 0 atol= 1e-3 # zero control error after 100s
283
- @test sol_lim[ref. output. u - plant. output. u][end ] ≈ 0 atol= 1e-3 # zero control error after 100s
329
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
330
+ @test all (isapprox .(sol_lim[ref. output. u], re_val, atol= 1e-3 )) # check reference
331
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
332
+ @test sol_lim[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
333
+ @test all (- 1.5 .<= sol_lim[pi_controller_lim. ctr_output. u] .<= 1.5 ) # test limit
284
334
285
335
# Plots.plot(sol; vars=[plant.output.u]) # without anti-windup measure
286
336
# Plots.plot!(sol_lim; vars=[plant.output.u]) # with anti-windup measure
287
337
end
288
338
289
339
@testset " LimPID" begin
290
- @named ref = Constant (; k= 1 )
340
+ re_val = 1
341
+ @named ref = Constant (; k= re_val)
291
342
@named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= 100 , u_max= 1.5 , u_min= - 1.5 , Ni= 0.1 / 0.5 )
292
343
@named plant = Plant ()
293
344
@named model = ODESystem (
@@ -304,5 +355,112 @@ end
304
355
sol = solve (prob, Rodas4 ())
305
356
306
357
# Plots.plot(sol, vars=[plant.output.u, plant.input.u])
307
- @test sol[ref. output. u - plant. output. u][end ] ≈ 0 atol= 1e-3 # zero control error after 100s
358
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
359
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
360
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
361
+
362
+ @testset " PI" begin
363
+ @named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= false , u_max= 1.5 , u_min= - 1.5 , Ni= 0.1 / 0.5 )
364
+ @named model = ODESystem (
365
+ [
366
+ connect (ref. output, pid_controller. reference),
367
+ connect (plant. output, pid_controller. measurement),
368
+ connect (pid_controller. ctr_output, plant. input),
369
+ ],
370
+ t,
371
+ systems= [pid_controller, plant, ref]
372
+ )
373
+ sys = structural_simplify (model)
374
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
375
+ sol = solve (prob, Rodas4 ())
376
+
377
+ # Plots.plot(sol, vars=[plant.output.u, plant.input.u])
378
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
379
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
380
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
381
+ end
382
+ @testset " PD" begin
383
+ @named pid_controller = LimPID (k= 10 , Ti= false , Td= 1 , u_max= 1.5 , u_min= - 1.5 )
384
+ @named model = ODESystem (
385
+ [
386
+ connect (ref. output, pid_controller. reference),
387
+ connect (plant. output, pid_controller. measurement),
388
+ connect (pid_controller. ctr_output, plant. input),
389
+ ],
390
+ t,
391
+ systems= [pid_controller, plant, ref]
392
+ )
393
+ sys = structural_simplify (model)
394
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
395
+ sol = solve (prob, Rodas4 ())
396
+
397
+ # Plots.plot(sol, vars=[plant.output.u, plant.input.u])
398
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
399
+ @test sol[plant. output. u][end ] > 0.5 # without I there will be a steady-state error
400
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
401
+ end
402
+ @testset " set-point weights" begin
403
+ @testset " wp" begin
404
+ @named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= 100 , u_max= 1.5 , u_min= - 1.5 , Ni= 0.1 / 0.5 , wp= 0 , wd= 1 )
405
+ @named model = ODESystem (
406
+ [
407
+ connect (ref. output, pid_controller. reference),
408
+ connect (plant. output, pid_controller. measurement),
409
+ connect (pid_controller. ctr_output, plant. input),
410
+ ],
411
+ t,
412
+ systems= [pid_controller, plant, ref]
413
+ )
414
+ sys = structural_simplify (model)
415
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
416
+ sol = solve (prob, Rodas4 ())
417
+
418
+ # Plots.plot(sol, vars=[plant.output.u, plant.input.u])
419
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
420
+ sol[pid_controller. addP. output. u] == - sol[pid_controller. measurement. u]
421
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
422
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
423
+ end
424
+ @testset " wd" begin
425
+ @named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= 100 , u_max= 1.5 , u_min= - 1.5 , Ni= 0.1 / 0.5 , wp= 1 , wd= 0 )
426
+ @named model = ODESystem (
427
+ [
428
+ connect (ref. output, pid_controller. reference),
429
+ connect (plant. output, pid_controller. measurement),
430
+ connect (pid_controller. ctr_output, plant. input),
431
+ ],
432
+ t,
433
+ systems= [pid_controller, plant, ref]
434
+ )
435
+ sys = structural_simplify (model)
436
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
437
+ sol = solve (prob, Rodas4 ())
438
+
439
+ # Plots.plot(sol, vars=[plant.output.u, plant.input.u])
440
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
441
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
442
+ sol[pid_controller. addD. output. u] == - sol[pid_controller. measurement. u]
443
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
444
+ end
445
+ end
446
+ @testset " PI without AWM" begin
447
+ @named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= false , u_max= 1.5 , u_min= - 1.5 , Ni= Inf )
448
+ @named model = ODESystem (
449
+ [
450
+ connect (ref. output, pid_controller. reference),
451
+ connect (plant. output, pid_controller. measurement),
452
+ connect (pid_controller. ctr_output, plant. input),
453
+ ],
454
+ t,
455
+ systems= [pid_controller, plant, ref]
456
+ )
457
+ sys = structural_simplify (model)
458
+ prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
459
+ sol = solve (prob, Rodas4 ())
460
+
461
+ # Plots.plot(sol, vars=[plant.output.u, plant.input.u])
462
+ @test all (isapprox .(sol[ref. output. u], re_val, atol= 1e-3 )) # check reference
463
+ @test sol[plant. output. u][end ] ≈ re_val atol= 1e-3 # zero control error after 100s
464
+ @test all (- 1.5 .<= sol[pid_controller. ctr_output. u] .<= 1.5 ) # test limit
465
+ end
308
466
end
0 commit comments