Gazebo ist ein beliebtes Simulationstool das uns nicht nur erlaubt den Roboter zu visualisieren, sondern auch eine Physikengine besitzt. Damit können wir unsere Anwendungen in einer realistischeren Umgebung testen in der externe Kräfte wie Gravitation wirken. In diesem Post gehen wir durch die einzelnen Schritte die nötig sind um den UR5 Roboterarm in Gazebo zu simulieren. Außerdem sehen wir uns an welche physikalischen Eigenschaften wir zur URDF unseres Roboters hinzufügen müssen um eine realistische Simulation zu erhalten. Zuerst aber starten wir mit Gazebo!
Notiz: Wenn du den Roboter nur in Gazebo simulieren möchtest ohne dich mit den Eigenschaften zu beschäftigen die in der URDF beschrieben werden kannst du auch direkt zum Absatz Kurzanleitung springen. Dort findest du alle nötigen Befehle und den UR5 Roboter in Gazebo zu starten.
Gazebo
Wenn du ROS noch nicht installiert hast, mach das bitte mit Hilfe dieses Artikels. Nach einer vollständigen ROS Installation sollte Gazebo bereits installiert sein. Falls nicht, führe einfach diesen Befehl im Linux-Terminal aus:
$ curl -sSL http://get.gazebosim.org | sh
Jetzt können wir bereits eine neue (leere) Umgebung in Gazebo öffnen. Probier es aus indem du folgendes ausführst:
$ roslaunch gazebo_ros empty_world.launch
Nun ist eine leere Welt natürlich recht langweilig, also fügen wir unseren Roboter ein. Im letzten Tutorial über URDFs haben wir bereits die URDF Datei des UR5 Roboters besprochen. Wenn du dieses vorherige Totorial noch nicht gelesen hast und mehr darüber wissen möchtest wäre jetzt der ideale Zeitpunkt dafür.
Gazebo kann den Roboter anhand der URDF Dateie simulieren. Unter der Haube wird die URDF allerding in ein anderes, sogenanntes SDF-Format konvertiert welches sich besser für Simulationen eignet. Damit nun Gazebo etwas mit unserer URDF anfangen kann, brauchen wir ein paar zusätzliche Zeilen. Wir müssen einige physikalische Eigenschaften ergänzen die beschreiben, wie genau sich unser Roboterarm bewegt damit wir eine realistische Simulation erhalten. Die erweiterte URDF für Gazebo findest du hier. Dort kannst du die hinzugefügten Eigenschaften die wir im Folgenden stichpunktartig besprechen für den ganzen Roboter nachvollziehen.
Trägheit hinzufügen
Im Vergleich zu Rviz muss Gazebo einige zusätzliche Eigenschaften unseres Roboters kennen um ihn richtig simulieren zu können. Dazu gehört das Gewicht unserer Roboterteile (die sogennanten Links) und wie dieses Gewicht verteilt ist, was im allgemeinen als Trägheit (eng. Intertia) bezeichnet wird. Diese Information <inertial>
muss in der URDF innerhalb des <link>
und nach den <visual>
und <collision>
Sektionen enthalten sein. Im Folgenden als Beispiel die Werte für die Basis:
</collision>
<inertial>
<mass value="2.275"/>
<origin rpy="0 0 0" xyz="0.0 0.0 0.25"/>
<inertia ixx="0.049443313556" ixy="0.0" ixz="0.0" iyy="0.049443313556" iyz="0.0" izz="0.004095"/>
</inertial>
Für starre Körper die im dreidimensionalen rotieren sieht die allgemeine Trägheitsmatrix, die im <inertia>
Tag definiert wird, folgendermaßen aus:
Die Matrixelemente definieren die Trägheitsmomente. \(I_{xx}\)beispielsweiße definiert das Trägheitsmoment um die x-Achse, während \(I_{xy}\) das xy produkt der Trägheit definiert. Eine detailiertere Befassung mit der Trägheitsmatrix würde den Rahmen des Artikels bei weitem sprengen aber eine Googlesuche sollte viele Ergebnisse liefern falls dich das Thema mehr interessiert. Das einzige was wir noch wissen müssen ist, dass die Elemente über der Diagonalen gleich den Elementen darunter sind, das heißt \(I_{xy} = I_{yx}\), \(I_{xz} = I_{zx}\) und \(I_{yz} = I_{zy}\). Daher müssen wir nur sechs Elemente für unsere 3×3 Trägheitsmatrix definieren.
Der <origin>
Tag definiert den Massen- bzw. Gravitationsschwerpunkt unserer Links. Formal gesehen ist das das Mittel aus den Positionen der Massenpunkte welche nach ihrer Masse gewichtet werden. Dieses Attribut ist beispielweiße nützlich wenn man Beschleunigungen berechnen möchte. Das <mass>
(Gewicht) Attribut ist recht selbsterklärend.
Kollisionseigenschaften
Für eine richtige Simulation muss Gazebo wissen wann der Roboter kollidiert, sowohl mit seiner Umwelt als auch mit sicht selbst. Dafür müssen wir die Geometrie unserer Links noch einmal speziell für diese Kollisionsberechnung definieren. Der Einfachheit halber benutzen wir wieder eine generierte Datei aus dem CAD-Modell im .stl Format. Es beschreibt einzig und allein die Geometrie unseres Roboters ohne Eigenschaften wie Farbe oder Material. Diese Modelle werden oft durch geometrische Annäherungen vereinfacht oder die Auflösung wird reduziert um Rechenzeit zu sparen.
<collision>
<geometry>
<mesh filename="package://ur_description/meshes/ur5/collision/shoulder.stl"/>
</geometry>
</collision>
Grenzen und dynamische Eigenschaften
Zusätzlich bestimmen wir Grenzen für gewisse Eigenschaften unserer Joints. Diese fügen wir wieder innerhalb der <joint>
Tags ein.
<limit effort="28.0" lower="-3.14159265" upper="3.14159265" velocity="3.2"/>
<dynamics damping="0.0" friction="0.0"/>
Das Attribut effort
bestimmt die maximale Kraft die wir am Joint aufbringen können wobei das hauptsächlich von der Stärke der Motoren abhängt. Mit den lower
und upper
Limits bestimmen wir die Bewegungsgrenzen in rad (Im oberen Fall dreht sich der Joint zwischen -180 und +180 Grad). Außerdem begrenzen wir die maximale Geschwindigkeit des Joints, in diesem Fall auf 3.2 rad/s (ca. eine halbe Umdrehung pro Sekunde).
Innerhalb des Tags <dynamics>
können wir zusätzlich damping
(Dämpfung) und friction
(Reibung) im Joint definieren. Weil uns dazu keine Daten vorliegen setzten wir beide Werte auf 0. Um allerdings ein noch realistischeres Verhalten, besonders der späteren Regelung, zu haben ist es generell wünschenswert hier sinnvolle Werte zu haben.
Die Attribute in diesem Abschnitt sind optional und nicht umbedingt nötig um das URDF in Gazebo zu verwenden.
Den Roboter im Boden verankern (Ein fixierter world joint)
Am Schluss, um den Roboter mit der Umgebung in Gazebo zu verbinden, fügen wir noch einen zusätzlichen Joint in unser URDF ein. Dieser, wir nennen ihn world_joint
, ist fixiert und seine einzige Daseinsberechtigung ist die, unseren Roboter in der Welt zu verankern. Deshalb definieren wir world
als seinen parent und base_link
als sein child.
<link name="world"/>
<joint name="world_joint" type="fixed">
<parent link="world"/>
<child link="base_link"/>
<!-- TODO: check base_link name of robot -->
<origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
</joint>
Jetzt da wir alles haben was Gazebo braucht können wir unseren Roboter in die Simulation einfügen. Kopiere zuerst den Inhalt der URDF Datei (link) in ein Textdokument und speicher es irgendwo auf deinem PC unter dem Namen ur5_gazebo.urdf. Danach, falls du das ur_description Package nicht schon vom vorigen Tutorial installiert hast, führe die folgenden Befehle aus und ersetze <distro> mit dem Namen deiner installierten ROS Distribution (noetic, melodic, …):
~/catkin_ws/src$ git clone -b <distro>-devel https://github.com/ros-industrial/universal_robot.git $
$ rosdep update
$ rosdep install --rosdistro $ROS_DISTRO --ignore-src --from-paths src
Dann kannst du deinen Workspace bauen:
~/catkin_ws/src$ cd ..
~/catkin_ws$ catkin_make
$ source $HOME/catkin_ws/devel/setup.bash
Wie zuvor starten wir wieder eine leere Gazebo Umgebung:
$ roslaunch gazebo_ros empty_world.launch
Schlussendlich können wir den Roboter laden indem wir in einem neuen Linux-Terminal folgeden Befehl ausführen:
$ rosrun gazebo_ros spawn_model -file /<path-to-your-gazebo-urdf-file>/ur5_gazebo.urdf -urdf -x 0 -y 0 -z 0.1 -model ur5
Wir übergeben den Pfad zur URDF Datei als Argument und spezifizieren die Koordinaten an denen unser Roboter stehen soll. Wir lassen einen kleinen Abstand von 0.1 zum Ursprung für unsere z-Achse da sich genau im Zentrum der geladenen Gazebo Umgebung eine Bodenplatte befindet die auch auf der linken Seite under Models auftaucht. Diese Platte ist unsichtbar aber sie erzeugt Kollisionen wenn wir versuchen den Roboter exakt an der gleichen Position zu plazieren.
Im obigen Bild sind die Schatten für bessere Sichtbarkeit deaktiviert. Dazu musst du nur auf der linken Seite im World Tab Scene auswählen und den Haken in der Checkbox unter shadows entfernen. Wenn wir uns nun unseren Roboter in Gazebo ansehen, schaut das etwas mitleiderregend aus wie er da so am Boden rumliegt. Das liegt daran, dass wir im Moment nichts am Roboter regeln. Das bedeutet, alles was im Moment in der Simulation passiert ist eine Reihe zusammengefügter Gewichte die wegen der Schwerkraft auf den Boden fallen. Im nächsten Tutorial fügen wir deshalb das ros_control package hinzu und definieren Positionsregler um unsere Joints bewegen zu können.
Kurzanleitung
Für Eilige sind hier die nötigen Terminalbefehle zusammengefasst:
Gazebo installieren (falls nötig):
$ curl -sSL http://get.gazebosim.org | sh
Falls nicht bereits vom vorherigen Tutorial existent, installiere das universal_robot Package aus dem ROS Industrial Projekt:
~/catkin_ws/src$ git clone -b <distro>-devel https://github.com/ros-industrial/universal_robot.git $
$ rosdep update
$ rosdep install --rosdistro $ROS_DISTRO --ignore-src --from-paths src
Dann baue deinen Workspace:
~/catkin_ws/src$ cd ..
~/catkin_ws$ catkin_make
$ source $HOME/catkin_ws/devel/setup.bash
Kopiere nun den Inhalt der URDF-Datei für Gazebo in ein Textdokument auf deinem PC und speichere es unter dem Namen ur5_gazebo.urdf. Dann führe die Folgenden beiden Befehle aus um den Roboter in Gazebo zu laden:
$ roslaunch gazebo_ros empty_world.launch
$ rosrun gazebo_ros spawn_model -file <path-to-your-gazebo-urdf/ur5_.urdf -urdf -x 0 -y 0 -z 0.1 -model ur5
Alternativ kannst du die Simulation auch mit der Launch-Datei des ur5_gazebo Package starten welches zusätzlich Regler für die Joints lädt.
$ roslaunch ur_gazebo ur5.launch
Wenn du den Roboter bewegen willst indem du die Joints (Gelenke) mit Hilfe des ros_control Package steuerst dann kannst du gleich weiter machen mit dem nächsten Tutorial.