Читать книгу Roboter mit ROS - Murat Calis - Страница 28
1.2.11ROS-Launch
ОглавлениеJe mehr Nodes wir entwickeln, die miteinander kommunizieren, desto mehr Nodes werden gestartet. Mit dem Befehl roscore würde man zunächst den ROS-Master starten und anschließend mit dem Befehl rosrun, welcher nur einen einzelnen Node starten kann, ein Node nach dem anderen in jeweils einem eigenen Terminal-Fenster. Schließlich hat man eine Menge offener Terminal-Fenster, was die Suche nach bestimmten Nodes erschwert, deren Ausgaben man gezielt beobachten möchte.
Der Befehl roslaunch erleichtert die Arbeit mit mehreren Nodes und verschafft uns einen Überblick, indem wir alle Nodes, die wir starten wollen, in einer launch-Datei zusammenfassen und zum Ausführen lediglich ein Terminal-Fenster öffnen, denn roslaunch startet auch den ROS-Master, wenn dieser noch nicht gestartet wurde. In einer launch-Datei können zudem auch andere entfernte launch-Dateien eingebunden werden. Alle Optionen und Tools rund um roslaunch werden auf den Wiki-Seiten unter http://wiki.ros.org/roslaunch und http://wiki.ros.org/roslaunch/Commandline%20Tools gezeigt.
Der gleichnamige Ordner für launch-Dateien befindet sich in einem ROS-Paket. Der Inhalt einer launch-Datei wird im XML-Format verfasst. In einer Datei können Nodes, Parameter und weitere launch-Dateien definiert werden. Mit Funktionen können Berechnungen und Namensauflösungen in einer launch-Datei verwendet werden. Ein ausführliches Beispiel und Möglichkeiten für eine launch-Datei finden wir unter folgendem Link http://wiki.ros.org/roslaunch/XML.
Der Befehl roslaunch startet wie bereits erwähnt gegebenenfalls einen ROS-Master und führt alle in einer launch-Datei aufgeführten Definitionen gleichzeitig aus. Es wird also nicht der Reihe nach abgearbeitet und genau dieses Verhalten sollte bei der Programmierung von Nodes beachtet werden, denn wenn ein Node auf einen Wert oder einen Service eines anderen Nodes zugreift, obwohl dieser noch nicht einmal gestartet ist, entstehen Fehlermeldungen der Kategorie fatal.
Als Beispiel soll hier die launch-Datei abot_description.launch aus dem gleichnamigen Paket abot_description erörtert werden.
<? xml version="1.0" encoding="utf-8" ?>
<launch>
<arg
name="urdf_file"
default="$(find xacro)/xacro --inorder
'$(find abot_description)/urdf/abot.xacro'" />
<param name="robot_description" command="$(arg urdf_file)" />
<node
name="robot_state_publisher"
pkg="robot_state_publisher"
type="robot_state_publisher"
output="screen"
respawn="false">
<param name="publish_frequency" type="double" value="100.0" />
</node>
<node
name="joint_state_publisher"
pkg="joint_state_publisher"
type="joint_state_publisher">
<param name="use_gui" value="false" />
</node>
<node
name="rviz"
pkg="rviz"
type="rviz"
args="-d $(find abot_description)/config/abot_urdf.rviz"
output="screen">
</node>
</launch>
Der XML-Prolog, inklusive Versionsangabe und UTF8-Kodierung, ist ein Hinweis für Anzeige- und Bearbeitungsprogramme, dass es sich um ein XML-Dokument handelt, damit diese es entsprechend formatiert auf dem Bildschirm ausgeben können. Weitere Details dieser launch-Datei finden wir in der folgenden Liste.
1 Der Wurzelknoten darf nur einmal vorkommen, er hat die Bezeichnung <launch> und muss am Ende auch mit </launch> geschlossen werden.
2 Ein Argument-Element <arg> mit dem Namen urdf_file kann entweder an roslaunch auf der Kommandozeile angefügt werden oder es wird der Befehl des default-Attributs übernommen, welcher erst in der nächsten Zeile im <param>-Element mit dem Attribut command aufgelöst und dann ausgeführt wird. Weitere Beispiele für die Verwendung von Argumenten gibt es unter http://wiki.ros.org/roslaunch/XML/arg.
3 Das <param>-Element ist eine weitere Möglichkeit, Parameter auf dem Parameter-Server zu setzen. Wird ein <param>-Element innerhalb eines <node>-Elements verschachtelt, dann handelt es sich um private3 Parameter, die dem Node-Namen untergeordnet werden, sobald sie auf dem Parameter-Server erscheinen. Ist ein <param>-Element keinem anderen Element untergeordnet, so handelt es sich um einen globalen Parameter. Die Attribute type und value hängen zusammen, wobei type den Datentyp bestimmt und value den Wert. Das Attribut type ist optional und wenn es nicht vorhanden ist, versucht roslaunch eigenständig, den Datentyp von value zu bestimmen. Weitere Informationen finden Sie unter http://wiki.ros.org/roslaunch/XML/param.
4 Am häufigsten arbeiten wir mit <node>-Elementen in einer launch-Datei. Die wichtigsten Attribute eines <node>-Elements lauten name, pkg und type. Ersteres ist ein frei wählbarer Namensraum, der mit dem Befehl rosnode list sichtbar wird. Als Nächstes wird im pkg-Attribut der ROS-Paketname genannt, wo roslaunch nach Nodes oder Programmen suchen soll. Letzteres ist der Programmname bzw. Node-Name innerhalb des mit dem pkg-Attribut definierten ROS-Pakets. Für ein besseres Verständnis stellen wir uns die Syntax von rosrun folgendermaßen vor: rosrun pkg type __name:=name. Verwendet man bei einem zweiten <node>-Element mit denselben pkg- und type-Angaben eine andere Bezeichnung im Attribut name, dann startet derselbe Node zweimal, nur mit unterschiedlichen Namen eben, zum Beispiel left_arm und right_arm. Ein Node kann also mehrmals gestartet werden, wenn man unterschiedliche Bezeichnungen im name-Attribut verwendet.Die output="screen"-Angabe leitet sämtliche Protokollausgaben, die standardmäßig in einer log-Datei landen, zusätzlich auf den Bildschirm um. Das Attribut respawn startet diesen Node automatisch wieder, sobald er beendet wurde, wenn der Wert von respawn true ist. Seit ROS Indigo kann eine Startverzögerung mit respawn_delay eingebaut werden. Wenn ein Node sehr wichtig für den Ablauf ist, aber ab und zu mal abstürzt, weil Treiber nicht korrekt funktionieren, kann dies eine Notlösung sein, um den Node am Leben zu halten.Eine ähnliche Funktion wie respawn, aber radikaler, hat das required-Attribut. Im Gegensatz zum Neustart beendet es alle aktiven Nodes und somit das gesamte ROS-Programm. Beendet man einen mit dem required-Attribut versehenen Node, dann werden alle anderen Nodes inklusive ROS beendet.Alle Attribute, Elemente und Beispiele befinden sich unter dem Link http://wiki.ros.org/roslaunch/XML/node.
5 Ein untergeordnetes <param>-Element wird automatisch zu einem privaten Parameter des übergeordneten Elements. Auf dem Parameter-Server ergibt sich hieraus folgende Schreibweise /robot_state_publisher/publish_frequency.
6 Aus dem Paket joint_state_publisher wird das Programm joint_state_publisher mit der Bezeichnung joint_state_publisher gestartet. Der private Parameter mit dem Attributwert use_gui weist das übergeordnete Element an, keine grafische Benutzeroberfläche anzuzeigen, da der Attributwert von value auf false gesetzt ist. Wird der Attributwert auf true gesetzt, erscheint für das Programm joint_state_publisher eine Schnittstelle aus Schiebereglern für bewegliche Gelenke.
7 Das <node>-Element enthält keine untergeordneten <param>-Elemente oder sonstigen Elemente und wird somit wie ein leeres Element behandelt. Leere Elemente müssen nicht mit einem schließenden Element versehen werden, sondern können vor der schließenden eckigen Klammer mit einem Schrägstrich geschlossen werden (z. B. <node name="rviz" />).Das <args>-Attribut ist eine Kommandozeilenoption, die in diesem Fall an das Programm RViz übergeben wird.
Launch-Dateien sind ein wesentlicher Bestandteil der Arbeit mit ROS. Dadurch erspart man sich den Wechsel zwischen unzähligen Terminalfenstern. Die Log-Ausgabe kann für jedes einzelne Programm mithilfe des output-Attributs angezeigt oder stumm geschaltet werden. Die Inklusion einer launch-Datei in einer launch-Datei eröffnet wichtige Möglichkeiten wie Kaskadierung. Die Zusammenstellung und Organisation umfangreicher launch-Dateien für unterschiedliche Szenarien ist damit gegeben. Im Idealfall sind auch die Dateinamen der launch-Dateien so gewählt, dass ihre Funktion daraus leicht zu erkennen ist. Als Beispiel soll hier die Startdatei für den Roboter im Navigationsmodus veranschaulicht werden. Sie finden diese launch-Datei im Verzeichnis abot_bringup/launch/.
<launch>
<incldude file="$(find abot_description)/launch/abot_base.launch" />
<include file="$(find abot_bringup)/launch/include/teensy32.launch" />
<include file="$(find abot_navigation)/launch/navigation.launch" />
<include file="$(find abot_bringup)/launch/include/rplidar.launch" />
<include file="$(find abot_laser_filter)/launch/laser_filter.launch" />
</launch>