\chapter{Komponenten-/Softwareauswahl} Die Auswahl der verwendeten Softwarekomponenten ist ein wichtiger Schritt in der Entwicklung. Die Festlegung auf eine Komponente beeinflusst den späteren Entwicklungsprozess nachhaltig. Alle Komponenten sollen später in der entwickelten Softwareumgebung ihre jeweiligen Teilbereiche abdecken. Alle diese Teilbereiche können dann zu einer Simulation vebunden werden, die das gesamte Problemfeld abdeckt. Wie bereits in Abbildung \ref{concept_overview} dargestellt, ist für die Erfüllung der Aufgaben eine Dienst- und eine Simulationsumgebung erforderlich. Dieses Kapitel beschreibt die Auswahl der Umgebungen und der in diesen laufenden Prozesse. \section{Dienstumgebung} Die Dienstumgebung bestimmt maßgeblich, wie Software im Entwicklungsprozess geschrieben wird. Durch sie werden häufig benötigte Funktionen bereitgestellt, die Programme innerhalb der Umgebung nutzen können. Bei einer Dienstumgebung für Roboter gehört die Nachrichtenübergabe zwischen den einzelnen Programmen zu den grundlegenden Aspekten. Diese wird genutzt, um eine gemeinsame Basis für ein erweiterbares System zu schaffen. Außerdem sind Werkzeuge zur Einstellungsübergabe an Teilsysteme sinnvoll, um die Einstellungen an einer Stelle gesammelt anpassen zu können. \subsection{Auswahl} Es existieren mehrere Systeme, die als Dienstumgebung für Roboter in Frage kommen, wenn es lediglich um die Nachrichtenübergabe zwischen Programmen geht. Jede Dienstumgebung, die Nachrichten zwischen Prozessen austauschen kann, ist potentiell als ein Roboterframework einsetzbar. Wichtige Aspekte sind dabei die Geschwindigkeit der Anbindung und die Definition der Nachrichten, die über das System ausgetauscht werden. Nutzbare, bereits als Interprozesskommunikation integrierte Systeme sind zum Beispiel Pipes, die Daten zwischen Prozessen über Buffer austauschen. Auch die Nutzung von Message Queues oder Shared Memory ist für diesen Einsatzzweck möglich. Diese Systeme sind performant, jedoch schwerer zu verwalten. Ein Problem dieser Methoden ist die direkte Kommunikation mehrerer Komponenen. Diese Art der Kommunikation sieht keine Modifikation von Nachrichten zur Anpassung an andere Szenarien vor. Eine Alternative stellen Sockets dar, die Daten zwischen mehreren Programmen austauschen können. Dabei dient ein Programm als Server, dass Anfragen von anderen Programmen, auch Clients genannt, entgegen nimmt. Die Kommunikation zwischen Client und Server ist bidirektional möglich, was kompliziertere Protokolle ermöglicht. Alle diese Lösungen besitzen einen gemeinsamen Nachteil in deren Nachrichtendefinition. Dieser Nachteil besteht in der potentiellen Variabilität dieser Kommunikationsmechanismen. Bei einem ausreichend großen Projekt treten so unweigerlich Unterschiede in der Handhabung von Nachrichten auf, die es zu berücksichtigen gilt. Durch solche Unterschiede kann es zu Inkompatibilitäten zwischen Programmen kommen, was sich auf die universelle Nutzbarkeit der Programme negativ auswirkt. In diesem Bereich ist ROS\cite{doi:10.1126/scirobotics.abm6074} als Dienstumgebung für Roboter bekannt, da es sich um ein etabliertes und quelloffenes System handelt. Der oben genannte Nachteil einzelner Systeme wird in ROS durch mehrere standardisierte und erweiterbare Nachrichtendefinition gelöst, die von den Programmen in der Umgebung genutzt werden. Um diese Nachrichten senden und empfangen zu können, liefert ROS eine eigene Implementation des Protokolls für mehrere Programmiersprachen mit. Für zum Beispiel Python\cite{python}, C und C++\cite{cpp} existieren entsprechende Implementationen in den Paketen \code{rospy}, \code{rclc} und \code{rclcpp}. Die neuste Version ROS2 bietet dabei mehrere Verbesserungen im Vergleich zu früheren Version ROS1 \cite{changesRosII}. Ein neues Nachrichtenformat mit Quality of Service kann beispielsweise Nachrichten zwischenspeichern und über sowohl TCP, als auch UDP kommunizieren. Außerdem werden neben CMake\cite{cmake} auch andere Buildsysteme unterstützt, was die Verwendung von Python erlaubt. Generell existieren im Feld der Roboter-Dienstumgebungen keine freien Alternativen mit ähnlichem Funktionsumfang und gleicher Reichweite. Vor allem die unzähligen ROS-Bibliotheken, die von Nutzern des Systems über die Jahre erstellt wurden, machen das System so populär.\cite{rospackages} ROS kann für simulierte Umgebungen, aber auch für echte Roboter eingesetzt werden. Diese beiden Anwendungsfälle werden durch unterschiedliche Controller realisiert. Für simulierte Umgebungen leitet der Controller die Steuerdaten an die Simulationsumgebung weiter. Bei dem Einsatz echter Hardware werden die Zielpositionen durch den Controller an die Roboterhardware weitergeleitet. %-Alternative Ökosysteme mit gleichem Umfang wie ROS existieren nicht. %-ROS2 %-Andere (nur) Messagingsysteme %-LCM %-ZeroMQ \subsection{Beschreibung} ROS2\cite{doi:10.1126/scirobotics.abm6074}, später auch nur ROS genannt, beschreibt sich selbst als ``a meta operating system for robots''\cite{ros-git}. Hierbei ist ``operating system'' nicht in seiner herkömmlichen Bedeutung eines vollständigen Betriebssystems zu verstehen. Es handelt sich dabei um eine gemeinsame Grundlage für Programme und Daten, die durch ROS bereitgestellt wird. Einzelne Bestandteile in der Umgebung sind dabei in Pakete gegliedert, wobei jedes Paket beliebig viele Daten und Programme beinhalten kann. Programme, die mit anderen Programmen in der Umgebung über die ROS internen Schnittstellen kommunizieren, werden in ROS ``Nodes'' genannt. Zu den Aufgaben von ROS zählen folgende Teilbereiche: \begin{description} \item[Organisation]\hfill \\ Um die einzelnen Teile einer Roboterumgebung zu separieren, werden diese in ROS auf unterschiedliche Pakete aufgeteilt. Jedes Paket enthält dabei eine \code{package.xml}-Datei. In dieser befindet sich eine in XML verfasste Definition des Paketinhalts, die verschiedene Aspekte des Pakets beschreibt. Darunter fallen Informationen über das Paket selbst, wie dessen Name, Beschreibung und Version. Außerdem sind Name und Mailadresse des Autors, sowie die gewählte Lizenz des Codes vermerkt. Um das Paket später korrekt ausführen zu können, sind benötigte Pakete für den Kompiliervorgang und die Ausführung des Pakets eingetragen. \item[Buildumgebung]\hfill \\ ROS nutzt die eigene Buildumgebung \code{colcon} \cite{colcon}, um Pakete in den Workspaces reproduzierbar zu erstellen. Zu deren Konfiguration wird eine \code{CMakeLists.txt}-Datei erstellt, die den Buildprozess beschreibt. In dieser sind die Buildinstruktionen für den Kompiler enhalten, mit welchen die im Paket befindlichen Programme kompiliert werden können. Der Aufruf des \code{ament_cmake}-Makros in dieser ergänzt den Kompiliervorgang um weitere Parameter aus der \code{package.xml}-Datei. Nach diesen Vorbereitungsschritten kann CMake das Paket kompilieren. Hierbei werden alle in der \code{CMakeLists.txt}-Datei angegebenen Programmteile kompiliert. Es ist außerdem möglich, bestimmte Pfade des Pakets nach dem Buildvorgang zu exportieren. Diese sind dann später im erstellten Workspace für die Nutzung durch andere Programme verfügbar. \item[Workspaceverwaltung]\hfill \\ Gruppen von Paketen befinden sich in sogenannen ``Workspaces''. Diese vereinfachen das Auffinden der enthaltenen Pakete durch Skripte, die diese im System registrieren. Die Erstellung der Skripte erfolgt anhand der bereits beschriebenen \code{CMakeLists.txt}-Datei. Das Programm \code{colcon} analysiert diese und generiert die Skripte. Um das Paket im System zu registrieren, muss der Nutzer die generierten Skripte ausführen, was die benötigten Umgebungsvariablen setzt. Hierfür wird meist ein weiteres Skript verwendet, was alle im Workspace befindlichen Pakete nacheinander der Umgebung hinzufügt. Dieser Vorgang erlaubt zum Beispiel das Auffinden von Paketen anhand deren Namen im Dateisystem. Das erleichtert die Verwaltung durch die Unabhängigkeit von spezifischen Pfaden im entwickelten System. Außerdem wird die Laufzeitumgebung für alle Programme konfiguriert, was definierte Bibliotheken für diese verfügbar macht. \item[Abhängigkeitsverwaltung]\hfill \\ ROS kann durch die in den Paketen deklarierten Abhängigkeiten prüfen, ob diese in der aktuellen Umgebung ausführbar sind. Die generierten Warnungen bei fehlenden Paketen vermeiden Abstürze und undefiniertes Verhalten in der Ausführung von Nodes, die diese benötigen. \item[Datenübertragung]\hfill \\ Um Daten zwischen Nodes austauschen zu können, müssen die Nodes miteinander auf einem festgelegten Weg kommunizieren können. Ein solcher Aufbau erlaubt den Austausch von Daten in vorher nicht durch die Entwickler bedachten Anwendungsfällen. Die von ROS gebotene Schnittstelle zur Datenübertragung wird in Form mehrerer Bibliotheken für unterschiedliche Programmiersprachen bereitgestellt. Der Datenaustausch geschieht in sogenannten Topics, die Nachrichtenkanäle zwischen den Nodes darstellen. Eine Node kann entweder als Server ein Topic anbieten, was durch andere Nodes gelesen wird, oder als Client auf solche bereitgestellten Topics zugreifen. Durch die Kombination mehrerer Topics ist eine komplexere Interaktion abbildbar, die zum Beispiel Rückgabewerte zum aktuell ausgeführten Steuerbefehl liefert. \item[Parameterübergabe]\hfill \\ Um Nodes auf neue Anwendungsfälle anpassen zu können, wird ein Konfigurationsmechanismus benötigt. In ROS geschieht dies durch die Übergabe sogenannter Parameter, die durch die Node gelesen werden können. Diese eignen sich zur Übergabe von Informationen, wie zum Beispiel Daten über ein verwendetes Robotermodell. Um neue Konfigurationen zu unterstützen, kann das Umbenennen von Topics einer Node nötig werden, was auch mit einen Parameter erfolgen kann. \item[Startverwaltung]\hfill \\ In sogenannten ``launch''-Files können verschiedene Nodes und andere ``launch''-Files zu komplexen Startvorgängen zusammengefasst werden. Das Einstellen von bestimmten Parametern erlaubt die Anpassung der Funktionen an den gewünschten Anwendungsfall. \end{description} Eine solche Umgebung erlaubt die Zerlegung der geplanten Simulation in mehrere Komponenten. Die daraus erfolgte Abgrenzung erhöht die Übersichtlichkeit der einzelnen Bestandteile. Dies vereinfacht die spätere Wartung des Projekts. \section{Simulationsumgebung} \subsection{Auswahl} Als Simulationsumgebung eignen sich verschiedenen Programme, die sich hinsichtlich ihres Funktionsumfangs stark unterscheiden. Hierfür kommen dedizierte Werkzeuge zur Robotersimulation, aber auch beispielsweise universell einsetzbare Gameengines in Frage. Ein Vergleich dieser Werkzeuge ist hierbei sinnvoll, da der gebotene Funktionsumfang der Softwares sich stark unterscheidet. Auch andere Aspekte, wie Lizenzen oder schwer bewertbare Aspekte wie Nutzerfreundlichkeit, sind hierbei zu betrachten. Eine Auswahl der als Simulationsumgebung in Frage kommenden Programme werden hier vorgestellt. CoppeliaSim\cite{coppelia}, früher auch V-REP genannt, ist eine Robotersimulationsumgebung mit integriertem Editor und ROS-Unterstützung. Es unterstützt viele Sprachen (C/C++, Python, Java, Lua, Matlab oder Octave) zur Entwicklung von Erweiterungen des Simulators. Der Simulator selbst unterstützt Menschliche Aktoren, jedoch können diese nur Animationen abspielen oder zusammen mit Bewegungen abspielen. CoppeliaSim existiert in 3 Versionen, die sich im Funktionsumfang unterscheiden. Jedoch besitzt nur die professionelle Version Zugriff auf alle Funktionen und Verwendungsszenarien. Gazebo Ignition\cite{gazebo} ist wie CoppeliaSim eine Robotersimulationsumgebung, jedoch ohne integrierten Editor und direkte ROS-Unterstützung. Gazebo setzt wie CoppeliaSim auf Erweiterungen, die die gewünschten Funktionen einbinden können. Zum Beispiel existiert auch eine ROS-Brücke, welche die Anbindung an ROS ermöglicht. Auch hier unterstützt der Simulator nur Animationen für menschliche Aktoren. Das Projekt ist Open Source, unter der Apache Lizenz (Version 2.0), was die Verwendung in jeglichen Szenarien erleichtert. Unity\cite{unity} hingegen ist primär eine Grafikengine für Nutzung in Computerspielen. Es existieren mehrere Systeme zur Anbindung der Engine an ROS, vor allem das offizielle ``Robotics Simulation''-Paket und ZeroSim. Beide Systeme erlauben die Erweiterung der Gameengine um die Simulation von Robotern. Unity besitzt eine gute Dokumentation, die vor allem auf die Nutzung im Einsteigerbereich zurückzuführen ist. Auch die Optionen zur Menschensimulation sind gut, da diese häufig in Spielen verwendet werden. Ein großer Nachteil hingegen ist die Lizenz, die nur für Einzelpersonen kostenlos ist. Die Unreal Engine\cite{unreal} ist wie Unity eine Grafikengine aus dem Spielebereich. Auch hier ist die Menschensimulation aufgrund oben genannter Gründe gut möglich. Jedoch existiert für Unreal Engine keine offizielle Lösung zur Anbindung an ROS2. Die Programmierung der Engine erfolgt in C++, was die Erstellung eines Plugins zur ROS-Anbindung der Unreal Engine ermöglichte, die von Nutzern gewartet wird. Die Lizenz der Unreal Engine erlaubt die kostenfreie Nutzung bis zu einem gewissen Umsatz mit der erstellten Software. Eine weitere Möglichkeit zur Simulation stellt die Grafikengine Godot\cite{godot} dar. Im Vergleich zu Unity und Unreal Engine ist Godot quelloffene Software unter der MIT-Lizenz. Auch hier stellt die Simulation von menschlichen Aktoren eine Standartaufgabe dar, jedoch befinden sich Teile des dafür verwendeten Systems derzeit in Überarbeitung. Auch für diese Engine existiert eine ROS2-Anbindung, jedoch ist diese nicht offiziell. Alle vorgestellten Softwares besitzten ein integriertes Physiksystem, dass die Simulation von starren Körpern und Gelenken erlaubt. Diese Funktionen erlauben den Aufbau eines Roboterarms, der durch eine ROS-Brücke gesteuert wird. Um den Entwicklungsvorgang zu beschleunigen, ist die Auswahl einer Umgebung mit bereits existierender ROS-Unterstützung sinnvoll. Durch diese Einschränkung scheiden sowohl Unreal Engine aber auch Godot aus. Diese bieten zwar diese Funktionalität, jedoch wird diese nur durch Nutzer gewartet und ist demzufolge nicht offiziell unterstützt. Für einen späteren Einsatz ist eine offene Lizenz von Vorteil, da diese einen Einsatz in nahezu allen Umständen erlaubt. Die Wahl der Simulationsumgebung fiel deshalb auf Gazebo Ignition, dass gleichzeitig bereits im ROS-Ökosystem etabliert ist. Dabei erlauben die offizielle ROS-Anbindung und offene Lizenz eine zuverlässige Verwendung in unterschiedlichsten Szenarien. \subsection{Welt- und Modellbeschreibung} Um die Simulationsumgebung zu beschreiben, nutzt Gazebo das .sdf-Dateiformat\cite{sdf-format}. Dieses Format basiert auf XML und wird zur Definition gesamter Welten, aber auch einzelner Objekte innerhalb dieser Welten benutzt. Um verschiedene Versionen des Formats zu unterstützen, enthält das einzige sdf-Element die gewünschte Versionsnummer. Eine solche Datei kann, wie bereits oben beschrieben, unterschiedliche Daten enthalten. Im Falle eines Objekts ist dies eine einzige Instanz von entweder einem Modell, Actor oder Licht. Andernfalls können in der Datei eine oder mehrere Welten definiert werden. Eine Welt definiert in Gazebo den kompletten Aubau des Simulators. Zuerst enthält ein Welt-Element die Daten über die physikalischen Konstanten der Simulationsumgebung. Außerdem werden alle benötigten Teile der Nutzeroberfläche deklariert, die im ausgeführten Simulator verfügbar sein sollen. Letzendlich ist auch die Definition mehrerer Modelle, Aktoren und Lichter in der Welt möglich. Diese können auch aus anderen URIs stammen, die in der Welt deklariert wurden. Dies erlaubt das Laden von zum Beispiel vorher definierten Objekten oder Objekten aus der offiziellen Bibliothek\cite{gazebo-app}. Ein Modell enthält einen Roboter oder ein anderes physikalisches Objekt in der Simulation. Die Deklaration eines weiteren Untermodells ist möglich, um komplexere Strukturen abbilden zu können. Über ein include-Element können auch andere .sdf-Dateien, die nur ein einzelnes Modell enthalten, zu einem Modell hinzugefügt werden. Jedes Modell wird über eine Translation und Rotation im Simulationsraum verankert. Dies geschieht immer relativ zum Referenzsystem des überliegenden Modells. Außerdem können im Modell Einstellungen für dessen Physiksimulation vorgenommen werden. Ein Modell enhält meist mindestens ein Link-Element, dass zur Darstellung von dessen Geometrie verwendet wird. Mehrere Link-Elemente können dabei mit der Welt oder anderen Link-Elementen über Joint-Elemente verbunden werden. Diese Joint-Elemente können jedoch nicht von außerhalb gesteuert werden, was dieses Dateiformat ungeeignet für Roboterdefinitionen macht. Lichter besitzen einen Lichttyp, der die Ausbreitung des Lichtes im Raum bestimmt. Die erste Art ist direktionales Licht, dass parallel zur gewünschten Achse auftrifft. Solche Lichter werden vor allem zur grundlegenden Raumausleuchtung genutzt. Außerdem existieren noch Punktlichtquellen, die von einer Position im Raum ausgehen. Neben den Punklichtquellen existieren auch noch Spots, die außerdem noch nur einen gewissen Winkel ausleuchten. Die Actor-Komponente wird für animierte Modelle in der Simulation eingesetzt. Sie besteht aus einem Namen für das Modell, einer Skin, welche das Aussehen des Modells definiert und mehreren Animationen. Diese können durch in einem Skript definierte Trajectories ausgeführt werden, was eine einfache Simulation eines Menschen erlaubt. Eine solche Befehlsfolge kann jedoch nicht von außerhalb der Simulation zur Laufzeit angepasst werden, was weitere Entwicklungsarbeit erforderlich macht. \subsection{Robotersimulation} Für die Robotersimulation wird ein Modell des Roboters benötigt, in dem dieser für die Simulationsumgebung beschrieben wird. Gazebo und ROS nutzen hierfür .urdf-Dateien\cite{urdf-format}, die auf XML basieren. In diesen werden die einzelnen Glieder des Roboterarms und die verbindenden Gelenke beschrieben. Jedes Glied des Modells besitzt eine Masse, einen Masseschwerpunkt und eine Trägheitsmatrix für die Physiksimulation in Gazebo. Außerdem werden Modelle für die visuelle Repräsentation des Roboters in Gazebo und die Kollisionserkennung in der Physiksimulation hinterlegt. Für beide existieren einfache Modelle wie Zylinder, Boxen und Kugeln. Da diese Formen nicht jeden Anwendungsfall abdecken und in der visuellen Repräsentation nicht ausreichen, können auch eigene Modelle hinterlegt werden. Hierbei werden die Modelle für die Physiksimulation und das Aussehen des Roboters unterschieden. Gelenke werden separat von den Gliedern definiert und verbinden jeweils zwei Glieder miteinander. Durch das Aneinanderreihen von mehreren Gliedern und Gelenken ist die Beschreibung eines beliebigen Roboteraufbaus möglich. Jedes Gelenk besitzt eine Position und Rotation im Raum. Diese werden für die Berechnung der Effekte genutzt, die vom spezifischen Gelenktyp abhängen. Aspekte wie Reibung und Dämpfung können auch hier für die Nutzung in der Physiksimulation beschrieben werden. Folgende Typen von Gelenken können in urdf-Dateien genutzt werden: \begin{description} \item[freie Gelenke] ermöglichen vollständige Bewegung in allen 6 Freiheitsgraden (Rotation und Translation). Sie stellen den normalen Zustand der Glieder zueinander dar. \item[planare Gelenke] erlauben Bewegungen senkrecht zur Achse des Gelenks. Sie werden zum Beispiel für Bodenkollisionen eingesetzt. \item[feste Gelenke] sperren alle 6 Freiheitsgrade und werden häufig zur Fixierung von Objekten in einer Szene genutzt. \item[kontinuierliche Gelenke] erlauben die beliebige Rotation um die Achse des Gelenks. Sie sind nur selten in rotierenden Gelenken mit Schleifkontakten oder anderen frei rotierbaren Übertragungsmechanismen zu finden. \item[drehbare Gelenke] verhalten sich wie kontinuierliche Gelenke, haben jedoch minimale und maximale Auslenkungen. Sie sind die häufigste Art von Gelenken in Roboterarmen. \item[prismatische Gelenke] ermöglichen die lineare Bewegung entlang der Achse des Gelenks. Sie werden zur Umsetzung von Linearaktuatore in der Simulation verwendet. \end{description} \subsection{Menschensimulation} Gazebo besitzt bereits ein simples Animationssystem für bewegliche Aktoren, dass auch für Menschen nutzbar ist. Für diesen existiert bereits ein Modell mit mehreren Animationen, die allein abgespielt, oder an Bewegungen gekoppelt werden können. Dadurch ist eine Laufanimation realisierbar, die synchronisiert zu einer Bewegung abgespielt wird. Dies setzt jedoch voraus, dass der gesamte Bewegungsablauf zum Simulationsstart bekannt ist. Der Grund dafür ist auf die Definition der Pfade zurück zu führen, die Aktionen wie Bewegungen und Animationen auslösen können. Diese können nur als dem Actor untergeordnetes Element in der .sdf-Datei definiert werden, was Veränderungen zur Laufzeit ausschließt. Durch diesen Umstand ist der somit realisierbare Simulationsumfang nicht ausreichend, um die gewünschten Szenarien abzubilden. Um diese Einschränkung zu beheben, ist die Entwicklung eines eigenen Systems zum Bewegen und Animieren des Menschen unausweichlich. Dieses System muss, wie im Konzept beschrieben, Steuerbefehle von außen empfangen, umsetzen und Feedback liefern können. Dafür soll ein ROS Action-Server verwendet werden, der die Befehle entgegennimmt, unter konstantem Feedback ausführt und nach Erfolgreicher Ausführung den Empfang des nächsten Befehlts zulässt. Ein solches System soll als Gazebo-Plugin einbindbar sein, um Modifikationen an der Simulationsumgebung selbst auszuschließen, die konstant weiter entwickelt wird. Dies vereinfacht die Wartung, da bei Updates der Simulationsumgebung nicht die Menschensimulation an den neuen Code angepasst werden muss. \section{Roboterumgebung} MoveIt2\cite{moveit-docs} ist das meist genutzte ROS2 Paket für Bewegungsplanung von Robotern. Deshalb existiert viel Dokumentation für die zahlreichen Komponenten, was die Entwicklung neuer Komponenten erleichtert. Außerdem sind zahlreiche direkte Integrationen mit anderen ROS-Paketen verfügbar, was das Nutzen dieser mit MoveIt zusammen erlaubt. Diese Eigenschaften machen das MoveIt als Bewegungsplanungsumgebung für dieses Projekt extrem attraktiv. MoveIt besteht aus meheren Komponmenten, die in ihrer Gesamtheit den Bereich der Bewegungsplanung abdecken. Der Nutzer kann mit MoveIt auf verschiedenen Wegen Steuerbefehle für den Roboter absenden, die durch die Software umgesetzt werden. Die erste Inbetriebnahme ist über das mitgelieferte RViz-Plugin und die demo-Launch-Files moglich. Diese wurden mit dem mitgelieferten Setupassistenten für den Roboter generiert. Durch die Ausführung dieser Demo startet RViz, eine Test- und Visualisierungsumgebung für ROS. In dieser können Roboterbewegungen unter Zuhilfenahme von Markierungen in RViz geplant und ausgeführt werden. Da sich eine solche Bewegungsplanung nur beschränkt zur Automatisierung durch Software eignet, müssen die der Demo zugrundeliegenden Schnittstellen genutzt werden. Für die Sprache Python existierte für die Vorgängerversion MoveIt noch das moveit_commander Paket, dass den Zugriff auf MoveIt in Pyhon erlaubt, dass aber für MoveIt2 noch nicht portiert wurde. \cite{moveitpython} Die direkte Nutzung der C++-API ist aktuell die einzige offizielle Möglichkeit, mit MoveIt2 direkt zu interagieren. Dabei kann sowohl die Planung und Ausführung von Bewegungen ausgelöst werden, aber auch Exklusionszonen eingerichtet werden. Außerdem können Objekte virtuell mit dem Roboter verbunden werden, wodurch sich diese in RViz mit dem Roboter bewegen. Natürlich können die Befehle auch direkt an die entsprechenden Topics gesendet werden um einzelne Bereiche des Systems zu testen, jedoch ist so kein einfacher Zugriff auf erweiterte Optionen möglich. Um die durch den Setupassistenten generierten Informationen an MoveIt zu übergeben, wird intern ein RobotStatePublisher verwendet. Dieser läd alle Daten des Robotermodells und gibt sie an andere Programme weiter, die Roboterparameter zur Laufzeit anfordern, unter diesen auch MoveIt selbst. Durch die vorher erwähne C++-API erhält die MoveGroup die Informationen über die gewünschte Bewegung. Dabei können auch bestimmte Einschränkungen des Arbeitsraums, spezielle Trajektorien, oder Limitierungen der Gelenke in der Planung berücksichtigt werden. Diese Daten können durch eine OccupancyMap ergänzt werden, welche die Bereiche beschreibt, die sich um den Roboter befinden. Eine solche Erweiterung erlaubt die automatische Nutzung von Kollisionsvermeidung mit Objekten im Planungsbereich. Die Planung der Bewegung wird durch einen der zahlreichen implementierten Solver erledigt, der durch die MoveGroup aufgerufen wird. Um die generierte Bewegung umzusetzen, werden die gewünschten Gelenkpositionen als Abfolge an die \code{ros_control} Controller des Roboters weitergegeben. Diese Abstaktion erlaubt die Nutzung von sowohl simulierten, aber auch echten Robotern. Hiefür kann ein anderer \code{ros_control} Controller geladen werden, der entweder die simulierte oder echte Hardware ansteuert. Der Erfolg der gesamten Pipeline kann dabei durch einen Feedbackmechanismus überwacht werden. Im Falle von Gazebo wird \code{ign_ros_control} genutzt, dass die benötigten \code{ros_control} Controller in die Simulation einbindet. Diese können dann wie normale Controller von \code{ros_control} genutzt werden. Dieser Ablauf ist auch im Anhang unter Abbildung \ref{moveitpipeline} im Anhang visualisiert. \section{Programmiersprache} Als Programmiersprache kommen in ROS standartmäßig Python\cite{python} und C++\cite{cpp} zum Einsatz. Diese beiden Sprachen sind in der Softwareentwicklung beliebt, unterscheiden sich jedoch stark in Funktionsumfang und Entwicklungsprozess. Python ist eine interpretierte Skriptsprache, die zu den hohen Programmiersprachen zählt. Sie wird in ROS zum Beispiel in .launch.py-Dateien eingesetzt, die den Start von Diensten in der Umgebung verwalten. Die Sprache kann aber auch für die Programmierung von Nodes innerhalb des ROS-Systems verwendet werden. C++ hingegen ist eine kompilierte, statisch typisierte, maschinennahe Programmiersprache. In ROS wird C++ für Code verwendet, der entweder häufig oder in zeitkritischen Szenarien ausgeführt wird. Aus diesem Grund wird C++ in Nodes verwendet, die schnell auf große Datenmengen reagieren müssen. Die Nutzung eines Kompilierers beschleunigt C++ deutlich im Vergleich zu Python, ist jedoch weniger geeignet für häufige Modifikation. Dies ist vor allem in häufig geänderten Programmen ein Nachteil, die nach einer Änderung wieder kompiliert werden müssen. Aus diesem Grund wird Python vor allem in .launch.py-Dateien verwendet, welche die Interaktion der anderen Programme in der Umgebung verwalten. Um die gewünschten Funktionen für die Simulation umsetzen zu können, ist die Programmierung in C++ nötig. Da zum Beispiel Gazebo-Plugins auf C++ als Programmiersprache ausgelegt sind, was die Nutzung anderer Sprachen stark erschwert. Ein Grund dafür ist die hohe Geschwindigkeit, die bei einer hohen Anzahl an Simulationsschritten pro Sekunde benötigt wird. Außerdem kann MoveIt2 zur aktuellen Zeit nur mit C++ direkt gesteuert werden. Die Verwendung von C++ für die zu entwickelnden Nodes erscheint deshalb aus oben genannten Gründen naheliegend. In den Launch-Skripten wird jedoch Python verwendet werden, da hier die Vorteile einer Skriptsprache überwiegen. \section{Behavior Trees} Zur Verwaltung der Abläufe sollen BehaviorTrees genutzt werden, die durch die Bibliothek \code{BehaviorTree.CPP} bereitgestellt werden. Diese Bibliothek wurde in C++ geschrieben, und ist somit in ROS und dem geplanten Konzept integrierbar. Es existieren aber auch viele Beispiele und eine gute Dokumentation über die erweiterten Funktionen, die im folgenden vorgestellt werden. \begin{description} \item[Asynchrone Nodes] sind in \code{BehaviorTree.CPP} leichter umsetzbar, da diese im Lebenszyklus der Nodes beim Konzept der Bibliothek mit bedacht wurden. Dies resultiert in Nodes, die ohne spezielle Logik langanhaltende Aktionen ausführen können, ohne die Ausführung des BehaviorTrees zu behindern. \item[Reaktives Verhalten] ist ein neues Konzept, um die Handhabung von asnchronen Nodes zu vereinfachen. Diese Strukturelemente erlauben die parallele Ausführung von mehreren Zweigen, die aktuell ausführende Aktionen beeinflussen können. Darunter fällt die Modifizierung von Parametern der Aktionen, aber auch der vollständige Abbruch einer Aktion durch äußere Einflüsse. \item[Das .xml-Format der Behavior Trees] ermöglicht einen Austausch des Verhaltens, ohne die unterliegende Programme verändern zu müssen. Dies ist vor allem in kompilierten Sprachen wie C++ sinnvoll, da Änderungen im Verhaltensablauf keiner Neukompilierung bedürfen, was die Iterationszeit für Änderungen verbessert. \item[Plugins] können zum Start geladen werden, um weitere Nodes dem ausgeführten Programm hinzufügen zu können. Dies vereinfacht die Erweiterung um neue Funktionen und das mehrfachen Nutzen von Code. \item[Das Blackboard] ist eine Interaktionsebene, die den Datenfluss zwischen den Nodes erlaubt. In diesem System kann unter Verwendung einer Zeichenkette als Identifikator ein Wert in Form einer Referenz hinterlegt werden. Sogenannte Ports erlauben Nodes, Daten aus dem Blackboard zu lesen und auf dieses zu schreiben. \item[Integriertes Logging] erlaubt es, Zustandsänderungen im Behavior Tree zu visualisieren, aufzunehmen und wieder abzuspielen. Dies erleichtert das häufig schwierige Debuggen von Zustandsmaschienen erheblich, da das Verhalten genau untersucht werden kann. \end{description} BehaviorTrees werden in \code{BehaviorTree.CPP} als .xml-Dateien gespeichert. Diese Dateien enthalten die Anordnung der Nodes selbst, aber auch weitere Konfigurationsmöglichkeiten in Form von Ein- und Ausgabeports. Ports können verwendet werden, um Nodes generischer zu gestalten. Durch veränderbare Parameter im später erstellten Tree können Nodes ohne Programmänderung verändert werden. Falls die Nodes mit Bedacht erstellt wurden, kann so auf viele spezialisierte Nodes verzichtet werden. Um dies zu ermöglichen kann deren Funktion durch mehrere andere Nodes in einem Subtree mit Parametern abgebildet werden. Diese in den Ports übertragenen Daten können sowohl aus einem String ausgelesen, aber auch aus dem sogenannten Blackboard entnommen werden. Um die Übersetzung aus einem String zu ermöglichen, muss eine entsprechende Funktion implementiert werden, die einen String in den gewünschten Zieltyp übersetzt. Viele primitive Datentypen, wie Ganzzahlen und Gleitkommazahlen, werden von BehaviorTree.Cpp bereits durch mitgelieferte Funktionen unterstützt. Das Blackboard ist ein System, dass die Nutzung von Variablen als Parameter für Ports erlaubt. Diese werden im Hintergrund als eine Referenz auf den eigentlichen Wert gespeichert. Eine solche Funktion erlaubt das weitere Zerlegen von Vorgängen innerhalb des BehaviorTrees. Solche kleineren Nodes sind durch ihren limitierten Umfang universeller einsetzbar, da sie nur kleinere Teilprobleme betrachten, die zu komplexeren Strukturen zusammengesetzt werden können. Um die dadurch wachsenden Strukturen besser überblicken zu können, lassen sich Nodes als sogenannte SubTrees abspeichern. Diese bilden dann in ihrer Gesamtheit eine neue Node, die im BehaviorTree eingesetzt werden kann. Um den Einsatz von Variablen innerhalb eines SubTrees zu ermöglichen, besitzt jeder SubTree ein separates Blackboard. Dadurch kann auch ein Eingriff durch äußere Einflüsse verhindert werden. Natürlich sollte es auch möglich sein, Variablen an solche SubTrees zu übergeben. Diese können, wie auch bei normalen Nodes, als Parameter an den SubTree übergeben werden. Die Bibliothek \code{BehaviorTree.CPP} verbindet dann diese Werte und erlaubt die Datenübergabe zu und von dem SubTree. \subsection{Asynchrone Nodes} Da nicht jeder Prozess sofort vollständig durchgeführt werden kann, muss die Möglichkeit geschaffen werden, lang anhaltende Prozesse abzubilden. Dies geschieht in \code{BehaviorTree.CPP} durch asynchrone Nodes. Eine asynchrone Node besitzt neben den Zuständen SUCCESS und FAILURE einer normalen Node auch noch die beiden neuen Zustände RUNNING und IDLE. Außerdem werden mehrere Funktionen definiert, die den Lebenszyklus der Node darstellen. Wird eine Node durch den Aufruf der \code{onStart}-Funktion gestartet, geht diese in einen der Zustände RUNNING, SUCCESS oder FAILURE über. Der Zustand RUNNING steht dabei für eine Node, die sich noch in der Ausführung befindet. So lang dieser Zustand anhält, wird die Node nicht noch ein weiteres Mal gestartet, sondern nur der Zustand in der neuen \code{onRunning}-Funktion abgefragt. Der IDLE-Zustand ist ein besonderer Zustand, der nur durch eine vollständige Ausführung erreichbar ist. Er wird von der Node angenommen, nachdem deren Ausführung durch SUCCESS oder FAILURE beendet wurde. Im Falle eines Abbruchs, der durch andere Nodes im Baum ausgelöst werden könnte, muss die Ausführung der Node vorzeitig beendet werden können. Dies geschieht mit der neuen \code{onHalted}-Funktion. Diese wird ausgeführt, wenn die Ausführung der Node abgebrochen werden soll. \subsection{Dateiformat} Das in BehaviorTree.Cpp verwendete Dateiformat, um Behavior Trees zu erstellen, basiert auf XML. Jedes Dokument beginnt dabei mit einem Root-Element, dass alle BehaviorTrees und eine Referenz auf die ID des Hauptbaumes enthält. Diese wird benötigt, da auch Unterbäume im selben Dokument deklariert und genuzt werden können, diese aber sonst nicht vom Hauptbaum unterscheidbar sind. Jeder Baum beginnt mit einem BehaviorTree-Element, dass als Attribut die ID des Baumes besitzen muss. Als untergeornete Elemente des Baumes werden die Nodes entsprechend der gewünschten Baumstruktur angeordnet. Zur besseren Visualisierung der XML-Struktur wurde hier die bereits aus dem Konzept bekannte Baumstruktur, hier noch einmal in Abbildung \ref{choice_tree_demo} zu sehen, umgewandelt. Die resultierende Datei ist in Abbildung \ref{choice_tree_xml} abgebildet. Dabei ist zu beachten, dass die Root-Node nicht in der Struktur existiert, da diese nur den Eintrittspunkt in die Struktur darstellt. Außerdem können selbst definierte Nodes sowohl direkt mit ihrem Namen, aber auch über den Namen Action mit ihrem Namen als ID-Parameter, referenziert werden. \begin{figure}[hpt] \includegraphics[width=\textwidth]{img/MA-tree-demo} \centering \caption{Beispiel eines BehaviorTrees} \label{choice_tree_demo} \end{figure} \begin{figure}[hpt] \begin{minted}[breaklines,frame=single,linenos]{xml} \end{minted} \caption{Beispiel eines BehaviorTrees als .xml} \label{choice_tree_xml} \end{figure} \section{Docker-Compose als Virtualisierungsumgebung} Docker ist eine Virtualisierungsumgebung für Anwendungen, die eine komplette Umgebung für deren Ausführung bereitstellt. Dadurch wird die Inbetriebnahme von Anwendungen, die spezielle Umgebungen für ihre Ausführung benötigen auf beliebigen Systemen ermöglicht. Dies wird durch den Einsatz von sogenannten Containern erreicht. Ein solcher Container wird über sogenannte Build-Files definiert. Ein Build-File enthält exakte Instruktionen, wie der Container aus anderen Containern, Dateien oder einer Kombination beider erstellt werden kann. Der so erstellte Container wird anhand dieser Definition durch den ausführenden Rechner erstellt. Um diesen Prozess weiter zu beschleunigen, ist auch der Einsatz eines Buildservers möglich, der benötigte Container als Download bereitstellt. Jeder Container enthält ein eigenes Dateisystem, das aus dem im Buildfile definierten Dateien und einem Overlay besteht. In diesem Overlay werden temporär Änderungen gespeichert, die am Container während dessen Laufzeit vorgenommen werden. Sofern nicht definiert, werden diese Änderungen beim Neustart des Containers wieder entfernt. Um dies zu vermeiden, kann entweder ein Volume, eine Art virtuelles Laufwerk in einem Systemverzeichnis des Hostsystems, oder ein ``bind mount'' eingerichtet werden. Ein ``bind mount'' ist eine direkte Verbindung zu einem Ort des Host-Dateisystems, dass in den Container hereingereicht wird. Docker-Compose stellt eine Erweiterung von Docker dar. Diese Erweiterung verwaltet die Inbetriebnahme der Container über ein spezielles Dateiformat. Eine solche Funktion erlaubt das wiederholte Einrichten von Containern mit gleichen Parametern. In dieser Datei werden weitere Optionen angegeben, die in die Umgebung des laufenden Containers eingreifen. Dazu gehört zum Beispiel das automatisierte Übergeben von Umgebungsvariablen, Einrichten von Netzwekumgebungen und Erstellen von Volumes und ``bind mounts''. Diese Automatisierung erleichtert die initiale Einrichtung eines Containers auf einem neuen System, da alle benötigten Aspekte leicht angepasst werden können.