Cette documentation explique comment créer une carte à partir d'un robot pour l'intégrer ensuite dans une interface Web et afficher la localisation du robot. Ce travail se base sur cet article : Voir l'article
Vidéo de démonstration de la solution : Voir la vidéo YouTube
Tous ces packages peuvent être installés en utilisant la commande :
sudo apt-get install ros-<ros_distribution>-<ros_package>
La liste des packages disponibles sur une distribution ROS peut être affichée comme ceci :
apt-cache search ros-<ros_distribution>
Pour Pepper, il faut utiliser ROS Kinetic (installable sur Ubuntu 16.04).
Pour RB-1, il faut utiliser ROS Indigo (installable sur Ubuntu 14.04).
Un “bag” dans ROS permet d'enregistrer et de rejouer à volonté les topics publiés par un robot pendant le temps d'enregistrement (voir les commandes disponibles).
On lance ROS si ce n'est pas déjà fait :
roscore
On se connecte au robot. Pour Pepper :
roslaunch pepper_bringup pepper_full_py.launch nao_ip:=<ip_de_pepper> roscore_ip:=127.0.0.1
Pour RB1 (il faut au préalable être connecté au WiFi du robot) :
export ROS_MASTER_URI=http://rb1:11311
On lance l'enregistrement des topics fournis par le robot :
NB : l'option “-a” permet d'enregistrer tous les topics mais si on souhaite uniquement quelques topics, c'est également possible et cela permet d'alléger le bag.
rosbag record -O </chemin/et/nomDuBag>.bag -a rosbag record -O </chemin/et/nomDuBag>.bag /<topic_1> /<topic_2>
On fait maintenant se déplacer le robot comme on le souhaite. On arrête ensuite l'enregistrement avec CTRL
+ C
.
On peut inspecter le contenu du rosbag avec la commande :
rosbag info <nom_du_rosbag>.bag
On lance ROS si ce n'est pas déjà fait :
roscore
Si on utilise un rosbag, on indique à ROS d'utiliser le temps de la simulation :
NB : il faut impérativement lancer cette commande avant de lancer tous les nodes.
rosparam set use_sim_time true
On génère ensuite une carte à l'aide de slam_gmapping. Il faut passer en argument le topic du robot correspondant au type sensor_msgs/LaserScan (i.e. les lasers du robot). Par défaut, les cartes générées sont trop “dé-zoomées”, il faut donc jouer sur la résolution (paramètre delta) et éventuellement sur les dimensions.
Par exemple, pour RB1, la commande suivante génère une carte exploitable :
rosrun gmapping slam_gmapping scan:=/front_laser/scan _xmin:=-1 _xmax:=1 _ymin:=-1 _ymax:=1 _delta:=0.035 _maxUrange:=10
On rejoue le bag :
rosbag play --clock <nom_du_bag>.bag
Avant d'annuler le gmapping, on enregistre la carte :
rosrun map_server map_saver -f <map_name>
Exemple de carte obtenue avec les lasers de RB-1 :
Les traits que l'on voit sont des aberrations dues aux lasers, on peut réduire leur impact en jouant sur les paramètres lors de la génération de la carte (paramètre Urange).
Les lasers de Pepper n'étant pas assez puissants, on ne peut pas utiliser son topic sensor_msgs/LaserScan. Il faut donc générer la carte à partir de la caméra 3D, ce qui demande plusieurs transformations des données récupérées. On lance un nodelet manager :
rosrun nodelet nodelet manager __name:=nodelet_manager
On lance notre nodelet depth_image_proc/convert_metric pour convertir au bon format :
Erreur bloquante ici, à revoir.
rosrun nodelet nodelet load depth_image_proc/convert_metric nodelet_manager image_raw:=/pepper_robot/camera/depth/camera/image_raw
On lance image_proc qui retire la distorsion des images :
rosrun image_proc image_proc image_raw:=image camera_info:=/pepper_robot/camera/depth/camera/camera_info
On lance notre nodelet depth_image_proc/point_cloud_xyz pour faire un nuage de points à partir de l'image raw de la caméra :
rosrun nodelet nodelet load depth_image_proc/point_cloud_xyz nodelet_manager image_rect:=/image_rect camera_info:=/camera/depth/camera/camera_info
On lance le package pointcloud_to_laserscan qui génère un sensor_msgs/LaserScan à partir du nuage de points :
rosrun pointcloud_to_laserscan pointcloud_to_laserscan_node cloud_in:=/points
Puis on génère la carte comme vu dans la partie 3.
Le principe est le suivant : rosbridge_server publie un WebSocket contenant les informations des topics au format JSON. roslibjs vient ensuite souscrire aux topics et permet la récupération des données dans une page Web (voir le tutoriel roslibjs). Enfin, ros2djs permet l’affichage d’un élément de type nav_msgs/OccupancyGrid (le format ROS des cartes) dans l’interface (voir le tutoriel ros2djs).
Pour cela, on publie un topic de map à partir du fichier de map enregistré.
NB : il faut bien utiliser le fichier .yaml et non le fichier .pgm de la carte.
rosrun map_server map_server <yaml_file>.yaml
On lance le WebSocket :
roslaunch rosbridge_server rosbridge_websocket.launch
Voici le code HTML de la page que nous avons utilisé. Attention à bien avoir les fichiers des librairies css et javascript positionnées au bon endroit.
Pour la localisation du robot, on utilise le package amcl.
Si ce n'est pas déjà fait, on publie la carte :
rosrun map_server map_server <yaml_file>.yaml
On lance la lecture du bag :
rosbag play --clock <nom_du_bag>.bag
On lance la détection AMCL à partir des lasers (pour RB1, /front_laser/scan)
rosrun amcl amcl scan:=<nom_du_topic_laser_scan>
La page Web s'abonne au topic de positionnement et affiche dynamiquement la position du robot sur la carte.