From 56d0afd3b6f39d49935ffed93c291c119d094ef2 Mon Sep 17 00:00:00 2001 From: Thies Lennart Alff Date: Thu, 2 Nov 2023 22:13:50 +0100 Subject: [PATCH] update --- code-block-settings.tex | 7 +- main.tex | 212 ++++++++++++++++++++++++++++++++++++---- mum-theme-beamer | 2 +- tikz-settings.tex | 1 + 4 files changed, 202 insertions(+), 20 deletions(-) diff --git a/code-block-settings.tex b/code-block-settings.tex index 93e4c2d..85959b7 100644 --- a/code-block-settings.tex +++ b/code-block-settings.tex @@ -10,7 +10,7 @@ nobeforeafter, minted style=friendly, minted language=python, - minted options={fontsize=\scriptsize,numbersep=3mm,texcl=true,linenos,#1}, + minted options={escapeinside=||,fontsize=\scriptsize,numbersep=3mm,texcl=true,linenos,#1}, left=5mm,enhanced, overlay={ \begin{tcbclipinterior} @@ -20,3 +20,8 @@ #2, } +\def\theFancyVerbLine{% + \rmfamily\tiny\arabic{FancyVerbLine}% + {\tikz[remember picture,overlay]\node(minted-\arabic{FancyVerbLine}){};}% +} + diff --git a/main.tex b/main.tex index 45652eb..360df5b 100644 --- a/main.tex +++ b/main.tex @@ -18,46 +18,222 @@ \begin{frame} \frametitle{How to Start?} + \pause + \textbf{\Large Starting from scratch\dots}\vskip0.5cm + \pause \textbf{\Large Identify the challenges:}\vskip0.25cm + \pause \begin{enumerate} - \item Communication/data flow -- the ROS perspective + \item Communication/data flow -- the ROS perspective \pause \item Implementing the control law -- the control perspective \end{enumerate} \end{frame} \begin{frame} \frametitle{ROS Graph} - \centering + \centering \begin{tikzpicture}[node distance=10mm and 20mm] - \node (baro) [rosnode] {Barometer}; - \node (setpoint_publisher)[rosnode, right=of baro] {Setpoint\\Publisher}; - \node (controller)[rosnode, right=of setpoint_publisher] {Controller}; - \node (depth_calculator)[rosnode, below=of setpoint_publisher] {Depth\\Calculator}; + \node (baro) [rosnode, alt=<2>{red}{}, alt=<3->{gray}{}] {Barometer}; + \node (depth_calculator) + [ + rosnode, + right=of baro, + alt=<4>{red}{}, + alt=<5->{gray}{}, + alt=<7->{mumgreen}{}, + ] {Depth\\Calculator}; + \node (controller)[rosnode, right=of depth_calculator, alt=<6>{red}{}, alt=<7->{mumgreen}{}] {Controller}; + \node (setpoint_publisher)[rosnode, below=of depth_calculator, alt=<5>{red}{}, alt=<6>{gray}{}, alt=<7->{mumgreen}{}] {Setpoint\\Publisher}; \draw[arrow] (baro) % edge node [sloped, anchor=center, above] {\footnotesize pressure} % node [sloped, anchor=center, below] {\tiny FluidPressure} % - (setpoint_publisher); + (depth_calculator); + + \draw[arrow] (depth_calculator) + edge node [sloped, anchor=center, above] {\footnotesize depth} + node [sloped, anchor=center, below] {\tiny DepthStamped} + (controller); \draw[arrow] (setpoint_publisher) - edge node [sloped, anchor=center, above] {\footnotesize depth} - node [sloped, anchor=center, below] {\tiny DepthStamped} - (controller); + edge node [sloped, anchor=center, above, xshift=-5mm] {\footnotesize depth\_setpoint} + node [sloped, anchor=center, below, xshift=-5mm] {\tiny Float64Stamped} + (controller); - \draw[arrow] (depth_calculator) - edge node [sloped, anchor=center, above, xshift=-5mm] {\footnotesize depth\_setpoint} - node [sloped, anchor=center, below, xshift=-5mm] {\tiny Float64Stamped} - (controller); + \node (empty_right) [right=of controller] {}; + \draw[arrow] (controller) + edge node [sloped, anchor=center, above] {\footnotesize thrust\_setpoint} + node [sloped, anchor=center, below] {\tiny ActuatorSetpoint} + (empty_right); \end{tikzpicture} + \begin{itemize} + \color{mumgreen} + \item these nodes are included in our template for assignment 1 \pause + \item communication between them is already set up! + \end{itemize} \end{frame} \begin{frame}[fragile] - \frametitle{Code-Block} + \frametitle{Where to Start?} % \begin{noindent} - \begin{pythoncode}{} -import time -print('hello') + \begin{pythoncode}[fontsize={\tiny}]{} +class DepthControlNode(Node): + + def __init__(self): + super().__init__(node_name='depth_controller') + + self.thrust_pub = self.create_publisher(ActuatorSetpoint, + 'thrust_setpoint', 1) + + self.setpoint_sub = self.create_subscription(Float64Stamped, + 'depth_setpoint', + self.on_setpoint, 1) + self.depth_sub = self.create_subscription(DepthStamped, 'depth', + self.on_depth, 1) + + |\vdots| + \end{pythoncode} + % \end{noindent} + \begin{itemize} + \item<2-> \color<4->{gray}{implement callbacks (\texttt{on\_setpoint}, \texttt{on\_depth})} \only<4->{\color{mumbluefont}{$\Rightarrow$ already given in our template!}} + \item<3-> \color<5->{red}{implement the control law} + \end{itemize} +\end{frame} + + +\begin{frame}[fragile] + \frametitle{Not Yet a PID Controller} + \textbf{\Large Again, starting point already provided in our template!} + \vskip0.5cm + % \begin{noindent} + \begin{pythoncode}[fontsize={\tiny}]{} +class DepthControlNode(Node): + |\vdots| + + def compute_control_output(self, current_depth: float) -> float: + thrust = current_depth + return thrust + \end{pythoncode} + % \end{noindent} +\end{frame} + +\begin{frame} + \frametitle{What was PID Control Again?} + \textbf{\Large Control law:}\vskip0.25cm + \begin{equation} + u = K_{\mathrm{p}} e + K_\mathrm{i} \int_0^{t} e\,\mathrm{d}\tau + K_{\mathrm{d}}\dot{e} + \end{equation} + \begin{tikzpicture}[node distance=10mm and 20mm] + \coordinate (start); + \coordinate[right=of start] (first_junction); + \node (integral)[right=of first_junction, rostopic]{$K_{\mathrm{i}}\int (\cdot)$}; + \node (proportional)[above=of integral, rostopic]{$K_{\mathrm{p}}$}; + \node (derivative)[below=of integral, rostopic]{$K_{\mathrm{d}}\frac{\mathrm{d}}{\mathrm{d}t}$}; + %\coordinate[right=of integral] (second_junction); + \node (second_junction)[right=of integral, draw, circle]{$\sum$}; + \coordinate[right=of second_junction] (end); + + \draw[] (start) edge node[above]{$e$} (first_junction); + \draw (first_junction) |- (proportional); + \draw (first_junction) |- (integral); + \draw (first_junction) |- (derivative); + \draw (proportional) -| (second_junction); + \draw (integral) -- (second_junction); + \draw (derivative) -| (second_junction); + \draw (second_junction) edge node[above]{$u$} (end); + \end{tikzpicture} + +\end{frame} + +\begin{frame}[fragile] + \frametitle{Proportional Control} + \textbf{\Large Control law:}\vskip0.25cm + \begin{equation} + u = \textcolor{red}{K_{\mathrm{p}} e} + K_\mathrm{i} \int_0^{t} e\,\mathrm{d}\tau + K_{\mathrm{d}}\dot{e} + \end{equation} + \textbf{\Large Code:}\vskip0.25cm + % \begin{noindent} + \begin{pythoncode}[fontsize={\tiny}]{} +class DepthControlNode(Node): + |\vdots| + + def compute_control_output(self, current_depth: float) -> float: + p_gain = 1.0 + error = current_depth - self.current_setpoint + thrust = p_gain * error + return thrust + \end{pythoncode} + % \end{noindent} +\end{frame} + +\begin{frame}[fragile] + \frametitle{PI-Control} + \begin{equation} + u = K_{\mathrm{p}} e + \textcolor{mumblue}{K_\mathrm{i} \int_0^{t} e\,\mathrm{d}\tau} + K_{\mathrm{d}}\dot{e} + \end{equation} + % \begin{noindent} + \begin{pythoncode}[fontsize={\tiny}]{} +class DepthControlNode(Node): + def __init__(self): + self.error_integral = 0.0 + self.last_time = self.get_clock().now().nanoseconds * 1e-9 + |\dots| + + def compute_control_output(self, current_depth: float) -> float: + p_gain = 1.0 + i_gain = 1.0 + error = current_depth - self.current_setpoint + + now = self.get_clock().now().nanoseconds * 1e-9 + dt = now - self.last_time + + self.error_integral = self.error_integral + dt * error + + thrust = p_gain * error + i_gain * self.error_integral + + self.last_time = now + return thrust + \end{pythoncode} + % \end{noindent} +\end{frame} + +\begin{frame}[fragile] + \frametitle{PID-Control} + \alt<1>{ + \begin{equation} + u = K_{\mathrm{p}} e + K_\mathrm{i} \int_0^{t} e\,\mathrm{d}\tau + \textcolor{mumgreen}{K_{\mathrm{d}}\dot{e}} + \end{equation} + }{} + \pause + % \begin{noindent} + \begin{pythoncode}[fontsize={\tiny}]{} +class DepthControlNode(Node): + def __init__(self): + self.error_integral = 0.0 + self.last_time = self.get_clock().now().nanoseconds * 1e-9 + self.last_error = 0.0 + |\dots| + + def compute_control_output(self, current_depth: float) -> float: + p_gain = 1.0 + i_gain = 1.0 + d_gain = 1.0 + + error = current_depth - self.current_setpoint + + now = self.get_clock().now().nanoseconds * 1e-9 + dt = now - self.last_time + + self.error_integral = self.error_integral + dt * error + + derror = (error - self._last_error) / dt + + thrust = p_gain * error + i_gain * self.error_integral + d_gain * derror + + self.last_time = now + self.last_error = error + return thrust \end{pythoncode} % \end{noindent} \end{frame} diff --git a/mum-theme-beamer b/mum-theme-beamer index 9dfb9af..21d6ecc 160000 --- a/mum-theme-beamer +++ b/mum-theme-beamer @@ -1 +1 @@ -Subproject commit 9dfb9afbda601b7bea70a24d2634d2783b71531b +Subproject commit 21d6ecc728481b664bebab10358de8e5364e9638 diff --git a/tikz-settings.tex b/tikz-settings.tex index 1422876..b4e9501 100644 --- a/tikz-settings.tex +++ b/tikz-settings.tex @@ -1,5 +1,6 @@ \usepackage{tikz} \usetikzlibrary{shapes.geometric, arrows, calc, chains, backgrounds} +\usetikzlibrary{overlay-beamer-styles} \tikzset{ rosbase/.style={minimum width=20mm, minimum height=7.5mm, text centered, draw=black, align=center},