How do I rotate the wrist 360 with a tcp respected?

Hello, I’m trying to rotate the wrist of a UR5e robot 360 degrees. If I just move from one waypoint to the other 360 rotated the wrist won’t move as it takes the shorted path to a pose and seems to treat 0 deg and 360 deg the same. I can use script commands and rotate the wrist joint 360 deg which would work but my tcp has an xy offset and I want to respect that and rotate about the tcp and not the wrist. I can loop a move command to a variable waypoint and have a thread increase the position, but the waypoint rotation position does not seem linear from say -2pi to 0 to 2pi the values will jump partway skipping over some throwing off my rotation goal also it would do several small rotations not one 360 smooth continuous rotation as I’d like.

Is there a better way or something I’m missing? Any help is appreciated thanks.

@jonny_march Hmm… this is just a thought and urcommunity might have a better solution, but try adding some URscript to your program once the robot has reached the desired waypoint for rotation.


creates TCP pose to rotate about z-axis only, change this sign (+/-) depending on direction needed, also need to convert degrees to radians using d2r() function.

move_wrt_base:=transpose(get_forward_kin(), move_wrt_tool)

get_forward_kin() I believe returns linear coordinates of robots actual/current position and transpose() performs kinematic calculations to translate TCP movement to Base movements of the robot. I need to brush up on my URscript-ese but basically this function allows you translate movement from different frames of reference (e.g. TCP to Base or vice versa Base to TCP)


this movej() can be done with node in polyscope (using a variable waypoint or you can URscript it)

That’s it!

In addition, you can manually move the the robot about the TCP in the “Move” Tab if you want check motion without running program:

  1. go to Installation Tab, check TCP offsets (in your case x and y distances are set) and it is the active TCP
  2. go to Move Tab, in large display window showing robot go to the upper left of window where it says “Feature:” and select “Tool” from drop down menu, by default it should be set to “View”
  3. the robot will now be able to move relative to the TCP, in your case rotating about the z-axis try pressing on the +Rz and -Rz arrows

**WARNING: not sure what your TCP offsets are (hopefully not too large or you will have reach issues) but I HIGHLY recommend you:
A) remove your end-effector (if expensive or fragile)
B) dial all your speeds and accelerations in this movej() WAY WAY down and increase as necessary, start out conservative as you may reach a singularity or generate a collision with arm.
C) always stand a safe distance away from robot and dial the speed slider down until comfortable with movement

Warnings are probably alittle excessive/extreme but in general are good practice after learning the hard way ruining an end-effector and/or pretzeling the robot a few times.

Anyways information overload and I hope I don’t scare ya, but hope that helps and best of luck!

If you are using standard Polyscope for your moves , just check the “Use Joint Angles” checkbox under the MoveJ’s properties.

Polyscope saves all waypoints as both a Pose and a JointPositions. This can be seen by selecting the “Variables” tab and checking the “Show Waypoints” checkbox at the bottom. The waypoints will have a “_p” or “_q” suffix for Pose or JointPositions respectively. image

When checking the “Use Joint Angles” checkbox, it will use the _q value and should just roll around your TCP.

1 Like

Thanks for the suggestions guys. But I tried both and the robot still treats 360 and 0 as the same so it doesn’t rotate.

You’re sure you’ve selected a MoveJ and checked “Use Joint angles”? I have done exactly this to rotate a part through the field of view of a camera. -360 degrees to +360 degrees. It may be beneficial to upload some of your code.

Yes I’m using moveJ and selected use joint angles.

My code simplified w/o gripper commands to:

moveJ Waypoint0

current_pose = get_actual_tcp_pose() - If this is changed to joint positions, it’ll rotate the wrist the correct amount but then my TCP is not respected

current_pose[5] = current_pose[5] +d2r(360) or current_pose = pose_add(current_pose, p[0,0,0,0,0 d2r(360)]) - Does not work/rotate

force - frame: x-0, y-0

So you are trying to rotate 360 degrees about a TCP that is off-center from the robot flange, is that correct?

Edit: Just re-read your post. Yes this is what you’re trying to do. You’re correct then in that the joint positions will not rotate around your TCP. You’ll have to do some pose_trans() magic. Lemme play around a bit and see if I can come up with that

Edit2: OK so my robot’s tool has cables such that it cannot really rotate 360 degrees about the TCP, but you might be able to just use a relative waypoint (jogging around your tool’s Z). If that still doesn’t work, you could try breaking the 360 degree move into 2 180 degree moves to trick the robot into moving

I’ve experienced this a few times as well. I teach a position manually then when I run the program it rotates 360 to get to the position. I have an air line attached to this TCP so it will wind around the robot arm and pull it loose. On the other robot it will just hit the limit and alarm out.

I’ve tried intermediate positions and it gives varied results.

This is an un-acceptable behavior IMO and would appreciate someone from UR explaining how to fix this.


Yes, my tcp is slightly off-center from the flange center unfortunately. I can do two rotations of 179 so it’s less than 180 so the rotation is correct, but I want one movement of constant speed. I’m going to try and see if the speedl command will work for me.

Sounds like your starting angle may be different between robots if one is hitting a limit and the other isn’t.

Update: The speedl command seems to work, it’s not ideal as the movement is time based, so I must calculate how long a move should take using the acceleration and velocity and then plug all three of those values into speedl. The position isn’t perfect from the time calculation (theoretical vs actual I think is the issue) but it should be close enough for what I’m doing.

1 Like

What I meant was the air line on the one robot may pull out and then the robot hits the limit. I don’t run the same programs on both robots. But both robots exhibit that same behavior at times and I have not figured out what causes it or how to work around it.

No clue on your particular application, but for one of mine I needed to spin a part through a camera’s field of view until finding a barcode, then rotate the part an additional 180 degrees so the code was facing out. I needed to add some code that checked the current value of wrist 3, and if adding 180 degrees to it would put it beyond its limit, I instead subtracted 180 degrees (and then used a few relative moves before going back to absolute positioning.) Maybe you can incorporate some sort of similar logic?

1 Like

Here is a section of code I use to check the wrist then spin in the positive or negative direction to get back close to 0 so I don’t hit limits. I use 2 steps here. I have used loops with smaller steps until a specific angle is reached as well. Both have worked well to reorient the gripper attached to wrist 3.


Hi there,
I went also through this dumb issue and dealt with it for days before finding a workaround by chance…
I had to address the point to my dealer who didn’t have more success with the 360° rotation trials, then he contacted UR who gave a tip by using the get_inverse_kin() function (don’t ask me why this one :face_with_raised_eyebrow:) )
Fiddling with this I finally found a piece of simple code that works without using this function:


then move to var_2 as variable point (in polyscope or with the move command of your choice)

Hope this may help :slightly_smiling_face: