Advanced Wandelscript examples
To inspire you when writing your own Wandelscript, we've published a set of example programs. These examples cover a wide range of automation tasks and involve robot movements, I/Os or other sensors, coordinate systems, and geometric operations.
A little selection of those examples can be found on this page, find the complete example collection (opens in a new tab) on GitHub.
Multi-robot
Pick and place using conveyors, sensors and OPC UA.
# defines the pick position of the box
# 0 - 8 --> back to 0
TCP_Sucker = frame("WOS_Sucker")
TCP_HookedHook = frame("WOS_HookedHook")
TCP_ABB = frame("BASE/tool0")
LEFT_SENSOR_IO = "digital_in[1]"
RIGHT_SENSOR_IO = "digital_in[0]"
RED_BUTTON_IO = "digital_in[2]"
GREEN_BUTTON_IO = "digital_in[3]"
prod = False
debug = False
run_no = 0
abb_home = (475.7, -94.4, 553.8, -0.027, -0.024, 1.176)
ur_home = (191.6, -717.3, 433.2, 0, pi, 0)
ur_pick_pose = (184, -1038, 150, 0, pi, 0)
ur_drop_pose = (460, -832, 346, 0, pi, 0)
abb_pick_pose = (484.1, 151.4, 446.6, 0.019, 0.006, 1.335)
abb_drop_pose = (484.3, -388.3, 303, 0.017, 0.004, 1.335)
def wait_for(key, value):
while (read(controller, key) != value):
pass
def wait_for_left_sensor_touched():
wait_for(LEFT_SENSOR_IO, True)
def wait_for_right_sensor_touched():
wait_for(RIGHT_SENSOR_IO, True)
def move_conveyor_belt_to_the_left():
already_left = read(controller, LEFT_SENSOR_IO)
if (already_left == False):
wait_for(RIGHT_SENSOR_IO, True)
write(controller, "digital_out[4]", True)
write(controller, "digital_out[5]", True)
write(controller, "digital_out[6]", False)
sync
def move_conveyor_belt_to_the_right():
already_right = read(controller, RIGHT_SENSOR_IO)
if (already_right == False):
wait_for(LEFT_SENSOR_IO, True)
write(controller, "digital_out[4]", True)
write(controller, "digital_out[5]", False)
write(controller, "digital_out[6]", True)
sync
def abb_gripper(open):
if open:
write(controller, "digital_out[0]", True)
write(controller, "digital_out[1]", False)
write(controller, "digital_out[2]", True)
else:
write(controller, "digital_out[0]", True)
write(controller, "digital_out[1]", True)
write(controller, "digital_out[2]", False)
def ur_gripper(on):
if on:
write(controller, "tool_out[1]", True)
else:
write(controller, "tool_out[1]", False)
def is_red_button_pressed():
return read(controller, "digital_in[2]") == False
def is_green_button_pressed():
return read(controller, "digital_in[3]") == False
def is_any_sensor_touched():
return (is_left_sensor_touched() + is_right_sensor_touched()) == 1
# def is_object_in_drop_position():
# return read(controller, "digital_in[4]") == 1
def get_grid_pose(corner_pose, idx):
grid_step = 63
grid_n = 3
dir_1 = (grid_step * modulo(idx, grid_n), 0, 0, 0, 0, 0)
dir_2 = (0, grid_step * intdiv(idx, grid_n), 0, 0, 0, 0)
pose_for_idx = corner_pose :: dir_1 :: dir_2
return pose_for_idx
def move_ur_to_suck_object(idx):
pick_pose = get_grid_pose(ur_pick_pose, idx)
move TCP_Sucker via p2p() to pick_pose :: (0, 0, -100)
ur_gripper(True)
move TCP_Sucker via p2p() to pick_pose
move TCP_Sucker via p2p() to pick_pose :: (0, 0, -100)
def move_ur_to_unsuck_object():
move TCP_Sucker via p2p() to ur_drop_pose :: (0, 0, -150)
ur_gripper(False)
move TCP_Sucker via p2p() to ur_drop_pose
wait(2000)
move TCP_Sucker via p2p() to ur_drop_pose :: (0, 0, -150)
move TCP_Sucker via p2p() to ur_home
def move_ur_to_hook_object():
pick_pose = [211.3, -1036.5, 211.0, 0, pi, 0] # TODO: find pick position
move TCP_HookedHook via p2p() to pick_pose :: (0, 0, -100)
move TCP_HookedHook via p2p() to pick_pose
move TCP_HookedHook via p2p() to pick_pose :: (0, 0, -100)
def move_ur_to_unhook_object():
pick_pose = (0, 0, 100, 0, pi, 0) # TODO: find pick position
move TCP_HookedHook via p2p() to pick_pose :: (0, 0, -100)
move TCP_HookedHook via p2p() to pick_pose
move TCP_HookedHook via p2p() to pick_pose :: (0, 0, -100)
def move_ur_to_suck_hook():
hook_pick_pose = (451, -543.7, 107.6, 0, pi, 0)
move TCP_Sucker via p2p() to hook_pick_pose :: (0, 0, -100)
move TCP_Sucker via p2p() to hook_pick_pose
ur_gripper(True)
move TCP_Sucker via p2p() to hook_pick_pose :: (0, 0, -100)
def move_ur_to_unsuck_hook():
hook_drop_pose = [451, -543.7, 107.6, 0, pi, 0]
move TCP_Sucker via p2p() to hook_drop_pose :: (0, 0, -100)
move TCP_Sucker via p2p() to hook_drop_pose
ur_gripper(False)
move TCP_Sucker via p2p() to hook_drop_pose :: (0, 0, -100)
def move_abb_to_pick_object():
with velocity(300):
do with robot_abb1200:
move TCP_ABB via p2p() to abb_pick_pose :: (0, 0, 100, 0, 0, 0)
move TCP_ABB via p2p() to abb_pick_pose
abb_gripper(False)
wait(1000)
do with robot_abb1200:
move TCP_ABB via p2p() to abb_pick_pose :: (0, 0, 100)
def move_abb_to_drop_object():
with velocity(300):
do with robot_abb1200:
move TCP_ABB via p2p() to abb_drop_pose :: (0, 0, 100)
move TCP_ABB via p2p() to abb_drop_pose :: (0, 0, 0, 0, 0, 0)
move TCP_ABB via p2p() to abb_drop_pose :: (-200, 200, 0, 0, 0, 0)
abb_gripper(True)
wait(500)
do with robot_abb1200:
move TCP_ABB via p2p() to abb_drop_pose :: (-200, 200, 100)
def reset_cell():
ur_gripper(False)
abb_gripper(False)
do with robot_ur10e:
move TCP_Sucker via p2p() to ur_home
#and do with robot_abb1200:
# move via p2p() to abb_home
# move_conveyor_belt_to_the_right()
def skill_suck(idx):
# skill_a picks the object with a vacuum gripper
move_ur_to_suck_object(idx)
move_conveyor_belt_to_the_right()
move_ur_to_unsuck_object()
move_conveyor_belt_to_the_left()
# ABB movement
wait_for_left_sensor_touched()
move_abb_to_pick_object()
sync
#abb_gripper(False)
move_abb_to_drop_object()
sync
#abb_gripper(True)
def skill_hook():
# skill_b picks the object with the hook
#move_ur_to_suck_hook()
#move_ur_to_hook_object()
#wait_for_io(controller, RIGHT_SENSOR_IO)
#move_ur_to_unhook_object()
#move_conveyor_belt_to_the_left()
#move_ur_to_unsuck_hook()
#wait_for_io(controller, LEFT_SENSOR_IO)
#move_abb_to_pick_object()
#move_abb_to_drop_object()
print("hook")
# -----------------------------------------
# TESTING
# -----------------------------------------
velocity(300)
# move to home
do with robot:
move TCP_Sucker via p2p() to ur_home
move TCP_Sucker via p2p() to ur_home :: (0, 0, -136)
and do with robot_abb1200:
move TCP_ABB via p2p() to abb_home
move TCP_ABB via p2p() to abb_home :: (0, 0, 100)
# abb_pose = read(robot_abb1200, "pose")
# print(abb_pose)
# -----------------------------------------
# MAIN
# -----------------------------------------
#abb_pose = read(robot_abb1200, "BASE/tool0")
#print(abb_pose)
#do with robot_abb1200:
# move TCP_ABB via p2p() to abb_home
# move TCP_ABB via p2p() to abb_home :: [0, 0, 100]
# move TCP_ABB via p2p() to abb_home
i = 0
while True:
print(i)
button_red_not_pressed = True
button_green_not_pressed = True
while True:
button_red_not_pressed = read(controller, RED_BUTTON_IO)
button_green_not_pressed = read(controller, GREEN_BUTTON_IO)
if button_red_not_pressed == False:
break
if button_green_not_pressed == False:
break
# reset_cell()
if button_red_not_pressed == False:
i = 0
skill_suck(i)
if button_green_not_pressed == False:
skill_suck(i)
i = i + 1
if i == 9:
i = 0
Applications
Sanding 2 edges and 2 surfaces. Including camera and IOs.
# ### -----------------------------------------------------------
# ### Includes -------------------------
def set_motor(state, is_active):
if is_active:
set_io_map(get_aov_motor_ios(state, aov))
def set_compliance(state, is_active):
if is_active:
set_io_map(get_aov_compliance_ios(state, aov))
def align_approach(pose, align_to_origin, flip_axis, use_x_axis):
if align_to_origin:
return rotate_z_origin_direction(pose, flip_axis, use_x_axis)
return rotate_z(pose, flip_axis, use_x_axis)
def move_via_collision_free_p2p(tool, joints):
convex_hulls = [ ]
move tool via collision_free_p2p(convex_hulls) to joints
def move_to_home_safely(flange_tcp_name, workspace_tcp_name, home, workspace_robot_mounting):
# ### -----------------------------------------------------------
# ### Definitions -------------------------
pullout_mm = 100
lift_mm = 100
moving_velocity_slow = 20
moving_velocity = 50
# ### -----------------------------------------------------------
# ### Path -------------------------
flange = frame(check_tcp_name(flange_tcp_name))
workspace_tcp = frame(check_tcp_name(workspace_tcp_name))
workspace_tcp_pose = get_tcp_pose(robot, check_tcp_name(workspace_tcp_name))
velocity(moving_velocity)
current = solve_point_forward(robot, read(robot, "joints"), check_tcp_name(workspace_tcp_name))
up_direction_pose = ~workspace_robot_mounting
home_global = workspace_robot_mounting :: solve_point_forward(robot, home, check_tcp_name(flange_tcp_name))
current_global = workspace_robot_mounting :: current
if home_global[2] - current_global[2] >= lift_mm:
pullout = current :: (0, 0, -pullout_mm, 0, 0, 0)
lift = up_direction_pose :: (0, 0, lift_mm, 0, 0, 0) :: ~up_direction_pose :: pullout
velocity(moving_velocity_slow)
move workspace_tcp via p2p() to current
move workspace_tcp via line() to pullout
velocity(moving_velocity)
move workspace_tcp via line() to lift
move_via_collision_free_p2p(workspace_tcp, home)
def sand_surface(path, pressure, moving_velocity, sanding_velocity, is_hot_sanding, up_direction_pose, start_joints, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_surface):
# ### -----------------------------------------------------------
# ### Definitions -------------------------
def align_pose(pose):
return align_approach(pose, approach_align_to_origin, approach_flip_axis, approach_use_x_axis)
ABOVE_HIGH = lift_above_surface
ABOVE_CLOSE = 10
# ### -----------------------------------------------------------
# ### Path -------------------------
set_compliance(pressure, is_hot_sanding)
velocity(moving_velocity)
highest_polygon_pose = get_highest_point(path, up_direction_pose)
move_via_collision_free_p2p(sanding_tool, start_joints)
move sanding_tool via p2p() to align_pose(highest_polygon_pose :: (0, 0, -ABOVE_HIGH, 0, 0, 0) :: ~tcp_offset)
move sanding_tool via line() to align_pose(highest_polygon_pose :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
move sanding_tool via line() to align_pose(path[0] :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
velocity(sanding_velocity)
for i = 0..<len(path):
if i == 1:
set_motor(True, is_hot_sanding)
move sanding_tool via line() to align_pose(path(i) :: ~tcp_offset)
velocity(moving_velocity)
move sanding_tool via line() to align_pose(path[-1] :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
set_motor(False, is_hot_sanding)
move sanding_tool via line() to align_pose(highest_polygon_pose :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
move sanding_tool via line() to align_pose(highest_polygon_pose :: (0, 0, -ABOVE_HIGH, 0, 0, 0) :: ~tcp_offset)
move_via_collision_free_p2p(sanding_tool, start_joints)
def sand_edge(path, pressure, moving_velocity, sanding_velocity, is_hot_sanding, sanding_tool, start_joints, up_direction_pose, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_edge):
# ### -----------------------------------------------------------
# ### Definitions -------------------------
def align_pose(pose):
return align_approach(pose, approach_align_to_origin, approach_flip_axis, approach_use_x_axis)
ABOVE_HIGH = lift_above_edge
ABOVE_CLOSE = 10
# ### -----------------------------------------------------------
# ### Path -------------------------
edge_no_approach = slice_array(path, 2, -2)
highest_pose = get_highest_point(edge_no_approach, up_direction_pose)
set_compliance(pressure, is_hot_sanding)
velocity(moving_velocity)
move_via_collision_free_p2p(sanding_tool, start_joints)
move sanding_tool via p2p() to align_pose(highest_pose :: (0, 0, -ABOVE_HIGH, 0, 0, 0))
move sanding_tool via line() to align_pose(highest_pose :: (0, 0, -ABOVE_CLOSE+1, 0, 0, 0))
move sanding_tool via line() to align_pose(edge_no_approach[0] :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
set_motor(True, is_hot_sanding)
velocity(sanding_velocity)
for i = 0..<len(edge_no_approach):
move sanding_tool via line() to align_pose(edge_no_approach[i] :: ~tcp_offset)
set_motor(False, is_hot_sanding)
velocity(moving_velocity)
move sanding_tool via line() to align_pose(edge_no_approach[-1] :: (0, 0, -ABOVE_CLOSE, 0, 0, 0) :: ~tcp_offset)
move sanding_tool via line() to align_pose(highest_pose :: (0, 0, -ABOVE_CLOSE-1, 0, 0, 0)) # The -1 here is to prevent a wbr bug https://wandelbots.atlassian.net/browse/AA-1405
move sanding_tool via line() to align_pose(highest_pose :: (0, 0, -ABOVE_HIGH, 0, 0, 0))
move_via_collision_free_p2p(sanding_tool, start_joints)
def sand_straight_edge(edge, target_radius, lane_number_range, lane_density_weight, level_distance, pressure, moving_velocity, sanding_velocity, is_hot_sanding, sanding_tool, start_joints, up_direction_pose, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_edge):
# ### -----------------------------------------------------------
# ### Path -------------------------
meander = generate_edge_meander(edge[0], edge[1], target_radius, lane_number_range, lane_density_weight, level_distance)
sand_edge(meander, pressure, moving_velocity, sanding_velocity, is_hot_sanding, sanding_tool, start_joints, up_direction_pose, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_edge)
def sand_curved_edge(edge, target_radius, lane_number_range, lane_density_weight, level_distance, pressure, moving_velocity, sanding_velocity, is_hot_sanding, sanding_tool, start_joints, up_direction_pose, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_edge):
# ### -----------------------------------------------------------
# ### Path -------------------------
meander = generate_curved_edge_meander(edge[0], edge[1], target_radius, lane_number_range, lane_density_weight, level_distance)
sand_edge(meander, pressure, moving_velocity, sanding_velocity, is_hot_sanding, sanding_tool, start_joints, up_direction_pose, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_edge)
def sand_planar_surface(poly, distance, margin, pressure, moving_velocity, sanding_velocity, is_hot_sanding, up_direction_pose, start_joints, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_surface):
# ### -----------------------------------------------------------
# ### Path -------------------------
meander = generate_plane_meander(poly, distance, margin)
sand_surface(meander, pressure, moving_velocity, sanding_velocity, is_hot_sanding, up_direction_pose, start_joints, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_surface)
def sand_curved_surface(pcd, distance, margin, pressure, moving_velocity, sanding_velocity, is_hot_sanding, up_direction_pose, start_joints, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_surface):
# ### -----------------------------------------------------------
# ### Path -------------------------
meander = generate_curved_surface_meander(pcd, distance, margin)
sand_surface(meander, pressure, moving_velocity, sanding_velocity, is_hot_sanding, up_direction_pose, start_joints, tcp_offset, approach_align_to_origin, approach_flip_axis, approach_use_x_axis, lift_above_surface)
# ### -----------------------------------------------------------
# ### Input parameters -------------------------
# General
polygons = read(arguments, "polygons")
edges = read(arguments, "edges")
curved_edges = read(arguments, "curved_edges")
curved_surfaces = read(arguments, "curved_surfaces")
hot_sanding_on = True
safety_offset_z = 0 # (mm) positive value goes away from the workpiece
moving_velocity = 1000
workspace_robot_mounting = (0,0,0,0,0,0)
workspace_tcp = "TOOL 5"
home = [-0.08263993263244629,0.17805440723896027,0.4916095733642578,0.014160103164613247,-2.345040798187256,1.635414719581604]
use_approach_optimization = False
approach_align_to_origin = False
approach_flip_axis = False
approach_use_x_axis = False
# ### -----------------------------------------------------------
# ### Definitions -------------------------
def align_pose(pose):
return align_approach(pose, approach_align_to_origin, approach_flip_axis, approach_use_x_axis)
# Safety features
MOVING_OFFSET_HIGHEST = 150
# Path optimization features
use_start_joint_search = False
max_allowed_joint_deviations = [1, 1, 3, 3, 6, 6]
apply_operation_sync = use_start_joint_search
# ### -----------------------------------------------------------
# ### Configuration settings (developer can change) -------------
sanding_tool = frame(check_tcp_name(workspace_tcp))
tcp_pose = get_tcp_pose(robot, check_tcp_name(workspace_tcp))
tcp_correction_offset = (0, 0, 0, 0, 0, 0) # Normally set to zero (This gets applied to the points before the actual robot TCP is used)
# Construct the via pose:
up_direction_pose = ~workspace_robot_mounting
highest_pose = get_highest_point(polygons + edges + curved_surfaces + curved_edges, up_direction_pose)
above_workpiece = (highest_pose[0], highest_pose[1], highest_pose[2], 0, 0, 0) :: up_direction_pose :: (0, 0, MOVING_OFFSET_HIGHEST, 0, 0, 0) :: (0, 0, 0, pi, 0, 0)
above_workpiece = align_pose(above_workpiece)
# ### -----------------------------------------------------------
# ### Preparation (don't change) --------------------------------
safety_offset = (0, 0, safety_offset_z, 0, 0, 0)
if hot_sanding_on:
tcp_offset = tcp_correction_offset
else:
# This variable is kind of a 'local/relative' tcp, in relation to the actual used TCP of the robot
tcp_offset = tcp_correction_offset :: safety_offset
# ### -----------------------------------------------------------
# ### Skill starts ---------------------------------
above_workpiece_joints = solve_point_inverse(robot, above_workpiece :: ~tcp_offset, check_tcp_name(workspace_tcp), home)
blending(10)
velocity(moving_velocity)
move_via_collision_free_p2p(sanding_tool, home)
move_via_collision_free_p2p(sanding_tool, above_workpiece_joints)
sand_straight_edge(edges[0], 4, [5,17], 0.2, 100, 0.5, moving_velocity, 100, hot_sanding_on, sanding_tool, above_workpiece_joints, up_direction_pose, tcp_offset, False, False, False, 100)
if apply_operation_sync:
sync
sand_straight_edge(edges[1], 4, [5,17], 0.2, 100, 0.5, moving_velocity, 100, hot_sanding_on, sanding_tool, above_workpiece_joints, up_direction_pose, tcp_offset, False, False, False, 100)
if apply_operation_sync:
sync
sand_planar_surface(polygons[0], 80, 0, 2, moving_velocity, 100, hot_sanding_on, up_direction_pose, above_workpiece_joints, tcp_offset, False, False, False, 100)
if apply_operation_sync:
sync
sand_planar_surface(polygons[1], 80, 0, 2, moving_velocity, 100, hot_sanding_on, up_direction_pose, above_workpiece_joints, tcp_offset, False, False, False, 100)
if apply_operation_sync:
sync
# ### -----------------------------------------------------------
move_via_collision_free_p2p(sanding_tool, home)
# Motions are not resolved at this point
motion = motion_trajectory_to_json_string(robot)
Control flow
Loop
Loop with any robot brand.
# Robot Agnostic
C1_HOME_J = [1.3950, 0.6053, 0.3194, 0.0089, 0.6564, 1.3092]
C1_PICK_APPROACH_ROTATED = (-62.1, 421.9, 434.9, -2.223, -2.22, 0)
C1_PICK_1 = (-44.9, 412.9, 118.8, 0, -3.1, 0)
C1_PICK_2 = (-231, 383.2, 119.1, 0, -3.1001, 0.0002)
C1_PICK_3 = (-265.7, 567.5, 118.8, -0.0001, -3.1079, 0.0113)
C1_PICK_4 = (-81.1, 595.1, 118.8, -0.0003, -3.1019, 0.0062)
# Piece 1
C1_SCANNER_APPROACH = (237.3, 478.1, 457.8, -2.225, -2.222, 0)
C1_SCANNER = (352.9, 478.1, 457.8, -2.224, -2.221, 0)
C1_SCANNER_LEAVE = (353.6, 319.0, 457.7, -2.226, -2.223, 0)
# Piece 2
C1_SCANNER_APPROACH_2 = (237.3, 478.1, 457.8, 0, -3.1, 0)
C1_SCANNER_2 = (352.9, 478.1, 457.8, 0, -3.1, 0)
C1_SCANNER_LEAVE_2 = (353.6, 319.0, 457.7, 0, -3.1, 0)
C1_PLACE_APPROACH = (484.3, 15.3, 200.9, -3.148, 0, 0)
C1_PLACE_1 = (452.2, -12.1, 132, 3.1, 0.0, 0.0)
C1_PLACE_2 = (635, 5, 132, 3.1367, 0, -0.0054)
def cell1_abb_open_gripper():
write(cell1_abb, True, "Local/SC_1/SC1CBCOK")
write(cell1_abb, False, "Local/SC_1/SC1CBCPREWARN")
def cell2_abb_close_gripper():
write(cell1_abb, False, "Local/SC_1/SC1CBCOK")
write(cell1_abb, True, "Local/SC_1/SC1CBCPREWARN")
# ---------------- programm ------------ '
velocity(300)
cell1_abb_open_gripper()
do with cell1_abb_0:
move via joint_p2p() to C1_HOME_J
move via p2p() to C1_PICK_2 :: (0, 0, -50, 0, 0, 0)
move via line() to C1_PICK_2
cell2_abb_close_gripper()
wait(1000)
do with cell1_abb_0:
move via line() to C1_PICK_2 :: (0, 0, -50, 0, 0, 0)
move via line() to C1_SCANNER_APPROACH_2
move via line() to C1_SCANNER_2 with velocity(50)
wait(2000)
do with cell1_abb_0:
move via line() to C1_SCANNER_APPROACH_2 with velocity(50)
move via line() to C1_PLACE_2 :: (0, 0, -50, 0, 0, 0)
move via line() to C1_PLACE_2 with velocity(50)
cell1_abb_open_gripper()
wait(1000)
velocity(300)
do with cell1_abb_0:
move via line() to C1_PLACE_APPROACH
move via joint_p2p() to C1_HOME_J
# Bringe back
wait(2000)
do with cell1_abb_0:
move via p2p() to C1_PLACE_2 :: (0, 0, -50, 0, 0, 0)
move via p2p() to C1_PLACE_2 :: (0, 0, 12.8, 0, 0, 0) with velocity(50)
cell2_abb_close_gripper()
wait(500)
do with cell1_abb_0:
move via p2p() to C1_PLACE_2 :: (0, 0, -50, 0, 0, 0)
move via joint_p2p() to C1_HOME_J
move via p2p() to C1_PICK_2 :: (0, 0, -50, 0, 0, 0)
move via p2p() to C1_PICK_2 :: (0, 0, -5, 0, 0, 0)
cell1_abb_open_gripper()
wait(500)
do with cell1_abb_0:
move via joint_p2p() to C1_HOME_J