How to run a background thread on a UR robot

Based on contributions by Jesse.

A thread runs a piece of URScript in parallel with your main program. Use it for work that shouldn’t block the main program’s execution, such as polling a socket, reading/writing IO, or doing small calculations while the robot keeps moving.

What you need

  • A Universal Robot with PolyScope (thread nodes are available in the program tree) or a text editor if you write raw URScript.
  • Restrictions to keep in mind:
    • Do not move the robot directly from a thread — this can conflict with the main program’s motion and trigger a protective stop.
    • Avoid blocking functions inside a thread (e.g. long waits or blocking socket reads without a timeout) — the thread may not finish in time.
    • Threads cannot take parameters, and any return value is discarded.

Steps

1. Create a thread in PolyScope

Add a Thread node to your program tree. The example below requests data over a socket only while a flag variable (getData) is True, then resets the flag at the end so it doesn’t keep looping:

Set getData = True from your main program whenever you want the thread to fetch new data.

2. Or create a thread in URScript

The same logic written directly in URScript:

thread getSocketDataThread():
  if getData:
    socket_open(IP, port)  # set IP and port to your socket server
    socket_send_string("x y r")
    received = socket_read_ascii_float(4, timeout=0)
    socket_close()
    x = received[1] / 1000
    y = received[2] / 1000
    z = 230 / 1000
    rx = (cos(0.5 * d2r(received[3]))) * 3.14 % 180
    ry = (sin(0.5 * d2r(received[3]))) * 3.14 % 180
    rz = 0
    getData = False
  end
  return False  # unused: thread return values are always discarded
end

:warning: Check: the rx/ry/rz calculation above is taken as-is from the source topic. It converts a single angle into three rotation-vector components using half-angle sine/cosine, but it never multiplies by a rotation axis, so it does not look like a standard axis-angle rotation vector. Verify this math against your own use case before reusing it.

3. Start, wait for, and stop the thread from the main program

thrd = run getSocketDataThread()   # start the thread

join thrd                          # block the main program until the thread finishes

kill thrd                          # stop the thread (and any threads it started) and delete it

Common mistakes

  • Trying to pass arguments to a thread, or relying on its return value — neither works.
  • Calling movej/movel (or similar motion commands) from inside a thread instead of the main program.
  • Using a blocking socket read with no timeout inside a thread, which can stall it indefinitely.

Related


Rewritten and consolidated (Sept 2026) from the original student how-to’s: How to use a Thread on a UR.