Commit 957f11ca authored by Fredrik Bagge Carlson's avatar Fredrik Bagge Carlson
Browse files

add docs

parent 9b59712d
Pipeline #731 failed with stage
\documentclass[12pt,a4paper]{article}
\usepackage[a4paper,text={16.5cm,25.2cm},centering]{geometry}
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
\usepackage{graphicx}
\usepackage{microtype}
\usepackage{hyperref}
\setlength{\parindent}{0pt}
\setlength{\parskip}{1.2ex}
\hypersetup
{ pdfauthor = { },
pdftitle={ },
colorlinks=TRUE,
linkcolor=black,
citecolor=blue,
urlcolor=blue
}
\usepackage[T1]{fontenc}
\usepackage{textcomp}
\usepackage{upquote}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
basicstyle=\ttfamily\footnotesize,
upquote=true,
breaklines=true,
keepspaces=true,
showspaces=false,
columns=fullflexible,
showtabs=false,
showstringspaces=false,
escapeinside={(*@}{@*)},
extendedchars=true,
}
\newcommand{\HLJLt}[1]{#1}
\newcommand{\HLJLw}[1]{#1}
\newcommand{\HLJLe}[1]{#1}
\newcommand{\HLJLeB}[1]{#1}
\newcommand{\HLJLo}[1]{#1}
\newcommand{\HLJLk}[1]{\textcolor[RGB]{148,91,176}{\textbf{#1}}}
\newcommand{\HLJLkc}[1]{\textcolor[RGB]{59,151,46}{\textit{#1}}}
\newcommand{\HLJLkd}[1]{\textcolor[RGB]{214,102,97}{\textit{#1}}}
\newcommand{\HLJLkn}[1]{\textcolor[RGB]{148,91,176}{\textbf{#1}}}
\newcommand{\HLJLkp}[1]{\textcolor[RGB]{148,91,176}{\textbf{#1}}}
\newcommand{\HLJLkr}[1]{\textcolor[RGB]{148,91,176}{\textbf{#1}}}
\newcommand{\HLJLkt}[1]{\textcolor[RGB]{148,91,176}{\textbf{#1}}}
\newcommand{\HLJLn}[1]{#1}
\newcommand{\HLJLna}[1]{#1}
\newcommand{\HLJLnb}[1]{#1}
\newcommand{\HLJLnbp}[1]{#1}
\newcommand{\HLJLnc}[1]{#1}
\newcommand{\HLJLncB}[1]{#1}
\newcommand{\HLJLnd}[1]{\textcolor[RGB]{214,102,97}{#1}}
\newcommand{\HLJLne}[1]{#1}
\newcommand{\HLJLneB}[1]{#1}
\newcommand{\HLJLnf}[1]{\textcolor[RGB]{66,102,213}{#1}}
\newcommand{\HLJLnfm}[1]{\textcolor[RGB]{66,102,213}{#1}}
\newcommand{\HLJLnp}[1]{#1}
\newcommand{\HLJLnl}[1]{#1}
\newcommand{\HLJLnn}[1]{#1}
\newcommand{\HLJLno}[1]{#1}
\newcommand{\HLJLnt}[1]{#1}
\newcommand{\HLJLnv}[1]{#1}
\newcommand{\HLJLnvc}[1]{#1}
\newcommand{\HLJLnvg}[1]{#1}
\newcommand{\HLJLnvi}[1]{#1}
\newcommand{\HLJLnvm}[1]{#1}
\newcommand{\HLJLl}[1]{#1}
\newcommand{\HLJLld}[1]{\textcolor[RGB]{148,91,176}{\textit{#1}}}
\newcommand{\HLJLs}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsa}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsb}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsc}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsd}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsdB}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsdC}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLse}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLsh}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsi}[1]{#1}
\newcommand{\HLJLso}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLsr}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLss}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLssB}[1]{\textcolor[RGB]{201,61,57}{#1}}
\newcommand{\HLJLnB}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLnbB}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLnfB}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLnh}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLni}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLnil}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLnoB}[1]{\textcolor[RGB]{59,151,46}{#1}}
\newcommand{\HLJLoB}[1]{\textcolor[RGB]{102,102,102}{\textbf{#1}}}
\newcommand{\HLJLow}[1]{\textcolor[RGB]{102,102,102}{\textbf{#1}}}
\newcommand{\HLJLp}[1]{#1}
\newcommand{\HLJLc}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLch}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLcm}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLcp}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLcpB}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLcs}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLcsB}[1]{\textcolor[RGB]{153,153,119}{\textit{#1}}}
\newcommand{\HLJLg}[1]{#1}
\newcommand{\HLJLgd}[1]{#1}
\newcommand{\HLJLge}[1]{#1}
\newcommand{\HLJLgeB}[1]{#1}
\newcommand{\HLJLgh}[1]{#1}
\newcommand{\HLJLgi}[1]{#1}
\newcommand{\HLJLgo}[1]{#1}
\newcommand{\HLJLgp}[1]{#1}
\newcommand{\HLJLgs}[1]{#1}
\newcommand{\HLJLgsB}[1]{#1}
\newcommand{\HLJLgt}[1]{#1}
\begin{document}
\section{LabProcesses}
\begin{verbatim}
Depth = 3
\end{verbatim}
This package contains an (programming- as well as connection-) interface to serve as a base for the implementation of lab-process software. The first example of an implementaiton of this interface is for the ball-and-beam process, which is used in Lab1 FRTN35: frequency response analysis of the beam. The lab is implemented in \href{https://gitlab.control.lth.se/processes/BallAndBeam.jl}{BallAndBeam.jl}, a package that makes use of \texttt{LabProcesses.jl} to handle the communication with the lab process and/or a simulated version thereof. This way, the code written for frequency response analysis of the beam can be run on another process implementing the same interface (or a simulated version) by changeing a single line of code :)
\subsection{Installation}
\begin{itemize}
\item[1. ] Start julia by typing \texttt{julia} in a terminal, make sure the printed info says it's
\end{itemize}
\texttt{v0.6+} running. If not, visit \href{https://julialang.org/downloads/}{julialang.org} to get the latest release.
\begin{itemize}
\item[2. ] Install LabProcesses.jl using command \texttt{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 \texttt{julia> Pkg.init()} before you install any packages.
\end{itemize}
\section{How to implement a new process}
\subsubsection{1.}
Locate the file \href{https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface.jl}{interface.jl}. When the package is installed, you find its directory under \texttt{{\sim}/.julia/v0.6/LabProcesses/}, if not, run \texttt{julia> Pkg.dir("LabProcesses")} to locate the directory. (Alternatively, you can copy all definitions from \href{https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl}{/interface\_implementations/ballandbeam.jl} instead. Maybe it's easier to work from an existing implementaiton.)
\subsubsection{2.}
Copy all function definitions.
\subsubsection{3.}
Create a new file under \texttt{/interface\_implementations} where you paste all the copied definitions and implement them. See \href{https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_implementations/ballandbeam.jl}{/interface\_implementations/ballandbeam.jl} for an example.
\subsubsection{4.}
Above all function implementations you must define the process type, e.g,
\begin{verbatim}
struct BallAndBeam <: PhysicalProcess
h::Float64
bias::Float64
end
BallAndBeam() = BallAndBeam(0.01, 0.0) # Constructor with default value of sample time
\end{verbatim}
Make sure you inherit from \texttt{PhysicalProcess} or \texttt{SimulatedProcess} as appropriate. This type must contains fields that hold information about everything that is relevant to a particular instance of the process. Different ballandbeam-process 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 \href{https://docs.julialang.org/en/stable/manual/types/#Composite-Types-1}{Types in julia documentation} for additional info regarding user defined types and (constructors)[https://docs.julialang.org/en/stable/manual/constructors/].
\subsubsection{5.}
Documentation of all interface functions is available in the file \href{https://gitlab.control.lth.se/processes/LabProcesses.jl/blob/master/src/interface_documentation.jl}{interface\_documentation.jl}
\section{How to control a process}
The interface \texttt{AbstractProcess} defines the functions \texttt{control(P, u)} and \texttt{measure(P)}. These functions can be used to implement your own control loops. A common loop with a feedback controller and a feedforward filter on the reference is implemented in the function \href{@ref}{\texttt{run\_control\_2DOF}}, where the user can supply $G_1$ and $G_4$ in the diagram below, with the process $P=G_2$. \begin{figure}
\centering
\includegraphics{feedback4.png}
\caption{block diagram}
\end{figure}
The macro \texttt{@periodically} might come in handy if you want to implement your own loop. Consider the following example, in which the loop body will be run periodically with a sample time of \texttt{h} seconds.
\begin{verbatim}
for (i,t) = enumerate(0:h:duration)
@periodically h begin
y[i] = measure(P)
r[i] = reference(t)
u[i] = calc_control(y,r)
control(P, u[i])
end
end
\end{verbatim}
Often one finds the need to implement a stateful controller, i.e., a function that has a memory or state. To this end, the type \href{@ref}{\texttt{SysFilter}} is provided. This type is used to implement control loops where a signal is filtered through a dynamical system, i.e., \texttt{U(z) = G1(z)E(z)}. Usage is demonstrated below, which is a simplified implementation of the block diagram above (transfer function- and signal names corresponds to the figure). First two \texttt{SysFilter} objects are created, these objects can now be used as functions of an input, and return the filtered output. The \texttt{SysFilter} type takes care of updating and remembering the state of the system when called.
\begin{verbatim}
G1f = SysFilter(G1)
G4f = SysFilter(G4)
function calc_control(y,r)
rf = G4f(r)
e = rf-y
u = G1f(e)
end
\end{verbatim}
\texttt{G1} and \texttt{G4} must here be represented by \href{http://juliacontrol.github.io/ControlSystems.jl/latest/lib/constructors/#ControlSystems.ss}{\texttt{StateSpace}} types from \href{https://github.com/JuliaControl/ControlSystems.jl}{\texttt{ControlSystems.jl}}, e.g., \texttt{G1 = ss(A,B,C,D)}. \texttt{TransferFunction} types can easily be converted to a \texttt{StateSpace} by \texttt{Gss = ss(Gtf)}. Continuous time systems can be discretized using \texttt{Gd = c2d(Gc, h)[1]}. (The sample time of a process is available through \texttt{h = sampletime(P)}.)
\section{How to implement a Simulated Process}
\subsection{Linear process}
This is very easy, just get a discrete time \texttt{StateSpace} model of your process (if you have a transfer function, \texttt{Gss = ss(Gtf)} will do the trick, if you have continuous time, \texttt{Gd = c2d(Gc,h)[1]} is your friend).
You now have to implement the methods \texttt{control} and \texttt{measure} for your simulated type. The implementation for \texttt{BeamSimulator} is shown below
\begin{verbatim}
control(p::BeamSimulator, u) = p.Gf(u)
measure(P) = vecdot(p.Gf.sys.C, p.Gf.state)
\end{verbatim}
The \texttt{control} method accepts a control signal (\texttt{u}) and propagates the system state (\texttt{p.Gf.state}) forward using the statespace model (\texttt{p.Gf.sys}) of the beam. The object \texttt{Gf} (of type \href{@ref}{\texttt{SysFilter}}) is familiar from the "Control" section above. What it does is essentially (simplified)
\begin{verbatim}
function Gf(input)
sys = Gf.sys
Gf.state .= sys.A*Gf.state + sys.B*input
output = sys.C*Gf.state + sys.D*input
end
\end{verbatim}
hence, it just performs one iteration of
\begin{align}
x' = Ax + Bu
\end{align}
\begin{align}
y = Cx + Du
\end{align}
The \texttt{measure} method performs the computation \texttt{y = Cx}, the reason for the call to \texttt{vecdot} is that \texttt{vecdot} produces a scalar output, whereas \texttt{C*x} produces a 1-element \texttt{Matrix}. A scalar output is preferred in this case since the \texttt{Beam} is SISO.
It should now be obvious which fields are required in the \texttt{BeamSimulator} type. It must know which sample time it has been discretized with, as well as its discrete-time system model. It must also remember the current state of the system. This is not needed in a physical process since it kind of remembers its own state. The system model and its state is conveniently covered by the type \href{@ref}{\texttt{SysFilter}}, which handles filtering of a signal through an LTI system. The full type specification for \texttt{BeamSimulator} is given below
\begin{verbatim}
struct BeamSimulator <: SimulatedProcess
h::Float64
Gf::SysFilter
BeamSimulator() = new(0.01, SysFilter(beam_system, 0.01))
BeamSimulator(h::Real) = new(Float64(h), SysFilter(beam_system, h))
end
\end{verbatim}
It contains three fields and two inner constructors. The constructors initializes the system filter by creating a \href{@ref}{\texttt{SysFilter}}. The variable \texttt{beam\_system} is already defined outside the type specification. One of the constructors provides a default value for the sample time, in case the user is unsure about a reasonable value.
\subsection{Non-linear process}
Your first option is to linearize the process and proceed like above. Other options include
\begin{itemize}
\item[1. ] Make \texttt{control} perform forward Euler, i.e., \texttt{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$.
\item[2. ] Integrate the system model using some fancy method like Runge-Kutta. See \href{http://docs.juliadiffeq.org/stable/types/discrete_types.html}{DifferentialEquations.jl} for discrete-time solving of ODEs (don't be discouraged, this is almost as simple as forward Euler above).
\end{itemize}
\section{Exported functions and types}
\begin{verbatim}
Modules = [LabProcesses]
Private = false
Pages = ["LabProcesses.jl", "controllers.jl", "reference_generators.jl", "utilities.jl"]
\end{verbatim}
\section{Process interface specification}
All processes must implement the following interface. See the existing implementations in the folder \texttt{interface\_implementations} for guidance.
\begin{verbatim}
Modules = [LabProcesses]
Private = false
Pages = ["interface_documentation.jl"]
\end{verbatim}
\section{Index}
\begin{verbatim}
\end{verbatim}
\end{document}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment