UniversalRobots / Universal_Robots_ROS_Driver

Universal Robots ROS driver supporting CB3 and e-Series
Apache License 2.0
747 stars 401 forks source link

How to run thread from python #668

Closed DejanDj79 closed 9 months ago

DejanDj79 commented 11 months ago

Hi all. I'm trying to control UR5e from python and I managed to make python script that controls arm in a way that arm goes to 3 positions. Now I need to add functionality to control gripper, close and open, between each position. I made a thread on teach pendant that closes and opens a gripper when digital_out[0] is HI. Now my problem is how to call that thread from python script and then when I send command set_digital_out(0, True) from python script then gripper closes and opens.

This is thread that I created on teach pendant

   Program
   Variables Setup
   Robot Program
     Set DO[0]= True 
     Wait DI[0]=HI
   Thread_1
     If digital_out[0] ≟  True 
       RG Grip
       RG Grip
       Set DO[0]= False 
     sync()

In python script I have this functions defined


    def openAndCloseGripper():
       f = open(pkg_path+'/scripts/gripthread4.script', "rb")
       l = f.read(1024)
    while (l):
        tcp_socket.send(l)
        l = f.read(1024)
    rospy.sleep(1)

def sendCommand(cmd):
    cmd = cmd + "\n"
    print(cmd)
    tcp_socket.sendall(cmd.encode())
    rcvd = tcp_socket.recv(4096)
    print(rcvd)   ```

And this is part of code when thread should be called

```#position 1
    pick_pose = geometry_msgs.msg.Pose()
    quat = tfm.quaternion_from_euler(0, 0, pi/2)
    pick_pose.orientation = geometry_msgs.msg.Quaternion(quat[0],quat[1],quat[2],quat[3])
    pick_pose.position.x = -0.25
    pick_pose.position.y = 0.4
    pick_pose.position.z = 0.65
    pick(group, pick_pose, 'string1')
    rospy.sleep(1)
    group.detach_object()
    openAndCloseGripper()

    #position  2
    pick_pose.position.x = 0.0
    pick(group, pick_pose, 'string2')
    rospy.sleep(1)
    group.detach_object()
    openAndCloseGripper()
    sendCommand("set_standard_digital_out(0,True)")

    #position 3
    pick_pose.position.x = 0.25
    pick(group, pick_pose, 'string3')
    rospy.sleep(1)
    group.detach_object()
    openAndCloseGripper()
    sendCommand("set_standard_digital_out(0,True)")```
fmauch commented 11 months ago

Why would you want to do it that way? I'm not sure whether I understand. As far as I understand, you have a gripper that is being controlled by setting digital_output[0] to 0 or 1 respectively.

You could directly set the digital output using the service /ur_hardware_interface/set_io. From the command line this would be

rosservice call /ur_hardware_interface/set_io "fun: 1
pin: 0
state: 1.0"

With this, you could obviously still create a function called openAndCliseGripper() that sets the output once to 0 and then to 1.

DejanDj79 commented 11 months ago

Whel I contacted onrobot regarding issues that I have and they told me that they dont have anything developed for ROS regarding gripper, and also suggest that I can control gripper by creating thread on teach pendant and then activate/deactivate thread by sending signals to digital_out pins. For me it is not important how I will achieve that, only important thing is to control gripper from ROS and python without using teach pendant so if there is another way you can suggest it. It is also important to do it in a way that will not kill main program so the gripper can close and open between each position.

fmauch commented 11 months ago

@masterdeki As far as I understand, calling the set_io service as explained above would be sufficient in your use case right?

DejanDj79 commented 11 months ago

@masterdeki As far as I understand, calling the set_io service as explained above would be sufficient in your use case right?

It is, for setting digital out to 1, but still remains question how to activate thread from python.

urrsk commented 10 months ago

@masterdeki your thread made on the UR teach pendant is started when you start the robot program. In addition, it by default also runs in a while loop, unless you have disabled it.

Here is an example: image

This results in the following urscript code: (when you save the program, it also saves a .script files) image You can see run Thread_1() is called to start the thread, right after the thread is defined. The sync() call makes the while loop sleep until next time step. This prevents it spinning multiple rounds within one time step. You can also use a wait node.

Hope this helps you forward.

DejanDj79 commented 10 months ago

I created program on teach pendant like you show me, but what's next? Should I send this .script file to robot controller over python? When i run program on teach pendant i get error that it cant connect to laptops ip address.There is also a error that gripperState is not initialized in variable setup. What value should gripperState have in initialization?

RobertWilbrandt commented 10 months ago

To add on to what @fmauch was saying: I am not quite sure why you want to use urscript to control the gripper. If you only need to toggle two I/Os to control the gripper you can do that without problems with the set_io service and don't need to make any changes on the urscript side.

As to your errors:

  1. Did you start the ros driver beforehand? You need to start the ros driver before the program on the teach pendant so this error would be expected.
  2. You need to setup the gripperState variable in the variables setup. Typically i would expect the gripper to open on startup (so True) and add a set_standard_digital_out(3, True) to the beginning of the thread (making sure that you are in the correct state at the beginning of the program), but this depends on what you want.
DejanDj79 commented 9 months ago

To add on to what @fmauch was saying: I am not quite sure why you want to use urscript to control the gripper. If you only need to toggle two I/Os to control the gripper you can do that without problems with the set_io service and don't need to make any changes on the urscript side.

As to your errors:

  1. Did you start the ros driver beforehand? You need to start the ros driver before the program on the teach pendant so this error would be expected.
  2. You need to setup the gripperState variable in the variables setup. Typically i would expect the gripper to open on startup (so True) and add a set_standard_digital_out(3, True) to the beginning of the thread (making sure that you are in the correct state at the beginning of the program), but this depends on what you want.
  1. Yes, I did start ros driver, but when i started script it kills ros driver, and that was my main problem.
  2. I did it exactly like that but still script was killing ros driver, and then script works and gripper opens and closes but arm was not moving since ros driver is killed.