StaticSystems
Basic Operation of StaticSystems
A static system is a system whose output y
at time t
depends on the current time t
and the value of its input u
. The input-output relation of a static systems is represented by its output function outputfunc
which is of the form
where g
is the output function outputfunc
. Note that outputfunc
is expected to have two inputs, the value u
of the input
and the current time t
. The simulation in Jusdl
is a clocked-simulation, that is the data flowing through the input and output connections of components is actually sampled at time t
. Therefore, for example, the system modeled by
is actually sampled at clock ticks t
which is generated by a Clock
. Therefore the sampled system corresponds to
where $k$ is $k_i T_s$ where $k_i$ is an integer number, $T_s$ is the sampling interval. $T_s$ corresponds to sampling time dt
of Clock
. Thus, the system given above is coded like
function g(u, t)
# Define the relation `y = g(u, t)`
end
For further clarity, let us continue with a case study. Consider the following static system,
Note that the number of inputs is 2 and the number of outputs of is 3. To define such a system, the output function is written as
julia> g(u, t) = [t * u[1], sin(u[1]), cos(u[2])]
g (generic function with 1 method)
Note that the function g
is defined in such a way that the input value u
is sampled, which implies u
is not a vector of function but is a vector of real. Having defined output function outputfunc
, the system can be constructed.
julia> ss = StaticSystem(g, Inport(2), Outport(3))
StaticSystem(outputfunc:g, input:Inport(numpins:2, eltype:Inpin{Float64}), output:Outport(numpins:3, eltype:Outpin{Float64}))
Note the construction of input bus Inport(2)
and output bus Outport(3)
by recalling that the number of input is 2 and the number of output is 3.
A StaticSystem
evolves by being triggered through its trigger
pin. When triggered from its trigger
pin, a StaticSystem
reads the current time t
from its trigger
pin and computes its output y
according to its output function outputfunc
and writes its output y(t)
to its output
port (if output
port exists since output
port may be nothing depending on the relation defined by outputfunc
). When constructed, a StaticSystem
is not ready to be triggered since its trigger
pin is not writeable.
julia> ss.trigger.link
ERROR: UndefRefError: access to undefined reference
To make ss
drivable, we need to construct the ports and pins for input-output and signaling.
julia> oport, iport, trg, hnd = Outport(length(ss.input)), Inport(length(ss.output)), Outpin(), Inpin{Bool}()
(Outport(numpins:2, eltype:Outpin{Float64}), Inport(numpins:3, eltype:Inpin{Float64}), Outpin(eltype:Float64, isbound:false), Inpin(eltype:Bool, isbound:false))
julia> connect(oport, ss.input)
2-element Array{Link{Float64},1}:
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect(ss.output, iport)
3-element Array{Link{Float64},1}:
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect(trg, ss.trigger)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> connect(ss.handshake, hnd)
Link(state:open, eltype:Bool, isreadable:false, iswritable:false)
julia> task = launch(ss)
Task (runnable) @0x00007fa67019dd50
julia> taskout = @async while true
all(take!(iport) .=== NaN) && break
end
Task (runnable) @0x00007fa67019e710
Now, ss
is drivable from its trg
pin.
julia> ss.trigger.link
Link(state:open, eltype:Float64, isreadable:false, iswritable:true)
Now let us drive ss
.
julia> put!(trg, 1.)
As this point ss
wait for its to be written. Let us write some data to oport
.
julia> put!(oport, [10., 10.])
2-element Array{Float64,1}:
10.0
10.0
ss
read the value u
of its input
(since ss.input
is connected to oport
), read the current time t
, and computed its output value y
and wrote it its output
port. To signal that it succeeded to be take the step, it put a true
to its handshake which needs to be taken.
julia> hnd.link
Link(state:open, eltype:Bool, isreadable:true, iswritable:false)
julia> take!(hnd)
true
We can see the current data in the output
of ss
through iport
(since iport
is connected to ss.output
)
julia> iport[1].link.buffer
64-element Buffer{Cyclic,Float64,1}:
10.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
⋮
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
Let us further drive ss
.
julia> for t in 2. : 10.
put!(trg, t)
put!(oport, [10 * t, 20 * t])
take!(hnd)
end
The data written to the output
of ss
is also written to the internal buffers of output
.
julia> iport[1].link.buffer
64-element Buffer{Cyclic,Float64,1}:
1000.0
810.0
640.0
490.0
360.0
250.0
160.0
90.0
40.0
10.0
⋮
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
0.0
In addition to the generic StaticSystem
, Jusdl
provides some well-known static systems given in the next section.
Full API
Jusdl.Adder
— TypeAdder(signs=(+,+))
Construts an Adder
with input bus input
and signs signs
. signs
is a tuplle of +
and/or -
. The output function g
of Adder
is of the form,
where n
is the length of the input
, $s_k$ is the k
th element of signs
, $u_k$ is the k
th value of input
and $y$ is the value of output
. The default value of signs
is all +
.
Example
julia> adder = Adder((+, +, -));
julia> adder.outputfunc([3, 4, 5], 0.) == 3 + 4 - 5
true
Jusdl.Coupler
— TypeCoupler(conmat::AbstractMatrix, cplmat::AbstractMatrix)
Constructs a coupler from connection matrix conmat
of size $n \times n$ and coupling matrix cplmat
of size $d \times d$. The output function g
of Coupler
is of the form
where $\otimes$ is the Kronecker product, $E$ is conmat
and $P$ is cplmat
, $u$ is the value of input
and y
is the value of output
.
Jusdl.Gain
— TypeGain(input; gain=1.)
Constructs a Gain
whose output function g
is of the form
where $K$ is gain
, $u$ is the value of input
and y
is the value of output
.
Example
julia> K = [1. 2.; 3. 4.];
julia> sfunc = Gain(Inport(2), gain=K);
julia> sfunc.outputfunc([1., 2.], 0.) == K * [1., 2.]
true
Jusdl.Memory
— TypeMemory(delay=1.; initial::AbstractVector{T}=zeros(1), numtaps::Int=5, t0=0., dt=0.01, callbacks=nothing,
name=Symbol()) where T
Constructs a 'Memorywith input bus
input. A 'Memory
delays the values of input
by an amount of numdelay
. initial
determines the transient output from the Memory
, that is, until the internal buffer of Memory
is full, the values from initial
is returned.
Example
julia> Memory(0.1)
Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
julia> Memory(0.1; numtaps=5)
Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
julia> Memory(0.1; numtaps=5, dt=1.)
Memory(delay:0.1, numtaps:5, input:Inport(numpins:1, eltype:Inpin{Float64}), output:Outport(numpins:1, eltype:Outpin{Float64}))
Jusdl.Multiplier
— TypeMultiplier(ops=(*,*))
Construts an Multiplier
with input bus input
and signs signs
. signs
is a tuplle of *
and/or /
. The output function g
of Multiplier
is of the form,
where n
is the length of the input
, $s_k$ is the k
th element of signs
, $u_k$ is the k
th value of input
and $y$ is the value of the output
. The default value of signs
is all *
.
Example
julia> mlt = Multiplier((*, *, /));
julia> mlt.outputfunc([3, 4, 5], 0.) == 3 * 4 / 5
true
Jusdl.StaticSystem
— TypeStaticSystem(input, output, outputfunc)
Construts a StaticSystem
with input input
, output output
and output function outputfunc
. outputfunc
is a two-argument function of the form
where g
is outputfunc
, t
is the time, u
is the input at time t
and y
is the output at time t
. input
and output
may be nothing
depending on relation defined in outputfunc
.
Example
julia> g(u, t) = [u[1] + u[2], sin(u[2]), cos([1])] # The system has 2 inputs and 3 outputs.
g (generic function with 1 method)
julia> ss = StaticSystem(g, Inport(2), Outport(3))
StaticSystem(outputfunc:g, input:Inport(numpins:2, eltype:Inpin{Float64}), output:Outport(numpins:3, eltype:Outpin{Float64}))
julia> g2(u, t) = t # The system does not have any input.
g2 (generic function with 1 method)
julia> ss2 = StaticSystem(g2, nothing, Outport())
StaticSystem(outputfunc:g2, input:nothing, output:Outport(numpins:1, eltype:Outpin{Float64}))
Jusdl.Terminator
— TypeTerminator(input::Inport)
Constructs a Terminator
with input bus input
. The output function g
is eqaul to nothing
. A Terminator
is used just to sink the incomming data flowing from its input
.