Simple pick and place program

Overview

This article describes the logic for a simple vision-guided pick and place robot program. The program continuously picks objects from a detection region and places them in a specified drop-off location until no more pickable objects are found.

The logic has the purpose of presenting the basic ideas for writing a good pick and place robot program. It is written in robot-independent pseudo-code using a syntax similar to that of Python.

Note

This article is ideal for understanding the basics of vision-guided pick and place, but it omits some useful functionality for the sake of clarity. The Complete pick and place program is a slightly more complex version that can serve as a great starting point to build real applications on. A complete description of the Pickit interface can be found here.

The code samples presented in this article are pseudo-code, and are not meant to be executed.

The program can be downloaded here and consists of two main parts:

The minimum inputs required to run the pick and place program are:

  • Pickit configuration: setup and product IDs to use for object detection.

  • Waypoints:

    • Detect Where to perform object detection from. Refer to this article for guidelines on how to make a good choice.

    • Dropoff Where to place objects.

    • AbovePickArea A point roughly above the pick area from which the above two can be reached without collision. In simple scenarios, it can be the same as Detect.

  • Robot tool actions: gripper_grasp() and gripper_release(), to grasp and release an object, respectively.

../../_images/waypoints.png

Generic pick and place logic

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
if not pickit_is_running():
    print("Pickit is not in robot mode. Please enable it in the web interface.")
    halt()

before_start()
pickit_configure(setup, product)

retries = 5  # Number of detection retries before bailing out.
goto_detection()
pickit_find_objects_with_retries(retries)
pickit_get_result()

while True:
    if not pickit_object_found():
        # There are no pickable objects, bail out.
        break

    # Compute pre-pick and post-pick points.
    PrePick = compute_pre_pick(PickitPick)
    PostPick = compute_post_pick(PickitPick)

    if pickit_is_reachable(PickitPick, PrePick, PostPick):
        # Object is pickable!
        pick()
        goto_detection()
        pickit_find_objects_with_retries(retries)
        place()  # In parallel to detection, saves cycle time.
        pickit_get_result()
    else:
        # Object is unreachable, get the next detection, if any.
        pickit_next_object()
        pickit_get_result()

after_end()

Lines where application-specific hooks are called are highlighted above. The following is a breakdown of the pick and place logic along with a flowchart illustrating it. Click on the entries below to expand them and learn more:

Lines 1-6: Initialization
1
2
3
4
5
6
if not pickit_is_running():
    print("Pickit is not in robot mode. Please enable it in the web interface.")
    halt()

before_start()
pickit_configure(setup, product)

These commands are run once before starting to pick and place. They take care of:

Lines 8-11: First detection
 8
 9
10
11
retries = 5  # Number of detection retries before bailing out.
goto_detection()
pickit_find_objects_with_retries(retries)
pickit_get_result()

The first object detection consists of:

Lines 13-32: Pick and place loop
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
while True:
    if not pickit_object_found():
        # There are no pickable objects, bail out.
        break

    # Compute pre-pick and post-pick points.
    PrePick = compute_pre_pick(PickitPick)
    PostPick = compute_post_pick(PickitPick)

    if pickit_is_reachable(PickitPick, PrePick, PostPick):
        # Object is pickable!
        pick()
        goto_detection()
        pickit_find_objects_with_retries(retries)
        place()  # In parallel to detection, saves cycle time.
        pickit_get_result()
    else:
        # Object is unreachable, get the next detection, if any.
        pickit_next_object()
        pickit_get_result()

The pick and place loop executes until there are no more objects to pick. The following cases are handled:

  • There are no pickable objects: Exit the pick and place loop, as either there are no detected objects or they are all unreachable.

  • The object is detected and reachable (i.e. pickable): Execute pick and place and trigger the next object detection.

  • The object is detected but not reachable: Get the next object from the last detection run. A single run can yield multiple object detections, and pickit_next_object() allows to access the next object, if any, without incurring the overhead of running a new detection.

Note

To save cycle time when executing pick and place, note that object detection is triggered after the pick() hook, such that it takes place in parallel to place(). This optimization is desirable in almost every application. An exception would be when the camera is robot-mounted and the picked object is large enough to block the camera view, as shown below. To disable it, move the call to place() two line above, such that it takes place after pick().

../../_images/cycle-time-optimization.png
Line 34: Termination
34
after_end()

The after_end() hook is called last, which contains application-specific termination logic.

Flowchart../../_images/pick-and-place-simple.png

Application-specific hooks

The contents of these hooks are typically specific to a particular application, as they contain motion sequences and logic that depend on the robot cell layout, including:

  • The robot type and location

  • The camera mount and location

  • The parts to pick

  • The gripper to use

  • The pick and place locations

The following implementations are a good starting point for a general-purpose pick and place application, but it’s typically necessary to adapt them to some extent by adding waypoints or extra logic. A detailed description of these hooks can be found in the Complete pick and place program article.

36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Action performed once before starting pick and place.
def before_start():
    gripper_release()

# Move the robot to the point from which object detection is triggered.
def goto_detection():
    movej(Detect)

# PrePick is parallel to the object's z-axis, i.e. it tilts with the object.
# The optional offset parameter is in millimeters.
def compute_pre_pick(PickitPick, pre_pick_offset=100):
    PrePick = PickitPick * Pose(0, 0, -pre_pick_offset, 0, 0, 0)
    return PrePick

# PostPick is along the robot base z-axis, which typically means straight-up.
# The optional offset parameter is in millimeters.
def compute_post_pick(PickitPick, post_pick_offset=100):
    PostPick = PickitPick
    PostPick.z = PostPick.z + post_pick_offset
    return PostPick

# Sequence for performing the picking motion:
# - Starts and ends at AbovePickArea, a point reachable in a collision-free way.
# - PrePick --> PickitPick: Linear approach to the pick point.
# - A grasping action.
# - PickitPick --> PostPick: Linear retreat away from the pick point.
def pick():
    movej(AbovePickArea)
    movel(PrePick)
    movel(PickitPick)
    gripper_grasp()  # For a suction-like gripper, do this one line above.
    movel(PostPick)
    movel(AbovePickArea)

# Sequence for placing the object at the specified dropof location.
def place():
    movej(Dropoff)
    gripper_release()

# Action performed once after pick and place has finished.
def after_end():
    if not pickit_object_found():
        if pickit_empty_roi():
            print("The ROI is empty.")
        elif pickit_no_image_captured():
            print("Failed to capture a camera image.")
        else:
            print("The ROI is not empty, but the requested object was not found or is unreachable.")