Exemples : Vision

Cette page vous montre comment utiliser le Set Vision de Ned.

Si vous souhaitez en apprendre davantage sur les fonctions de Vision de Ned, consultez la rubrique PyNiryo - Vision.
Si vous souhaitez apprendre à faire du traitement d’images, consultez la section traitement d’images.

Note

Si vous ne possédez pas le Set Vision, vous pouvez toutefois réaliser ces exemples avec la simulation Gazebo.

Danger

Si vous utilisez le robot, assurez vous que l’environnement autour de celui-ci est dégagé

Parties de code nécessaires

Important

Afin de réaliser les exemples suivants, vous devez créer un workspace pour la vision. Dans ces exemples, le workspace utilisé est appelé workspace_1. Afin de le créer, vous devez vous rendre sur Niryo Studio.

Puisque tous les exemples commencent de la même manière, ajoutez les lignes suivantes au début de vos codes :

# Imports
from pyniryo import *

# - Constants
workspace_name = "workspace_1"  # Robot's Workspace Name
robot_ip_address = "x.x.x.x"

# The pose from where the image processing happens
observation_pose = PoseObject(
    x=0.16, y=0.0, z=0.35,
    roll=0.0, pitch=1.57, yaw=0.0,
)
# Place pose
place_pose = PoseObject(
    x=0.0, y=-0.2, z=0.12,
    roll=0.0, pitch=1.57, yaw=-1.57
)

# - Initialization

# Connect to robot
robot = NiryoRobot(robot_ip_address)
# Calibrate robot if the robot needs calibration
robot.calibrate_auto()
# Updating tool
robot.update_tool()

# --- -------------- --- #
# --- CODE GOES HERE --- #
# --- -------------- --- #

robot.close_connection()

Indication

Les exemples suivants ne sont qu’une petite partie de ce qui peut être fait avec l’API en termes de Vision. Nous vous recommandons de vous référer à la fonction de la commande API - Vision afin d’en apprendre davantage.

Simple Pick & Place par la Vision

L’objectif d’un Pick & Place par la Vision est le même qu’avec un Pick & Place classique, avec une légère différence : la caméra détecte où le robot doit se rendre pour attraper !

Ce court exemple vous montre comment réaliser votre premier prélèvement par la Vision en utilisant la fonction vision_pick().

robot.move_pose(observation_pose)
# Trying to pick target using camera
obj_found, shape_ret, color_ret = robot.vision_pick(workspace_name)
if obj_found:
    robot.place_from_pose(place_pose)

robot.set_learning_mode(True)

Détails du code - Simple Pick & Place par la Vision

Pour exécuter un prélèvement par la Vision, nous avons tout d’abord besoin de nous rendre à l’endroit depuis lequel le robot est capable de voir le workspace :

robot.move_pose(observation_pose)

Ensuite, on essaye de réaliser un prélèvement par la Vision sur le workspace en appelant la fonction vision_pick() :

obj_found, shape_ret, color_ret = robot.vision_pick(workspace_name)

Les variables shape_ret et color_ret sont respectivement de type ObjectShape et ObjectColor, et enregistrent la forme et la couleur des objets détectés. Nous n’allons pas les utiliser pour ce premier exemple.

La variable obj_found est un booléen qui indique si un objet a été détecté et attrapé, ou non. Ainsi, si le prélèvement a été réussi, on peut placer l’objet à la position de placement.

if obj_found:
    robot.place_from_pose(place_pose)

Enfin, on active le mode apprentissage :

robot.set_learning_mode(True)

Note

Si votre variable obj_found indique False, vérifiez que :

  • Rien n’obstrue le champs de vision de la caméra;

  • Les 4 marqueurs du workspace sont visibles;

  • Au moins un objet est entièrement placé sur le workspace.

Premier conditionnement par la Vision

Dans la plupart des cas d’usage, le robot devra faire plus d’un Pick & Place. Dans cet exemple, nous verrons comment conditionner plusieurs objets selon une ligne droite :

# Initializing variables
offset_size = 0.05
max_catch_count = 4

# Loop until enough objects have been caught
catch_count = 0
while catch_count < max_catch_count:
    # Moving to observation pose
    robot.move_pose(observation_pose)

    # Trying to get object via Vision Pick
    obj_found, shape, color = robot.vision_pick(workspace_name)
    if not obj_found:
        robot.wait(0.1)
        continue

    # Calculate place pose and going to place the object
    next_place_pose = place_pose.copy_with_offsets(x_offset=catch_count * offset_size)
    robot.place_from_pose(next_place_pose)

    catch_count += 1

robot.go_to_sleep()

Détails du code - Premier conditionnement par la Vision

Nous souhaitons attraper le nombre d’objets indiqués dans max_catch_count, et espacer chacun d’entre eux d’une distance en mètre indiquée dans offset_size

offset_size = 0.05
max_catch_count = 4

Nous démarrons une boucle jusqu’à ce que le robot a attrapé le nombre d’objets indiqués dans max_catch_count :

catch_count = 0
while catch_count < max_catch_count:

Pour toutes les itérations, nous commençons par aller en position d’observation puis nous essayons de faire un prélèvement par Vision sur le workspace :

robot.move_pose(observation_pose)

obj_found, shape, color = robot.vision_pick(workspace_name)

Si le prélèvement par Vision a échoué, nous attendons 0.1 seconde et commençons une nouvelle itération :

if not obj_found:
    robot.wait(0.1)
    continue

Autrement, nous calculons une nouvelle position en fonction du nombre de saisies puis plaçons l’objet à cette position :

next_place_pose = place_pose.copy_with_offsets(x_offset=catch_count * offset_size)
robot.place_from_pose(next_place_pose)

Nous incrémentons également la variable catch_count :

catch_count += 1

Une fois le nombre de saisies voulues atteint, le robot retourne en position de repos :

robot.go_to_sleep()

Conditionnement multi-références

Pendant une tâche de conditionnement, les objets peuvent ne pas être placés au même endroit en fonction de leur type. Dans cet exemple, nous vous montrerons comment aligner des objets en fonction de leur couleur, en utilisation l’élément ObjectColor renvoyé par la fonction vision_pick().

# Distance between elements
offset_size = 0.05
max_failure_count = 3

# Dict to write catch history
count_dict = {
    ObjectColor.BLUE: 0,
    ObjectColor.RED: 0,
    ObjectColor.GREEN: 0,
}

try_without_success = 0
# Loop until too much failures
while try_without_success < max_failure_count:
    # Moving to observation pose
    robot.move_pose(observation_pose)
    # Trying to get object via Vision Pick
    obj_found, shape, color = robot.vision_pick(workspace_name)
    if not obj_found:
        try_without_success += 1
        robot.wait(0.1)
        continue

    # Choose X position according to how the color line is filled
    offset_x_ind = count_dict[color]

    # Choose Y position according to ObjectColor
    if color == ObjectColor.BLUE:
        offset_y_ind = -1
    elif color == ObjectColor.RED:
        offset_y_ind = 0
    else:
        offset_y_ind = 1

    # Going to place the object
    next_place_pose = place_pose.copy_with_offsets(x_offset=offset_x_ind * offset_size,
                                                   y_offset=offset_y_ind * offset_size)
    robot.place_from_pose(next_place_pose)

    # Increment count
    count_dict[color] += 1
    try_without_success = 0

robot.go_to_sleep()

Détails du code - conditionnement multi-références

Nous souhaitons attraper des objets jusqu’à ce que le prélèvement par Vision échoue autant de fois qu’indiquées dans max_failure_count. Tous les objets seront placés dans une colonne spécifique en fonction de leur couleur. Le nombre de saisies pour chaque objet sera stocké dans le dictionnaire count_dict.

# Distance between elements
offset_size = 0.05
max_failure_count = 3

# Dict to write catch history
count_dict = {
    ObjectColor.BLUE: 0,
    ObjectColor.RED: 0,
    ObjectColor.GREEN: 0,
}

try_without_success = 0
# Loop until too much failures
while try_without_success < max_failure_count:

Pour chaque itération, nous commençons par aller en position d’observation puis nous essayons de réaliser un prélèvement par la Vision sur le workspace :

robot.move_pose(observation_pose)

obj_found, shape, color = robot.vision_pick(workspace_name)

Si le prélèvement par Vision a échoué, nous attendons 0.1 seconde et commençons une nouvelle itération, en n’oubliant pas d’incrémenter un compteur d’erreurs :

if not obj_found:
    try_without_success += 1
    robot.wait(0.1)
    continue

Autrement, nous calculons une nouvelle position en fonction du nombre de saisies puis plaçons l’objet à cette position :

# Choose X position according to how the color line is filled
offset_x_ind = count_dict[color]

# Choose Y position according to ObjectColor
if color == ObjectColor.BLUE:
    offset_y_ind = -1
elif color == ObjectColor.RED:
    offset_y_ind = 0
else:
    offset_y_ind = 1

# Going to place the object
next_place_pose = place_pose.copy_with_offsets(x_offset=offset_x_ind * offset_size,
                                               y_offset=offset_y_ind * offset_size)
robot.place_from_pose(next_place_pose)

Nous incrémentons le dictionnaire count_dict et réinitialisons try_without_success :

count_dict[color] += 1
try_without_success = 0

Une fois le nombre de saisies voulues atteint, le robot retourne en position de repos :

robot.go_to_sleep()

Tri avec le convoyeur

Utiliser un convoyeur est une façon intéressante d’amener des objets au robot. Dans ces exemples, nous vous montrerons comment attraper uniquement un certain type d’objets en arrêtant le convoyeur dès que l’objet est détecté sur le workspace.

# Initializing variables
offset_size = 0.05
max_catch_count = 4
shape_expected = ObjectShape.CIRCLE
color_expected = ObjectColor.RED

conveyor_id = robot.set_conveyor()

catch_count = 0
while catch_count < max_catch_count:
    # Turning conveyor on
    robot.run_conveyor(conveyor_id)
    # Moving to observation pose
    robot.move_pose(observation_pose)
    # Check if object is in the workspace
    obj_found, pos_array, shape, color = robot.detect_object(workspace_name,
                                                             shape=shape_expected,
                                                             color=color_expected)
    if not obj_found:
        robot.wait(0.5)  # Wait to let the conveyor turn a bit
        continue
    # Stopping conveyor
    robot.stop_conveyor(conveyor_id)
    # Making a vision pick
    obj_found, shape, color = robot.vision_pick(workspace_name,
                                                shape=shape_expected,
                                                color=color_expected)
    if not obj_found:  # If visual pick did not work
        continue

    # Calculate place pose and going to place the object
    next_place_pose = place_pose.copy_with_offsets(x_offset=catch_count * offset_size)
    robot.place_from_pose(next_place_pose)

    catch_count += 1

# Stopping & unsetting conveyor
robot.stop_conveyor(conveyor_id)
robot.unset_conveyor(conveyor_id)

robot.go_to_sleep()

Détails du code - Tri

Pour commencer, initialisons votre process : nous voulons que le robot attrape 4 cercles rouges. Pour cela, nous définissons les variables shape_expected et color_expected avec ObjectShape.CIRCLE et ObjectColor.RED :

offset_size = 0.05
max_catch_count = 4
shape_expected = ObjectShape.CIRCLE
color_expected = ObjectColor.RED

Nous activons ensuite la connexion avec le convoyeur et démarrons une boucle jusqu’à ce que le robot a attrapé le nombre d’objets indiqués dans max_catch_count :

conveyor_id = robot.set_conveyor()

catch_count = 0
while catch_count < max_catch_count:

Pour toutes les itérations, nous débutons par lancer le Convoyeur (si ce dernier est déjà lancé, alors rien ne se passera), puis nous allons en position d’observation :

# Turning the Conveyor Belt on
robot.run_conveyor(conveyor_id)
# Moving to observation pose
robot.move_pose(observation_pose)

Nous vérifions ensuite si un objet répondant à notre critère est présent sur le workspace. Si non, nous attendons 0.5 secondes et démarrons alors une nouvelle itération :

obj_found, pos_array, shape, color = robot.detect_object(workspace_name,
                                                         shape=shape_expected,
                                                         color=color_expected)
if not obj_found:
    robot.wait(0.5)  # Wait to let the conveyor turn a bit
    continue

Sinon, nous stoppons le convoyeur et essayons de réaliser un prélèvement par la Vision :

# Stopping Conveyor Belt
robot.stop_conveyor(conveyor_id)
# Making a Vision pick
obj_found, shape, color = robot.vision_pick(workspace_name,
                                            shape=shape_expected,
                                            color=color_expected)
if not obj_found:  # If visual pick did not work
    continue

Si le prélèvement par la vision est réusi, nous calculons une nouvelle position et y plaçons l’objet :

# Calculate place pose and going to place the object
next_place_pose = place_pose.copy_with_offsets(x_offset=catch_count * offset_size)
robot.place_from_pose(next_place_pose)

catch_count += 1

Une fois le nombre de saisies voulues atteint, nous arrêtons le convoyeur et le robot retourne en position de repos :

# Stopping & unsetting Conveyor Belt
robot.stop_conveyor(conveyor_id)
robot.unset_conveyor(conveyor_id)

robot.go_to_sleep()