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)