Navigation autonome avec Nav2
À la page précédente, le robot savait comment il avait bougé (l’odométrie) mais pas
où il se trouvait : il lui manquait une frame map, la référence absolue. Lui donner
ce qui lui manque pour se déplacer vers un but dans un environnement qu’il découvre
se fait en deux temps, qui structurent cette page :
- Cartographier l’environnement pendant
qu’on s’y localise — le SLAM (
slam_toolbox) — puis sauvegarder la carte. - Naviguer dans cette carte : planifier et suivre des trajectoires en évitant les obstacles — la stack Nav2.
Le premier temps comble exactement le manque repéré à la page précédente : c’est le SLAM
qui (re)construit la frame map et y ancre le robot.
1 · Cartographier l’environnement
Section intitulée « 1 · Cartographier l’environnement »SLAM = Simultaneous Localization And Mapping. Le robot construit une carte de son
environnement en même temps qu’il s’y localise. Sur ROS 2, l’implémentation de
référence pour des bases 2D avec LiDAR est
slam_toolbox.
Entrées / sorties
Section intitulée « Entrées / sorties »slam_toolbox consomme et ce qu’il produit.Ce qu’il faut surtout retenir : slam_toolbox publie la transformation
map → odom, qui corrige la dérive de l’odométrie en recalant les scans laser.
On obtient enfin la chaîne complète map → odom → base_footprint.
Lancer le SLAM (tout-en-un)
Section intitulée « Lancer le SLAM (tout-en-un) »Un seul launch démarre Gazebo + SLAM + RViz (le scan apparaît en bleu) :
ros2 launch lekiwi_navigation slam.launch.py sim:=trueDans RViz, vous devez voir :
- l’
OccupancyGrid/mapapparaître au fur et à mesure ; - la silhouette du LeKiwi suivre la base ;
- les rayons laser en couleur.
Téléop pour cartographier
Section intitulée « Téléop pour cartographier »Lancez en plus la téléop clavier (cf. première page) et baladez le robot dans le monde :
ros2 run lekiwi_bringup teleop_azertyQuelques principes pour une bonne carte :
- Vitesses modérées (< 0,3 m/s) : les itérations SLAM ont le temps de fitter chaque scan.
- Boucle fermée : revenez régulièrement à un endroit déjà visité, ça aide l’algo à corriger la dérive (fermeture de boucle).
- Couverture complète : longez les murs pour qu’ils soient nets.
Sauvegarder la carte
Section intitulée « Sauvegarder la carte »Une fois satisfait, sauvegardez la carte dans un sous-dossier de maps/ (une carte =
un dossier map.yaml + map.pgm). map_saver_cli ne crée pas le dossier : créez-le
d’abord, puis sauvegardez :
# 1. créer le dossier de la cartemkdir -p ~/ros2_bootcamp_ws/src/lekiwi_ros2/lekiwi_navigation/maps/bootcamp
# 2. sauvegarder la carte dedansros2 run nav2_map_server map_saver_cli \ -f ~/ros2_bootcamp_ws/src/lekiwi_ros2/lekiwi_navigation/maps/bootcamp/mapCela produit deux fichiers dans maps/bootcamp/ :
map.yaml: métadonnées (origine, résolution, seuils) ;map.pgm: image grayscale de l’OccupancyGrid.
Vous pouvez les inspecter directement, hors ROS :
# métadonnées de la carte (origine, résolution, seuils)cat ~/ros2_bootcamp_ws/src/lekiwi_ros2/lekiwi_navigation/maps/bootcamp/map.yaml
# image de l'OccupancyGrid, dans une visionneuse d'imagesxdg-open ~/ros2_bootcamp_ws/src/lekiwi_ros2/lekiwi_navigation/maps/bootcamp/map.pgm# ... ou : eog map.pgm2 · Naviguer dans la carte
Section intitulée « 2 · Naviguer dans la carte »Nav2 est la stack de navigation de référence pour ROS 2 : planning global, suivi local, recovery, comportements, gestion des obstacles dynamiques.
Vue d’ensemble
Section intitulée « Vue d’ensemble »/cmd_vel : planification globale, suivi local et costmaps.Les briques importantes :
bt_navigator: orchestre l’ensemble via un behavior tree (planifier, suivre, recovery si échec…).- Planner : trajectoire globale point-à-point (Smac hybrid, NavFn…).
- Controller : suit le chemin localement en évitant les obstacles dynamiques (MPPI ici).
- Costmaps : représentations grille du monde (statique + locale) avec inflation autour
des obstacles, exprimées dans
base_footprint.
La pile complète tourne en 6 nœuds (controller, planner, behavior, bt_navigator,
velocity_smoother, collision_monitor) gérés par un lifecycle_manager.
Contrôleur pour base holonome
Section intitulée « Contrôleur pour base holonome »Une base omnidirectionnelle (kiwi) peut translater sans tourner. Tous les controllers Nav2 ne le savent pas :
| Controller | Holonome ? |
|---|---|
DWB | Oui, à activer via vy_samples > 0 dans la config |
MPPI | Oui, nativement (motion_model: Omni) |
Regulated Pure Pursuit | Non, suppose une base différentielle |
Sur LeKiwi, on utilise MPPI en motion_model: Omni : meilleur tracking et nativement
holonome. Sa sortie est publiée sur /cmd_vel_nav (puis arbitrée par twist_mux).
Lancement
Section intitulée « Lancement »Le launch tout-en-un empile la sim, la localisation sur la carte bootcamp et la pile
Nav2 complète, plus RViz, en une seule commande :
ros2 launch lekiwi_navigation navigation.launch.py slam_mode:=amcl map_name:=bootcampPremier goal au clic dans RViz
Section intitulée « Premier goal au clic dans RViz »Dans RViz :
- 2D Pose Estimate (bouton dans la toolbar) : cliquez la pose réelle du robot et orientez la flèche selon le cap. C’est la pose initiale du filtre de localisation.
- 2D Goal Pose : cliquez la destination. Nav2 planifie et exécute la trajectoire.
Vous pouvez suivre l’avancement via :
ros2 topic echo /behavior_server/behavior_tree_logEnvoyer un goal par le code
Section intitulée « Envoyer un goal par le code »Plutôt que de cliquer dans RViz, on peut envoyer un goal depuis Python via l’action
navigate_to_pose. Téléchargez le client de départ et recopiez-le dans un package :
- 📄
go_to.py— client Nav2 minimal (un seul goal, avec suivi de la distance restante).
Ce client est générique : déposez-le dans le package ROS 2 de votre choix
(<votre_package>) et déclarez son point d’entrée console_scripts dans le setup.py :
entry_points={ "console_scripts": [ "go_to = <votre_package>.go_to:main", ],},Puis, la navigation lancée, exécutez-le :
ros2 run <votre_package> go_toAdaptez les coordonnées du goal (GOAL_X, GOAL_Y en tête de fichier) à votre carte —
le monde bootcamp est une enceinte 8 × 8 m (origine au centre). Visez par exemple une
zone repère, p. ex. zone_a en (-3, 3) (cf. exercice final).
Recoveries
Section intitulée « Recoveries »Quand le robot est bloqué, Nav2 déclenche un comportement de recovery défini dans le
behavior tree : spin, back_up, wait, puis clear_costmap ou réessai. Les bases
holonomes peuvent utiliser drive_on_heading plutôt que back_up pour des manœuvres
latérales.
3 · Exercice final — le tour des 3 zones
Section intitulée « 3 · Exercice final — le tour des 3 zones »Objectif (capstone) : sur votre carte bootcamp (cartographiée et sauvegardée à la
section 1), faites visiter au robot les trois zones
repères du monde, dans l’ordre de votre choix, sans collision.
Le monde bootcamp est une pièce de 8 × 8 m (origine au centre, x et y de −4 à +4)
contenant trois zones colorées :
| Zone | Couleur | Position (x, y) | Emplacement |
|---|---|---|---|
zone_a | 🔴 rouge | (-3, 3) | coin haut-gauche |
zone_b | 🟢 vert | (3, 3) | coin haut-droite |
zone_c | 🔵 bleu | (0, -3) | bas, au centre |
Lancez la navigation en localisation sur votre carte :
ros2 launch lekiwi_navigation navigation.launch.py slam_mode:=amcl map_name:=bootcampTout se pilote par le code, sans aucun clic dans RViz — c’est la contrainte de l’exercice :
- Initialisez la pose en publiant une fois sur
/initialpose(geometry_msgs/PoseWithCovarianceStamped) au lieu du 2D Pose Estimate. - Choisissez votre ordre de visite (ex.
zone_a → zone_c → zone_b) et enchaînez les trois poses automatiquement —- soit en adaptant
go_to.pypour boucler sur une liste de goals ; - soit via l’action
/follow_waypoints(waypoint_follower) : publiez les troisPoseStamped(l’orientationyawfinale est libre) et le robot les visite dans l’ordre, avec une pause à chaque zone.
- soit en adaptant
Bonus : émettez un message ROS personnalisé à chaque zone atteinte (préparation aux Jours 5-6 — intégration).
Aller plus loin
Section intitulée « Aller plus loin »Une fois la mission réussie, voici quelques pistes optionnelles pour approfondir.
Tuner le controller MPPI
Section intitulée « Tuner le controller MPPI »Objectif : observer l’effet de quelques paramètres clés du controller sur le
comportement du robot. Le fichier lekiwi_navigation/config/nav2/nav2.yaml contient
toutes les options.
Jouez avec, un par un :
vx_max,vy_max,wz_max(vitesses max —vy_maxnon nul = holonome) ;time_steps×model_dt(horizon de prédiction) ;critic_names: ajoutez / retirezObstaclesCritic,GoalAngleCritic;inflation_radiusdu global costmap (marge gardée autour des murs).
Pour chaque changement, relancez le même goal et notez : le temps total, la distance parcourue, le « confort » de la trajectoire (saccadée vs lisse).
Obstacle dynamique
Section intitulée « Obstacle dynamique »Objectif : ajouter un cube dans Gazebo pendant que le robot navigue, et vérifier que Nav2 le contourne.
Indices :
- Ajoutez manuellement un cube dans Gazebo Ionic (gz-sim 9) pendant la sim (ou via un
service
createdu monde). - Le
local_costmapdoit s’allumer autour de l’objet quand le LiDAR le voit. - Le controller MPPI doit replanifier localement.
Que se passe-t-il si vous placez l’objet exactement dans la trajectoire ? Combien de temps avant qu’il réagisse ?
Monitorer la navigation avec Foxglove
Section intitulée « Monitorer la navigation avec Foxglove »Objectif : inspecter en direct ce que produit la pile de navigation avec Foxglove, en complément de RViz.
Étapes :
-
Lancer la navigation (
navigation.launch.py) puis le pont Foxglove dans un autre terminal :Fenêtre de terminal ros2 launch foxglove_bridge foxglove_bridge_launch.xml # ws://localhost:8765 -
Se connecter à
ws://localhost:8765dans Foxglove et préparer un panneau 3D. Dans ses réglages, fixez Fixed frame =odom(oumap), puis activez les topics dans la section Topics :/scan(sensor_msgs/LaserScan) — ce que « voit » le robot : les rayons du LiDAR se dessinent autour de lui et épousent les murs/obstacles. Ajustez taille et couleur des points dans les réglages du topic ;/map(nav_msgs/OccupancyGrid) — la carte du SLAM, qui se remplit au fil du déplacement (n’apparaît que SLAM lancé) ;- les costmaps global et local pour voir l’inflation autour des obstacles.
-
Ajoutez en plus :
- un panneau Plot sur les composantes de
/cmd_vel; - un panneau Raw Messages sur
/odompour relever une valeur de pose.
- un panneau Plot sur les composantes de
-
Poser un 2D Goal Pose dans RViz et observer, côté Foxglove : le
/scanqui balaie, la trajectoire suivie, le local costmap qui s’allume autour des obstacles, et la courbe/cmd_vel.
Prochaine étape
Section intitulée « Prochaine étape »Retour au sommaire J2, ou enchaînez sur Jour 3 — Manipulation.
Cours conçu et animé par Etienne Schmitz