Travailler à plusieurs robots ============================= **S'applique à :** :bdg-info-line:`Simulation` :bdg-warning-line:`Robot réel` Le RatBot est conçu pour le travail en flotte : plusieurs robots partagent le même réseau, sont pilotés depuis le même PC, et s'arrêtent ensemble. Un robot seul n'en est pas affecté : tout ce qui suit est sans effet tant qu'il n'y en a qu'un. Un numéro par robot ------------------- Chaque robot porte un **numéro**, de **1 à 19**. Ce numéro préfixe tout ce qui le concerne : .. list-table:: :header-rows: 1 :widths: 34 33 33 * - - robot 1 - robot 2 * - topics - ``/ratbot_1/scan`` - ``/ratbot_2/scan`` * - repères de position - ``ratbot_1/base_link`` - ``ratbot_2/base_link`` * - nom du Raspberry Pi - ``ratbot-1`` - ``ratbot-2`` * - adresse réseau - ``192.168.1.171`` - ``192.168.1.172`` Les topics de deux robots ne se mélangent donc jamais. Ce qui est commun à tout le parc vit sous ``/ratbot_fleet/``. La limite de 19 vient des **adresses réseau** : le robot ``N`` reçoit l'adresse ``192.168.1.(170 + N)``, soit ``.171`` à ``.189``. Au-delà, le robot 20 prendrait l'adresse du serveur de temps du labo (``.190``). .. tab-set:: :sync-group: env .. tab-item:: Simulation :sync: sim Le nombre de robots se donne au lancement, jusqu'à 4 ; chaque décor déclare où les poser : .. code-block:: bash ./scripts/ratbot up hampton_simple 4 Pour en ajouter un pendant que la simulation tourne, lui donner un numéro encore libre et une position dans le décor. Par exemple, après ``./scripts/ratbot up rooms 1``, le robot 2 à sa place de départ : .. code-block:: bash ros2 launch ratbot_gazebo spawn_robot.launch.py robot_id:=2 x:=0.6 y:=0.0 Voir :doc:`simulation` pour les décors et leurs places de départ. .. tab-item:: Robot réel :sync: reel Le numéro est attribué à la mise en service : au Raspberry Pi par sa fiche d'identité, à la carte du robot par un réglage (voir :doc:`nouveau_robot`). .. danger:: Une carte neuve se présente comme **le robot 1**. Tant qu'elle n'a pas reçu son numéro, elle se confond avec le vrai robot 1 : renumérotez-la, robot 1 éteint, avant de les allumer ensemble. Le parc et son état ------------------- Le parc est décrit dans un seul fichier, ``deploy/fleet.yaml``. On y trouve : - les robots qui existent ; - leur état : **en service**, **en montage**, **en réparation** ou **retiré** ; - leur matériel : lidar et son montage, capteur de distance, batterie, bras ; - les machines qui ne sont pas des robots, le PC de navigation par exemple. Le fichier ne contient pas ce qui découle du numéro (nom, adresse, topics) ni les réglages de la carte, qui restent dans la carte. La date des calibrations n'y est pas non plus : elle est lue dans le cahier de labo, là où ``ratbot-calibrate`` l'écrit. Les commandes, lancées sur le PC : .. code-block:: bash ./scripts/ratbot fleet show # le parc, après vérification du fichier ./scripts/ratbot fleet status # l'état de chaque robot en service ./scripts/ratbot fleet # la même chose que fleet status ./scripts/ratbot fleet battery # la batterie de chaque robot ./scripts/ratbot fleet time # les horloges : PC, Raspberry Pi, cartes ./scripts/ratbot fleet diag # les diagnostics qui ne sont pas OK ./scripts/ratbot fleet who # qui roule, qui navigue, depuis où ./scripts/ratbot fleet identify 2 # le robot 2 clignote en blanc et bipe Toutes ne font que **lire** : elles ne redémarrent rien et ne modifient rien, ni sur le PC ni sur les robots. Seule ``identify`` agit, sur le voyant et le buzzer, et jamais sur les roues. Ce qu'il faut avant ~~~~~~~~~~~~~~~~~~~ ``fleet status`` se connecte à chaque robot par SSH **sans mot de passe**. La clé du PC doit donc être installée une fois sur chaque Raspberry Pi : .. code-block:: bash ssh-copy-id ratbot@192.168.1.171 # une fois par robot ssh ratbot@192.168.1.171 true # une connexion à la main, pour # accepter l'empreinte du robot Lire le résultat ~~~~~~~~~~~~~~~~ Par exemple : .. code-block:: text parc : domaine 77, ROS humble, heure 192.168.1.190 robot etat reseau service depot horloge batterie calibration ratbot-1 in_service oui active daad056 +3 ms 11.82 V 64 % umbmark 2026-10-04, gyro 2026-10-04, lidar 2026-10-16 ratbot-2 assembly - - - - - umbmark -, gyro -, lidar - Une ligne par robot : .. list-table:: :header-rows: 1 :widths: 22 78 * - colonne - signification * - reseau - le robot répond-il sur son adresse ? ``-`` : il n'est pas en service, on ne l'a pas interrogé * - service - l'état du service du robot ; ``active`` s'il tourne * - depot - la version du logiciel sur le robot (les 7 premiers caractères du commit) * - horloge - l'écart de son horloge à celle de **ce PC**, mesuré directement ; ``+`` s'il est en avance. Au-delà de 0,1 s, une alerte : la navigation en souffre (voir « fleet time » plus bas) * - batterie - tension et charge, lues sur le topic ``sensors/battery`` du robot * - calibration - la date de la dernière calibration **appliquée** de l'odométrie (``umbmark``) et du gyroscope, et du dernier contrôle du lidar Le programme rend le code **1** dès qu'un robot en service a une alerte, et **0** sinon. Un script peut donc s'en servir pour refuser de continuer. Les alertes ~~~~~~~~~~~ Sous un robot, une ligne marquée ``/!\`` signale un problème. Une ligne marquée ``.`` est une simple information. .. list-table:: :header-rows: 1 :widths: 42 58 * - message - que faire * - ``192.168.1.17N ne repond pas`` - le robot est éteint, n'a pas fini de démarrer (une minute environ), ou n'est pas sur le réseau du labo * - ``SSH : empreinte du robot inconnue`` - se connecter une fois à la main (``ssh ratbot@…``) et accepter l'empreinte * - ``SSH : empreinte du robot changee`` - le Raspberry Pi a été réinstallé : ``ssh-keygen -R 192.168.1.17N``, puis se reconnecter une fois à la main * - ``SSH : cle refusee`` - installer la clé du PC : ``ssh-copy-id ratbot@192.168.1.17N`` * - ``ratbot.service : inactive`` (ou ``failed``) - le logiciel du robot ne tourne pas : voir :doc:`depannage` * - ``horloge non synchronisee`` - le robot n'a pas joint le serveur de temps : voir :doc:`heure` * - ``pas de mesure de batterie`` - le robot répond, mais pas sa carte : carte éteinte, liaison avec le Raspberry Pi coupée, ou robot sur un autre domaine ROS * - ``umbmark : jamais appliquee`` (ou ``gyro``) - la calibration n'a jamais été écrite dans la carte : voir :doc:`calibration` et :doc:`gyroscope` * - ``lidar : jamais controle`` - le montage du lidar n'a jamais été vérifié : voir :doc:`lidar` * - ``… avant l'intervention du … : a refaire`` - une intervention notée dans le fichier est postérieure à la calibration : la refaire * - ``date « applied » illisible dans …`` - corriger la date dans le ``campagne.yaml`` cité (forme ``AAAA-MM-JJ``) * - ``. depot a …, cette machine a …`` - le robot n'a pas la même version que le PC. Ce n'est pas forcément une erreur, mais à vérifier avant un essai * - ``. campagne … non appliquee`` - une mesure plus récente que la calibration n'a pas été écrite dans la carte. C'est normal pour une mesure de vérification. Les robots en montage, en réparation ou retirés sont listés sans être interrogés : aucune alerte n'est donnée pour eux. Batterie, heure, diagnostics, activité ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ces commandes interrogent tous les robots en service en même temps, en trois secondes environ. Comme ``status``, elles rendent le code **1** dès qu'un robot a une alerte. **fleet battery** donne, pour chaque robot, la tension, la charge et la tension par élément, avec la batterie déclarée dans le fichier : .. code-block:: text robot tension charge par elem. batterie ratbot-1 11.82 V 64 % 3.94 V lipo_3s 5200 mAh Elle alerte sous 20 % de charge, comme le voyant, et sous **3,5 V par élément** : en dessous, une LiPo s'abîme. Il faut alors la recharger. **fleet time** compare les horloges. L'écart de chaque Raspberry Pi est **mesuré directement** depuis le PC, avec son incertitude. On ne lit pas seulement chrony, car un robot qui ne joint plus le serveur peut se dire encore synchronisé. La dernière colonne donne l'écart de la RTC de la carte à son Raspberry Pi : .. code-block:: text serveur de temps 192.168.1.190 ; ecarts a cette machine (lea) machine ecart ici au serveur RTC carte / Pi lea (reference) +1 ms ok - ratbot-1 +4 ms ±3 ms -1 ms ok +0.3 s Un écart de plus de **0,1 s** entre le PC et un robot est signalé : la navigation en souffre, car les positions et les mesures ne sont plus datées de la même façon. L'écart de la RTC n'est signalé qu'au-delà de 2 s, car elle ne sert qu'à dater le journal. La colonne ``au serveur`` vaut ``NON`` quand la machine n'est pas synchronisée. Le plus souvent, le serveur de temps n'est pas démarré : voir :doc:`heure`. **fleet diag** écoute ``/diagnostics`` et ne montre que les blocs qui ne sont **pas OK** (avertissement, erreur, périmé), rangés par robot : .. code-block:: text ratbot-1 22 blocs, 1 pas OK WARN ratbot_1: clock : RTC never set sans robot : 3 blocs, tous OK La signification de chaque bloc est dans :doc:`diagnostics`. Les blocs « sans robot » viennent de programmes qui ne disent pas de quel robot ils sont (le multiplexeur de commandes, le filtre de localisation). **fleet who** dit ce qui tourne pour chaque robot, et sur quelle machine : avant une mise à jour ou un essai, on sait ainsi si quelqu'un d'autre s'en sert. .. code-block:: text ratbot-1 ROULE Nav2 bt_navigator ici (lea) localisation (AMCL) amcl ici (lea) commande (cmd_vel_nav) /ratbot_1/controller_server ici (lea) commande (cmd_vel_teleop) /ratbot_fleet/teleop_ratbot_1 une autre machine Les commandes listées sont les programmes qui envoient des vitesses au robot. « Une autre machine » veut dire que le programme est vu sur le réseau, mais ni sur ce PC ni sur le Raspberry Pi du robot. Reconnaître un robot ~~~~~~~~~~~~~~~~~~~~ Quand plusieurs robots identiques sont sur la table : .. code-block:: bash ./scripts/ratbot fleet identify 2 # 10 secondes ./scripts/ratbot fleet identify 2 --seconds 30 Le voyant du robot 2 clignote en **blanc** et il bipe chaque seconde (``Ctrl-C`` arrête plus tôt). Un état plus grave reste affiché : un robot en arrêt d'urgence garde son rouge. Si rien ne se passe, la commande dit que personne n'écoute : le robot est éteint, ou son logiciel ne tourne pas. En simulation ~~~~~~~~~~~~~ Ces commandes écoutent par défaut le domaine des robots (77). Pour une simulation lancée dans un autre domaine, il faut le donner : .. code-block:: bash ./scripts/ratbot fleet diag --domain 0 Le robot réel ne répondant pas, ``time`` et la colonne ``reseau`` le disent ; ``battery``, ``diag``, ``who`` et ``identify`` fonctionnent sur les robots simulés. Modifier le parc ~~~~~~~~~~~~~~~~ Le fichier est **vérifié** à chaque commande. Une faute (numéro en double, état inconnu, date mal écrite…) est refusée avec l'endroit où elle se trouve, et rien n'est interrogé. **Ajouter un robot.** On l'ajoute avec son numéro, d'abord en montage. On le passe en service quand il est mis en service (voir :doc:`nouveau_robot`) : .. code-block:: yaml - id: 2 state: assembly # in_service, assembly, repair, retired label: "autocollant bleu" # pour le reconnaître sur la table lidar: {model: rplidar_a1, mount_yaw_deg: 180} tof: {mounted: false} wheels: {servo: ax18a} # ou xl430 : voir « Mettre en service un nouveau robot » battery: {type: lipo_3s, capacity_mah: 5200} **Noter une intervention.** Une intervention sur un robot (une roue changée, un moteur remplacé, le lidar démonté) se note avec sa date. La calibration faite avant cette date est alors signalée **à refaire**. ``affects`` dit ce que l'intervention touche : ``umbmark`` pour les roues et l'entraxe, ``gyro``, ``lidar``. Sans ``affects``, l'intervention touche ``umbmark`` et ``gyro``. .. code-block:: yaml interventions: - {date: 2026-10-20, what: "roue gauche changee"} # umbmark et gyro - {date: 2026-10-22, what: "lidar demonte", affects: [lidar]} - {date: 2026-10-23, what: "cable refait", affects: []} # rien a refaire Les interventions s'écrivent dans l'ordre des dates. Une intervention et une calibration du **même jour** ne donnent pas d'alerte : on suppose que la calibration a été faite après la réparation. Piloter plusieurs robots ------------------------ Une seule manette pilote jusqu'à **quatre robots** : la gâchette tenue désigne le robot qui bouge — L1 pour le robot 1, L2 pour le 2, R1 pour le 3, R2 pour le 4. Voir :doc:`pilotage`, qui décrit aussi la variante à une manette par robot. Au clavier ou par programme, il suffit de viser le bon numéro : ``/ratbot_2/base/cmd_vel`` pour le robot 2. Voir plusieurs robots --------------------- Deux façons, dans RViz (voir :doc:`rviz`) : - **tous ensemble**, en simulation : ``./scripts/ratbot up … rviz:=true`` ouvre une vue du décor avec tous les robots ; - **un par fenêtre** : ``./scripts/ratbot rviz N`` pour regarder le robot ``N`` ; la cartographie, la navigation et l'exploration ouvrent aussi le RViz de leur robot, et son outil de but ne commande que lui. Arrêter tout le parc -------------------- Le bouton **PS** de la manette, ou le topic ``/ratbot_fleet/emergency_stop``, arrêtent **tous** les robots d'un coup. Ce n'est pas un arrêt d'urgence : il passe par le réseau. Chaque robot garde son propre bouton d'arrêt. Voir :doc:`arrets`. Cartes et navigation à plusieurs -------------------------------- L'architecture prévoit **une carte commune** : un seul serveur publie la carte du lieu, et chaque robot s'y localise de son côté. .. warning:: **Limites actuelles, à corriger :** - **une seule exploration à la fois** : l'exploration publie sa carte sur ``/map``, commun à tous. La cartographie à la manette, elle, donne à chaque robot sa carte (``/ratbot_N/map``) et sa fenêtre RViz ; les cartes restent séparées, sans fusion en une carte commune ; - **la navigation de plusieurs robots ne se lance pas encore telle quelle** : chaque lancement de la navigation démarre son propre serveur de carte, et un second lancement entre en conflit avec le premier. Dans l'état actuel, plusieurs robots peuvent **cartographier** en même temps, chacun sa carte ; un seul à la fois **navigue** ou **explore**. Les autres peuvent être pilotés à la manette pendant ce temps.