Closed non-Jedi closed 2 years ago
The saturation is a nonlinear function, whereas transfer functions are linear. You could simulate a saturation on the input using the function interface to lsim or the Simulator type, but for more advanced usage you would have to resort to Differentialequations.jl directly.
Is there an example somewhere of using the function interface to lsim to hold the output of one particular tf to some saturation limits? I have to admit I'm slightly out of my depth here, but if it's possible without having to actually write out the system of ODEs, that would be great.
My current usage looks something like:
using ControlSystems
Gp = tf(args1...) # Process tf
Gc = tf(args2...) # PID controller tf
Gv = tf(args3...) # actuator tf
Gd = tf(args4...) # disturbance tf
Gm = tf(args4...) # sensor tf
# tf between disturbance and controlled variable
YD = Gd * feedback(tf(1), Gm * Gc * Gv * Gp)
lsimplot(YD, (x,t) -> [t < 30.0 ? 33.0 : 0.0], 0:0.2:100)
So ideally I'd like to put the saturation block between Gc
and
Gv
. I don't see any examples that are related to this kind of thing.
No, connecting systems like that is not something that is supported so far. You may either try your luck with Differentialequations.jl directly, or possibly one of the modeling languages like Modia.jl or Modelingtoolkit.jl
This is definetely something where we could consider creating a simple API for creating the required differential equations (in the case of no direct terms). For example
dGp, fGp = diffeq(Gp)
dGc, fGc = diffeq(Gc)
# Functions so that dG returns derivative of internal state and
# u = fGc(x1), where x1 is internal state of controller
# y = fGp(x2) , where x2 is internal state of process
# Some definiton of feedback that could be returned by Controllsystems.jl
function dx(x,r)
x1 = # appropriate index in x vector
x2 = # appropriate index in x vector
u = fGc(x1)
y = fGp(x2)
e = r - y
[dGc(x1, e); dGp(x2, u)]
end
y(x) = fGp(x["indices for x2"])
The dx
function can now be used in DifferentialEquations.jl, and y(x)
would return output.
There are some details regarding efficiency and direct terms, but in general it would make it easier for the user to add nonlinearities and build their own differential equations.
The Simulator
type already does more or less this. A library of nonlinearities feels somewhat out of scope, because people would then want not only saturations, but all other common nonlinearities as well. It would perhaps fit well into an add-on package, but making use of the existing ecosystem for simulation is probably a more powerful apporach.
It is not clear how you would use the Simulator directly for the feedback case. I agree that we don't need a library of non-linearities, but what we could add is some simple manipulations (for example on the Simulator type) such as feedback with other Simulators.
ComponentArrays.jl was built in part to facilitate composing dynamical systems together, they have a tutorial using ControlSystems here https://jonniedie.github.io/ComponentArrays.jl/dev/examples/adaptive_control/#Helper-Functions-1 The interface in that tutorial is rather low-level, but I believe it could be made very approachable with a slightly higher-level interface built on top.
When simulating real-world systems, the saturation block in simulink is very important. Would it be possible to include something like that to compose with transfer functions?
https://www.mathworks.com/help/simulink/slref/saturation.html