Skip to content

Commit 418188a

Browse files
committed
refactor: Blocks/continuous.jl
1 parent 07111c2 commit 418188a

File tree

2 files changed

+145
-109
lines changed

2 files changed

+145
-109
lines changed

src/Blocks/continuous.jl

Lines changed: 139 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Integrator(;name, k=1, x_start=0.0)
2+
Integrator(;name, k = 1, x = 0.0)
33
44
Outputs `y = ∫k*u dt`, corresponding to the transfer function `1/s`.
55
@@ -11,20 +11,23 @@ Outputs `y = ∫k*u dt`, corresponding to the transfer function `1/s`.
1111
# Parameters:
1212
1313
- `k`: Gain of integrator
14-
- `x_start`: Initial value of integrator
14+
- `x`: Initial value of integrator
1515
"""
16-
@component function Integrator(; name, k = 1, x_start = 0.0)
17-
@named siso = SISO()
18-
@unpack u, y = siso
19-
sts = @variables x(t)=x_start [description = "State of Integrator $name"]
20-
pars = @parameters k=k [description = "Gain of Integrator $name"]
21-
eqs = [D(x) ~ k * u
22-
y ~ x]
23-
extend(ODESystem(eqs, t, sts, pars; name = name), siso)
16+
@mtkmodel Integrator begin
17+
@extend u, y = siso = SISO()
18+
@variables begin
19+
x(t) = 0.0, [description = "State of Integrator"]
20+
end
21+
@parameters begin
22+
k = 1, [description = "Gain of Integrator"]
23+
end
24+
@equations begin
25+
D(x) ~ k * u
26+
y ~ x
27+
end
2428
end
25-
2629
"""
27-
Derivative(; name, k=1, T, x_start=0.0)
30+
Derivative(; name, k = 1, T, x = 0.0)
2831
2932
Outputs an approximate derivative of the input. The transfer function of this block is
3033
@@ -44,28 +47,36 @@ A smaller `T` leads to a more ideal approximation of the derivative.
4447
4548
- `k`: Gain
4649
- `T`: [s] Time constants (T>0 required; T=0 is ideal derivative block)
47-
- `x_start`: Initial value of state
50+
- `x`: Initial value of state
4851
4952
# Connectors:
5053
5154
- `input`
5255
- `output`
5356
"""
54-
@component function Derivative(; name, k = 1, T, x_start = 0.0)
55-
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
56-
@named siso = SISO()
57-
@unpack u, y = siso
58-
sts = @variables x(t)=x_start [description = "State of Derivative $name"]
59-
pars = @parameters T=T [description = "Time constant of Derivative $name"] k=k [
60-
description = "Gain of Derivative $name",
61-
]
62-
eqs = [D(x) ~ (u - x) / T
63-
y ~ (k / T) * (u - x)]
64-
extend(ODESystem(eqs, t, sts, pars; name = name), siso)
57+
@mtkmodel Derivative begin
58+
begin
59+
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
60+
end
61+
@extend u, y = siso = SISO()
62+
@variables begin
63+
x(t) = 0.0, [description = "State of Derivative $name"]
64+
end
65+
@parameters begin
66+
T=T, [description = "Time constant of Derivative $name"]
67+
k = 1, [description = "Gain of Derivative $name"]
68+
end
69+
begin
70+
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
71+
end
72+
@equations begin
73+
D(x) ~ (u - x) / T
74+
y ~ (k / T) * (u - x)
75+
end
6576
end
6677

6778
"""
68-
FirstOrder(; name, k=1, T, x_start=0.0, lowpass=true)
79+
FirstOrder(; name, k=1, T, x = 0.0, lowpass=true)
6980
7081
A first-order filter with a single real pole in `s = -T` and gain `k`. If `lowpass=true` (default), the transfer function
7182
is given by `Y(s)/U(s) = `
@@ -88,7 +99,7 @@ sT + 1 - k
8899
89100
- `k`: Gain
90101
- `T`: [s] Time constants (T>0 required)
91-
- `x_start`: Initial value of state
102+
- `x`: Initial value of state
92103
93104
# Connectors:
94105
@@ -97,21 +108,27 @@ sT + 1 - k
97108
98109
See also [`SecondOrder`](@ref)
99110
"""
100-
@component function FirstOrder(; name, k = 1, T, x_start = 0.0, lowpass = true)
101-
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
102-
@named siso = SISO()
103-
@unpack u, y = siso
104-
sts = @variables x(t)=x_start [description = "State of FirstOrder filter $name"]
105-
pars = @parameters T=T [description = "Time constant of FirstOrder filter $name"] k=k [
106-
description = "Gain of FirstOrder $name",
107-
]
108-
eqs = [D(x) ~ (k * u - x) / T
109-
lowpass ? y ~ x : y ~ k * u - x]
110-
extend(ODESystem(eqs, t, sts, pars; name = name), siso)
111+
@mtkmodel FirstOrder begin
112+
@extend u, y = siso = SISO()
113+
@variables begin
114+
x(t) = 0.0, [description = "State of FirstOrder filter $name"]
115+
end
116+
@parameters begin
117+
lowpass = true
118+
T = T, [description = "Time constant of FirstOrder filter $name"]
119+
k = 1, [description = "Gain of FirstOrder $name"]
120+
end
121+
begin
122+
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
123+
end
124+
@equations begin
125+
D(x) ~ (k * u - x) / T
126+
getdefault(lowpass) ? y ~ x : y ~ k * u - x
127+
end
111128
end
112129

113130
"""
114-
SecondOrder(; name, k=1, w, d, x_start=0.0, xd_start=0.0)
131+
SecondOrder(; name, k = 1, w, d, x = 0.0, xd = 0.0)
115132
116133
A second-order filter with gain `k`, a bandwidth of `w` rad/s and relative damping `d`. The transfer function
117134
is given by `Y(s)/U(s) = `
@@ -130,38 +147,42 @@ Critical damping corresponds to `d=1`, which yields the fastest step response wi
130147
- `k`: Gain
131148
- `w`: [`rad/s`] Angular frequency
132149
- `d`: Damping
133-
- `x_start`: Initial value of state (output)
134-
- `xd_start`: Initial value of derivative of state (output)
150+
- `x`: Initial value of state (output)
151+
- `xd`: Initial value of derivative of state (output)
135152
136153
# Connectors:
137154
138155
- `input`
139156
- `output`
140157
"""
141-
@component function SecondOrder(; name, k = 1, w, d, x_start = 0.0, xd_start = 0.0)
142-
@named siso = SISO()
143-
@unpack u, y = siso
144-
@variables x(t)=x_start [description = "State of SecondOrder filter $name"]
145-
@variables xd(t)=xd_start [description = "Derivative state of SecondOrder filter $name"]
146-
@parameters k=k [description = "Gain of SecondOrder $name"]
147-
@parameters w=w [description = "Bandwidth of SecondOrder $name"]
148-
@parameters d=d [description = "Relative damping of SecondOrder $name"]
149-
eqs = [D(x) ~ xd
158+
@mtkmodel SecondOrder begin
159+
@extend u, y = siso = SISO()
160+
@variables begin
161+
x(t) = 0.0, [description = "State of SecondOrder filter"]
162+
xd(t) = 0.0, [description = "Derivative state of SecondOrder filter"]
163+
end
164+
@parameters begin
165+
k = 1, [description = "Gain of SecondOrder"]
166+
w, [description = "Bandwidth of SecondOrder"]
167+
d, [description = "Relative damping of SecondOrder"]
168+
end
169+
@equations begin
170+
D(x) ~ xd
150171
D(xd) ~ w * (w * (k * u - x) - 2 * d * xd)
151-
y ~ x]
152-
extend(ODESystem(eqs, t; name = name), siso)
172+
y ~ x
173+
end
153174
end
154175

155176
"""
156-
PI(;name, k=1, T, x_start=0.0)
177+
PI(;name, gainPI.k = 1, T, int.x = 0.0)
157178
158179
Textbook version of a PI-controller without actuator saturation and anti-windup measure.
159180
160181
# Parameters:
161182
162183
- `k`: Gain
163184
- `T`: [s] Integrator time constant (T>0 required)
164-
- `x_start`: Initial value for the integrator
185+
- `x`: Initial value for the integrator
165186
166187
# Connectors:
167188
@@ -170,22 +191,27 @@ Textbook version of a PI-controller without actuator saturation and anti-windup
170191
171192
See also [`LimPI`](@ref)
172193
"""
173-
@component function PI(; name, k = 1, T, x_start = 0.0)
174-
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
175-
@named err_input = RealInput() # control error
176-
@named ctr_output = RealOutput() # control signal
177-
@named gainPI = Gain(k)
178-
@named addPI = Add()
179-
@named int = Integrator(k = 1 / T, x_start = x_start)
180-
sys = [err_input, ctr_output, gainPI, addPI, int]
181-
eqs = [
182-
connect(err_input, addPI.input1),
183-
connect(addPI.output, gainPI.input),
184-
connect(gainPI.output, ctr_output),
185-
connect(err_input, int.input),
186-
connect(int.output, addPI.input2),
187-
]
188-
ODESystem(eqs, t, [], []; name = name, systems = sys)
194+
@mtkmodel PI begin
195+
@parameters begin
196+
T
197+
end
198+
begin
199+
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
200+
end
201+
@components begin
202+
err_input = RealInput() # control error
203+
ctr_output = RealOutput() # control signal
204+
gainPI = Gain(; k = 1.0)
205+
addPI = Add()
206+
int = Integrator(k = 1 / T, x = 0.0)
207+
end
208+
@equations begin
209+
connect(err_input, addPI.input1)
210+
connect(addPI.output, gainPI.input)
211+
connect(gainPI.output, ctr_output)
212+
connect(err_input, int.input)
213+
connect(int.output, addPI.input2)
214+
end
189215
end
190216

191217
"""
@@ -224,12 +250,12 @@ See also [`LimPID`](@ref)
224250
@named gainPID = Gain(k)
225251
@named addPID = Add3()
226252
if with_I
227-
@named int = Integrator(k = 1 / Ti, x_start = xi_start)
253+
@named int = Integrator(k = 1 / Ti, x = xi_start)
228254
else
229255
@named Izero = Constant(k = 0)
230256
end
231257
if with_D
232-
@named der = Derivative(k = Td, T = 1 / Nd, x_start = xd_start)
258+
@named der = Derivative(k = Td, T = 1 / Nd, x = xd_start)
233259
else
234260
@named Dzero = Constant(k = 0)
235261
end
@@ -274,42 +300,51 @@ Text-book version of a PI-controller with actuator saturation and anti-windup me
274300
- `k`: Gain
275301
- `T`: [s] Integrator time constant (T>0 required)
276302
- `Ta`: [s] Tracking time constant (Ta>0 required)
277-
- `x_start`: Initial value for the integrator
303+
- `x`: Initial value for the integrator
278304
279305
# Connectors:
280306
281307
- `err_input`
282308
- `ctr_output`
283309
"""
284-
@component function LimPI(; name, k = 1, T, u_max, u_min = -u_max, Ta, x_start = 0.0)
285-
@symcheck Ta > 0 ||
286-
throw(ArgumentError("Time constant `Ta` has to be strictly positive"))
287-
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
288-
@symcheck u_max u_min || throw(ArgumentError("u_min must be smaller than u_max"))
289-
@named err_input = RealInput() # control error
290-
@named ctr_output = RealOutput() # control signal
291-
@named gainPI = Gain(k)
292-
@named addPI = Add()
293-
@named addTrack = Add()
294-
@named int = Integrator(k = 1 / T, x_start = x_start)
295-
@named limiter = Limiter(y_max = u_max, y_min = u_min)
296-
@named addSat = Add(k1 = 1, k2 = -1)
297-
@named gainTrack = Gain(1 / Ta)
298-
sys = [err_input, ctr_output, gainPI, addPI, int, addTrack, limiter, addSat, gainTrack]
299-
eqs = [
300-
connect(err_input, addPI.input1),
301-
connect(addPI.output, gainPI.input),
302-
connect(gainPI.output, limiter.input),
303-
connect(limiter.output, ctr_output),
304-
connect(limiter.input, addSat.input2),
305-
connect(limiter.output, addSat.input1),
306-
connect(addSat.output, gainTrack.input),
307-
connect(err_input, addTrack.input1),
308-
connect(gainTrack.output, addTrack.input2),
309-
connect(addTrack.output, int.input),
310-
connect(int.output, addPI.input2),
311-
]
312-
ODESystem(eqs, t, [], []; name = name, systems = sys)
310+
@mtkmodel LimPI begin
311+
@parameters begin
312+
T
313+
u_max
314+
u_min = -u_max
315+
Ta
316+
x = 0.0
317+
end
318+
begin
319+
@symcheck Ta > 0 ||
320+
throw(ArgumentError("Time constant `Ta` has to be strictly positive"))
321+
@symcheck T > 0 || throw(ArgumentError("Time constant `T` has to be strictly positive"))
322+
@symcheck u_max u_min || throw(ArgumentError("u_min must be smaller than u_max"))
323+
end
324+
@components begin
325+
err_input = RealInput() # control error
326+
ctr_output = RealOutput() # control signal
327+
gainPI = Gain(k = 1)
328+
addPI = Add()
329+
addTrack = Add()
330+
int = Integrator(k = 1 / T, x = x)
331+
limiter = Limiter(y_max = u_max, y_min = u_min)
332+
addSat = Add(k1 = 1, k2 = -1)
333+
gainTrack = Gain(k = 1 / Ta)
334+
end
335+
@equations begin
336+
connect(err_input, addPI.input1)
337+
connect(addPI.output, gainPI.input)
338+
connect(gainPI.output, limiter.input)
339+
connect(limiter.output, ctr_output)
340+
connect(limiter.input, addSat.input2)
341+
connect(limiter.output, addSat.input1)
342+
connect(addSat.output, gainTrack.input)
343+
connect(err_input, addTrack.input1)
344+
connect(gainTrack.output, addTrack.input2)
345+
connect(addTrack.output, int.input)
346+
connect(int.output, addPI.input2)
347+
end
313348
end
314349

315350
"""
@@ -376,7 +411,7 @@ where the transfer function for the derivative includes additional filtering, se
376411
@named measurement = RealInput()
377412
@named ctr_output = RealOutput() # control signal
378413
@named addP = Add(k1 = wp, k2 = -1)
379-
@named gainPID = Gain(k)
414+
@named gainPID = Gain(; k)
380415
@named addPID = Add3()
381416
@named limiter = Limiter(y_max = u_max, y_min = u_min)
382417
if with_I
@@ -387,12 +422,12 @@ where the transfer function for the derivative includes additional filtering, se
387422
else
388423
@named addI = Add(k1 = 1, k2 = -1)
389424
end
390-
@named int = Integrator(k = 1 / Ti, x_start = xi_start)
425+
@named int = Integrator(k = 1 / Ti, x = xi_start)
391426
else
392427
@named Izero = Constant(k = 0)
393428
end
394429
if with_D
395-
@named der = Derivative(k = Td, T = 1 / Nd, x_start = xd_start)
430+
@named der = Derivative(k = Td, T = 1 / Nd, x = xd_start)
396431
@named addD = Add(k1 = wd, k2 = -1)
397432
else
398433
@named Dzero = Constant(k = 0)

0 commit comments

Comments
 (0)