@@ -17,7 +17,8 @@ an integrator with a constant input is often used together with the system under
1717 sys = structural_simplify (iosys)
1818 prob = ODEProblem (sys, Pair[int. x=> 1.0 ], (0.0 , 1.0 ))
1919 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
2122end
2223
2324@testset " Derivative" begin
3435 sys = structural_simplify (iosys)
3536 prob = ODEProblem (sys, Pair[int. x=> 0.0 ], (0.0 , 10.0 ))
3637 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 ) )
3839end
3940
4041@testset " PT1" begin
8889 sys = structural_simplify (model)
8990 prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
9091 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
9195 # equilibrium point is at [1, 0]
9296 @test sol[ss. x[1 ]][end ] ≈ 1 atol= 1e-3
9397 @test sol[ss. x[2 ]][end ] ≈ 0 atol= 1e-3
@@ -108,7 +112,8 @@ function Plant(;name, x_start=zeros(2))
108112end
109113
110114@testset " PI" begin
111- @named ref = Constant (; k= 2 )
115+ re_val = 2
116+ @named ref = Constant (; k= re_val)
112117 @named pi_controller = PI (k= 1 , T= 1 )
113118 @named plant = Plant ()
114119 @named fb = Feedback ()
@@ -125,11 +130,13 @@ end
125130 sys = structural_simplify (model)
126131 prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
127132 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
129135end
130136
131137@testset " PID" begin
132- @named ref = Constant (; k= 2 )
138+ re_val = 2
139+ @named ref = Constant (; k= re_val)
133140 @named pid_controller = PID (k= 3 , Ti= 0.5 , Td= 100 )
134141 @named plant = Plant ()
135142 @named fb = Feedback ()
146153 sys = structural_simplify (model)
147154 prob = ODEProblem (sys, Pair[], (0.0 , 100.0 ))
148155 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
150196end
151197
152198@test_skip begin
236282end
237283
238284@testset " LimPI" begin
239- @named ref = Constant (; k= 1 )
285+ re_val = 1
286+ @named ref = Constant (; k= re_val)
240287 @named pi_controller_lim = LimPI (k= 3 , T= 0.5 , u_max= 1.5 , u_min= - 1.5 , Ta= 0.1 )
241288 @named pi_controller = PI (k= 3 , T= 0.5 )
242289 @named sat = Limiter (y_max= 1.5 , y_min= - 1.5 )
@@ -279,15 +326,19 @@ end
279326 sol = solve (prob, Rodas4 ())
280327 end
281328
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
284334
285335 # Plots.plot(sol; vars=[plant.output.u]) # without anti-windup measure
286336 # Plots.plot!(sol_lim; vars=[plant.output.u]) # with anti-windup measure
287337end
288338
289339@testset " LimPID" begin
290- @named ref = Constant (; k= 1 )
340+ re_val = 1
341+ @named ref = Constant (; k= re_val)
291342 @named pid_controller = LimPID (k= 3 , Ti= 0.5 , Td= 100 , u_max= 1.5 , u_min= - 1.5 , Ni= 0.1 / 0.5 )
292343 @named plant = Plant ()
293344 @named model = ODESystem (
@@ -304,5 +355,112 @@ end
304355 sol = solve (prob, Rodas4 ())
305356
306357 # 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
308466end
0 commit comments