Simulation avec Gazebo

En robotique il est souvent très utile de pouvoir travailler en simulation. Un simulateur physique permet essentiellement de simuler des forces/couples sur des objets et des articulations. Gazebo est un environnement de simulation physique pour robotique, supporté par ROS. Nous nous servirons de la simulation dans Gazebo de manière transparente, “comme si” il s’agissait du véritable robot.

img

La simulation va nous permettre :

  1. De charger des modèles URDF
  2. De simuler des moteurs
  3. De simuler une caméra
  4. De simuler les contacts

Notons que Gazebo est constitué d’un serveur (non graphique, gzserver) et d’un client (graphique, gzclient) ce qui permet également de calculer une simulation sur une machine distante par exemple.

1. Lancement de Gazebo avec un monde “vide”

roslaunch gazebo_ros empty_world.launch Ce que nous allons utiliser, mais il est bien sur possible de créer des environnements plus complexes.

2. Chargement d’un modèle

Les modèles sont décrit par un fichier xml selon la norme URDF (Universal Robot Description Format).

3. Un simple cube

Pour la suite du TP, créez un ROS workspace et clonez le package poppy_ergo_jr_gazebo:

mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
git clone https://github.com/poppy-project/poppy_ergo_jr_gazebo.git
cd ~/catkin_ws/
catkin_make
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

Dans poppy_ergo_jr_gazebo/urdf on peut voir la définition d’un cube. Pour charger cet URDF dans l’instance Gazebo executée précédemment, lancez la commande : rosrun gazebo_ros spawn_model -file cube.urdf -urdf -model test -x 0 -y 0 -z 1

Pour supprimer le modèle : rosservice call gazebo/delete_model "model_name: 'test'"

4. Chargement du modèle du robot

La description du robot se trouve ici. Clonnez ce repertoire git dans le dossier src de votre catkin_ws mettez vous sur la branche camera_integration puis compilez le avec la commande catkin_make (à lancer à la racine du workspace).

On utilise ici un format intermédiaire “xacro”, permettant d’ajouter un capacité de “script” (pour calculer des position par exemple) et générer un URDF. On peut visualiser la topologie du modèle en allant dans poppy_ergo_jr_description/urdf en en lancant la commande : urdf_to_graphiz poppy_ergo_jr.urdf (un pdf est généré).

Ouvrez le PDF obtenu puis déterminez :

Pour importer le modèle dans Gazebo : roslaunch poppy_ergo_jr_gazebo load_ergo_model.launch. On peut “explorer” le modèle dans le menu à gauche. Pour mieux visualiser les articulations : View/Transparent View/Joints

Le modèle s’effondre car les moteurs ne sont pas simulés.

5. Chargement des contrôleurs de moteurs

Afin de rendre la simulation plus réaliste, nous allons lancer des contrôleurs de moteurs qui vont simuler le comportement de moteurs réels. Il existe plusieurs type de contrôleurs disponible dans Gazebo, nous allons tout d’abord expérimenter avec les contrôleurs en position les plus simples.

Clonez ce repertoire dans le dossier src, mettez vous sur la branche camera_integration de votre workspace et compilez le.

6. MoveIt

Dans le cas général, calculer les mouvements nécessaires pour atteindre un objectif sans collision est un problème compliqué (cf. robotique théorique). Cette tâche est effectuée par un planificateur, tel quel MoveIt qui intègre :

img

Pour installer moveit lancez: sudo apt install ros-noetic-moveit*

7. Démarrer MoveIt

Précédemment nous avons expérimenté avec les contrôleurs en position. MoveIt a besoin de contrôleurs légèrement différents (contrôleurs de trajectoire).

8. Créer un node python pour contrôler le robot

8.1. Créer un package ROS ros4pro

cd ~/catkin_ws/src
catkin_create_pkg ros4pro             # Cette commande créé le package
mkdir -p ros4pro/src                  # On créé un dossier src dans le package
touch ros4pro/src/manipulate.py       # On créé un noeud Python "manipulate.py"
chmod +x ros4pro/src/manipulate.py    # On rend ce noeud exécutable pour pouvoir le lancer avec rosrun

8.2. Éditer manipulate.py

#!/usr/bin/env python

import rospy
from moveit_commander.move_group import MoveGroupCommander
from geometry_msgs.msg import Pose
from math import radians, cos, sin
import tf_conversions as transform
rospy.init_node('ros4pro_node')
commander = MoveGroupCommander("arm")
current_pose = commander.get_current_pose().pose
commander.set_pose_target(pose) #envoie la pose au commander
plan = commander.go(wait=True) #éxécute le mouvement avec attente
commander.stop() #force l'arrêt du mouvement pour plus de sécurité
commander.clear_pose_targets() #force le nettoyage des objectifs du commander pour plus de sécurité

Remarque, la méthode commander.set_joint_value_target(pose) semble trouver des solutions plus facilement avec des obstacles. Pour nous aider on peut créer un quaternion à partir d’une rotation au format Roll/Pitch/Yaw avec :

q = transform.transformations.quaternion_from_euler(roll, pitch, yaw)

q retourné est une liste de 4 éléments contenant x, y, z, w roll, pitch, yaw sont des angles en radian (la fonction radians(angle) permet de convertir des degrés en radians)

8.3. Utiliser la pince

img

8.4. Ajouter des obstacles

scene = PlanningSceneInterface()
rospy.sleep(1) #petite attente nécessaire

ps = PoseStamped()
ps.header.frame_id = "base_link"

ps.pose.position.x = 0.0543519994715
ps.pose.position.y = -0.202844423521
ps.pose.position.z = 0.1
q = transform.transformations.quaternion_from_euler(0, 0, radians(15))
ps.pose.orientation.x = q[0]
ps.pose.orientation.y = q[1]
ps.pose.orientation.z = q[2]
ps.pose.orientation.w = q[3]
scene.add_box("obstacle", ps, (0.025, 0.1, 0.2)) #dimensions de la boite

On peut ensuite enlever l’obstacle avec :

scene.remove_world_object("obstacle")