From 91750c14e2558f52dc95add89a7354d29013b567 Mon Sep 17 00:00:00 2001 From: Fredrik Bagge Carlson <cont-frb@ulund.org> Date: Tue, 22 Aug 2017 20:18:47 +0200 Subject: [PATCH] Implement BeamSimulator --- src/interface.jl | 1 + src/interface_implementations/ballandbeam.jl | 23 ++++++-- .../define_beam_system.jl | 52 +++++++++++++++++++ src/utilities.jl | 8 +-- 4 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 src/interface_implementations/define_beam_system.jl diff --git a/src/interface.jl b/src/interface.jl index db99995..44a7b84 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -6,6 +6,7 @@ export num_outputs, isstable, isasstable, sampletime, + bias, control, measure, initialize, diff --git a/src/interface_implementations/ballandbeam.jl b/src/interface_implementations/ballandbeam.jl index d91092f..05543f5 100644 --- a/src/interface_implementations/ballandbeam.jl +++ b/src/interface_implementations/ballandbeam.jl @@ -17,11 +17,16 @@ struct Beam <: PhysicalProcess end Beam() = Beam(0.01, 0.0) +include("define_beam_system.jl") +const beam_system, nice_beam_controller = define_beam_system() +# nice_beam_controller gives ϕₘ=56°, Aₘ=4, Mₛ = 1.6. Don't forget to discretize it before use struct BeamSimulator <: SimulatedProcess h::Float64 - state::Vector{Float64} # angle,ω + state::Vector{Float64} # states defined by the file define_beam_system + sys::StateSpace + BeamSimulator() = new(0.01, init_sysfilter(beam_system), c2d(beam_system, 0.01)[1]) + BeamSimulator(h::Real) = new(Float64(h), init_sysfilter(beam_system), c2d(beam_system, h)[1]) end -BeamSimulator() = BeamSimulator(0.01, zeros(2)) struct BallAndBeam <: PhysicalProcess h::Float64 @@ -52,18 +57,26 @@ isstable(p::AbstractBallAndBeam) = false isasstable(p::AbstractBeamOrBallAndBeam) = false sampletime(p::AbstractBeamOrBallAndBeam) = p.h bias(p::AbstractBeamOrBallAndBeam) = p.bias +bias(p::BeamSimulator) = 0 bias(p::BallAndBeamSimulator) = 0 control(p::AbstractBeamOrBallAndBeam, u) = ccall((:comedi_write, comedipath),Int32, (Int32,Int32,Int32,Int32),0,1,1,num2io(u[1]+p.bias)) + +function control(p::BeamSimulator, u) + sysfilter!(p.state, p.sys, u) +end +control(p::BallAndBeamSimulator, u) = error("Not yet implemented") + measure(p::Beam) = io2num(ccall((:comedi_read,comedipath), Int32, (Int32,Int32,Int32), 0,0,0)) measure(p::BallAndBeam) = [io2num(ccall((:comedi_read,comedipath), Int32, (Int32,Int32,Int32), 0,0,i)) for i = 0:1] -control(p::BallAndBeamSimulator, u) = error("Not yet implemented") -measure(p::BallAndBeamSimulator) = [p.state[1], p.state[3]] +measure(p::BeamSimulator) = vecdot(p.sys.C,p.state) +measure(p::BallAndBeamSimulator) = error("Not yet implemented") + const comedipath = Pkg.dir("LabProcesses","c","comedi_bridge.so") const conversion = 65535/20 @@ -74,3 +87,5 @@ initialize(p::AbstractBeamOrBallAndBeam) = ccall((:comedi_start, comedipath),Int finalize(p::AbstractBeamOrBallAndBeam) = (control(p,0);ccall((:comedi_stop, comedipath),Int32,(Int32,), 0)) initialize(p::BallAndBeamSimulator) = nothing finalize(p::BallAndBeamSimulator) = nothing +initialize(p::BeamSimulator) = nothing +finalize(p::BeamSimulator) = nothing diff --git a/src/interface_implementations/define_beam_system.jl b/src/interface_implementations/define_beam_system.jl new file mode 100644 index 0000000..5aba53b --- /dev/null +++ b/src/interface_implementations/define_beam_system.jl @@ -0,0 +1,52 @@ +using ControlSystems + +""" + beammodel, beamcontroller = define_beam_system(;doplot=false) + +Return a continuous time model of the beam (`::StateSpace`) and a feedback controller that +gives ϕₘ = 56°, Aₘ = 4, Mₛ = 1.6. +Don't forget to discretize both before use. Call this method with +doplot = true to display a bunch of plots to convince yourself. + +The numbers in the code have been selected based on the fra performed and reported in +`beamdetails.pdf` +""" +function define_beam_system(;doplot=false) + K = 5 # gain of internal velocity control + I1 = 1 # intertia of motor mass + I2 = 1 # inertia of beam + C = 5 # beam flexibility + D = 0.1 # beam damping + T = 0.01 # motor torque time constant + E = 1 # motor viscous damping + + # transfer function from input signal to motor position + G1 = 2*tf([I2, D, C]*K,conv([T, 1],conv([I1, (D+E), C],[I2, D, C]) - [0; 0; conv([D, C],[D, C])]) + K*[0, 0, I2, D, C, 0]) + + G2 = 2*tf([D, C]*K,conv([T, 1],conv([I1, (D+E), C],[I2, D, C]) - [0; 0; conv([D, C],[D, C])]) + K*[0, 0, I2, D, C, 0]) + # pzmap(G1) + # bodeplot([G1,G2], logspace(-2,3,500)) + + # Above model is super inaccurate and I have no idea where it comes from, let's define + # a simple but more accurate model // Bagge + + G1 = zpk([-145],[0, -60, -100], 4.5*60*100/145) + ωz = 145 + ζz = 0.01 + ωp = 150 + ζp = 0.005 + G1 *= tf([1,2ζz*ωz, ωz^2]*ωp^2, [1,2ζp*ωp, ωp^2]*ωz^2) + + + sysFBc = ss(zpk([], [-40, -40], 2*40*40)) # Controller suggesten in assistant manual, works fine =) + # gives ϕₘ = 56°, Aₘ = 4, Mₛ = 1.6. Don't forget to discretize it before use. Call this method with + # doplot = true to display a bunch of plots to convince yourself + if doplot + ControlSystems.setPlotScale("log10") + bodeplot(tf(G1), logspace(0,log10(200),300)) + bodeplot([tf(G1), sysFBc*G1], logspace(0,log10(200),300)) + marginplot(sysFBc*tf(G1)) + gangoffourplot(tf(G1), tf(sysFBc)) + end + ss(G1), sysFBc +end diff --git a/src/utilities.jl b/src/utilities.jl index 14373fc..7cff5ca 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -18,7 +18,7 @@ end Use together with [`sysfilter!`](@ref) """ function init_sysfilter(sys::StateSpace) - zeros(sys.nx,1) + zeros(sys.nx) end """ @@ -28,7 +28,7 @@ Returns the filtered output `y` in `y = Cx+Du, x'=Ax+Bu` This function is used to implement control loops where a signal is filtered through a dynamical system, i.e., `U(z) = C(z)E(z)`. Initialize `state` using [`init_sysfilter`](@ref). """ -function sysfilter!(state, sys::StateSpace, input) - state .= sys.A*state + sys.B*input - output = sys.C*state + sys.D*input +function sysfilter!(state::AbstractVector, sys::StateSpace, input) + state .= vec(sys.A*state + sys.B*input) + output = vec(sys.C*state + sys.D*input) end -- GitLab