# Overview

RTDE allows you to exchange data and measurements with the robot at high speed, up to 500Hz on the latest cobots.

For more information about RTDE, see : https://www.universal-robots.com/articles/ur/interface-communication/real-time-data-exchange-rtde-guide/

## Overview of RTDE

RTDE allows you to receive and send certain data between the robot and your application.

When connecting, you must specify the list of data that will be exchanged, as well as the frequency at which the robot should send you data. Data sent by the robot to your application is called "Outputs" and data sent by your application to the robot is called "Inputs". The name is given from the point of view of the robot.

In operation, data is received and the OutputDataReceived event is periodically raised when data arrives.

Other events are used to be notified of RTDE link activities.

You can asynchronously write data to the robot controller.

It is also possible to pause and resume the streaming of measurements.

**C# : Rtde**
```csharp
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();

    // Disconnect every interfaces (Primary Interface, Dashboard, RTDE, ...)
    robot.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);
  }
  /**/
}
```

It is possible to create a RTDE client outside an instance of `UR`.
To do this, you just need to instantiate a `RtdeClient` object.

**C# : RtdeDirect**
```csharp
using UnderAutomation.UniversalRobots.Common;
using UnderAutomation.UniversalRobots.Rtde;

class RtdeDirect
{
  static void Main(string[] args)
  {
    /**/
    // Create a dashboard client alone, outside any UR instance
    var client = new RtdeClient();

    // Select output data to receive from the robot
    var outputSetup = new RtdeOutputSetup();
    outputSetup.Add(RtdeOutputData.ActualCurrent);

    // Select input data to send to the robot
    var inputSetup = new RtdeInputSetup();
    inputSetup.Add(RtdeInputData.InputIntRegisters, 4);
    inputSetup.Add(RtdeInputData.StandardAnalogOutput0);

    // Connect at 500Hz
    client.Connect("192.168.0.1", outputSetup, inputSetup, RtdeVersions.V2, frequency: 500);

    //...

    // Receive data at 500Hz
    client.OutputDataReceived += (o, e) =>
    {
      JointsDoubleValues actualCurrent = e.OutputDataValues.ActualCurrent;
    };

    //...

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

    //...

    // Close connection to the robot
    client.Disconnect();
    /**/
  }
}
```

In order for your robot to accept writing registers commands, it must be in “Remote” mode, which can be selected using the switch located at the top right of Polyscope.

![switch remote](/universal-robots/switch-remote.png)

## Setup connection

RTDE is not activated by default when connecting to the robot. You must set the `Enable` property in the connection settings.

In this same object, you must add the inputs and outputs you want to exchange with the robot.

To do this, use the `Add` function on `InputSetup` and `OutputSetup` to add the data to exchange. This function takes as parameter an enum `RtdeOutputData` or `RtdeInputData`.

In the case of array registers, e.g. `RtdeOutputData.OutputDoubleRegisters` or `RtdeInputData.InputIntRegisters`, it is necessary to additionally specify the register number as the second parameter of `Add`. Please refer to the register comment for the register size and the upper and lower range.

You can also specify a frequency of data reception. By default, if nothing is set, the communication is at 10Hz. The `Frequency` property of the setup parameters allows you to change the frequency up to 500Hz.

If the frequency is set to 0, the communication will be done at the maximum frequency allowed by the robot.

You can also specify the RTDE protocol version. Version 2 allows frequency to be taken into account. If your robot is not compatible with version 2, version 1 is automatically selected. If you do not set the version, version 2 is automatically selected.
At runtime, you can control the version actually used via the property `Rtde.Version`.

**C# : RtdeSetup**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Rtde;

class RtdeSetup
{
  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;

    // Set RTDE version
    param.Rtde.Version = RtdeVersions.V2;

    // Select data you want to write in robot controller
    param.Rtde.InputSetup.Add(RtdeInputData.StandardDigitalOutput);
    param.Rtde.InputSetup.Add(RtdeInputData.ExternalForceTorque);
    param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput1);
    param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters, 64);

    // 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);
    /**/
    // ...

    robot.Rtde.Disconnect();
  }
}
```

In the robot, the Real Time Data Exchange (RTDE) must be enabled in the Polyscope settings for security reasons, see : [this page](connect)

## Receive data from robot

The `OutputDataReceived` event is raised at the frequency of data reception from the robot. It contains the received data, the connection ID and the frequency of data reception estimated from the timestamp if this data is part of the output.

It is possible to access the last received values with the property `OutputDataValues`.

**C# : RtdeReceive**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Common;
using UnderAutomation.UniversalRobots.Rtde;

class RtdeReceive
{
  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;

    // Set RTDE version
    param.Rtde.Version = RtdeVersions.V2;

    // Select data you want to write in robot controller
    param.Rtde.InputSetup.Add(RtdeInputData.StandardDigitalOutput);
    param.Rtde.InputSetup.Add(RtdeInputData.ExternalForceTorque);
    param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput1);
    param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters, 64);

    // 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);
    /**/
    // Get latest received data
    Pose actualTcpPose = robot.Rtde.OutputDataValues.ActualTcpPose;
    double x = actualTcpPose.X;
    double y = actualTcpPose.Y;
    double z = actualTcpPose.Z;
    int toolOutputVoltage = robot.Rtde.OutputDataValues.ToolOutputVoltage;
    double outputDoubleRegisters10 = robot.Rtde.OutputDataValues.OutputDoubleRegisters.X10;

    // Subscribe to event to receive data is real time
    robot.Rtde.OutputDataReceived += (o, e) =>
    {
      double realFreq = e.MeasuredFrequency;

      Pose pose = robot.Rtde.OutputDataValues.ActualTcpPose;
      int voltage = robot.Rtde.OutputDataValues.ToolOutputVoltage;

      double register10 = robot.Rtde.OutputDataValues.OutputDoubleRegisters.X10;
    };
    /**/
    // ...

    robot.Rtde.Disconnect();
  }
}
```

## Send data to robot

To write data, simply instantiate an `RtdeInputValues` list and fill the fields with your values.
Then call the `WriteInputs` function to send these values to the robot.

**C# : RtdeSend**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Common;
using UnderAutomation.UniversalRobots.Rtde;

class RtdeSend
{
  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;

    // Set RTDE version
    param.Rtde.Version = RtdeVersions.V2;

    // Select data you want to write in robot controller
    param.Rtde.InputSetup.Add(RtdeInputData.StandardDigitalOutput);
    param.Rtde.InputSetup.Add(RtdeInputData.ExternalForceTorque);
    param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput1);
    param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters, 64);

    // 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);
    /**/
    var inputs = new RtdeInputValues();
    inputs.StandardDigitalOutput = 128;
    inputs.ExternalForceTorque = new CartesianCoordinates(0, 0, 1, 0, 0, 0.1);
    inputs.StandardAnalogOutput1 = 0.1;
    inputs.InputBitRegisters.X64 = true;

    // Send data to robot
    robot.Rtde.WriteInputs(inputs);
    /**/
    // ...

    robot.Rtde.Disconnect();
  }
}
```

## Pause and resume

The `Pause` method allow the connection to be paused without being closed, so no data is received. It is possible to resume the stream with the `Resume` function.

**C# : RtdePauseResume**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Rtde;

class RtdePauseResume
{
  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;

    // Set RTDE version
    param.Rtde.Version = RtdeVersions.V2;

    // Select data you want to write in robot controller
    param.Rtde.InputSetup.Add(RtdeInputData.StandardDigitalOutput);
    param.Rtde.InputSetup.Add(RtdeInputData.ExternalForceTorque);
    param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput1);
    param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters, 64);

    // 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);

    //...
    /**/
    // Pause RTDE data streaming from robot
    robot.Rtde.Pause();

    // Event triggered when RTDE is paused
    robot.Rtde.PauseReceived += Rtde_PauseReceived;

    // Resume RTDE after a pause
    robot.Rtde.Resume();

    // RTDE streaming started or resumed
    robot.Rtde.StartReceived += Rtde_StartReceived;
    /**/
    // ...

    robot.Rtde.Disconnect();
  }


  private static void Rtde_PauseReceived(object sender, RtdeBasicRequestEventArgs e)
  {
    if (e.Accepted)
    {
      Console.WriteLine("RTDE has been paused");
    }
    else
    {
      Console.WriteLine("RTDE pause command has failed");
    }
  }

  private static void Rtde_StartReceived(object sender, RtdeBasicRequestEventArgs e)
  {
    if (e.Accepted)
    {
      Console.WriteLine("RTDE streaming has started");
    }
    else
    {
      Console.WriteLine("RTDE streaming start has failed");
    }
  }
}
```

## Other features

The state of the connection can be controlled via the `Connected` and `State` properties.

Text messages can be received to describe an error in connection or operation. The last message is stored in `LastTextMessage` and the `TextMessageReceived` event is raised when a text message is received.

Likewise, if an internal library error occurs, the `InternalErrorOccured` event is raised.

**C# : RtdeOther**
```csharp
using UnderAutomation.UniversalRobots;
using UnderAutomation.UniversalRobots.Rtde;

class RtdeOther
{
  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;

    // Set RTDE version
    param.Rtde.Version = RtdeVersions.V2;

    // Select data you want to write in robot controller
    param.Rtde.InputSetup.Add(RtdeInputData.StandardDigitalOutput);
    param.Rtde.InputSetup.Add(RtdeInputData.ExternalForceTorque);
    param.Rtde.InputSetup.Add(RtdeInputData.StandardAnalogOutput1);
    param.Rtde.InputSetup.Add(RtdeInputData.InputBitRegisters, 64);

    // 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);

    //...
    /**/
    // Frequency requested in connect parameters for V2 protocol
    double appliedFrequency = robot.Rtde.AppliedFrequency;

    // RTDE TCP/IP connection is still active
    bool isConnected = robot.Rtde.Connected;

    // Unique ID of the RTDE connection for writing data to the robot
    byte inputRecipe = robot.Rtde.InputRecipeId;

    // Unique ID of the RTDE connection for receiving data from robot
    byte outputRecipe = robot.Rtde.OutputRecipeId;

    // State property has current RTDE state (paused, disabled, started, ...)
    bool isPaused = robot.Rtde.State == RTDEStates.Paused;

    // Special warning text messages sent by the robot
    robot.Rtde.TextMessageReceived += Rtde_TextMessageReceived;

    // Event raised by the library when something went wrong
    robot.Rtde.InternalErrorOccured += Rtde_InternalErrorOccured;
    /**/
    // ...

    robot.Rtde.Disconnect();
  }

  private static void Rtde_InternalErrorOccured(object sender, UnderAutomation.UniversalRobots.Common.InternalErrorEventArgs e)
  {
    throw new NotImplementedException();
  }

  private static void Rtde_TextMessageReceived(object sender, RtdeTextMessageEventArgs e)
  {
    Console.WriteLine(e.Source);
    Console.WriteLine(e.Message);
    Console.WriteLine(e.WarningLevel);
  }
}
```

## API reference

**Members of Rtde.Internal.RtdeClientBase**
```csharp
public abstract class RtdeClientBase : URServiceBase {
    protected RtdeClientBase()

    // Output data frequency requested to the robot, only for RTDE version 2
    public double AppliedFrequency { get; }

    protected void ConnectInternal(string ip, int port, RtdeOutputSetup outputSetup, RtdeInputSetup inputSetup, RtdeVersions preferedVersion, double frequency)

    // Gets a value indicating if RTDE client is connected to the robot
    public bool Connected { get; }

    // Close the RTDE connection to the robot
    public void Disconnect()

    // IP address of the robot
    public string IP { get; }

    // Recipe Identifier of input sent data
    public byte InputRecipeId { get; }

    // Indicates that the recipe is valid, i.e. that all the registers have been found and are not already reserved for writing by another RTDE client.
    // Check event SetupInputsReceived to see which registers are NOT_FOUND or IN_USE
    public bool InputRecipeIsValid { get; }

    // List of all data the PC can write to the robot (robot point of view)
    public RtdeInputSetupItem[] InputSetup { get; }

    // Last text received from the robot
    public RtdeTextMessageEventArgs LastTextMessage { get; }

    // Measured output data packet frequency. "Timestamp" output data shoud be part of output setup to measure frequency.
    public double MeasuredFrequency { get; }

    // Event raised when data from the robot is comming at specified frequency
    public event EventHandler<RtdeDataPackageEventArgs> OutputDataReceived

    // Last data received from the robot
    public RtdeOutputValues OutputDataValues { get; }

    // Recipe Identifier of output received data
    public byte OutputRecipeId { get; }

    // List of all data sent from the robot to the PC (robot point of view)
    public RtdeOutputSetupItem[] OutputSetup { get; }

    // Generic event raised each time a RTDE package is received
    public event EventHandler<PackageEventArgs> PackageReceived

    // Pause data streaming without disconnecting client
    public void Pause()

    // Event raised when streaming is paused
    public event EventHandler<RtdeBasicRequestEventArgs> PauseReceived

    // Event raised during connection when the robot specifies if asked protocol version is supported
    public event EventHandler<RtdeProtocolVersionEventArgs> ProtocolVersionReceived

    // Restart data streaming after a Pause
    public void Resume()

    // Event raised during connection when the robot acknowledges input setup
    public event EventHandler<RtdeControlPackageSetupInputsEventArgs> SetupInputsReceived

    // Event raised during connection when the robot acknowledges output setup
    public event EventHandler<RtdeControlPackageSetupOutputsEventArgs> SetupOutputsReceived

    // Event raised as soon as data streaming starts
    public event EventHandler<RtdeBasicRequestEventArgs> StartReceived

    // Current RTDE state
    public RTDEStates State { get; }

    // Event raised when a RTDE message is received
    public event EventHandler<RtdeTextMessageEventArgs> TextMessageReceived

    // Current protocol version used to stream data
    public RtdeVersions Version { get; }

    // Write data to controller. Data must be those selected in connect parameters
    public void WriteInputs(RtdeInputValues inputValues)
}
```

**Members of Rtde.Internal.RtdeParametersBase**
```csharp
public abstract class RtdeParametersBase {
    protected RtdeParametersBase()

    // Default RTDE TCP port used (30004)
    public const int DEFAULT_PORT = 30004

    // For RTDE version 2, you can specify a frequency for output received data. Maximum frequency depends on your robot version.
    // If you set frequency to 0, maximum frequency will be choosen
    // Default value is 10Hz
    public double Frequency { get; set; }

    // List of all input data you can send to the robot
    public RtdeInputSetup InputSetup { get; set; }

    // List of all output data the robot will send to your application
    public RtdeOutputSetup OutputSetup { get; set; }

    // TCP port used for RTDE connection. Default : 30004
    public int Port { get; set; }

    // RTDE version. If set to Auto, the most recent version will be choosen according to your robot version
    // Default value is V2
    public RtdeVersions Version { get; set; }
}
```

**Members of Rtde.RtdeVersions**
```csharp
public enum RtdeVersions {
    // Rtde version 1
    V1 = 1

    // Rtde version 2
    V2 = 2
}
```

**Members of Rtde.RtdeOutputData**
```csharp
public enum RtdeOutputData {
    // Actual joint currents
    ActualCurrent = 8

    // Current state of the digital inputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool
    ActualDigitalInputBits = 15

    // Current state of the digital outputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool
    ActualDigitalOutputBits = 30

    // Controller real-time thread execution time
    ActualExecutionTime = 17

    // Actual joint voltages
    ActualJointVoltage = 29

    // Safety Control Board: Main voltage
    ActualMainVoltage = 26

    // Norm of Cartesian linear momentum
    ActualMomentum = 25

    // Actual joint positions
    ActualQ = 6

    // Actual joint velocities
    ActualQd = 7

    // Safety Control Board: Robot current
    ActualRobotCurrent = 28

    // Safety Control Board: Robot voltage (48V)
    ActualRobotVoltage = 27

    // Generalized forces in the TCP. It compensates the measurement for forces and torques generated by the payload
    ActualTcpForce = 12

    // Actual Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation
    ActualTcpPose = 10

    // Actual speed of the tool given in Cartesian coordinates. The speed is given in [m/s] and the rotational part of the TCP speed (rx, ry, rz) is the angular velocity given in [rad/s]
    ActualTcpSpeed = 11

    // Tool x, y and z accelerometer values
    ActualToolAccelerometer = 22

    // Bits 0-3: analog input 0 | analog input 1 | analog output 0 | analog output 1, {0=current[mA], 1=voltage[V]}
    AnalogIOTypes = 36

    // Position of robot elbow in Cartesian Base Coordinates
    ElbowPosition = 32

    // Velocity of robot elbow in Cartesian Base Coordinates
    ElbowVelocity = 33

    // Euromap67 input bits
    Euromap67InputBits = 42

    // Euromap67 output bits
    Euromap67OutputBits = 43

    // Euromap 24V current [mA]
    Euromap67_24VCurrent = 45

    // Euromap 24V voltage [V]
    Euromap67_24VVoltage = 44

    // Raw force and torque measurement, not compensated for forces and torques caused by the payload
    FTRawWrench = 71

    // I/O current [mA]
    IOCurrent = 41

    // 64 general purpose bits, X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS).
    InputBitRegisters = 61

    // General purpose bits (input read back). This range of the boolean output registers is reserved for FieldBus/PLC interface usage.
    InputBitRegisters0To31 = 59

    // General purpose bits (input read back), This range of the boolean output registers is reserved for FieldBus/PLC interface usage.
    InputBitRegisters32To63 = 60

    // 48 general purpose double registers. X: [0..23] - The lower range of the double input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double input registers can be used by external RTDE clients (i.e URCAPS).
    InputDoubleRegisters = 63

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer input registers can be used by external RTDE clients (i.e URCAPS).
    InputIntRegisters = 62

    // Joint control currents
    JointControlOutput = 9

    // Joint control modes
    JointMode = 19

    // Temperature of each joint in degrees Celsius
    JointTemperatures = 16

    // 64 general purpose bits. X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS).
    OutputBitRegisters = 56

    // General purpose bits
    OutputBitRegisters0To31 = 54

    // General purpose bits
    OutputBitRegisters32To63 = 55

    // 48 general purpose double registers. X: [0..23] - The lower range of the double output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double output registers can be used by external RTDE clients (i.e URCAPS).
    OutputDoubleRegisters = 58

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer output registers can be used by external RTDE clients (i.e URCAPS).
    OutputIntRegisters = 57

    // Payload mass Kg
    Payload = 67

    // Payload Center of Gravity (CoGx, CoGy, CoGz) m
    PayloadCOG = 68

    // Payload inertia matrix elements (Ixx,Iyy,Izz,Ixy,Ixz,Iyz] expressed in kg*m^2
    PayloadInertia = 69

    // Robot mode
    RobotMode = 18

    // Bits 0-3:Is power on | Is program running | Is teach button pressed | Is power button pressed
    RobotStatusBits = 34

    // Program state
    RuntimeState = 31

    // Safety mode
    SafetyMode = 20

    // Safety status
    SafetyStatus = 21

    // Bits 0-10: Is normal mode | Is reduced mode | Is protective stopped | Is recovery mode | Is safeguard stopped | Is system emergency stopped | Is robot emergency stopped | Is emergency stopped | Is violation | Is fault | Is stopped due to safety
    SafetyStatusBits = 35

    // Script line number that is actually in control of the robot given the robot is locked by one of the threads in the script. If no thread is locking the robot this field is set to '0'. Script line number should not be confused with program tree line number displayed on polyscope.
    ScriptControlLine = 70

    // Speed scaling of the trajectory limiter
    SpeedScaling = 23

    // Standard analog input 0 [mA or V]
    StandardAnalogInput0 = 37

    // Standard analog input 1 [mA or V]
    StandardAnalogInput1 = 38

    // Standard analog output 0 [mA or V]
    StandardAnalogOutput0 = 39

    // Standard analog output 1 [mA or V]
    StandardAnalogOutput1 = 40

    // Target joint currents
    TargetCurrent = 4

    // Target joint moments (torques)
    TargetMoment = 5

    // Target joint positions
    TargetQ = 1

    // Target joint velocities
    TargetQd = 2

    // Target joint accelerations
    TargetQdd = 3

    // Target speed fraction
    TargetSpeedFraction = 24

    // Target Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation
    TargetTcpPose = 13

    // Target speed of the tool given in Cartesian coordinates. The speed is given in [m/s] and the rotational part of the TCP speed (rx, ry, rz) is the angular velocity given in [rad/s]
    TargetTcpSpeed = 14

    // TCP force scalar [N]
    TcpForceScalar = 53

    // Time elapsed since the controller was started [s]
    Timestamp = 0

    // Tool analog input 0 [mA or V]
    ToolAnalogInput0 = 48

    // Tool analog input 1 [mA or V]
    ToolAnalogInput1 = 49

    // Output domain {0=current[mA], 1=voltage[V]} Bits 0-1: tool_analog_input_0 | tool_analog_input_1
    ToolAnalogInputTypes = 47

    // The current mode of digital output 0
    ToolDigitalOutput0mode = 65

    // The current mode of digital output 1
    ToolDigitalOutput1Mode = 66

    // Tool mode
    ToolMode = 46

    // Tool current [mA]
    ToolOutputCurrent = 51

    // The current output mode
    ToolOutputMode = 64

    // Tool output voltage [V]
    ToolOutputVoltage = 50

    // Tool temperature in degrees Celsius
    ToolTemperature = 52
}
```

**Members of Rtde.RtdeInputData**
```csharp
public enum RtdeInputData {
    // Configurable digital outputs
    ConfigurableDigitalOutput = 5

    // Configurable digital output bit mask
    ConfigurableDigitalOutputMask = 3

    // Input external wrench when using ft_rtde_input_enable builtin.
    ExternalForceTorque = 15

    // 64 general purpose bits. X: [64..127] - The upper range of the boolean input registers can be used by external RTDE clients (i.e URCAPS).
    InputBitRegisters = 12

    // General purpose bits. This range of the boolean input registers is reserved for FieldBus/PLC interface usage.
    InputBtRegisters0To31 = 10

    // General purpose bits. This range of the boolean input registers is reserved for FieldBus/PLC interface usage.
    InputBtRegisters32To63 = 11

    // 48 general purpose double registers. X: [0..23] - The lower range of the double input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double input registers can be used by external RTDE clients (i.e URCAPS).
    InputDoubleRegisters = 14

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer input registers can be used by external RTDE clients (i.e URCAPS).
    InputIntRegisters = 13

    // new speed slider value
    SpeedSliderFraction = 1

    // 0 = don't change speed slider with this input, 1 = use speed_slider_fraction to set speed slider value
    SpeedSliderMask = 0

    // Standard analog output 0 (ratio) [0..1]
    StandardAnalogOutput0 = 8

    // Standard analog output 1 (ratio) [0..1]
    StandardAnalogOutput1 = 9

    // Standard analog output mask
    StandardAnalogOutputMask = 6

    // Output domain {0=current[mA], 1=voltage[V]}. Bits 0-1: standard_analog_output_0 | standard_analog_output_1
    StandardAnalogOutputType = 7

    // Standard digital outputs
    StandardDigitalOutput = 4

    // Standard digital output bit mask
    StandardDigitalOutputMask = 2
}
```

**Members of Rtde.RtdeInputValues**
```csharp
public class RtdeInputValues : RtdeBaseValues<RtdeInputData> {
    public RtdeInputValues()

    // Configurable digital outputs
    public byte ConfigurableDigitalOutput { get; set; }

    // Configurable digital output bit mask
    public byte ConfigurableDigitalOutputMask { get; set; }

    // Input external wrench when using ft_rtde_input_enable builtin.
    public CartesianCoordinates ExternalForceTorque { get; set; }

    public object GetValue(RtdeInputSetupItem item)

    // 64 general purpose bits. X: [64..127] - The upper range of the boolean input registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeBitRegistersValue InputBitRegisters { get; }

    // General purpose bits. This range of the boolean input registers is reserved for FieldBus/PLC interface usage.
    public uint InputBtRegisters0To31 { get; set; }

    // General purpose bits. This range of the boolean input registers is reserved for FieldBus/PLC interface usage.
    public uint InputBtRegisters32To63 { get; set; }

    // 48 general purpose double registers. X: [0..23] - The lower range of the double input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double input registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeDoubleRegistersValue InputDoubleRegisters { get; }

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer input registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeIntRegistersValue InputIntRegisters { get; }

    protected override RtdeValue[] InternalValues { get; }

    protected override RtdeValue InternaleGetValue(RtdeInputData data)

    public void Reset()

    public void SetValue(RtdeInputData data, int index, object value)

    public void SetValue(RtdeInputData data, object value)

    public void SetValue(RtdeInputSetupItem item, object value)

    // new speed slider value
    public double SpeedSliderFraction { get; set; }

    // 0 = don't change speed slider with this input, 1 = use speed_slider_fraction to set speed slider value
    public uint SpeedSliderMask { get; set; }

    // Standard analog output 0 (ratio) [0..1]
    public double StandardAnalogOutput0 { get; set; }

    // Standard analog output 1 (ratio) [0..1]
    public double StandardAnalogOutput1 { get; set; }

    // Standard analog output mask
    public byte StandardAnalogOutputMask { get; set; }

    // Output domain {0=current[mA], 1=voltage[V]}. Bits 0-1: standard_analog_output_0 | standard_analog_output_1
    public byte StandardAnalogOutputType { get; set; }

    // Standard digital outputs
    public byte StandardDigitalOutput { get; set; }

    // Standard digital output bit mask
    public byte StandardDigitalOutputMask { get; set; }
}
```

**Members of Rtde.RtdeOutputValues**
```csharp
public class RtdeOutputValues : RtdeBaseValues<RtdeOutputData> {
    // Actual joint currents
    public JointsDoubleValues ActualCurrent { get; set; }

    // Current state of the digital inputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool
    public ulong ActualDigitalInputBits { get; set; }

    // Current state of the digital outputs. 0-7: Standard, 8-15: Configurable, 16-17: Tool
    public ulong ActualDigitalOutputBits { get; set; }

    // Controller real-time thread execution time
    public double ActualExecutionTime { get; set; }

    // Actual joint voltages
    public JointsDoubleValues ActualJointVoltage { get; set; }

    // Safety Control Board: Main voltage
    public double ActualMainVoltage { get; set; }

    // Norm of Cartesian linear momentum
    public double ActualMomentum { get; set; }

    // Actual joint positions
    public JointsDoubleValues ActualQ { get; set; }

    // Actual joint velocities
    public JointsDoubleValues ActualQd { get; set; }

    // Safety Control Board: Robot current
    public double ActualRobotCurrent { get; set; }

    // Safety Control Board: Robot voltage (48V)
    public double ActualRobotVoltage { get; set; }

    // Generalized forces in the TCP. It compensates the measurement for forces and torques generated by the payload
    public CartesianCoordinates ActualTcpForce { get; set; }

    // Actual Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation
    public Pose ActualTcpPose { get; set; }

    // Actual speed of the tool given in Cartesian coordinates. The speed is given in [m/s] and the rotational part of the TCP speed (rx, ry, rz) is the angular velocity given in [rad/s]
    public Pose ActualTcpSpeed { get; set; }

    // Tool x, y and z accelerometer values
    public Vector3D ActualToolAccelerometer { get; set; }

    // Bits 0-3: analog input 0 | analog input 1 | analog output 0 | analog output 1, {0=current[mA], 1=voltage[V]}
    public uint AnalogIOTypes { get; set; }

    // Position of robot elbow in Cartesian Base Coordinates
    public Vector3D ElbowPosition { get; set; }

    // Velocity of robot elbow in Cartesian Base Coordinates
    public Vector3D ElbowVelocity { get; set; }

    // Euromap67 input bits
    public uint Euromap67InputBits { get; set; }

    // Euromap67 output bits
    public uint Euromap67OutputBits { get; set; }

    // Euromap 24V current [mA]
    public double Euromap67_24VCurrent { get; set; }

    // Euromap 24V voltage [V]
    public double Euromap67_24VVoltage { get; set; }

    // Raw force and torque measurement, not compensated for forces and torques caused by the payload
    public CartesianCoordinates FTRawWrench { get; set; }

    public object GetValue(RtdeOutputSetupItem item)

    // I/O current [mA]
    public double IOCurrent { get; set; }

    // 64 general purpose bits, X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeBitRegistersValue InputBitRegisters { get; }

    // General purpose bits (input read back). This range of the boolean output registers is reserved for FieldBus/PLC interface usage.
    public uint InputBitRegisters0To31 { get; set; }

    // General purpose bits (input read back), This range of the boolean output registers is reserved for FieldBus/PLC interface usage.
    public uint InputBitRegisters32To63 { get; set; }

    // 48 general purpose double registers. X: [0..23] - The lower range of the double input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double input registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeDoubleRegistersValue InputDoubleRegisters { get; }

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer input registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer input registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeIntRegistersValue InputIntRegisters { get; }

    protected override RtdeValue[] InternalValues { get; }

    protected override RtdeValue InternaleGetValue(RtdeOutputData data)

    // Joint control currents
    public JointsDoubleValues JointControlOutput { get; set; }

    // Joint control modes
    public JointsIntValues JointMode { get; set; }

    // Temperature of each joint in degrees Celsius
    public JointsDoubleValues JointTemperatures { get; set; }

    // 64 general purpose bits. X: [64..127] - The upper range of the boolean output registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeBitRegistersValue OutputBitRegisters { get; }

    // General purpose bits
    public uint OutputBitRegisters0To31 { get; set; }

    // General purpose bits
    public uint OutputBitRegisters32To63 { get; set; }

    // 48 general purpose double registers. X: [0..23] - The lower range of the double output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the double output registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeDoubleRegistersValue OutputDoubleRegisters { get; }

    // 48 general purpose integer registers. X: [0..23] - The lower range of the integer output registers is reserved for FieldBus/PLC interface usage. X: [24..47] - The upper range of the integer output registers can be used by external RTDE clients (i.e URCAPS).
    public RtdeIntRegistersValue OutputIntRegisters { get; }

    // Payload mass Kg
    public double Payload { get; set; }

    // Payload Center of Gravity (CoGx, CoGy, CoGz) m
    public Vector3D PayloadCOG { get; set; }

    // Payload inertia matrix elements (Ixx,Iyy,Izz,Ixy,Ixz,Iyz] expressed in kg*m^2
    public CartesianCoordinates PayloadInertia { get; set; }

    // Robot mode
    public int RobotMode { get; set; }

    // Bits 0-3:Is power on | Is program running | Is teach button pressed | Is power button pressed
    public uint RobotStatusBits { get; set; }

    // Program state
    public uint RuntimeState { get; set; }

    // Safety mode
    public int SafetyMode { get; set; }

    // Safety status
    public int SafetyStatus { get; set; }

    // Bits 0-10: Is normal mode | Is reduced mode | Is protective stopped | Is recovery mode | Is safeguard stopped | Is system emergency stopped | Is robot emergency stopped | Is emergency stopped | Is violation | Is fault | Is stopped due to safety
    public uint SafetyStatusBits { get; set; }

    // Script line number that is actually in control of the robot given the robot is locked by one of the threads in the script. If no thread is locking the robot this field is set to '0'. Script line number should not be confused with program tree line number displayed on polyscope.
    public uint ScriptControlLine { get; set; }

    // Speed scaling of the trajectory limiter
    public double SpeedScaling { get; set; }

    // Standard analog input 0 [mA or V]
    public double StandardAnalogInput0 { get; set; }

    // Standard analog input 1 [mA or V]
    public double StandardAnalogInput1 { get; set; }

    // Standard analog output 0 [mA or V]
    public double StandardAnalogOutput0 { get; set; }

    // Standard analog output 1 [mA or V]
    public double StandardAnalogOutput1 { get; set; }

    // Target joint currents
    public JointsDoubleValues TargetCurrent { get; set; }

    // Target joint moments (torques)
    public JointsDoubleValues TargetMoment { get; set; }

    // Target joint positions
    public JointsDoubleValues TargetQ { get; set; }

    // Target joint velocities
    public JointsDoubleValues TargetQd { get; set; }

    // Target joint accelerations
    public JointsDoubleValues TargetQdd { get; set; }

    // Target speed fraction
    public double TargetSpeedFraction { get; set; }

    // Target Cartesian coordinates of the tool: (x,y,z,rx,ry,rz), where rx, ry and rz is a rotation vector representation of the tool orientation
    public Pose TargetTcpPose { get; set; }

    // Target speed of the tool given in Cartesian coordinates. The speed is given in [m/s] and the rotational part of the TCP speed (rx, ry, rz) is the angular velocity given in [rad/s]
    public Pose TargetTcpSpeed { get; set; }

    // TCP force scalar [N]
    public double TcpForceScalar { get; set; }

    // Time elapsed since the controller was started [s]
    public double Timestamp { get; set; }

    // Tool analog input 0 [mA or V]
    public double ToolAnalogInput0 { get; set; }

    // Tool analog input 1 [mA or V]
    public double ToolAnalogInput1 { get; set; }

    // Output domain {0=current[mA], 1=voltage[V]} Bits 0-1: tool_analog_input_0 | tool_analog_input_1
    public uint ToolAnalogInputTypes { get; set; }

    // The current mode of digital output 0
    public byte ToolDigitalOutput0mode { get; set; }

    // The current mode of digital output 1
    public byte ToolDigitalOutput1Mode { get; set; }

    // Tool mode
    public uint ToolMode { get; set; }

    // Tool current [mA]
    public double ToolOutputCurrent { get; set; }

    // The current output mode
    public byte ToolOutputMode { get; set; }

    // Tool output voltage [V]
    public int ToolOutputVoltage { get; set; }

    // Tool temperature in degrees Celsius
    public double ToolTemperature { get; set; }
}
```