Using path_offset_set to offset entire program

Hi there! :grinning:

For context:
A welding program including search routines is created by a worker for an item on a welding table. E.g. the starting position is on the corner of the item.

Now the item is moved e.g. 0.5 meters to the left of where the original position of the item was. (So we need to transpose the program 0.5 meters)

I would like a worker to be able to move the end-effector to the new starting position, e.g. the new X,Y,Z (Maybe also Yaw if possible) of the corner on the new item.

The script will then calculate the offset between where the old item was programmed, and the new item, to offset the entire program (including the search routines.)

Here is some code that I have tried setting up, but it does not currently work as expected, and the movements always remain the same without being offset:

#Recording the start pose of TCP
relative_starting_point = get_actual_tcp_pose()

#This is the original start pose from the program.
pOriginal = p[0.5380162871794699, -0.5486028565561584, 0.41514857359159973, 2.2182829077273887, -2.2131184297607467, -0.004239291622238593]

#Figure out the offset between those two points
pOffset = pose_sub(pOriginal, relative_starting_point)

path_offset_enable()

#I am trying to offset the item at least 50 cm, so I change the limits here:
path_offset_set_max_offset(1, 30)
#Alfa filter value is set very low, or the program wonā€™t run.
path_offset_set_alpha_filter(0.000001)

#Define the offset thread:
thread OffsetFromCamera():
while(True):
#Here, I offset the
path_offset_set([pOffset[0],pOffset[1], pOffset[2],pOffset[3],pOffset[4], pOffset[5]], 2)
sync()
end
end
#Start/Run the offset thread
relative_offset_thread = run OffsetFromCamera()

#From here on out, I just run the rest of the program as is, expecting that the values get offset in cartesian space. E.g as #seen in the line below:
#Is this not the correct way to do it?
movej(get_inverse_kin(pOriginal),1.3962634015954636, 1.0471975511965976, 0,0.001)

Looking forward to your feedback!

Edit:
I guess I could do something like:
relative_starting_point = get_actual_tcp_pose()

pOriginal = p[0.5380162871794699, -0.5486028565561584, 0.41514857359159973, 2.2182829077273887, -2.2131184297607467, -0.004239291622238593]

pOffset = pose_sub(pOriginal, relative_starting_point)

and then manually offset each point in the program by adding the pOffset values to every single point in the program. But that will be very inelegant (and tedious for complex programs)

You really just need to teach the points to a Feature, and then just programmatically change the Featureā€™s pose. Then all the moves that were programmed against that Feature will shift automatically. Path_offset functions are primarily used for modifying a Base path with some superposition of motion, like adding oscillation to create a weave.

1 Like

Perfect, thanks for the feedback!

Anyone with a similar problem, set a userFrame from the current tcp pose.
Then have the starting point of the program something easy to remember like pO.

now calculate pX_pO as the pose_trans(pose_inv(pX), pO)
Lastly, pose_trans(userFrame, pX_pO) should give you a value that can be used for something.

Hey Eric,

How do you change the feature programmatically? I have a custom palletizing program since I canā€™t get the template to work without null pointer exception. I have two layers with identical patterns, just finished programming the bottom layer. I am using the pallet as a feature and would like to change the feature pose by keeping track of ā€˜layerā€™ variable that increments to 2 at the end of layer 1. This will help me avoid having to reprogram layer 2. I am using a switch case with 12 cases, one case per item where I have the locations programmed in based on the pallet feature. I would like to do the feature change at the end of case 12 so my program can restart at the top of the switch but based on a new feature position.

Yep, makes sense to me. You need to use the Assignment node:
image

An important thing to note about Features is they have 2 representations: The one you find in the ā€œposeā€ dropdown box of the Assignment node will have ā€œ_constā€ at the end of it. This cannot be changed, and is ONLY modified when you teach the feature using the wizard. The version of the Feature you see in the VARIABLE dropdown box is the one you want to reassign. So from there you have some options. You can opt to keep pose_adding() from the _const version of the Feature, which would mean your offset values may need to be dynamic, or else if you use the variable version of the plane in your pose_add(), you will be accumulating that translation each time.

The last important thing that can trip you up if you donā€™t remember to do it is to re-assign the variable version of the feature back to the _const version either in the before start, or at the end of your program so it can start fresh. Youā€™d do this with the Assignment node as well.