@@ -113,46 +113,50 @@ z(k + 1) ~ z′(k)
113
113
]
114
114
@named sys = ODESystem (eqs)
115
115
ss = structural_simplify (sys);
116
- if VERSION >= v " 1.7"
117
- prob = ODEProblem (ss, [x => 0.0 , y => 0.0 ], (0.0 , 1.0 ),
118
- [kp => 1.0 ; z => 3.0 ; z (k + 1 ) => 2.0 ])
119
- sol = solve (prob, Tsit5 (), kwargshandle = KeywordArgSilent)
120
- # For all inputs in parameters, just initialize them to 0.0, and then set them
121
- # in the callback.
122
-
123
- # kp is the only real parameter
124
- function foo! (du, u, p, t)
125
- x = u[1 ]
126
- ud = p[2 ]
127
- du[1 ] = - x + ud
128
- end
129
- function affect! (integrator, saved_values)
130
- z_t, z = integrator. p[3 ], integrator. p[4 ]
131
- yd = integrator. u[1 ]
132
- kp = integrator. p[1 ]
133
- r = 1.0
134
- ud = kp * (r - yd) + z
135
- integrator. p[2 ] = ud
136
116
137
- push! (saved_values. t, integrator. t)
138
- push! (saved_values. saveval, [z_t, z])
117
+ Tf = 1.0
118
+ prob = ODEProblem (ss, [x => 0.0 , y => 0.0 ], (0.0 , Tf),
119
+ [kp => 1.0 ; z => 3.0 ; z (k + 1 ) => 2.0 ])
120
+ @test sort (prob. p) == [0 , 1.0 , 2.0 , 3.0 , 4.0 ] # yd, kp, z(k+1), z(k), ud
121
+ sol = solve (prob, Tsit5 (), kwargshandle = KeywordArgSilent)
122
+ # For all inputs in parameters, just initialize them to 0.0, and then set them
123
+ # in the callback.
124
+
125
+ # kp is the only real parameter
126
+ function foo! (du, u, p, t)
127
+ x = u[1 ]
128
+ ud = p[2 ]
129
+ du[1 ] = - x + ud
130
+ end
131
+ function affect! (integrator, saved_values)
132
+ z_t, z = integrator. p[3 ], integrator. p[4 ]
133
+ yd = integrator. u[1 ]
134
+ kp = integrator. p[1 ]
135
+ r = 1.0
136
+
137
+ push! (saved_values. t, integrator. t)
138
+ push! (saved_values. saveval, [z_t, z])
139
139
140
- # Update the discrete state
141
- z_t, z = z + yd, z_t
142
- integrator. p[3 ] = z_t
143
- integrator. p[4 ] = z
144
- nothing
145
- end
146
- saved_values = SavedValues (Float64, Vector{Float64})
147
- cb = PeriodicCallback (Base. Fix2 (affect!, saved_values), 0.1 )
148
- # kp ud z_t z
149
- prob = ODEProblem (foo!, [0.0 ], (0.0 , 1.0 ), [1.0 , 4.0 , 3.0 , 2.0 ], callback = cb)
150
- # ud initializes to kp * (r - yd) + z = 1 * (1 - 0) + 3 = 4
151
- sol2 = solve (prob, Tsit5 ())
152
- @test sol. u == sol2. u
153
- @test saved_values. t == sol. prob. kwargs[:disc_saved_values ][1 ]. t
154
- @test saved_values. saveval == sol. prob. kwargs[:disc_saved_values ][1 ]. saveval
140
+ # Update the discrete state
141
+ z_t, z = z + yd, z_t
142
+ # @show z_t, z
143
+ integrator. p[3 ] = z_t
144
+ integrator. p[4 ] = z
145
+
146
+ ud = kp * (r - yd) + z
147
+ integrator. p[2 ] = ud
148
+
149
+ nothing
155
150
end
151
+ saved_values = SavedValues (Float64, Vector{Float64})
152
+ cb = PeriodicCallback (Base. Fix2 (affect!, saved_values), 0.1 )
153
+ # kp ud z_t z
154
+ prob = ODEProblem (foo!, [0.0 ], (0.0 , Tf), [1.0 , 4.0 , 2.0 , 3.0 ], callback = cb)
155
+ # ud initializes to kp * (r - yd) + z = 1 * (1 - 0) + 3 = 4
156
+ sol2 = solve (prob, Tsit5 ())
157
+ @test sol. u == sol2. u
158
+ @test saved_values. t == sol. prob. kwargs[:disc_saved_values ][1 ]. t
159
+ @test saved_values. saveval == sol. prob. kwargs[:disc_saved_values ][1 ]. saveval
156
160
157
161
@info " Testing multi-rate hybrid system"
158
162
dt = 0.1
@@ -314,7 +318,7 @@ if VERSION >= v"1.7"
314
318
prob = ODEProblem (foo!, [0.0 ], (0.0 , 1.0 ), [1.0 , 1.0 , 1.0 ], callback = cb)
315
319
sol2 = solve (prob, Tsit5 ())
316
320
317
- @test sol. u ≈ sol2. u atol = 1e-6
321
+ @test sol. u≈ sol2. u atol= 1e-6
318
322
end
319
323
320
324
# #
@@ -341,10 +345,10 @@ k = ShiftIndex(d)
341
345
y (t)
342
346
end
343
347
@equations begin
344
- x (k + 1 ) ~ x (k) + ki * u
345
- output. u ~ y
346
- input. u ~ u
347
- y ~ x (k) + kp * u
348
+ x (k) ~ x (k - 1 ) + ki * u (k)
349
+ output. u (k) ~ y (k)
350
+ input. u (k) ~ u (k)
351
+ y (k) ~ x (k - 1 ) + kp * u (k)
348
352
end
349
353
end
350
354
@@ -414,35 +418,55 @@ ci, varmap = infer_clocks(expand_connections(model))
414
418
415
419
ssys = structural_simplify (model)
416
420
417
- timevec = 0 : (d. dt): 10
421
+ Tf = 0.2
422
+ timevec = 0 : (d. dt): Tf
418
423
419
424
import ControlSystemsBase as CS
420
425
import ControlSystemsBase: c2d, tf, feedback, lsim
421
- P = c2d (tf (0.3 , [1 , 1 ]), d. dt)
426
+ # z = tf('z', d.dt)
427
+ # P = c2d(tf(0.3, [1, 1]), d.dt)
428
+ P = c2d (CS. ss ([- 1 ], [0.3 ], [1 ], 0 ), d. dt)
422
429
C = CS. ss ([1 ], [2 ], [1 ], [2 ], d. dt)
423
430
424
431
# Test the output of the continuous partition
425
432
G = feedback (P * C)
426
433
res = lsim (G, (x, t) -> [0.5 ], timevec)
427
434
y = res. y[:]
428
435
429
- prob = ODEProblem (ssys,
430
- [model. plant. x => 0.0 ],
431
- (0.0 , 10.0 ),
432
- [model. controller. kp => 2.0 ; model. controller. ki => 2.0 ])
433
-
434
- @test prob. p[9 ] == 1 # constant output * kp issue https://github.com/SciML/ModelingToolkit.jl/issues/2356
435
- sol = solve (prob, Tsit5 (), kwargshandle = KeywordArgSilent)
436
- # plot([sol(timevec .+ 1e-12, idxs=model.plant.output.u) y])
437
-
438
- # #
439
-
440
- @test sol (timevec, idxs = model. plant. output. u)≈ y rtol= 1e-8 # The output of the continuous partition is delayed exactly one sample
441
-
442
- # Test the output of the discrete partition
443
- G = feedback (C, P)
444
- res = lsim (G, (x, t) -> [0.5 ], timevec)
445
- y = res. y[:]
446
-
447
- @test_broken sol (timevec .+ 1e-10 , idxs = model. controller. output. u)≈ y rtol= 1e-8 # Broken due to discrete observed
448
- # plot([sol(timevec .+ 1e-12, idxs=model.controller.output.u) y])
436
+ # plant = FirstOrder(k = 0.3, T = 1)
437
+ # controller = DiscretePI(kp = 2, ki = 2)
438
+ # ref = Constant(k = 0.5)
439
+
440
+ # ; model.controller.x(k-1) => 0.0
441
+ @test_skip begin
442
+ prob = ODEProblem (ssys,
443
+ [model. plant. x => 0.0 ; model. controller. kp => 2.0 ; model. controller. ki => 2.0 ],
444
+ (0.0 , Tf))
445
+
446
+ @test prob. p[9 ] == 1 # constant output * kp issue https://github.com/SciML/ModelingToolkit.jl/issues/2356
447
+ @test prob. p[10 ] == 0 # c2d
448
+ @test prob. p[11 ] == 0 # disc state
449
+ sol = solve (prob,
450
+ Tsit5 (),
451
+ kwargshandle = KeywordArgSilent,
452
+ abstol = 1e-8 ,
453
+ reltol = 1e-8 )
454
+ plot ([y sol (timevec, idxs = model. plant. output. u)], m = :o , lab = [" CS" " MTK" ])
455
+
456
+ # #
457
+
458
+ @test sol (timevec, idxs = model. plant. output. u)≈ y rtol= 1e-8 # The output of the continuous partition is delayed exactly one sample
459
+
460
+ # Test the output of the discrete partition
461
+ G = feedback (C, P)
462
+ res = lsim (G, (x, t) -> [0.5 ], timevec)
463
+ y = res. y[:]
464
+
465
+ @test_broken sol (timevec .+ 1e-10 , idxs = model. controller. output. u)≈ y rtol= 1e-8 # Broken due to discrete observed
466
+ # plot([y sol(timevec .+ 1e-12, idxs=model.controller.output.u)], lab=["CS" "MTK"])
467
+
468
+ # TODO : test the same system, but with the PI contorller implemented as
469
+ # x(k) ~ x(k-1) + ki * u
470
+ # y ~ x(k-1) + kp * u
471
+ # Instead. This should be equivalent to the above, but gve me an error when I tried
472
+ end
0 commit comments