RTDE connect with C#

Hi all,

I’m doning that control UR3 with C#, socket communication.

I have success the control UR3 using the URscript functions like this:

string strQhome = "movej(p[0.20, -0.20, 0.50, 0.0, 2.20, -2.20], a=1.4, v=1.05, t=0, r=0)" + "\n";
byte[] sendURbuffer = Encoding.UTF8.GetBytes(strQhome);
socket_UR.Send(sendURbuffer);

However, I wanna feedback(or listen) from my UR3 state data(like actual_TCP_pose, is_steady… etc.) using the RTDE interface.

I already checked the UR support site, but I don’t understand how to work the RTDE interface using C#.

Is any example for C#?
or
Send to the some protocol to UR3 using socket communication?

Please help me.
Thank you.

2 Likes

It is not easy to implement an RTDE client using C#. I have done it successfully for my company’s product but won’t be able to share any code.

You will need to follow and truly understand the RTDE specification and the example Python implementation provided at the support site you linked. One significant problem you will face with C# is that CLR on Windows uses small-endian byte order while the RTDE messages need to be in the big-endian (“network”) byte order so you need to do your own marshalling.

I also found it useful to capture packets from the reference Python implementation using Wireshark and compare those with my own implementation. This way I also noticed that the RTDE specification had some errors and missing important information that I reported and have since been corrected.

Thank you…!

I’ll try something as your advise!

You have to be careful with UTF8 encoding. Controller expects ASCII codes, and will not recognize multibyte UTF8 encoded characters (or worse, misinterpret them). In production code you should either make sure that no character is encoded as multibyte, or use ASCII encoding.

2 Likes

OMG…!
I don’t know about that… wow…
Thank you so much !!!

To quickly connect to RTDE (or even primary interface to receive info and send script), you can take a look at this library that allows you to connect to the robot in a few lines:

https://underautomation.com/universal-robots/documentation/rtde

using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Common;
using UnderAutomation.UniversalRobots.Rtde;
using UnderAutomation.UniversalRobots.Rtde.Internal;

class Rtde
{
    static void Main(string[] args)
    {
        /**/
        var robot = new UR();

        var param = new ConnectParameters("192.168.0.1");

        // Enable RTDE
        param.Rtde.Enable = true;

        // Exchange data at 500Hz
        param.Rtde.Frequency = 500;

        // Select data you want to write in robot controller
        param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput0);
        param.Rtde.InputSetup.Add(RtdeInputData.InputIntRegisters, 0);

        // Select data you want the robot to send
        param.Rtde.OutputSetup.Add(RtdeOutputData.ActualTcpPose);
        param.Rtde.OutputSetup.Add(RtdeOutputData.ToolOutputVoltage);
        param.Rtde.OutputSetup.Add(RtdeOutputData.OutputDoubleRegisters, 10);

        // Connect to robot
        robot.Connect(param);

        // Be notified at 500Hz when data is received
        robot.Rtde.OutputDataReceived += Rtde_OutputDataReceived;

        //...

        // Get last received data in cache
        Pose actualTcpPose = robot.Rtde.OutputDataValues.ActualTcpPose;
        int toolOutputVoltage = robot.Rtde.OutputDataValues.ToolOutputVoltage;
        double outputDoubleRegisters10 = robot.Rtde.OutputDataValues.OutputDoubleRegisters.X10;

        //...

        // Write input values in robot
        var inputValues = new RtdeInputValues();
        inputValues.StandardAnalogOutput0 = 0.2;
        inputValues.InputIntRegisters.X0 = 12;
        robot.Rtde.WriteInputs(inputValues);

        // Disconnect only RTDE communication
        robot.Rtde.Disconnect();
        /**/
    }

    /**/
    private static void Rtde_OutputDataReceived(object sender, RtdeDataPackageEventArgs e)
    {
        // Get frequency of received message (OutputSetup contains Timestamp by default)
        var realMessageFrequency = e.MeasuredFrequency;

        // Get the value of the data you have selected in the setup 
        Pose actualTcpPose = e.OutputDataValues.ActualTcpPose;
        int toolOutputVoltage = e.OutputDataValues.ToolOutputVoltage;
        double outputDoubleRegisters10 = e.OutputDataValues.OutputDoubleRegisters.X10;

        // Write inputs at 500Hz
        var inputValues = new RtdeInputValues();
        inputValues.StandardAnalogOutput0 = 0.5;
        inputValues.InputIntRegisters.X0 = -10;
        (sender as RtdeClientBase)?.WriteInputs(inputValues);
    }
    /**/
}