Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • processes/LabProcesses.jl
  • martinheyden/LabProcesses.jl
2 results
Select Git revision
Loading items
Show changes
Commits on Source (8)
......@@ -14,10 +14,10 @@
script:
# Let's run the tests. Substitute `coverage = false` below, if you do not
# want coverage results.
- /opt/julia/bin/julia -e 'Pkg.rm("LabProcesses");Pkg.clone(pwd()); Pkg.test("LabProcesses",coverage = false)'
#- /opt/julia/bin/julia -e 'Pkg.update();Pkg.test("LabProcesses", coverage = true)'
- julia -e 'Pkg.rm("LabProcesses");Pkg.clone(pwd()); Pkg.test("LabProcesses",coverage = false)'
#- julia -e 'Pkg.update();Pkg.test("LabProcesses", coverage = true)'
# Comment out below if you do not want coverage results.
#- /opt/julia/bin/julia -e 'Pkg.add("Coverage"); cd(Pkg.dir("LabProcesses"));
#- julia -e 'Pkg.add("Coverage"); cd(Pkg.dir("LabProcesses"));
# using Coverage; cl, tl = get_summary(process_folder());
# println("(", cl/tl*100, "%) covered")'
......
## News
2018-12-07: Updated to julia v1.0, see commit eac09291 for last julia v0.6 version
[![pipeline status](https://gitlab.control.lth.se/processes/LabProcesses.jl/badges/master/pipeline.svg)](https://gitlab.control.lth.se/processes/LabProcesses.jl/commits/master)
[![coverage report](https://gitlab.control.lth.se/processes/LabProcesses.jl/badges/master/coverage.svg)](https://gitlab.control.lth.se/processes/LabProcesses.jl/commits/master)
......
julia 0.6
julia 0.7
ControlSystems
Parameters
DSP
......@@ -22,12 +22,16 @@ to get the latest release.
2. Install LabProcesses.jl using command `Pkg.clone("https://gitlab.control.lth.se/processes/LabProcesses.jl.git")` Lots of packages will now be installed, this will take some time. If this is your first time using Julia, you might have to run `julia> Pkg.init()` before you install any packages.
# How to implement a new process
1. Locate the file [interface.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface.jl). When the package is installed, you find its directory under `~/.julia/v0.6/LabProcesses/`, if not, run `julia> Pkg.dir("LabProcesses")` to locate the directory.
### 1.
Locate the file [interface.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface.jl). When the package is installed, you find its directory under `~/.julia/v0.6/LabProcesses/`, if not, run `julia> Pkg.dir("LabProcesses")` to locate the directory.
(Alternatively, you can copy all definitions from [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) instead. Maybe it's easier to work from an existing implementaiton.)
2. Copy all function definitions.
3. Create a new file under `/interface_implementations` where you paste all the
### 2.
Copy all function definitions.
### 3.
Create a new file under `/interface_implementations` where you paste all the
copied definitions and implement them. See [/interface_implementations/ballandbeam.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl) for an example.
4. Above all function implementations you must define the process type, e.g,
### 4.
Above all function implementations you must define the process type, e.g,
```julia
struct BallAndBeam <: PhysicalProcess
h::Float64
......@@ -42,7 +46,8 @@ have different biases, hence this must be stored. A simulated process would have
to keep track of its state etc. in order to implement the measure and control
methods. See [Types in julia documentation](https://docs.julialang.org/en/stable/manual/types/#Composite-Types-1)
for additional info regarding user defined types and (constructors)[https://docs.julialang.org/en/stable/manual/constructors/].
5. Documentation of all interface functions is available in the file [interface_documentation.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_documentation.jl)
### 5.
Documentation of all interface functions is available in the file [interface_documentation.jl](https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_documentation.jl)
# How to control a process
The interface `AbstractProcess` defines the functions `control(P, u)` and `measure(P)`.
......@@ -150,12 +155,8 @@ the user is unsure about a reasonable value.
## Non-linear process
Your first option is to linearize the process and proceed like above.
Other options include
1. Make `control` perform forward Euler, i.e., `x' = f(x,u)*h` for a general
system model ``x' = f(x,u); y = g(x,u)`` and sample time ``h``.
2. Integrate the system model using some fancy method like Runge-Kutta. See
[DifferentialEquations.jl](http://docs.juliadiffeq.org/stable/types/discrete_types.html)
for discrete-time solving of ODEs (don't be discouraged, this is almost as simple as
forward Euler above).
1. Make `control` perform forward Euler, i.e., `x[t+1] = x[t] + f(x[t],u[t])*h` for a general system model ``x' = f(x,u); y = g(x,u)`` and sample time ``h``.
2. Integrate the system model using some fancy method like Runge-Kutta. See [DifferentialEquations.jl](http://docs.juliadiffeq.org/stable/types/discrete_types.html) for discrete-time solving of ODEs (don't be discouraged, this is almost as simple as forward Euler above).
# Exported functions and types
```@autodocs
......
# __precompile__()
using Pkg
installed_packages = Pkg.installed()
if "LabConnections" keys(installed_packages)
Pkg.clone("https://gitlab.control.lth.se/cont-frb/LabConnections.jl")
......@@ -8,7 +9,7 @@ end
module LabProcesses
using ControlSystems, LabConnections.Computer, Parameters
using ControlSystems, LabConnections.Computer, Parameters, DSP, LinearAlgebra
include("utilities.jl")
......
......@@ -27,16 +27,16 @@ function run_control_2DOF(P::AbstractProcess,sysFB, sysFF=nothing; duration = 10
rf = sysFF == nothing ? r[:,i] : Gff(r[:,i])
e = rf-y[:,i]
ui = Gfb(e)
ui + bias(P)
ui .+ bias(P)
end
simulation = isa(P, SimulatedProcess)
initialize(P)
for (i,t) = enumerate(0:h:duration)
@periodically h simulation begin
y[:,i] = measure(P)
r[:,i] = reference(t)
u[:,i] = calc_control(i) # y,r must be updated before u
y[:,i] .= measure(P)
r[:,i] .= reference(t)
u[:,i] .= calc_control(i) # y,r must be updated before u
control(P, [clamp.(u[j,i], inputrange(P)[j]...) for j=1:nu])
end
end
......
......@@ -48,7 +48,7 @@ const beam_system, nice_beam_controller = define_beam_system()
struct BeamSimulator <: SimulatedProcess
h::Float64
s::SysFilter
BeamSimulator(;h::Real = 0.01) = new(Float64(h), SysFilter(beam_system, h))
BeamSimulator(;h::Real = 0.01, bias=0) = new(Float64(h), SysFilter(beam_system, h))
end
struct BallAndBeam <: PhysicalProcess
......@@ -96,15 +96,15 @@ bias(p::BallAndBeamSimulator) = 0
function control(p::AbstractBeamOrBallAndBeam, u::AbstractArray)
length(u) == 1 || error("Process $(typeof(p)) only accepts one control signal, tried to send u=$u.")
send(p.control,u[1])
control(p,u[1])
end
control(p::AbstractBeamOrBallAndBeam, u::Number) = send(p.control,u)
control(p::BeamSimulator, u) = p.s(u)
control(p::BallAndBeamSimulator, u) = error("Not yet implemented")
control(p::BeamSimulator, u::Number) = p.s(u)
control(p::BallAndBeamSimulator, u::Number) = error("Not yet implemented")
measure(p::Beam) = read(p.measure)
measure(p::BallAndBeam) = [read(p.measure1), read(p.measure2)]
measure(p::BeamSimulator) = vecdot(p.s.sys.C,p.s.state)
measure(p::BeamSimulator) = dot(p.s.sys.C,p.s.state)
measure(p::BallAndBeamSimulator) = error("Not yet implemented")
......
using ControlSystems
using ControlSystems, DSP
"""
beammodel, beamcontroller = define_beam_system(;doplot=false)
......
......@@ -9,7 +9,7 @@ macro periodically(h, body)
local start_time = time()
$(esc(body))
local execution_time = time()-start_time
sleep(max(0,$(esc(h))-execution_time))
Libc.systemsleep(max(0,$(esc(h))-execution_time))
end
end
......@@ -37,22 +37,22 @@ Create a SysFilter object that can be used to implement control loops and simula
with LTI systems, i.e., `U(z) = C(z)E(z)`. To filter a signal `u` through the filter,
call like `y = Csf(u)`. Calculates the filtered output `y` in `y = Cx+Du, x'=Ax+Bu`
"""
struct SysFilter
sys::StateSpace
struct SysFilter{T<:StateSpace}
sys::T
state::Vector{Float64}
function SysFilter(sys::StateSpace, state::AbstractVector)
@assert !ControlSystems.iscontinuous(sys) "Can not filter using continuous time model."
@assert length(state) == sys.nx "length(state) != sys.nx"
new(sys, state)
new{typeof(sys)}(sys, state)
end
function SysFilter(sys::StateSpace)
@assert !ControlSystems.iscontinuous(sys) "Can not filter using continuous time model. Supply sample time."
new(sys, init_sysfilter(sys))
new{typeof(sys)}(sys, init_sysfilter(sys))
end
function SysFilter(sys::StateSpace, h::Real)
@assert ControlSystems.iscontinuous(sys) "Sample time supplied byt system model is already in discrete time."
sysd = c2d(sys, h)[1]
new(sysd, init_sysfilter(sysd))
new{typeof(sysd)}(sysd, init_sysfilter(sysd))
end
end
(s::SysFilter)(input) = sysfilter!(s.state, s.sys, input)
......
using LabProcesses, ControlSystems
using Base.Test
using LabProcesses, ControlSystems, DSP
using Test
# Reference generators
r = PRBSGenerator(Int(4))
......