Guide and example: UR Remote Control via TCPIP

UR Remote Control via TCPIP

Note: the original note was written in Chinese, and translated to English by AI tool, if something unclear or wrong, would you please comment the proper description. thanks.
for chinese version, just search 远程控制 in Forum

Universal Robots, as the world’s first collaborative robot, is widely used in various factory automation scenarios for its safety, flexibility, and user-friendliness. Its open system development also gives it an advantage in fields such as integrated products, educational research, and application ecosystems. Whether in industrial scenarios with composite robots, emerging service robots, or the latest artificial intelligence algorithm experiments, Universal Robots can be seen. In such applications, robots mainly serve as executive mechanisms, with their motion trajectories generated and controlled by upper-level computer programs based on tasks and external environments, known as remote control.

There are many methods to achieve remote control in Universal Robots systems. This article will focus on how to remotely control them via TCP/IP clients to perform functions including power on/off, data acquisition, data transmission, and motion control.

1. Preparation

1.1 Hardware

  • Option 1: A Computer + URSim
    Suitable for: Initial development; when the robot is not available
    URSim is the offline simulator for Universal Robots, mirroring the characteristics of a real robot controller, including programming instructions, motion control, and communication interfaces like TCP/IP and Modbus. URSim is available for free download from the official website https://www.universal-robots.com/download/?query=URsim.
    It’s worth noting that URSim software is divided into Linux and Non-Linux versions. The Linux version can be directly installed on Linux systems; the Non-Linux version is a virtual machine image that requires software like Vmbox to load. In general, it is recommended to install the Non-Linux version. Installation instructions can be found on the corresponding download page.

    Fig 1.1 URsim E-series controller version 5.11.5. This virtual machine includes all E-series robot models, click on the icon to open the corresponding controller.
  • Option 2: A Computer + A UR Robot + Ethernet Cable
    Suitable for: Anytime with the robot
    Make the real robot move with a computer, but be careful not to have fragile items around!

    Fig 1.2 Computer connected to the robot. Refer to the corresponding robot user manual for detailed Ethernet port specifications.

1.2 Software

  • Network Debugging Tool
    Use network debugging tools like Network Debugging Assistant for initial verification and port testing.

    Fig 1.3 Network Debugging Assistant, connect to the robot’s 29999 dashboard port, send commands to power on the robot.
  • Programming Software
    Choose a familiar programming language and IDE for development and testing.

2. Connecting UR Robot

Establishing communication between the host computer and the robot is fundamental for remote operations. This section explains how to connect the UR robot to the host computer and open the UR robot through the Dashboard port.

2.1 Setting Robot IP

Click on the icon of three horizontal lines in the upper right corner of the robot’s operating interface (referred to as the hamburger menu by UR) to enter the settings interface. Under the System menu, there is a network settings interface. Here, set the robot’s IP address as needed.


Fig 2.1 Setting the IP address of the UR robot, a “Network is connected” indication will appear upon successful connection

When using URSim in a virtual machine, the virtual machine’s IP address is the robot controller’s address. To facilitate communication with the host machine, it is recommended to set the virtual machine network to “Host-only Adapter.”


Fig 2.2 Setting the virtual machine network to Host-only in VMbox

2.2 Controlling the Robot through the Dashboard Port

The UR dashboard port, port number 29999, allows the host computer to send a series of specified command statements to the robot to control basic functions such as powering on/off, loading programs, checking robot status, and setting robot operating modes. Instructions can be found here:

Taking E-Series as an example:

  • The Command column shows available commands, which must be strictly formatted when sending;
  • The Return Value column indicates the robot’s response, useful for monitoring command execution success;
  • The Description column provides an explanation of the command;
  • The Only Remote Control column with an “x” symbol indicates that the command can only be executed when the robot is in remote mode (a feature introduced in the E-Series to prevent multi-terminal control, refer to the E-Series robot user manual for details);
  • The Supported in Version column is not significant; executing the command is possible after upgrading the robot to the latest version.
    fig2.3 Dashboard Command Table
    Fig 2.3 Screenshot of the E-Series Dashboard Command Table

When sending commands to the Dashboard port from the host computer, they should end with a newline character “\n,” for example:

power on\n

In Python programming:

import socket

mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# change the robot IP address here
host = '192.168.56.103'
port = 29999

mySocket.connect((host, port))
print(mySocket.recv(4096).decode())
mySocket.send("robotmode\n".encode())
print(mySocket.recv(4096).decode())
mySocket.close()

In practical applications, besides powering on/off and loading programs, the “unlock protective stop” and “close safety popup” commands are also practical. Users can test and deploy them according to their needs.

3. Obtaining UR Robot Data

Using the Dashboard port allows for a “question and answer” style of information retrieval, with limited information. How can real-time data such as robot position, speed, and acceleration be obtained?
In the UR robot system, several types of ports can achieve this: low-frequency ports (30001 & 30002), real-time port (30003), and custom port (30004).

  • Low-frequency ports (30001 & 30002) send data in a fixed format to the client at a 10Hz rate, used for communication between the robot teach pendant and controller;
  • Real-time port (30003) sends data at a maximum of 125Hz (CB-Series) or 500Hz (E-Series) in a fixed format to the client;
  • Custom port (30004) sends customized data to the client at a customized frequency (up to 125Hz or 500Hz).

3.1 Low Frequency Ports 30001 30002

In the Universal Robots system, ports 30001 and 30002 are referred to as primary and secondary interfaces respectively. Port 30001 transmits robot state information (such as speed, acceleration, program status) and additional robot information (safety status, error codes, pop-up messages) to the external environment. On the other hand, port 30002 only sends out robot state information. In essence, port 30002 sends a fixed data packet, whereas port 30001, in addition to this fixed data packet, may send other data packets as needed, for instance, in the event of a robot error, an additional error code data packet will be sent. For detailed information, refer to https://s3-eu-west-1.amazonaws.com/ur-support-site/16496/ClientInterfaces_Primary.pdf

Format of Port Information

Port information is always transmitted in a header + content format. Taking the shared robot state information in ports 30001 and 30002 as an example:

  • The gray section represents the header, with the first 4 bytes indicating the data packet length and the fifth byte indicating the data packet type.
  • The blue section represents the content starting from the sixth byte. As this data packet contains some sub-packets, there will be headers and content for these sub-packets as well.

fig3.1 message format

fig3.1 message format of messages sent to primary and secondary clients

fig3.2 robot state message structure, messageType=16

Interpreting Port Information

Connect to the URSim 30001 port using software debugging tools to capture a frame of data (in hexadecimal):

00 00 02 CC 10 00 00 00 2F 00 00 00 00 00 06 63 E5 10 01 01 01 00 00 01 00 07 00 3F F0 00 00 00 00 00 00 3F F0 00 00 00 00 00 00 3F F0 00 00 00 00 00 00 00 00 00 00 FB 01 BF F9 9C 77 9A 6B 50 B0 BF F9 9C 77 9A 6B 50 B0 00 00 00 00 00 00 00 00 A3 95 12 CF 00 00 00 00 41 CC 00 00 00 00 00 00 FD BF FB A2 33 9C 0E BE E0 BF FB A2 33 9C 0E BE E0 00 00 00 00 00 00 00 00 40 12 2D 4A 00 00 00 00 41 C8 00 00 00 00 00 00 FD C0 01 9F BE 76 C8 B4 38 C0 01 9F BE 76 C8 B4 38 00 00 00 00 00 00 00 00 3F CE DA B6 00 00 00 00 41 C4 00 00 00 00 00 00 FD BF E9 DB 22 D0 E5 60 40 BF E9 DB 22 D0 E5 60 40 00 00 00 00 00 00 00 00 3E 92 6C 8B 00 00 00 00 41 C0 00 00 00 00 00 00 FD 3F F9 85 87 93 DD 97 F6 3F F9 85 87 93 DD 97 F6 00 00 00 00 00 00 00 00 3B 2F 79 9B 00 00 00 00 41 BC 00 00 00 00 00 00 FD BF 9F BE 76 C8 B4 39 00 BF 9F BE 76 C8 B4 39 00 00 00 00 00 00 00 00 00 B9 CC 65 32 00 00 00 00 41 B8 00 00 00 00 00 00 FD 00 00 00 65 04 BF C2 6D 90 A0 1D E7 77 BF DB E1 32 F6 A8 66 44 3F C9 DC 1E B0 03 31 E6 BF 54 02 C0 F8 E6 E6 79 40 08 EE 22 63 78 FA E0 3F A3 E9 A4 23 7A 7B 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 35 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 4B 03 00 00 00 00 00 00 00 08 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F 70 62 4D E0 00 00 00 3F 70 62 4D E0 00 00 00 41 C0 00 00 42 40 00 00 00 00 00 00 00 00 00 00 01 00 00 EB CF B6 4C 01 01 01 00 00 00 25 02 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FD 00 00 00 3D 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F 6C F5 AC 1D B9 A1 08 00 00 00 09 08 00 01 00 01 00 00 00 2B 0A EB CF B6 4C 01 01 BF B8 4D C2 84 9F ED CF BF B0 37 9E D0 87 BA 97 3F E2 A2 5B 78 C3 9F 6C 3F C0 A3 D7 0A 3D 70 A4 00 00 00 1A 0B 00 00 01 C2 00 00 00 00 00 00 00 00 01 3F C0 00 00 40 60 00 00 00 00 00 08 0C 00 01 01 
  • The first 4 bytes 00 00 02 CC indicate a data packet length, which equals 716 bytes in decimal.
  • The fifth byte 10 represents data packet type 16, which according to the documentation corresponds to MESSAGE_TYPE_ROBOT_STATE = 16, indicating a robot state data packet.
  • The remaining bytes contain specific content that can be interpreted based on the data explanation documentation.

Below is an example of how to interpret other data sent solely through port 30001, such as alarm code information.
fig3.3 robot comm message structure
fig3.3 robot comm message structure

To trigger an alarm on the robot:


fig3.4 protective stop, C150A0

Capture a frame of data with a different length using a program or network debugging tool:

00 00 00 23 14 00 00 00 00 30 65 8E 90 FE 06 00 00 00 96 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 
  • The first 4 bytes 00 00 00 23 indicate a data packet length, which is 35 in decimal.
  • The fifth byte 14 represents data packet type 20, which corresponds to MESSAGE_TYPE_ROBOT_MESSAGE.
  • Bytes 6-13 00 00 00 00 30 65 8E 90 represent a timestamp.
  • The 14th byte FE indicates the source, which in decimal is -2 (in two’s complement), identified as MESSAGE_SOURCE_ROBOTINTERFACE according to the reference table.
  • The 15th byte 06 represents robotMessageType 6, i.e., ROBOT_MESSAGE_TYPE_ERROR_CODE.
  • Bytes 16-19 00 00 00 96 represent robotMessageCode, which converts to 150 in decimal.
  • Bytes 20-24 00 00 00 00 represent robotMessageArgument, converting to 0 in decimal.
  • The 25th byte 02 indicates robotMessageReportLevel, which converts to 2 in decimal, identified as REPORT_LEVEL_WARNING according to the reference table.
  • Other bytes can be parsed according to the list in fig3.3.

According to the analysis, this data packet contains error code information, categorized as an alarm, with error code keywords 150 and 0, i.e., C150A0, matching the information in fig3.4.
If the principles of data parsing are clear, the above process can be automated through program code, for example using Python:

import socket
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '192.168.56.103'
port = 30001
mySocket.connect((host, port))

print("get error code:")
while True:
    msg = mySocket.recv(4096)
    msgHEX = msg.hex()
    Totalsize = msgHEX[0:8]
    msgType = msgHEX[8:10]
    # check if the msg type is MESSAGE_TYPE_ROBOT_MESSAGE
    if int(msgType, 16) == 20:
        msgType_2 = msgHEX[28:30]
        # check if the msg type is ROBOT_MESSAGE_TYPE_ERROR_CODE
        if int(msgType_2, 16) == 6:
            ErrCodeFirst = msgHEX[30:38]
            ErrCodeSec = msgHEX[38:46]
            # print(f"raw data:{msgHEX}")
            print(f"Error code: C{int(ErrCodeFirst, 16)}A{int(ErrCodeSec, 16)} ")
            break
    else:
        print("normal")

When an error occurs, the program outputs:

Error code: C150A0

3.2 Real time Port 30003

In the Universal Robots system, 30003 is referred to as the real-time interface, with data transmission content and format similar to port 30002, but with a higher frequency. The CB series and E series can achieve frequencies of 125Hz and 500Hz respectively. For detailed information, refer to https://s3-eu-west-1.amazonaws.com/ur-support-site/16496/ClientInterfaces_Realtime.pdf.

Format of Port Information

The information on port 30003 also consists of a header and content, but this port only has one data packet, hence the header only contains the data packet length without type variables.


fig3.5 part of the realtime interface data list

Parsing Port Information

Due to the simplified information format, the parsing process is simpler, without the need to determine the data packet type. Simply extract and parse the received information according to the data table.
Connect URSim to port 30003 using software debugging tools to obtain a frame of data (in hexadecimal). You can try to parse its TCP position and other information.

00 00 04 C4 40 A5 F4 C2 8F 5C 28 F5 3F A1 DF 50 1C F3 6B 80 BF FB A2 33 9C 0E BE E0 C0 01 9F BE 76 C8 B4 38 BF E9 DB 22 D0 E5 60 40 3F F9 85 87 93 DD 97 F6 BF 9F BE 76 C8 B4 39 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BC 92 0F B1 44 3A 56 73 40 0D 5E 6D 01 0F 61 94 40 09 61 77 7E 3E 6D 99 3F D3 E9 45 7F F3 FF 31 3F 62 86 A7 61 4C 26 4A 00 00 00 00 00 00 00 00 BC CB 4A 36 DF 00 00 00 40 46 30 05 33 C9 2C 3C 40 3F 81 67 93 15 62 61 40 0B 09 D0 77 98 5F A8 3F 99 28 43 57 70 EA 82 00 00 00 00 00 00 00 00 3F A1 DF 50 1C F3 6B 80 BF FB A2 33 9C 0E BE E0 C0 01 9F BE 76 C8 B4 38 BF E9 DB 22 D0 E5 60 40 3F F9 85 87 93 DD 97 F6 BF 9F BE 76 C8 B4 39 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BC 92 0F B1 44 3A 56 73 40 0D 5E 6D 01 0F 61 94 40 09 61 77 7E 3E 6D 99 3F D3 E9 45 7F F3 FF 31 3F 62 86 A7 61 4C 26 4A 00 00 00 00 00 00 00 00 BC 92 0F B1 44 3A 56 73 40 0D 5E 6D 01 0F 61 94 40 09 61 77 7E 3E 6D 99 3F D3 E9 45 7F F3 FF 31 3F 62 86 A7 61 4C 26 4A 00 00 00 00 00 00 00 00 3F E3 DC A7 9B 7A 64 E2 BF C3 2A E9 F0 BA 4D 93 3F D0 B3 C0 55 35 DF E3 40 02 55 EC E3 74 2B 70 C0 01 2B B4 3A CB AB 1B BF AC 6D B8 68 89 0B AD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F E3 DC A7 9B 7A 64 E2 BF C3 2A E9 F0 BA 4D 93 3F D0 B3 C0 55 35 DF E3 40 02 55 EC E3 74 2B 70 C0 01 2B B4 3A CB AB 1B BF AC 6D B8 68 89 0B AD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 39 80 00 00 00 00 00 40 39 00 00 00 00 00 00 40 38 80 00 00 00 00 00 40 38 00 00 00 00 00 00 40 37 80 00 00 00 00 00 40 37 00 00 00 00 00 00 3F BD 56 F3 2B DC 26 DD 40 00 00 00 00 00 00 00 40 1C 00 00 00 00 00 00 40 6F A0 00 00 00 00 00 40 6F A0 00 00 00 00 00 40 6F A0 00 00 00 00 00 40 6F A0 00 00 00 00 00 40 6F A0 00 00 00 00 00 40 6F A0 00 00 00 00 00 3F F0 00 00 00 00 00 00 40 06 D3 86 C4 91 33 00 40 20 8B B7 BA 7E 5A 68 40 1C 32 26 77 BA 6A 04 40 0B B2 1B 3A 40 28 D7 40 03 4F B4 93 AC E5 83 3F ED 74 CE 5F 7D B9 9C BF CF 85 C5 D2 DF FA 13 3F CF 5A 28 B9 E6 3C 11 C0 23 A0 B1 A4 A7 53 E8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 48 00 00 00 00 00 00 40 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F F0 00 00 00 00 00 00 3F B9 79 55 89 66 D2 04 BF BD D9 61 C3 55 D9 61 3F E9 26 58 6D A3 13 D7 80 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F F0 00 00 00 00 00 00 40 48 80 00 00 00 00 00 40 41 80 00 00 00 00 00 00 00 00 00 00 00 00 00 3F B9 99 99 99 99 99 9A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3F 01 4D 2F 5D BB 9C FA 3F 01 4D 2F 5D BB 9C FA 3F 01 4D 2F 5D BB 9C FA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

In port 30003, a frame of data consists of 1220 bytes. While much of this information may not be necessary for users, the transmission of large amounts of high-frequency data can lead to communication issues. Due to this, port 30003 has been discontinued, with Universal Robots recommending the use of port 30004 in scenarios requiring higher real-time performance, i.e., RTDE (Real-time Data Exchange).

3.3 Custom Port 30004

In the Universal Robots system, port 30004 is known as the real-time data exchange interface, RTDE. The information transmitted through this port is user-configurable, including robot status and some registers. For detailed information, refer to https://www.universal-robots.com/articles/ur/interface-communication/real-time-data-exchange-rtde-guide/.


fig3.6 part of configurable RTDE outputs

Format and Parsing of Port Information

The format and parsing method of port 30004 are similar to the previous ports and can be operated according to the RTDE manual.
For user convenience, Universal Robots provides a function library for using RTDE, including:

With the function library, users can focus more on application deployment without spending excessive effort on basic information parsing and communication handling. The following example illustrates how to use the RTDE Python library to retrieve robot information.

In the downloaded RTDE library, the information in the control_loop_configuration.xml file represents the configured input and output information types. The names and types in the configuration information should be filled in according to the information in the RTDE protocol manual, for example:

<recipe key="state">
	<field name="target_q" type="VECTOR6D"/>
	<field name="target_qd" type="VECTOR6D"/>
	<field name="output_int_register_0" type="INT32"/>
</recipe>

The example_control_loop.py file is an example of receiving robot information and controlling robot movement by sending information. This section first explains how to receive information. Modify the code loop section to:

while keep_running:
    # receive the current state
    state = con.receive()
    if state is None:
        break;
    # do something...
    print(state.target_q)
    # comment all other lines in while loop

After correctly setting the ROBOT_HOST address in the program, connect to URSim and run the Python program to output:

target joint position:
[0.03490686753658334, -1.7271, -2.2029999999999994, -0.8079999999999998, 1.5951, -0.030999999999999694]
target joint velocity:
[-0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

4. Controlling UR Robot Movement

Finally back to the main topic, how to remotely make the robot move? The ports 30001/30002/30003/30004 introduced in the previous section can all achieve this function, categorized based on the form of information sent by the host computer into two types:

  • Sending Script (30001/30002/30003): The host computer directly sends UR script commands to the controller, without the need for a program running on the robot
  • Sending Data (30004): The host computer sends register data to the controller, requiring a program running on the robot to read and use the register data

In addition, the E-series robots have developed a new feature called interpreter mode, which is not detailed here as it is not compatible with the CB series, but can be referenced in the E-series script manual.

4.1 Sending Script

Firstly, let’s introduce URScript. Universal Robots is renowned for its simple and user-friendly graphical programming interface, which is the preferred programming method for most users operating Universal Robots. However, it also supports traditional code-style programming and has developed and opened up a relatively simple and easy-to-learn programming language called URScript. Any program written in the graphical interface can be accomplished using URScript. URScript is a programming language similar to Python, encompassing functionalities such as variable definition, flow control, mathematical operations, motion control, and IO control. For more details, refer to:


fig4.1 program GUI

The UR script code to implement the above program is as follows:

def test_move():
  global P_start_p=p[.620685390156, -.149747126143, .260971148694, 2.291955735190, -2.146339854565, -.055524599801]
  global P_mid_p=p[.620685390102, -.149747126145, .372113482044, 2.291955735190, -2.146339854565, -.055524599800]
  global P_end_p=p[.620685390051, -.149747126147, .465855815391, 2.291955735190, -2.146339854565, -.055524599800]
  while (True):
    movel(P_start_p, a=1.2, v=0.25)
    movel(P_mid_p, a=1.2, v=0.25)
    movel(P_end_p, a=1.2, v=0.25)
  end
end

The above script program is written according to the script manual, and instructions or functions can be found in the manual, such as the linear motion movel:


fig4.2 movel description

Sending Single-Line Scripts

Single-line scripts can be directly sent to control the robot through ports 30001-30003. When sending, it is similar to the Dashboard interface, requiring a newline character “\n” at the end. For example, setting digital output 0 to high level:
Connect to port 30001 on URSim and send the following command

set_standard_digital_out(0, True)\n

You can observe that the I/O interface displays digital output 0 as a high level

Sending Multi-Line Scripts

When the robot receives scripts through ports 30001-30003, it is non-buffered, meaning the robot always executes the latest received script instructions and interrupts the previous ones. To achieve continuous motion as in fig4.1, the method is to write multi-line scripts in a function form and send them all at once. Using the Python language as an example:

import socket

mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# change the robot IP address here
host = '192.168.56.103'
port = 30001

mySocket.connect((host, port))

script_text="def test_move():\n" \
            "   global P_start_p=p[.6206, -.1497, .2609, 2.2919, -2.1463, -.0555]\n" \
            "   global P_mid_p=p[.6206, -.1497, .3721, 2.2919, -2.1463, -.0555]\n" \
            "   global P_end_p=p[.6206, -.1497, .4658, 2.2919, -2.1463, -.0555]\n" \
            "   while (True):\n" \
            "     movel(P_start_p, a=1.2, v=0.25)\n" \
            "     movel(P_mid_p, a=1.2, v=0.25)\n" \
            "     movel(P_end_p, a=1.2, v=0.25)\n" \
            "   end\n" \
            "end\n"

mySocket.send((script_text + "\n").encode())
mySocket.close()

After sending the above script, if the robot has received it, you can record a message Program test_move started in the teaching pendant’s Log interface. If this message does not appear, it indicates that the script has not been received or there is a format error.

4.2 Sending Data

While sending scripts directly to the controller via ports is convenient, it may be challenging to implement in applications that require real-time feedback, parallel operation with robot programs, and strong timeliness.

The RTDE port allows sending information such as registers and IO control words to control robot movements. Configuration is necessary for sending information; for detailed instructions, refer to the RTDE guide at https://www.universal-robots.com/articles/ur/interface-communication/real-time-data-exchange-rtde-guide/


fig4.3 part of configurable RTDE inputs

The rtde Python library and C++ library mentioned in section 3.3 serve as comprehensive rtde libraries, including functions for sending data to the robot. The example demonstrates how to send data to registers using the Python library and implement motion on the robot.

Begin by configuring the input information type in the control_loop_configuration.xml file. The name and type in the configuration information should be filled in according to the information in the RTDE protocol manual:

<recipe key="setp">
	<field name="input_double_register_0" type="DOUBLE"/>
	<field name="input_double_register_1" type="DOUBLE"/>
	<field name="input_double_register_2" type="DOUBLE"/>
	<field name="input_double_register_3" type="DOUBLE"/>
	<field name="input_double_register_4" type="DOUBLE"/>
	<field name="input_double_register_5" type="DOUBLE"/>
</recipe>

The example_control_loop.py file is an example of receiving robot information and controlling robot motion by sending information. Add the following code to the program written in section 3.3:

while keep_running:
  # leave the output part used in #3.3 up here
  setp_list = [.6206, -.1497, .2609, 2.2919, -2.1463, -.0555]
  setp.input_double_register_0 = setp_list[0]
  setp.input_double_register_1 = setp_list[1]
  setp.input_double_register_2 = setp_list[2]
  setp.input_double_register_3 = setp_list[3]
  setp.input_double_register_4 = setp_list[4]
  setp.input_double_register_5 = setp_list[5]
  con.send(setp)

For testing on URSim, after executing the above program, it will assign values to robot floating point registers 0-5. In the downloaded Python library, rtde_control_loop.urp is a robot controller program. Copy it to URSim or a physical robot for testing. After copying, comment out the lines rtde_set_watchdog and movel in the program as shown in the following image:


fig4.4 rtde ur robot program exmple

The function read_input_float_register(x) is used to read the corresponding register value of the robot. After running it, you can see that the value of setp has been set to the values in the setp_list in the Python program. Try modifying the values in the setp_list in the Python program and observe if the robot variables will change after running it.


fig4.5 rtde ur robot program test variable

If the movel in rtde_control_loop.urp is uncommented, the robot will move to the setp position after running the program again.

5. Summary

Summary in Comments due to the characters number limit

4 Likes

5. Summary

With a variety of ports and open resources, the development of remote control programs for Universal Robots is convenient and diverse. This article briefly introduces the basic methods for PC-side connection to the robot using the TCP/IP protocol, obtaining robot data, and controlling robot motion, with examples provided. The ports and their characteristics mentioned in the article can be summarized in the table below:

table 5.1 Summary of UR robot TCP/IP client

item Dashboard Primary Secondary Real-time Real-time data exchange(RTDE)
Port Number 29999 30001 30002 30003 30004
Frequency Request-response 10Hz 10Hz 125Hz, 500Hz configurable max 125Hz, 500Hz
Robot Receives Dashboard commands UR script UR script UR script Configurable data, registers, etc.
Robot Sends Response commands Status information and additional information Status information Status information Configurable status information, registers, etc.

When developing remote control applications, one can choose one or several of the above ports according to the requirements, such as:

  • Low-frequency monitoring: Using 29999 for power on/off, 30001 for data reception, and robot controller program execution
  • Real-time control: Using 29999 for power on/off, 30001 for sending robot program scripts, and 30004 for data reception and transmission

Among these port types, Universal Robots only provide Python and C++ function libraries that support the RTDE port (refer to the section Format and Parsing of Port Information 30004 in the article). When using other ports, users often need to understand the protocols and parse information. However, some partners and developers have developed libraries that integrate one or more ports of Universal Robots, such as:

We hope this article is helpful for you in developing remote control applications for Universal Robots. The next step is to introduce how to develop practical applications using the ports mentioned in the article. Possible options include:

  • Windows + Python + RTDE Python library
  • Linux + C++ + Universal_Robots_Client_library
3 Likes

Original Chinese Version:

优傲机器人远程控制(TCP/IP) - 知乎 (zhihu.com)

Great, it will be useful for me and other colleagues.

Hello,

First of all, thank you so much for this documentation, it’s very well explained and very usefull.

I’m waiting for your next article about Windows+Python+RTDE, however, because I don’t know how long will you take to post that here, could you answer some doubts I have?

  1. Working with RTDE, I have seen it is needed to use a .urp, how do I create this file? or do you have to use always the same? I have been reading a lot of forums here in UR and followed the videos of YouTube explaining the examples about RTDE that UR has on their Github, but I don’t understant how to create this file I just know I have to upload it to the robot.

  2. Is there a way to upload the .urp needed to use RTDE to the robot without use an USB to the Teach Pendant?

Again, thank you so much!!

Best regards, Paula.

You can use Polyscope itself to create the .urp file and then copy it over to robot via ftp.

Hello,

Thank you so much! However I still don’t know how to create the .urp, I mean, I have been watching the control_loop example from the Github and I understand what to do with Python, but not what I have to do to create the .urp that controls the regeisters, the watch_dog and all this stuffs. Is there any guide to understand that? or if I just want to move robot from a point to another I can use this .urp already provided?

Best regards, Paula.

Hi Paula

SimpleStudent have made a nice series of videos on how to set up and run RTDE.
In video #6 and #7 he shows how to program the robot to use the data send to the registers

/Henning

Hi, Thanks for the comment.

about using .URP, there is a rtde_control_loop.urp file in the python library download page, which can be used as start point. please copy it to UR robot then run it.

there are two ways to transfer URP to robot other than using USB:

  1. using FTP to put the urp into robot controller memory;
  2. the urp is finally transferred to UR Script to run in robot controller. So you can draft the function as script lines, then use 30001 port to send it to robot controller, as explained in article above. ##chapter: sending multiple line ##

for example:
(replace the script to read/write register functions.)

import socket

mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#change the robot IP address here
host = ‘192.168.56.103’
port = 30001

mySocket.connect((host, port))

script_text=“def test_move():\n”
" global P_start_p=p[.6206, -.1497, .2609, 2.2919, -2.1463, -.0555]\n"
" global P_mid_p=p[.6206, -.1497, .3721, 2.2919, -2.1463, -.0555]\n"
" global P_end_p=p[.6206, -.1497, .4658, 2.2919, -2.1463, -.0555]\n"
" while (True):\n"
" movel(P_start_p, a=1.2, v=0.25)\n"
" movel(P_mid_p, a=1.2, v=0.25)\n"
" movel(P_end_p, a=1.2, v=0.25)\n"
" end\n"
“end\n”

mySocket.send((script_text + “\n”).encode())
mySocket.close()