Environnement Docker ==================== **S'applique à :** :bdg-info-line:`Simulation` :bdg-warning-line:`Robot réel` Le RatBot est développé sous ROS 2 Humble (Ubuntu 22.04). Si vous disposez déjà de cet environnement, vous pouvez travailler directement sur votre machine et ignorer cette page. Dans les autres cas, le dépôt fournit une image Docker contenant ROS 2, la simulation, les piles de cartographie et de navigation, et les outils de mise au point. Elle assure un environnement reproductible sans installation sur le système hôte, et sert aussi bien à la **simulation** qu'au **pilotage des robots réels** depuis le PC. .. note:: L'environnement est testé **sous Linux**. Docker existe aussi sous Windows et peut y être utilisé, mais cet usage n'a pas été testé. Prérequis --------- **Docker Engine** avec le plugin **Docker Compose** (commande ``docker compose``) : https://docs.docker.com/engine/install/ Votre compte doit appartenir au groupe ``docker``, sans quoi chaque commande exige ``sudo``. Une fois, puis fermer et rouvrir la session : .. code-block:: bash sudo usermod -aG docker $USER Avec une **carte graphique NVIDIA**, installer aussi, avant le premier démarrage, le ``nvidia-container-toolkit`` (voir **Accès GPU**, plus bas) : le ``compose.yaml`` réserve le GPU, et sans ce paquet ``docker compose run`` échoue. Cloner le dépôt du RatBot, puis se placer à sa racine, où se trouvent ``Dockerfile`` et ``compose.yaml`` : .. code-block:: bash git clone ratbot_ws cd ratbot_ws Construire l'image ------------------ Depuis la racine du dépôt, une fois : .. code-block:: bash docker compose build La construction télécharge ROS 2 et les outils du ``Dockerfile`` : elle dure plusieurs minutes et demande un accès à Internet. L'image obtenue, ``ratbot-dev``, sert ensuite à chaque démarrage. Elle n'est à reconstruire, par la même commande, que si le ``Dockerfile`` change. Démarrage --------- Autoriser l'accès au serveur graphique, une fois par session de l'hôte : .. code-block:: bash xhost +local:docker ``xhost`` confirme par ``non-network local connections being added to access control list`` : les programmes de la machine, conteneur compris, peuvent ouvrir des fenêtres. L'autorisation dure jusqu'à la fin de la session ; ``xhost -local:`` la retire plus tôt. Ouvrir un shell dans le conteneur : .. code-block:: bash docker compose run --rm ratbot ``--rm`` supprime le conteneur à la sortie, non l'image. Le **dépôt entier** est monté depuis l'hôte, dans ``/workspace`` : code, artefacts de compilation et cartes y sont conservés, et la commande ``./scripts/ratbot`` y est disponible. Le conteneur s'ouvre **dans** ``screen`` (voir **Terminaux multiples**, plus bas), à la racine du dépôt, ``/workspace`` : ``./scripts/ratbot`` s'y lance tel quel. L'historique du shell est également persistant, via un volume nommé. .. warning:: **Seul** ``/workspace`` est conservé. Un fichier écrit ailleurs — dans ``~``, c'est-à-dire ``/root`` — disparaît à la sortie du conteneur. Les paquets installés manuellement dans un conteneur (``apt install``) sont en revanche perdus à la sortie ; les ajouter au ``Dockerfile`` pour les rendre permanents. Compilation ----------- Depuis le shell du conteneur : .. code-block:: bash ./scripts/ratbot build source ros2_ws/install/setup.bash À la première compilation, ``ratbot build`` récupère aussi les paquets externes que le workspace compile à partir de leurs sources (exploration autonome, pont avec la carte du robot ; voir :doc:`paquets`) : elle demande un accès à Internet. Les suivantes se contentent de recompiler. Chaque shell du conteneur source automatiquement ROS 2 et le workspace ; le ``source`` explicite n'est nécessaire qu'après une compilation. Le conteneur exécute le code de ``ros2_ws/`` tel qu'il est sur l'hôte : après un ``git pull``, il suffit de recompiler dans le conteneur, l'image n'est à reconstruire (``docker compose build``) que si le ``Dockerfile`` change. Une compilation faite sur le PC ne fonctionne pas dans le conteneur, et inversement. Les deux restent donc séparées : dans le conteneur, les dossiers ``build/``, ``install/`` et ``log/`` sont en réalité ceux du PC nommés ``build_docker/``, ``install_docker/`` et ``log_docker/``. On peut compiler des deux côtés et passer de l'un à l'autre sans rien effacer. Simulation ou robot réel : le domaine ROS ----------------------------------------- Les machines ROS 2 ne se voient que si elles partagent le même **domaine**, un numéro fixé par la variable ``ROS_DOMAIN_ID``. Les robots utilisent le domaine **77**. Le conteneur est réglé sur ce domaine (``ROS_DOMAIN_ID=77``, dans ``compose.yaml``) : il voit les robots allumés sans autre réglage, comme une installation native. .. code-block:: bash ros2 topic list # les topics /ratbot_N/... des robots allumés Une simulation lancée dans ce domaine pendant que des robots réels sont allumés s'y mélangerait : robots simulés et réels porteraient les mêmes noms. ``./scripts/ratbot up`` le vérifie avant de démarrer et refuse dans ce cas (voir :doc:`simulation`). Pour simuler pendant que des robots tournent, choisir un autre domaine, **dans chaque terminal** de la simulation : .. code-block:: bash export ROS_DOMAIN_ID=0 Piloter un robot réel depuis le conteneur ----------------------------------------- Le conteneur partage le réseau du PC : il voit les robots allumés sur le même réseau, comme une installation native. La manette, branchée **avant** le démarrage du conteneur, y est accessible. Toutes les commandes de :doc:`commande_ratbot` s'utilisent depuis la racine du dépôt : .. code-block:: bash ./scripts/ratbot slam 1 # cartographie du robot 1 ./scripts/ratbot map save 1 salon # dans les cartes du dépôt ./scripts/ratbot nav 1 salon Une carte désignée par son seul nom est rangée **dans le dépôt**, sous ``/workspace`` : elle est conservée sur le PC, alors qu'une carte écrite dans ``~/cartes`` serait perdue à la sortie du conteneur. Terminaux multiples ------------------- La plupart des nœuds ROS restent au premier plan, ce qui impose plusieurs terminaux. Le conteneur s'ouvre donc dans ``screen``, qui en gère plusieurs dans la même fenêtre. Ses commandes sont préfixées par **Ctrl-a** : .. list-table:: :header-rows: 1 :widths: 34 66 * - Après ``Ctrl-a`` - Action * - ``c`` - Nouvelle fenêtre * - ``n`` / ``p`` - Fenêtre suivante / précédente * - ``0``, ``1``, ``2``… - Accès direct à une fenêtre * - ``|`` puis ``Tab`` - Partage vertical de l'écran, changement de zone * - ``d`` - Détachement : retour à un shell simple, ``screen -r`` pour reprendre La barre d'état affiche les fenêtres ouvertes et la fenêtre courante. Fermer la dernière fenêtre (``exit``) quitte le conteneur. On peut aussi ouvrir un shell supplémentaire dans le conteneur en cours, depuis un autre terminal de l'hôte : .. code-block:: bash docker exec -it $(docker ps -qf name=ratbot) bash Cette commande suppose un seul conteneur RatBot en cours. S'il y en a plusieurs, ``docker ps`` les liste : passer à ``docker exec -it`` l'identifiant de celui qui convient. Outils de mise au point ----------------------- L'image inclut : - ``rqt_robot_monitor`` — visualisation de ``/diagnostics`` ; - ``ros2 run tf2_tools view_frames`` — génération de l'arbre TF ; - ``plotjuggler`` — tracé temporel de topics (vitesses, batterie, cap) ; - ``ros2 bag`` — enregistrement et rejeu des topics ; - utilitaires système : ``nano``, ``htop``, ``tree``, ``ping``, ``ip``. Accès GPU --------- La simulation requiert un accès à la carte graphique : Gazebo (moteur *ogre2*) exige OpenGL 3.3 et le lidar simulé (``gpu_lidar``) est calculé par le GPU. Deux symptômes en cas d'accès manquant : - échec au démarrage de Gazebo (*OGRE EXCEPTION: OpenGL 3.3 is not supported*, éventuellement suivi d'une erreur de segmentation) ; - ou fonctionnement apparent mais lidar en retard : le repli logiciel est trop lent, les balayages sont horodatés en deçà de ``/clock`` et ne peuvent plus être appariés à une pose. Le SLAM échoue alors sans message explicite (« Failed to compute odom pose », « No map received »). .. note:: Pour une carte NVIDIA, ``--device /dev/dri`` est insuffisant : les bibliothèques NVIDIA doivent être présentes dans le conteneur, ce que fournit le ``nvidia-container-toolkit``. Prérequis : pilote NVIDIA fonctionnel sur l'hôte (``nvidia-smi``). Installation du toolkit, sur l'hôte, une fois : .. code-block:: bash sudo apt-get install -y --no-install-recommends ca-certificates curl gnupg curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \ | sudo gpg --dearmor --yes -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg curl -sL https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \ | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \ | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi Le ``compose.yaml`` réserve déjà le GPU et fixe ``NVIDIA_DRIVER_CAPABILITIES=all`` — la valeur par défaut ``utility,compute`` n'expose pas OpenGL. .. tip:: Sans GPU NVIDIA, le rendu logiciel (Mesa/llvmpipe) permet de dépanner mais reste insuffisant pour le SLAM. Les avertissements ``libEGL warning`` isolés sont sans conséquence si le reste fonctionne. Divers ------ La distribution ROS 2 est paramétrée par ``ROS_DISTRO`` (``humble`` par défaut), modifiable dans ``compose.yaml`` ; reconstruire ensuite l'image (``docker compose build``). Suppression complète, image comprise (le code, monté depuis l'hôte, n'est pas affecté) : .. code-block:: bash docker compose down --rmi all Une manette de jeu doit être connectée avant le démarrage du conteneur pour être visible (:doc:`simulation`).