Ever since Pally v2.6.0, it has been possible to change the robot’s movements to fit your palletizing project!

This page describes the general outline of when and how to use the custom path feature:

In the sub-pages, important variables that must be used in the custom path are explained.


Using the custom path feature, Pally will still use the positions you have calibrated in the Pally program node; such as:

However, after the robot has picked up the box from the pickup position, then your custom robot path can take over and move the robot to place the box in its target position1 on the pallet. Once the box has been placed on the pallet, your path must then move the robot back towards the pick up position.

To create your custom path, you must be able to program the robot using URScript commands. Refer to Universal Robot’s URScript API reference for more details: URScript API Reference (2018)

When to Use It?

If there are some problematic boxes in your palletizing routine where the robot crashes or the Pally robot movements do not achieve the desired result, then a solution could be to use the custom path feature.

By using the custom path feature, you are responsible for all the robot’s movements between the pick up position and the box’s position on the pallet (and back again).

It is possible to only use the custom path feature on certain problematic boxes, and then use the path provided by Pally for the remaining boxes. This can be achieved by setting the rf_custom_path variable to False / True. Refer to the page explaining this variable: rf_custom_path

How to Use It?

To actually use the custom path feature in Pally, you must use URScript commands and define two functions: (1) for moving the robot to the target position and (2) for moving the robot back towards the pick up position. These two functions need to be called in the Pally callbacks afterGrab and afterRelease respectively. The robot program should then look something like this:

A Pally program where a customized path is used

In the example above, the customPath.script-file contains URScript code that defines the two functions, MoveToTarget() and MoveBack(); where MoveToTarget() is used to move the robot from the pick up position to the target position and MoveBack() (obviously) moves the robot back towards the pick up position. Here is an example of how the customPath.script could be defined:

p_boxfree = p[0,0,0,0,0,0]
p_boxfree2= p[0,0,0,0,0,0]
p_boxfree3= p[0,0,0,0,0,0]
p_exit= p[0,0,0,0,0,0]
j_exit = [0,0,0,0,0,0]
p_approach = p[0,0,0,0,0,0]
p_waypoint = p[0,0,0,0,0,0]

rf_custom_path = True

def GetBlend(to_point, next_point):
  this_point = get_actual_tcp_pose()
  d1 = point_dist(this_point, to_point)
  d2 = point_dist(to_point, next_point)
  if (d1 < d2):
    return d1 * 0.25
  else:
    return d2 * 0.25
  end
end

def MoveToTarget():

if (rf_custom_path):
  
  # move up
  p_boxfree = pose_trans(get_actual_tcp_pose(), p[0,0,-rf_box_free,0,0,0])

  # move closer to the robot
  p_boxfree2= p_boxfree
  d = sqrt(rf_camera[0] * rf_camera[0] + rf_camera[1] * rf_camera[1]) / sqrt(p_boxfree2[0] * p_boxfree2[0] + p_boxfree2[1] * p_boxfree2[1]) 
  p_boxfree2[0] = p_boxfree2[0] * d
  p_boxfree2[1] =  p_boxfree2[1] * d

  # move up
  p_boxfree3= p_boxfree2 
  if (MoveTarget[2] + ProductHeight > p_boxfree3[2]):
    p_boxfree3[2] = MoveTarget[2] + ProductHeight
  end

  # move away from the conveyor and rotate
  if (PalletNr == 1): # right pallet
    p_exit = pose_trans(p[-0.35, 0, 0, 0, 0, 0], p_boxfree3)
  else: # left pallet
    p_exit = pose_trans(p[0.35, 0, 0, 0, 0, 0], p_boxfree3)
  end

  p_exit[3] = MoveTarget[3]
  p_exit[4] = MoveTarget[4]
  p_exit[5] = MoveTarget[5]

  # approach the pallet
  if (PalletNr == 1): # right pallet
    p_approach = pose_trans(p[0.05, -0.05, 0.05, 0, 0, 0], MoveTarget)
  else: # left pallet
    p_approach = pose_trans(p[-0.05, -0.05, 0.05, 0, 0, 0], MoveTarget)
  end

  # this may be actual for the top layer:
  # the approach should be closer than usual to have enough reach

  if (not is_within_safety_limits(p_approach)):
    # should not use normally
    p_approach = MoveTarget
  end


  # a waypoint before approach
  p_waypoint = p_approach
  if (p_waypoint[2] < p_boxfree[2]):
    p_waypoint[2] = p_boxfree[2]
  end

  if (p_waypoint[2] < MoveTarget[2] + ProductHeight + rf_approach[2]):
    p_waypoint[2] = MoveTarget[2] + ProductHeight + rf_approach[2]
  end

  movel(p_boxfree, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_boxfree, p_boxfree2))
  movel(p_boxfree2, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_boxfree2, p_boxfree3))
  movel(p_boxfree3, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_boxfree3, p_exit))
  movel(p_exit, a=rf_max_acceleration, v=rf_speed, r=0.01)
  j_exit = get_actual_joint_positions()
  if (is_within_safety_limits(p_waypoint)):
    movej(p_waypoint, a=rf_max_acceleration, v=rf_speed, r=0.01)
    movel(p_approach, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_approach, MoveTarget))
  else:
    movej(p_approach, a=rf_max_acceleration, v=rf_speed, r=0.01)
  end
  movel(MoveTarget, a=rf_precise_acceleration, v=rf_precise_speed, r=0)
  MovePerformed=True
end
end

def MoveBack():
if (rf_custom_path):
  if (is_within_safety_limits(p_waypoint)):
    movel(p_waypoint, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_waypoint, p_exit))
  else:
    movel(p_approach, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_approach, p_exit))
  end
  movej(j_exit, a=rf_max_acceleration, v=rf_speed, r=0.01)
  movel(p_boxfree3, a=rf_max_acceleration, v=rf_speed, r=GetBlend(p_boxfree3, p_boxfree2))
  movel(p_boxfree2, a=rf_max_acceleration, v=rf_speed, r=0)
  MovePerformed=True
end
end

An example of how MoveToTarget() and MoveBack() functions can be defined in the customPath.script

You may define the customPath.script as you wish! This is just an example.

The names of the functions MoveToTarget() and MoveBack() is also not of importance, though they must be called in the afterGrab- and afterRelease-callbacks.

To add these script commands, add a ‘Script’-node by pressing the ‘Script’-button in Polyscope:

Important Variables for Custom Path

Pally makes it easier for you to create a custom path by making all the necessary variables available through global variables. The important global variables you must use for the custom path feature are as follows:

Click on the links to be re-directed to the pages explaining each variable in more detail.

Footnotes:

note

1The target position for the current box according to your selected pattern is one of many global variables made available to you via Pally.

1The target position for the current box according to your selected pattern is one of many global variables made available to you via Pally.