Two Methods for Obtaining TCP Force

Hi, community

I’m a beginner in UR development. I found two methods for obtaining TCP force within the community. However, the values obtained are inconsistent.

Is my understanding incorrect? Please advise.

demo1: get_wrench_at_tcp()

def get_wrench_at_tool_flange():
	ft= get_tcp_force()  #Tcp force returns the force and torques at the tool flange with base orientation
	t_flange_in_base = pose_trans(get_target_tcp_pose(), pose_inv(get_tcp_offset()))
	flange_rot= pose_inv(p[0, 0, 0,t_flange_in_base[3],t_flange_in_base,[4],t_flange_in_base[5]])
	f= pose_trans(flange_rot,p[ft[0],ft[1],ft[2], 0, 0, 0])
	t= pose_trans(flange_rot,p[ft[3],ft[4],ft[5], 0, 0, 0])
	return [f[0],f[1],f[2],t[0],t[1],t[2]]
end
	
def get_wrench_at_tcp():
	return wrench_trans(get_tcp_offset(),get_wrench_at_tool_flange())
end

demo2: get_tcp_force_tool()

def get_tcp_force_tool():
	force_torque = get_tcp_force()
	force_B = p[ force_torque[0], force_torque[1], force_torque[2], 0, 0, 0 ]
	torque_B = p[ force_torque[3], force_torque[4], force_torque[5], 0, 0, 0 ]
	tcp = get_actual_tcp_pose()
	rotation_BT = p[ 0, 0, 0, tcp[3], tcp[4], tcp[5] ]
	force_T = pose_trans( pose_inv(rotation_BT), force_B )
	torque_T = pose_trans( pose_inv(rotation_BT), torque_B )
	force_torque_T = p[ force_T[0], force_T[1], force_T[2], torque_T[0], torque_T[1], torque_T[2] ]
	return force_torque_T
end

thanks

Hello @DoraBa

The first method you have listed is the one also mentioned inside our UR Script manual on how to use the get_tcp_force() - function.

At first sight the second function does not take the TCP offset into account.

Thanks for you kind reply.

Indeed, the first function (demo1) comes from UR Script Manual, the second function (demo2) comes from universal-robots.com.

At first sight the second function does not take the TCP offset into account.

As you said, I ran two tests:

 # Test A: with default tcp offset p[0,0,0,0,0,0]
	  
      # the first function 
      local wrench_at_tool_flange = get_wrench_at_tool_flange()
      local wrench_at_tcp = wrench_trans(get_tcp_offset(),wrench_at_tool_flange)

      textmsg(""tcp_offset = "", get_tcp_offset())
      textmsg(""wrench_at_tool_flange = "", wrench_at_tool_flange)
      textmsg(""wrench_at_tcp = "", wrench_at_tcp)

      # the second function :get_tcp_force_tool
      local wrench_at_tcp_tool = get_tcp_force_tool()
      textmsg(""wrench_at_tcp_tool = "", wrench_at_tcp_tool)

      # the print
      # tcp_offset = p[0,0,0,0,0,0]
      # wrench_at_tool_flange = [0.197695,4.27879,2.91762,0.222555,0.0324379,0.41454]
      # wrench_at_tcp = [0.197695,4.27879,2.91762,0.222555,0.0324379,0.41454]
      # wrench_at_tcp_tool = p[0.197553,4.27837,2.91824,0.222525,0.032375,0.414562]



 # Test B: with my tcp offset p[0.13576,0.13576,0.12651,0.0145742,-0.0437474,2.31727]
	  
      # the first function 
      local wrench_at_tool_flange = get_flange_wrench()
      local wrench_at_tcp = wrench_trans(get_tcp_offset(),wrench_at_tool_flange)

      textmsg(""tcp_offset = "", get_tcp_offset())
      textmsg(""wrench_at_tool_flange = "", wrench_at_tool_flange)
      textmsg(""wrench_at_tcp = "", wrench_at_tcp)

      # the second function :get_tcp_force_tool
      local wrench_at_tcp_tool = get_tcp_force_tool()
      textmsg(""wrench_at_tcp_tool = "", wrench_at_tcp_tool)

      # the print
      # tcp_offset = 0.13576,0.13576,0.12651,0.0145742,-0.0437474,2.31727
      # wrench_at_tool_flange = [3.64337,-2.21221,2.03934,0.917855,-0.115615,-0.855018]
      # wrench_at_tcp = [-0.858366,4.09975,2.18682,-0.757643,0.37723,-0.155802]
      # wrench_at_tcp_tool = p[-4.04778,-1.22544,2.10728,-0.729278,-0.572403,-0.85287]

Test A proves what you said (ignore the error).

How to interpret “wrench_at_tcp “ and “wrench_at_tcp_tool “ in Test B ?

thanks!