\documentclass[aspectratio=169]{beamer}
\usepackage{mum-theme-beamer/mum-theme}
\usepackage{graphicx}
\input{code-block-settings.tex}
\input{tikz-settings.tex}

\title{Getting Started}
\subtitle{Introduction into ROS}
\date{24.10.2024}
\author[\textbf{L. Alff}, N. Bauschmann, D.A. Duecker]{Lennart Alff, Nathalie Bauschmann, Daniel Duecker}
\institute[TUHH]{Hamburg University of Technology}

\renewcommand<>{\fbox}[1]{\alt#2{\fcolorbox{black}{white}{#1}}{\fcolorbox{white}{white}{#1}}}

\begin{document}
\begin{frame}
	\titlepage
\end{frame}

\begin{frame}
	\frametitle{Motivation}

    \fbox<3->{\begin{minipage}[]{0.45\textwidth}
        \onslide<1->{\textbf{Scenario:}}
        \begin{itemize}
            \item<1-> Mobile robot with a camera
        \end{itemize}
        \onslide<2->{\textbf{Goal:}}
        \begin{itemize}
            \item<2-> Autonomous navigation
        \end{itemize}
\end{minipage}}
    \begin{minipage}[]{0.45\textwidth}
        \centering
        \includegraphics<1->[width=0.7\textwidth]{images/robot-bin.png}
\end{minipage}\\
\vspace{2mm}

\visible<4->{\begin{minipage}{\textwidth}
        \begin{tikzpicture}[node distance=8mm and 10mm]
            \node[fill=white] (camera) [rosnode]{Camera};
            \node[fill=white] (image) [rostopic, right=of camera, xshift=10mm]{Image};
            \node[fill=white] (localization) [rosnode, right=of image]{Localization};
            \node[fill=white] (position) [rostopic, right=of localization]{Position};
            \node[fill=white] (controller) [rosnode, below=of position]{Controller};
            \node[fill=white] (motor-commands) [rostopic, left=of controller]{Motor Commands};
            \node[fill=white] (motor-drivers) [rosnode, below=of camera]{Motor Drivers};
            \begin{scope}[on background layer]
                \draw[thick, rounded corners=2mm, fill=blue!10] ($(camera.north west)+(-1.5, 0.5)$) rectangle ($(motor-drivers.south east)+(1.0,-0.5)$);
                \draw[thick, rounded corners=2mm, fill=green!10] ($(image.north west)+(-0.5, 0.5)$) rectangle ($(controller.south east)+(0.5,-0.5)$);
            \end{scope}
            \path[-latex, thick] (camera) edge (image)
                (image) edge (localization)
                (localization) edge (position)
                (position) edge (controller)
                (controller) edge (motor-commands)
                (motor-commands) edge (motor-drivers)
                ;
            % align needed for line break
            \node (env)[above=of camera, yshift=-4.5mm, align=center]{Interaction with\\Environment};
            \node (env)[above=of localization, yshift=-4mm, align=center]{Internal Processing};

        \end{tikzpicture}
    \end{minipage}
}
\end{frame}

\begin{frame}
    \frametitle{How to do it?}
    
    \onslide<1->\textbf{\Large Naive Approach:}
    \begin{itemize}
        \item<2->Single monolithic program
            \begin{itemize}
                \item<3-> scales badly
                \item<3->hard to introspect/debug
                \item<3->what if multiple computers/devices used?
            \end{itemize}
    \end{itemize}
    \vspace{5mm}

    \onslide<4->\textbf{\Large Better Approach:}
    \begin{itemize}
        \item<5-> Use ROS $\Rightarrow$ write small programs
            \begin{itemize}
                \item<6->solve big problems by subdividision (divide \& conquer)
                \item<7->ROS brings a lot of utility
                    \begin{itemize}
                        \item<8-> plotting
                        \item<9-> logging
                        \item<10-> ...
                    \end{itemize}
            \end{itemize}
    \end{itemize}
\end{frame}

\begin{frame}
    \frametitle{From Theory to Practice}
    \centering
    \textbf{\Huge From zero to depth!}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Hello World}
    \begin{pythoncode}
print('hello world!')
    \end{pythoncode}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Hello World With Good Practice}
    \begin{pythoncode}
def main():
    print('hello world')


if __name__ == '__main__':
    main()
    \end{pythoncode}
    \pause
    \vspace{5mm}
    \begin{itemize}[<+->]
        \item not strictly required but a convention
        \item analog to the \texttt{int main()} in C/C++
    \end{itemize}
\end{frame}

\begin{frame}[fragile]
    \frametitle{First Contact with ROS}
    \begin{minipage}{0.48\textwidth}
        \begin{pythoncode}
import rclpy
from rclpy.node import Node


def main():
    rclpy.init()
    node = Node(node_name='my_node')
    rclpy.spin(node)


if __name__ == '__main__':
    main()
        \end{pythoncode}
    \end{minipage}
    \begin{minipage}{0.48\textwidth}
        \begin{itemize}[<+->]
            \item minimal ROS program 
            \item the generic \texttt{Node} does nothing on its own
            \begin{itemize}[<+->]
                \item not particularly useful
            \end{itemize}
        \end{itemize}
        \vspace{10mm}
        \pause
        \textbf{\Large $\Rightarrow$ we implement our own node!}
    \end{minipage}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Our First Custom Node}
    \begin{minipage}{0.48\textwidth}
        \begin{pythoncode}
import rclpy
from rclpy.node import Node

class DepthCalculatorNode(Node):

    def __init__(self):
        super().__init__(node_name='my_node')


def main():
    rclpy.init()
    node = DepthCalculatorNode()
    rlcpy.spin(node)


if __name__ == '__main__':
    main()
        \end{pythoncode}
    \end{minipage}
    \begin{minipage}{0.48\textwidth}
        \pause
        \begin{itemize}[<+->]
            \small
            \item our custom node does exactly the same as the generic \texttt{rclpy.Node} $\rightarrow$ \textbf{nothing}
            \item this is the boilerplate code we need for every node we write
            \item doing nothing $\neq$ not beeing able to do something
        \end{itemize}
        \vspace{5mm}
        \pause
        \textbf{Provides us with these functions:}
        \begin{itemize}[<+->]
            \small
            \item \texttt{create\_publisher}
            \item \texttt{create\_subscription}
            \item \texttt{create\_timer}
            \item \texttt{get\_logger}
            \item \texttt{get\_clock}
        \end{itemize}
    \end{minipage}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Receiving Pressure Measurements}
    \begin{pythoncode}
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import FluidPressure

class DepthCalculatorNode(Node):

    def __init__(self):
        super().__init__(node_name='my_node')

        self.pressure_sub = self.create_subscription(FluidPressure, 'pressure',
                                                     self.on_pressure, 1)

    def on_pressure(self, msg: FluidPressure):
        self.get_logger().info('Pressure measurement received')


def main():
    ...
    \end{pythoncode}
\end{frame}

\begin{frame}[fragile]
    \frametitle{Publishing Depth Values}
    
    \begin{pythoncode}
import rclpy
from hippo_msgs.msg import DepthStamped
from rclpy.node import Node
from sensor_msgs.msg import FluidPressure

class DepthCalculatorNode(Node):

    def __init__(self):
        super().__init__(node_name='my_node')

        self.pressure_sub = self.create_subscription(FluidPressure, 'pressure',
                                                     self.on_pressure, 1)
        self.depth_pub = self.create_publisher(DepthStamped, 'depth', 1)

    def on_pressure(self, msg: FluidPressure):
        self.get_logger().info('Pressure measurement received')
        pressure = msg.fluid_pressure
        depth = self.pressure_to_detph(pressure)

        depth_msg = DepthStamped() # do not forget the parentheses!
        depth_msg.header.stamp = msg.header.stamp
        depth_msg.depth = depth

        self.depth_pub.publish(depth_msg)

    def pressure_to_depth(self, pressure):
        depth = ???
        return depth



def main():
    ...
    \end{pythoncode}
\end{frame}

\end{document}
