Aller au contenu

La base mobile LeKiwi

La base LeKiwi est une plateforme open-source à 3 roues omnidirectionnelles réparties à 120°. Cette configuration en fait une base holonome : elle peut se déplacer dans n’importe quelle direction sans avoir à se réorienter au préalable.

Dans cette partie, vous découvrez le robot, vous le lancez en simulation pour inspecter son graphe ROS 2 et comprendre qui parle à qui (et comment il transforme une consigne de vitesse en rotation de roues), puis vous le téléopérez pour valider sa cinématique.

Base LeKiwi vue de dessus : left_wheel à 60°, right_wheel à 300°, back_wheel à 180°, LiDAR au centre, avant vers le haut (axe +X).

Les trois roues sont identiques, montées sur des moteurs indépendants et réparties à 120° autour du châssis :

  • left_wheel à 60° (avant-gauche) ;
  • right_wheel à 300° (avant-droit) ;
  • back_wheel à 180° (arrière).

Chaque roue est omnidirectionnelle (roue + galets latéraux) : elle n’entraîne le sol que dans son axe principal et glisse librement latéralement. C’est la combinaison des trois qui produit un mouvement holonome — la base translate dans n’importe quelle direction sans avoir à se réorienter.

Au centre, un LiDAR 360° (laser_link) balaie l’environnement — c’est lui qui rendra la cartographie possible. La pose est estimée à partir de l’odométrie des roues (affinée, en simulation, par une IMU ; sur un robot réel sans IMU, les roues seules suffisent et le SLAM corrige la dérive).

Avant la sim physique, on peut afficher le modèle seul (URDF + RViz) :

Fenêtre de terminal
ros2 launch lekiwi_description display.launch.py

Cela démarre robot_state_publisher + RViz avec une config qui charge le modèle ; vous pouvez agiter les roues avec le joint_state_publisher_gui.

RViz reste notre outil d’interaction 3D, mais pour inspecter ce qui circule sur le graphe — voir le robot et lire les valeurs brutes des topics — Foxglove est plus confortable (interface web, panneaux Raw Messages et Plot, pas de GPU requis).

Gardez display.launch.py lancé et démarrez le pont dans un autre terminal :

Fenêtre de terminal
ros2 launch foxglove_bridge foxglove_bridge_launch.xml # ws://localhost:8765

Dans l’application Foxglove (cf. Installation), connectez-vous à ws://localhost:8765, puis ajoutez deux panneaux :

  • un panneau 3D : pour voir le maillage du robot (et pas seulement les repères), ajoutez une couche URDF via Custom layers → + → URDF. Réglez Source = Parameter et Parameter = robot_description (la source Topic refuse /robot_description, qui est un std_msgs/String). La base suit ensuite la tf en direct ;
  • un panneau Raw Messages abonné à /joint_states : vous y lisez en direct la valeur de chaque articulation.
Fenêtre de terminal
ros2 launch lekiwi_bringup sim_base.launch.py

Ce launch ouvre Gazebo Ionic sur le monde bootcamp.sdf (une enceinte 8 × 8 m avec plusieurs obstacles et trois zones repères colorées), spawn la base LeKiwi et démarre toute la chaîne logicielle : robot_state_publisher, le pont ros_gz (/clock, /scan, /imu/data), les contrôleurs ros2_control, twist_mux et l’EKF.

Le robot tourne : avant de le piloter, inspectez son graphe ROS 2 pour comprendre qui parle à qui. Dans un nouveau terminal, lancez vous-même la visualisation :

Fenêtre de terminal
ros2 run rqt_graph rqt_graph

Activez l’affichage des topics (cochez Nodes/Topics) : vous devez retrouver les nœuds ros_gz, twist_mux, controller_manager et ekf_filter_node reliés par leurs topics.

En reliant les réponses ci-dessus, vous reconstituez la chaîne des commandes de vitesse — du clavier (ou de Nav2) jusqu’aux roues :

Chaîne des commandes de vitesse : téléop AZERTY (prioritaire) → /cmd_vel_teleop et Nav2 → /cmd_vel_nav sont arbitrés par twist_mux → /cmd_vel → omni_wheel_drive_controller, qui pilote les 3 roues et publie /odom.
Du clavier (ou de Nav2) jusqu’aux roues, en passant par twist_mux et omni_wheel_drive_controller.

twist_mux arbitre les sources (la téléop est prioritaire sur Nav2) et tous ces topics sont en geometry_msgs/TwistStamped — c’est pourquoi le téléop AZERTY publie directement des TwistStamped sur /cmd_vel_teleop.

Le dernier maillon, omni_wheel_drive_controller, est un plugin ros2_control (chargé par le controller_manager). C’est lui — et pas un nœud maison — qui transforme une consigne (vx, vy, ω) en vitesse pour chacune des trois roues. Pour une roue i située à l’angle θᵢ du centre :

vi=sin(θi)vx+cos(θi)vy+Lωv_i = -\sin(\theta_i)\, v_x + \cos(\theta_i)\, v_y + L\, \omega

avec L = rayon entre le centre du robot et chaque roue (≈ 0,13 m sur le LeKiwi). C’est cette cinématique inverse qui, en combinant les trois roues, produit le mouvement holonome. En retour, le contrôleur publie l’odométrie /odom (intégration des vitesses de roues), que l’EKF fusionnera avec l’IMU.

Architecture ros2_control de la base : /cmd_vel entre dans le controller_manager (omni_wheel_drive_controller + joint_state_broadcaster), qui écrit les consignes via les command_interfaces vers le hardware interface (gz_ros2_control en sim, driver moteurs en réel) et lit l'état via les state_interfaces ; le hardware interface pilote le robot et le contrôleur publie /odom, le broadcaster /joint_states.
L’architecture ros2_control de la base : la même pile en simulation et sur le robot réel — seul le hardware interface change.

Pour valider la cinématique, pilotez la base au clavier avec le téléop AZERTY fourni par le bootcamp : il publie directement des TwistStamped sur /cmd_vel_teleop — aucun remap ni option à ajouter.

Fenêtre de terminal
ros2 launch lekiwi_bringup sim_base.launch.py

Touches (clavier AZERTY) :

  • z / s : avancer / reculer
  • q / d : translation latérale gauche / droite (la magie d’une base holonome)
  • a / e : rotation gauche / droite
  • espace : arrêt
  • + / - : vitesse linéaire ; * / : : vitesse angulaire

Si la base se déplace latéralement sans changer de cap, la cinématique est correcte. ✅

Pendant que vous pilotez, regardez les données circuler :

Fenêtre de terminal
ros2 topic echo /cmd_vel_teleop # vos consignes (TwistStamped)
ros2 topic echo /odometry/filtered # la pose estimée par l'EKF
ros2 run tf2_tools view_frames # arbre des frames -> frames.pdf

Dans frames.pdf, vous obtenez la chaîne odom → base_footprint → base_link → roues / laser_link. Il n’y a pas encore de frame map : sans SLAM, le robot sait comment il a bougé (odométrie) mais pas où il est dans une carte. C’est précisément ce qu’on ajoute à la page suivante.

Navigation autonome avec Nav2 — cartographier puis naviguer.

Cours conçu et animé par Etienne Schmitz