ITSkillsCenter
Intelligence Artificielle

Construire une passerelle entre ROS 2 et un automate industriel

13 min de lecture
📍 Guide principal de la série : Robotique industrielle open source : ROS 2, Modbus, OPC-UA et automates. Ce tutoriel assemble tout ce que la série a construit.

Vous avez maintenant deux mondes qui s’ignorent. D’un côté, ROS 2 et son robot, qui raisonnent en messages typés et en topics. De l’autre, un automate qui exécute sa logique et expose son état en Modbus. Pour qu’une cellule fonctionne, ces deux mondes doivent coopérer : le robot doit savoir ce que fait l’automate, et l’automate doit pouvoir recevoir des ordres du robot. C’est le rôle d’une passerelle — un traducteur permanent entre les deux protocoles. Dans ce tutoriel, vous allez la construire et refermer la boucle de toute la série.

🎯 Ce que vous allez apprendre

  • Comprendre pourquoi une passerelle est nécessaire entre ROS 2 et un automate.
  • Lire l’état d’un automate en Modbus depuis un nœud ROS 2.
  • Republier cet état sous forme de topics ROS 2 exploitables par le robot.
  • Transmettre des commandes ROS 2 vers l’automate.
  • Savoir où OPC-UA prend le relais pour franchir une frontière sécurisée.

🛠️ Ce que vous allez construire

Un nœud ROS 2 unique qui fait le pont. D’un côté, il parle Modbus à l’automate OpenPLC du tutoriel précédent : il lit son voyant et son compteur de cycles. De l’autre, il publie ces informations sur des topics ROS 2, et écoute un topic de commande pour piloter l’automate en retour. À la fin, vous commanderez l’automate d’une simple ligne ROS 2, et vous verrez l’état de l’automate circuler dans le graphe ROS 2 comme n’importe quelle donnée de robot.

Prérequis

  • ROS 2 Jazzy installé avec un espace de travail fonctionnel (premiers tutoriels de la série).
  • Un automate OpenPLC qui tourne et expose son serveur Modbus (tutoriel précédent), ou à défaut l’automate Python simulé du tutoriel Modbus.
  • La bibliothèque pymodbus disponible pour l’interpréteur Python de ROS 2. Test express : si vos nœuds ROS 2 et votre client Modbus fonctionnent séparément, vous êtes prêt à les marier.
  • ⏱️ Temps estimé : 45 minutes.

Pourquoi une passerelle, et pas une connexion directe ?

ROS 2 ne parle pas Modbus, et un automate ne parle pas DDS. Ce sont deux univers conçus pour des besoins différents : ROS 2 pour la richesse logicielle et la coordination, Modbus pour la simplicité robuste du terrain. Plutôt que de tordre l’un pour qu’il imite l’autre, on intercale un composant dont c’est le seul métier : traduire. La passerelle lit d’un côté, écrit de l’autre, et impose un point de contrôle unique — précieux pour la sécurité, car c’est là qu’on filtre, qu’on valide et qu’on journalise les échanges entre le réseau robotique et le réseau d’automates.

Étape 1 — Préparer le nœud passerelle

On crée le nœud dans l’espace de travail ROS 2, dans un paquet dédié. Le nœud aura besoin de pymodbus ; on l’installe pour l’interpréteur utilisé par ROS 2.

cd ~/ros2_cellule_ws/src
ros2 pkg create --build-type ament_python --license Apache-2.0 passerelle
pip install pymodbus

On crée le paquet passerelle comme pour les nœuds précédents, puis on installe pymodbus afin que le nœud puisse parler Modbus. Si votre environnement ROS 2 isole ses paquets Python, installez pymodbus dans ce même environnement pour qu’il soit visible à l’exécution. Le nœud combinera deux bibliothèques que vous connaissez déjà : rclpy pour ROS 2 et pymodbus pour l’automate.

Étape 2 — Lire l’automate et publier dans ROS 2

Le cœur de la passerelle : à intervalle régulier, lire l’état de l’automate en Modbus et le republier sur des topics ROS 2. Créez pont.py dans le dossier de code du paquet :

import rclpy
from rclpy.node import Node
from std_msgs.msg import Bool, Int32
from pymodbus.client import ModbusTcpClient

class Passerelle(Node):
    def __init__(self):
        super().__init__('passerelle_automate')
        # Connexion Modbus vers l'automate (IP et port à adapter).
        self.modbus = ModbusTcpClient('127.0.0.1', port=502)
        self.modbus.connect()
        # Publieurs ROS 2 pour l'état de l'automate.
        self.pub_voyant = self.create_publisher(Bool, 'automate/voyant', 10)
        self.pub_cycles = self.create_publisher(Int32, 'automate/cycles', 10)
        # Abonnement aux commandes venues de ROS 2.
        self.create_subscription(Bool, 'automate/commande', self.on_commande, 10)
        # Lecture périodique deux fois par seconde.
        self.create_timer(0.5, self.lire_automate)
        self.get_logger().info('Passerelle ROS 2 <-> automate demarree')

    def lire_automate(self):
        coil = self.modbus.read_coils(0, count=1, device_id=1)
        reg = self.modbus.read_holding_registers(0, count=1, device_id=1)
        if not coil.isError():
            self.pub_voyant.publish(Bool(data=bool(coil.bits[0])))
        if not reg.isError():
            self.pub_cycles.publish(Int32(data=reg.registers[0]))

    def on_commande(self, msg):
        # Une commande ROS 2 écrit un coil dans l'automate.
        self.modbus.write_coil(1, msg.data, device_id=1)
        self.get_logger().info('Commande transmise a l automate : %s' % msg.data)

def main(args=None):
    rclpy.init(args=args)
    noeud = Passerelle()
    rclpy.spin(noeud)
    noeud.modbus.close()
    noeud.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

Décortiquons ce nœud charnière. Le constructeur ouvre une connexion Modbus vers l’automate, déclare deux publieurs ROS 2 (l’un pour le voyant, l’autre pour le compteur), s’abonne à un topic de commande, et arme un minuteur. Toutes les demi-secondes, lire_automate interroge le coil 0 et le holding register 0 de l’automate, vérifie l’absence d’erreur, puis publie les valeurs dans ROS 2 : l’état de l’automate devient un flux de robot ordinaire. Dans l’autre sens, on_commande réagit à un message ROS 2 en écrivant un coil dans l’automate. La passerelle traduit donc dans les deux directions, en continu.

Étape 3 — Déclarer et compiler

Comme pour tout nœud Python ROS 2, on déclare le programme dans setup.py et ses dépendances dans package.xml. Dans setup.py, à la section console_scripts :

    entry_points={
        'console_scripts': [
            'pont = passerelle.pont:main',
        ],
    },

Dans package.xml, ajoutez les dépendances ROS 2 utilisées (les messages standards) :

  <exec_depend>rclpy</exec_depend>
  <exec_depend>std_msgs</exec_depend>

Puis compilez et sourcez l’espace de travail :

cd ~/ros2_cellule_ws
colcon build --packages-select passerelle
source install/setup.bash

L’option --packages-select ne recompile que le paquet de la passerelle, plus rapide quand l’espace de travail grossit. La compilation doit se terminer sans erreur. Assurez-vous que l’automate OpenPLC tourne et que son serveur Modbus est actif avant de lancer la passerelle.

Étape 4 — Lancer et observer la traduction

Tout est prêt. Démarrez la passerelle :

ros2 run passerelle pont

Le nœud annonce son démarrage et commence à lire l’automate. Dans un second terminal sourcé, observez les topics qu’il publie :

ros2 topic echo /automate/voyant
ros2 topic echo /automate/cycles

Le premier affiche data: true puis data: false en alternance, au rythme du clignotant de l’automate ; le second montre le compteur de cycles qui grimpe. L’état d’un automate industriel circule désormais dans ROS 2, prêt à être consommé par un nœud de robot — par exemple pour synchroniser un mouvement du bras avec une étape du procédé.

Point d’étape — Si les valeurs de l’automate apparaissent dans les topics ROS 2, la moitié « lecture » de la passerelle fonctionne. Reste à commander l’automate depuis ROS 2.

Étape 5 — Commander l’automate depuis ROS 2

Pour fermer la boucle, on envoie une commande depuis ROS 2 et on vérifie qu’elle atteint l’automate. ROS 2 permet de publier sur un topic en une ligne. Dans un troisième terminal sourcé :

ros2 topic pub --once /automate/commande std_msgs/msg/Bool "{data: true}"

Cette commande publie une fois un message True sur le topic de commande. La passerelle le reçoit, le journalise, et écrit le coil 1 dans l’automate. Côté automate, ce coil peut servir d’ordre que la logique prend en compte au cycle suivant — par exemple lancer une séquence. Vous venez de piloter un automate industriel depuis l’écosystème d’un robot, à travers votre propre passerelle.

Point d’étape final — Une commande ROS 2 qui se traduit en écriture Modbus dans l’automate : la passerelle fonctionne dans les deux sens. La cellule complète — robot, automate, supervision — peut désormais coopérer.

Étape 6 — Quand passer par OPC-UA

La passerelle que vous venez d’écrire parle Modbus, ce qui convient à l’intérieur d’un réseau de terrain de confiance. Mais dès que les données doivent franchir une frontière — remonter vers une supervision distante, traverser le réseau bureautique, atteindre une plateforme d’analyse — Modbus n’offre aucune protection. C’est là qu’OPC-UA prend le relais.

Le principe est identique, seul le protocole change : au lieu de lire des coils Modbus, la passerelle se connecte en client OPC-UA (avec asyncua, comme dans le tutoriel dédié), lit des variables nommées et sécurisées, et les republie dans ROS 2. L’authentification et le chiffrement d’OPC-UA garantissent alors que les échanges franchissant la frontière sont identifiés et illisibles pour un tiers. Architecture type : Modbus au plus près des machines, une passerelle qui agrège, OPC-UA sécurisé pour sortir de la zone de terrain. Garder cette règle en tête, c’est concevoir des cellules qui restent sûres en grandissant.

Robustesse : le chien de garde et la gestion des pertes

Une passerelle de démonstration lit et écrit ; une passerelle de production survit aux incidents. Le réseau d’atelier est hostile : un câble qui se débranche, un automate qui redémarre, une rafale de trafic qui retarde une réponse. Un nœud passerelle écrit naïvement se fige ou plante au premier de ces aléas, et entraîne avec lui la coordination de la cellule. Quelques principes transforment notre pont en composant fiable.

D’abord, la reconnexion automatique. Quand une lecture Modbus échoue, il ne faut pas seulement l’ignorer : il faut détecter que la connexion est tombée et tenter de la rétablir. En pratique, on enveloppe l’accès Modbus dans une vérification de l’état de connexion, et l’on rappelle connect() si nécessaire avant de réessayer. Ainsi, un automate qui redémarre est retrouvé tout seul dès qu’il revient, sans intervention.

Ensuite, le chien de garde (watchdog). C’est un mécanisme par lequel chaque partie surveille que l’autre donne signe de vie. Si la passerelle ne reçoit plus de données fraîches de l’automate pendant un délai donné, elle doit le signaler clairement dans ROS 2 — par exemple en publiant un état « automate injoignable » — plutôt que de continuer à diffuser la dernière valeur connue comme si de rien n’était. Du côté de l’automate, on prévoit symétriquement un repli sûr si les commandes de la passerelle cessent d’arriver : un robot qui ne sait plus ce que fait la chaîne doit s’arrêter, pas continuer à l’aveugle. Cette philosophie du repli sûr — en cas de doute, on se met dans un état inoffensif — est au cœur de la sécurité des systèmes automatisés.

Enfin, la qualité de service ROS 2 évoquée dans le guide principal trouve ici son application : pour l’état de l’automate, un profil fiable garantit qu’aucune transition importante n’est perdue ; pour un flux à haute fréquence, un profil au mieux réduit la latence. Choisir consciemment ces profils, c’est accorder la passerelle au comportement attendu de la cellule.

🐞 Pièges fréquents

Symptôme / erreur Cause probable Correctif
ModuleNotFoundError: pymodbus pymodbus absent de l’environnement de ROS 2 Installer pymodbus dans le même interpréteur Python que ROS 2
La passerelle ne lit rien Automate arrêté ou serveur Modbus inactif Démarrer l’automate, activer son serveur Modbus, vérifier l’IP
Les topics restent vides Erreurs Modbus silencieuses Journaliser les isError() pour diagnostiquer
La commande n’a pas d’effet Coil de commande non exploité par la logique d’automate Adapter le programme ST pour lire le coil commandé
Connexion qui se fige Lecture Modbus bloquante trop longue Réduire la fréquence du minuteur, traiter les délais d’attente

✅ Récapitulatif

Vous avez construit la pièce qui manquait : une passerelle qui lit un automate en Modbus, republie son état dans ROS 2, et transmet en retour les commandes du monde robotique vers l’automate. Vous avez vu comment OPC-UA prend le relais pour franchir une frontière sécurisée. La cellule imaginée au début de la série est désormais complète et cohérente : un robot ROS 2, un automate ouvert, des protocoles industriels, et un pont qui les fait coopérer — entièrement avec des outils libres que vous maîtrisez de bout en bout.

🧾 Aide-mémoire

Élément Rôle
rclpy + pymodbus dans un nœud Marier ROS 2 et Modbus
create_timer Interroger l’automate périodiquement
create_publisher / create_subscription Exposer l’état / recevoir des commandes
ros2 topic echo Observer l’état de l’automate dans ROS 2
ros2 topic pub --once Envoyer une commande à l’automate
OPC-UA (asyncua) Variante sécurisée pour franchir une frontière

💪 À vous de jouer

Faites coopérer le robot et l’automate pour de bon : écrivez un nœud ROS 2 qui s’abonne à /automate/cycles et, tous les dix cycles de l’automate, déclenche un mouvement du bras simulé du tutoriel dédié (en publiant sur /joint_states). Vous obtenez une véritable coordination : le procédé piloté par l’automate cadence le robot.

Voir la piste

Dans un nouveau nœud, abonnez-vous à /automate/cycles. Dans le callback, comparez la valeur reçue au dernier multiple de dix traité ; si un nouveau palier est franchi, publiez une position d’articulation sur /joint_states. Le robot bouge alors au rythme du procédé, sans couplage direct entre les deux — toute la valeur de la passerelle.

Tutoriels frères

Pour aller plus loin

FAQ

Une lecture Modbus bloquante dans un nœud ROS 2 pose-t-elle problème ?
Pour une cadence modérée comme ici, non : la lecture est rapide et le minuteur lui laisse la place. Pour des fréquences élevées ou de nombreux équipements, on isole les accès Modbus dans un fil d’exécution ou on passe à un client asynchrone, afin de ne pas retarder le reste du nœud.

Pourquoi ne pas tout faire en OPC-UA et abandonner Modbus ?
Parce que d’innombrables équipements ne parlent que Modbus. La passerelle a justement pour vertu d’accueillir le terrain tel qu’il est — souvent en Modbus — et de présenter une façade moderne et sécurisée vers le haut, en OPC-UA. C’est l’art de l’intégration : composer avec l’existant.

La passerelle est-elle un point unique de défaillance ?
Elle peut l’être, et c’est à considérer : en production, on la redonde et on la surveille. Mais son rôle de point de passage unique est aussi un atout pour la sécurité et la traçabilité, car tout transite par un endroit que l’on contrôle.

Peut-on relier plusieurs automates à un même robot ?
Oui : la passerelle peut ouvrir plusieurs connexions Modbus ou OPC-UA et publier autant de jeux de topics. C’est ainsi qu’on agrège une cellule entière — plusieurs automates, un robot — dans un graphe ROS 2 unique.

Partager
Service ITSkillsCenter

Application mobile Android et iOS

Création d'application mobile Android et iOS. À partir de 350 000 FCFA.

Démarrer mon projet
Publicité