Palletizing

Robotic palletizers pick up and place boxes from a conveyor onto a pallet according to a predefined configuration that includes the pallet and box dimensions and a placement pattern. The use of robotic palletizers has become increasingly popular in manufacturing, warehousing, and distribution facilities due to the faster and safer automated palletizing process they offer. However, the increasing demand for 6 or 7-axis robots, while enhancing flexibility, also brings greater complexity in programming and optimization, leading to higher costs for engineering, onsite support, and reprogramming. In this tutorial, we introduce a short program created using the Jacobi platform, designed to be easily configurable for robotic palletizing.

Video

Application Code

 1from pathlib import Path
 2
 3from jacobi import Box, Obstacle, Frame, Motion, LinearSection, Planner
 4from jacobi.drivers import SimulatedDriver
 5
 6
 7if __name__ == '__main__':
 8    # Load project from Studio Download
 9    project_path = Path.home() / 'Downloads' / 'TechCrunch Video.jacobi-project'
10    planner = Planner.load_from_project_file(project_path)
11    robot = planner.environment.get_robot()
12
13    # Get important waypoints for motion planning
14    home = planner.environment.get_waypoint('Home')
15    pick = planner.environment.get_waypoint('Pick')
16    pallet = planner.environment.get_obstacle('Pallet Left')
17
18    # Define box properties
19    box_geometry = Box(0.4, 0.34, 0.3)
20    box_color = 'C09B6A'
21    pick = pick.position * Frame(z=box_geometry.z)
22
23    # Set and reset Studio project for visualization
24    driver = SimulatedDriver(planner, sync_with_studio=True)
25    driver.speed = 24.0
26    driver.set_current_joint_position(home.position)
27    driver.studio.reset()
28    driver.studio.set_item(None)
29
30    # Add a first box on the conveyor belt
31    box_at_pick = Obstacle('box_at_pick', box_geometry, pick * Frame(z=-box_geometry.z / 2), color=box_color)
32    driver.studio.add_obstacle(box_at_pick)
33
34    # Going from home to the first pick
35    motion = Motion('home_to_pick', driver.current_joint_position, pick)
36    motion.linear_approach = LinearSection(offset=Frame(z=0.05), speed=0.5)
37    trajectory = planner.plan(motion)
38    driver.run(trajectory)
39
40    for layer_i in range(5):
41        layer = pallet.origin * Frame(z=pallet.collision.z / 2) * Frame(z=(box_geometry.z + 0.005) * layer_i)
42
43        for box_i, box_frame in enumerate([
44            Frame(x=-0.41, y=-0.18 - 0.04),
45            Frame(x=0.0, y=-0.18 - 0.04),
46            Frame(x=0.41, y=-0.18 - 0.04),
47            Frame(x=-0.41, y=0.18 - 0.04),
48            Frame(x=0.0, y=0.18 - 0.04),
49            Frame(x=0.41, y=0.18 - 0.04),
50        ]):
51            # Grasp the box, and update collision model and Studio
52            driver.studio.remove_obstacle(box_at_pick)
53            box_as_item = Obstacle('box_as_item', box_geometry, Frame(z=-box_geometry.z / 2), color=box_color)
54            robot.item_obstacle = box_as_item
55            driver.studio.set_item(box_as_item)
56
57            # Calculate place position on pallet
58            place = layer * box_frame * Frame(z=box_geometry.z)
59
60            # Calculate the pick -> place motion
61            motion = Motion(f'{layer_i + 1}_{box_i + 1}_pick_to_place', driver.current_joint_position, place)
62            motion.linear_retraction = LinearSection(offset=Frame(z=0.2))
63            motion.linear_approach = LinearSection(offset=Frame(x=0.1, y=0.1, z=0.1))
64            motion.orientation_loss_weight = 2.0
65            trajectory = planner.plan(motion)
66            driver.run(trajectory)
67
68            # Release box
69            robot.item_obstacle = None
70            driver.studio.set_item(None)
71
72            # Add box at place position to collision model and Studio
73            box_at_place_frame = place * Frame(z=-box_geometry.z / 2)
74            box_at_place = Obstacle(f'Box {box_i + 1} - Layer {layer_i + 1} ', box_geometry, box_at_place_frame, color=box_color)
75            planner.environment.add_obstacle(box_at_place)
76            driver.studio.add_obstacle(box_at_place)
77            driver.studio.add_obstacle(box_at_pick)
78
79            # Calculate the place -> pick return motion
80            motion = Motion(f'{layer_i + 1}_{box_i + 1}_place_to_pick', driver.current_joint_position, pick)
81            motion.linear_retraction = LinearSection(offset=Frame(z=0.05))
82            motion.linear_approach = LinearSection(offset=Frame(z=0.1))
83            trajectory = planner.plan(motion)
84            driver.run(trajectory)