I am trying to rotate a user frame around its own Z axis using TP. I know this is easy to do in Karel, but I do not have the luxury. Has anyone done anything like this before?
Rotating a User Frame by its own Z axis

Nation 
November 29, 2016 at 6:54 PM 
Thread is Resolved


You can update any coordinate UFrame
PR[GP1:3,1]=651.349 ;
PR[GP1:3,2]=(3.139) ;
PR[GP1:3,3]=1500.34 ;
PR[GP1:3,4]=0 ;
PR[GP1:3,5]=0 ;
PR[GP1:3,6]=AR[1] ;UFRAME[1]=PR[3] ;

That works if the the user frame's z axis is lined up with the robot's z axis, but I need to rotate around the user frame's z axis for a frame in any orientation relative to the robot's coordinate system. A general solution.

I have found two ways to do this, a good way and a hacky way.
Good way: If you purchase the vision support tool option, which is cheap, it includes a matrix math function. Done.
Hacky way: Move the robot to the origin point, with an R offset applied. Set UFrame_num=0, then record LPOS into a PR. Finally, set your UF = to that PR. (In fact it doesn't even have to be at the origin, but that reduces the math you need to do.)
Sent from my VS985 4G using Tapatalk

Hacky way: Move the robot to the origin point, with an R offset applied. Set UFrame_num=0, then record LPOS into a PR. Finally, set your UF = to that PR. (In fact it doesn't even have to be at the origin, but that reduces the math you need to do.)I was originally considering going this way, but while manipulating the $MCR_GRP[1].$MACHINELOCK to lock motion while I did the move, so it was hidden from the user. I didn't as it felt really hacky, as you said.
I did find a way to do it without buying anything, and in TP. I do it by using the matrix representation of a PR to do matrix multiplication manually. Nice thing about this code, is that with two line changes, you can tell it to rotate about a user frame's X or Y axis as well.
Here is my code:
Code
Display More/PROG RZ_UFRAME Macro /ATTR OWNER = MNEDITOR; COMMENT = "Rotate UF about Z"; /APPL /MN : ! AR[1] is the UFrame index ; : ! AR[2] is the amount of ; : ! degrees ; : !Store passed in arguments ; : R[80:ARG 1]=AR[1] ; : R[81:ARG 2]=AR[2] ; : ; : !Check argument values. ; : IF R[80:ARG 1]<1 OR R[80:ARG 1]>9,CALL FAULT(1) ; : IF R[81:ARG 2]<(180) OR R[81:ARG 2]>180,CALL FAULT(1) ; : ; : !Tell the robot to store frames ; : ! as transform rep. ; : $PR_CARTREP=(0) ; : ; : !Store the frame we want to ; : ! shift as transform rep. ; : PR[90:Scratch1]=UFRAME[R[80]] ; : ; : !Force the following PR as a ; : ! cart rep ; : PR[91:Scratch2]=LPOS ; : PR[91,1:Scratch2]=0 ; : PR[91,2:Scratch2]=0 ; : PR[91,3:Scratch2]=0 ; : PR[91,4:Scratch2]=0 ; : PR[91,5:Scratch2]=0 ; : PR[91,6:Scratch2]=R[81:ARG 2] ; : ; : !Frame 9 is a temp storage ; : ! frame. Use it to convert the ; : ! above PR from cart rep to ; : ! transform rep. ; : UFRAME[9]=PR[91:Scratch2] ; : PR[91:Scratch2]=UFRAME[9] ; : ; : !Set PR[92] as a transform rep ; : ! by setting it to an existing ; : ! transform rep. ; : PR[92:Scratch3]=PR[90:Scratch1] ; : ; : !Preform matrix multiplication ; : ! of only the rotation portion ; : ! of the two matricies. ; : PR[92,1:Scratch3]=((PR[90,1:Scratch1]*PR[91,1:Scratch2])+(PR[90,4:Scratch1]*PR[91,2:Scratch2])+(PR[90,7:Scratch1]*PR[91,3:Scratch2])) ; : PR[92,2:Scratch3]=((PR[90,2:Scratch1]*PR[91,1:Scratch2])+(PR[90,5:Scratch1]*PR[91,2:Scratch2])+(PR[90,8:Scratch1]*PR[91,3:Scratch2])) ; : PR[92,3:Scratch3]=((PR[90,3:Scratch1]*PR[91,1:Scratch2])+(PR[90,6:Scratch1]*PR[91,2:Scratch2])+(PR[90,9:Scratch1]*PR[91,3:Scratch2])) ; : PR[92,4:Scratch3]=((PR[90,1:Scratch1]*PR[91,4:Scratch2])+(PR[90,4:Scratch1]*PR[91,5:Scratch2])+(PR[90,7:Scratch1]*PR[91,6:Scratch2])) ; : PR[92,5:Scratch3]=((PR[90,2:Scratch1]*PR[91,4:Scratch2])+(PR[90,5:Scratch1]*PR[91,5:Scratch2])+(PR[90,8:Scratch1]*PR[91,6:Scratch2])) ; : PR[92,6:Scratch3]=((PR[90,3:Scratch1]*PR[91,4:Scratch2])+(PR[90,6:Scratch1]*PR[91,5:Scratch2])+(PR[90,9:Scratch1]*PR[91,6:Scratch2])) ; : PR[92,7:Scratch3]=((PR[90,1:Scratch1]*PR[91,7:Scratch2])+(PR[90,4:Scratch1]*PR[91,8:Scratch2])+(PR[90,7:Scratch1]*PR[91,9:Scratch2])) ; : PR[92,8:Scratch3]=((PR[90,2:Scratch1]*PR[91,7:Scratch2])+(PR[90,5:Scratch1]*PR[91,8:Scratch2])+(PR[90,8:Scratch1]*PR[91,9:Scratch2])) ; : PR[92,9:Scratch3]=((PR[90,3:Scratch1]*PR[91,7:Scratch2])+(PR[90,6:Scratch1]*PR[91,8:Scratch2])+(PR[90,9:Scratch1]*PR[91,9:Scratch2])) ; : ; : !Store the newly rotated frame ; : ! back. ; : UFRAME[R[80]]=PR[92:Scratch3] ; : ; : !Tell the robot to store frames ; : ! as cart rep. ; : $PR_CARTREP=(1) ; /POS /END

Nice bit of code there and free is always good!
The Vision Support Tools is about $200 list price and includes some other nice functions. If you are interested here is what the same code looks like with that option.
Simple case of rotating 90 degrees.

Ha, pretty amazing to see the ~70 lines of code reduced to 6.
For $200 I should have just went that route. Probably a wash at that price. I assumed it would be the Fanuc standard of $500.
Kinda of annoying that on the R30iA controller I could have just dropped in the matrix.pc file and been done. At least this was an interesting challenge.

I know this is easy to do in Karel, but I do not have the luxury.
I do have the luxury, but am wondering how you would achieve this in an easy way in Karel? I can handle rotation matrices, but I'm new to computations/manipulations with rotations expressed in euler angles.
My approach would be:
1) manually express the user frame's WPR rotation as a rotation matrix R_uf
2) multiplying matrix R_uf by a rotation matrix around the specified axis (R_z in your example) to get R_uf' = R_uf*Rz
3) translating R_uf' back into WPR/euler angle representation.
I'm interested to know if I can save some complexity here
EDIT:
The penny might just have dropped.. Would this work:
1) create a new XYZWPR P at the user frame's origin, with the desired rotation around Z (all elements 0, except P.R=[angle])
2) express the position in world coordinates (UF : P)
3) set the outcome as a user frame
and it's as simple as that?
EDIT2: yes it is! just tested it