1. Accueil
  2. Docs
  3. Niryo un
  4. Tutoriels
  5. Contrôlez simultanément plusieurs robots avec le multithreading

Contrôlez simultanément plusieurs robots avec le multithreading

https://niryo.com/wp-content/uploads/2020/11/Schéma-MultiThreading-600×709.png

Dans ce tutoriel, nous verrons comment contrôler plusieurs robots en même temps depuis le même programme Python en utilisant Python filetage bibliothèque. Pour ce faire, nous utiliserons :

  • Logiciels
    • Python 3.7
    • Le "filetage" Bibliothèque (automatiquement installée avec Python)
    • Le "API PyNiryo» bibliothèque pour le Niryo One.
  • Matériel
    • Deux Niryo Un

Tout d’abord, il faut se connecter au robot.

Pour utiliser l'exemple de ce programme, vous devrez remplacer « » et « » par les adresses IP de vos robots. 

de niryo_one_tcp_client importer *

robot1_ip =
robot2_ip =

Connexion #robot1
client1 = NiryoOneClient()
client1.connect(robot1_ip)
client1.calibrate(CalibrateMode.AUTO)

Connexion #robot2
client2 = NiryoOneClient()
client2.connect(robot2_ip)
client2.calibrate(CalibrateMode.AUTO)

sommeil_joints =
Séquence #robot1
client1.move_joints(*sleep_joints)
client1.set_learning_mode(Vrai)

Séquence #robot2
client2.move_joints(*sleep_joints)
client2.set_learning_mode(Vrai)

Dans cet exemple, nous nous connectons à deux robots puis leur demandons d'effectuer un léger mouvement. Le premier robot effectuera le mouvement demandé, passera en mode apprentissage, puis le deuxième robot effectuera le mouvement demandé et passera également en mode apprentissage. 

Cela est dû à l’utilisation de la fonction move_joints(). Le programme attend que le robot termine son mouvement pour exécuter la ligne suivante.

Pour effectuer un mouvement sur les deux robots de manière simultanée, nous utiliserons le filetage bibliothèque fournie par défaut avec Python. 

Le multithreading vous permet d'exécuter plusieurs parties du même programme en parallèle. Il est souvent utilisé pour répartir la charge de calculs entre plusieurs processeurs et pour exécuter plusieurs actions simultanément. Ainsi, cela nous permettra d'exécuter plusieurs commandes de l'API Python TPC/IP en même temps. Pour ce faire, nous allons créer un fil de discussion pour chaque robot.

Si vous ne connaissez pas encore le multithreading, nous vous invitons à lire et suivre les liens ci-dessous :

Nous pouvons maintenant modifier le programme afin d'exécuter les actions de chaque robot dans un thread différent.

de niryo_one_tcp_client importer *
importer filetage
de filetage importer *robot1_ip =
robot2_ip =sommeil_joints = classe RobotThread(threading.Thread):


def __init__(soi, client, robot_id) :

Sujet.__init__(soi)
soi.client = client
self.robot_id = robot_id

#programme des robots
def courir(soi):

impression("robot n°", self.robot_id, "démarrer")
self.client.calibrate(CalibrateMode.AUTO)
self.client.move_joints(*sleep_joints)
self.client.set_learning_mode(Vrai)
impression("robot n°", self.robot_id, "finir")

client1 = NiryoOneClient()
client1.connect(robot1_ip)

client2 = NiryoOneClient()
client2.connect(robot2_ip)

#créer un fil de discussion pour chaque robot
robot1 = RobotThread(client1, 1)
robot2 = RobotThread(client2, 2)

#démarrage des discussions
robot1.start()
robot2.start()

Dans ce programme, les deux robots effectuent leurs mouvements simultanément. Les deux threads que nous avons créés dans cet exemple ne partagent aucune donnée. Pour synchroniser les deux robots, nous aurons besoin d'une variable partagée par les deux threads.

Il existe deux manières de partager une variable entre plusieurs threads :

  • La première façon est de créer des variables globales
  • La deuxième façon consiste à utiliser une classe mère qui contiendra les deux classes des threads.

En donnant la classe mère comme argument au « RobotThread », nous leur accordons l'accès aux variables contenues dans la classe mère. De cette façon, le « RobotThread » conservera les variables qu’il contient en privé et utilisera ses variables de classe mère pour communiquer. 

Dans l'exemple suivant, la classe mère est « RobotsMains ».

de niryo_one_tcp_client importer *
importer filetage
de filetage importer *robot1_ip =
robot2_ip = sommeil_joints = classe RobotsPrincipal:

def __init__(soi, client1, client2) :

soi.client1 = client1
soi.client2 = client2

self.share_var_examples = 0

def courir(soi):

#créer un fil de discussion pour chaque robot
robot1 = self.RobotThread(self, self.client1, 1)
robot2 = self.RobotThread(self, self.client2, 2)

#démarrage des discussions
robot1.start()
robot2.start()

classe RobotThread(threading.Thread):

def __init__(soi, parent, client, robot_id) :

Sujet.__init__(soi)
soi.parent = parent
soi.client = client
self.robot_id = robot_id

#programme des robots
def courir(soi):

self.client.calibrate(CalibrateMode.AUTO)
self.client.move_joints(*sleep_joints)
self.parent.share_var_examples += 1

impression("robot n°", self.robot_id, "valeur var partagée",self.parent.share_var_examples)

self.client.set_learning_mode(Vrai)

client1 = NiryoOneClient()
client1.connect(robot1_ip)

client2 = NiryoOneClient()
client2.connect(robot2_ip)

secteurs = RobotsMains (client1, client2)
mains.run()

Pour synchroniser correctement plusieurs robots, nous vous recommandons d'utiliser les fonctions suivantes :

  • « Événement » = threading.Event()
    • Permet de créer un objet « Event » sur lequel un thread peut attendre en utilisant la fonction « Event ».wait(). Il peut être déverrouillé par un autre thread en utilisant « Event ».set(). Donc « Event ».wait() peut fonctionner à nouveau, « Event ».clear() doit être rappelé.
  • « Verrouiller » = threading.Lock()
    • Permet de créer un verrou pouvant être utilisé par un seul thread. Une façon instinctive d'imaginer l'utilisation de la serrure est de la considérer comme une clé qui donne accès à une partie du code. Avant qu'un thread n'utilise la clé, il doit attendre que l'autre ait fini de l'utiliser également. 

Notes

Si vous utilisez plusieurs threads pour contrôler le même robot, sachez qu'une instance NiryoOneClient() ne peut être utilisée que par un seul thread à la fois. Pensez à utiliser threading.Event() pour éviter l'envoi de deux commandes TCP simultanées au même robot.

Comment pouvons-nous vous aider ?