This page shows how to read the current position of a Staubli robot on a CS8 or CS9 controller: the joint values, and the Cartesian position of the flange or of a tool, in the world or in another frame.

## Joints and Cartesian position

`GetCurrentCartesianJointPosition(robot)` returns the joints and the Cartesian position of the flange in the world frame, in one request.

**C# : PositionRead**
```csharp
using UnderAutomation.Staubli;
using UnderAutomation.Staubli.Soap.Data;

public class PositionRead
{
    static void Main()
    {
        var controller = new StaubliController();
        controller.Connect("192.168.0.254");

        /**/
        // Joints and flange position of the first robot, in one request
        CartesianJointPosition position = controller.Soap.GetCurrentCartesianJointPosition(robot: 0);

        // Joint values, in radians
        double[] joints = position.JointsPosition;

        // Flange position in the world frame: X, Y, Z in meters, Rx, Ry, Rz in radians
        CartesianPosition flange = position.CartesianPosition;
        Console.WriteLine($"X={flange.X} Y={flange.Y} Z={flange.Z}");
        Console.WriteLine($"Rx={flange.Rx} Ry={flange.Ry} Rz={flange.Rz}");
        /**/

        controller.Disconnect();
    }
}
```

**Python : PositionRead**
```python
from underautomation.staubli.staubli_controller import StaubliController

controller = StaubliController()
controller.connect("192.168.0.254")

##
# Joints and flange position of the first robot, in one request
position = controller.soap.get_current_cartesian_joint_position(0)

# Joint values, in radians
joints = list(position.joints_position)

# Flange position in the world frame: X, Y, Z in meters, Rx, Ry, Rz in radians
flange = position.cartesian_position
print(f"X={flange.x} Y={flange.y} Z={flange.z}")
print(f"Rx={flange.rx} Ry={flange.ry} Rz={flange.rz}")
##

controller.disconnect()
```

**Matlab : PositionRead**
```matlab
NET.addAssembly(fullfile(pwd, 'net48', 'UnderAutomation.Staubli.dll'));
import UnderAutomation.Staubli.*

controller = StaubliController();
controller.Connect('192.168.0.254');

%%
% Joints and flange position of the first robot, in one request.
% Pass [] for the optional tool and frame.
position = controller.Soap.GetCurrentCartesianJointPosition(0, [], []);

% Joint values in radians, as a Matlab row vector
joints = double(position.JointsPosition);

% Flange position in the world frame: X, Y, Z in meters, Rx, Ry, Rz in radians
flange = position.CartesianPosition;
fprintf('X=%.4f Y=%.4f Z=%.4f\n', flange.X, flange.Y, flange.Z);
fprintf('Rx=%.4f Ry=%.4f Rz=%.4f\n', flange.Rx, flange.Ry, flange.Rz);
%%

controller.Disconnect();
```

| Value                                | Unit    |
| ------------------------------------ | ------- |
| `JointsPosition`, one value per axis | radians |
| `X`, `Y`, `Z`                        | meters  |
| `Rx`, `Ry`, `Rz`                     | radians |

## Joints only

`GetCurrentJointPosition(robot)` returns only the joint values. Use it when you do not need the Cartesian position.

**C# : PositionJoints**
```csharp
using UnderAutomation.Staubli;

public class PositionJoints
{
    static void Main()
    {
        var controller = new StaubliController();
        controller.Connect("192.168.0.254");

        /**/
        // Only the joints, in radians
        double[] joints = controller.Soap.GetCurrentJointPosition(robot: 0);

        for (int i = 0; i < joints.Length; i++)
            Console.WriteLine($"J{i + 1} = {joints[i] * 180 / Math.PI:F2} deg");
        /**/

        controller.Disconnect();
    }
}
```

**Python : PositionJoints**
```python
import math

from underautomation.staubli.staubli_controller import StaubliController

controller = StaubliController()
controller.connect("192.168.0.254")

##
# Only the joints, in radians
joints = controller.soap.get_current_joint_position(0)

for i, joint in enumerate(joints):
    print(f"J{i + 1} = {math.degrees(joint):.2f} deg")
##

controller.disconnect()
```

## With a tool and a frame

By default, the Cartesian position is the one of the flange, in the world frame. Pass a tool and a frame to get the position of the tool center point in the frame of your part or table.

- `tool`: position of the tool center point, given in the flange frame.
- `frame`: position of the reference frame, given in the world frame.

**C# : PositionTool**
```csharp
using UnderAutomation.Staubli;
using UnderAutomation.Staubli.Soap.Data;

public class PositionTool
{
    static void Main()
    {
        var controller = new StaubliController();
        controller.Connect("192.168.0.254");

        /**/
        // Tool center point, given in the flange frame: 120 mm along Z
        var tool = new CartesianPosition { Z = 0.120 };

        // Reference frame, given in the world frame: a table 500 mm in front of the robot
        var frame = new CartesianPosition { X = 0.500 };

        CartesianJointPosition position = controller.Soap.GetCurrentCartesianJointPosition(robot: 0, tool, frame);

        // Position of the tool center point in the table frame
        CartesianPosition tcp = position.CartesianPosition;
        /**/

        controller.Disconnect();
    }
}
```

**Python : PositionTool**
```python
from underautomation.staubli.staubli_controller import StaubliController
from underautomation.staubli.soap.data.cartesian_position import CartesianPosition

controller = StaubliController()
controller.connect("192.168.0.254")

##
# Tool center point, given in the flange frame: 120 mm along Z
tool = CartesianPosition()
tool.z = 0.120

# Reference frame, given in the world frame: a table 500 mm in front of the robot
frame = CartesianPosition()
frame.x = 0.500

position = controller.soap.get_current_cartesian_joint_position(0, tool, frame)

# Position of the tool center point in the table frame
tcp = position.cartesian_position
##

controller.disconnect()
```

Pass `null` (`None` in Python) for the flange or for the world frame.

## Position of a joint configuration

To get the Cartesian position of joint values that are not the current ones, use the forward kinematics: see [Kinematics](/staubli/documentation/soap-kinematics).

## Try it in the demo application



## Reference

**Methods of SoapClientBase**
```csharp
// Get the Cartesian position and joint positions of a robot
CartesianJointPosition GetCurrentCartesianJointPosition(int robot = 0, CartesianPosition tool = null, CartesianPosition frame = null);

// Get the current joint position of a robot
double[] GetCurrentJointPosition(int robot = 0);
```

Every method also exists in an asynchronous version, with the same name followed by `Async` and an optional `CancellationToken`.

**Members of Soap.Data.CartesianJointPosition**
```csharp
public class CartesianJointPosition {
    public CartesianJointPosition()

    // The Cartesian position of the robot end effector.
    public CartesianPosition CartesianPosition { get; set; }

    public override bool Equals(object obj)

    public override int GetHashCode()

    // The joint positions in radians.
    public double[] JointsPosition { get; set; }

    public override string ToString()
}
```

**Members of Soap.Data.CartesianPosition**
```csharp
public class CartesianPosition {
    // Initializes a new instance of the <xref href="UnderAutomation.Staubli.Soap.Data.CartesianPosition" data-throw-if-not-resolved="false"></xref> class.
    public CartesianPosition()

    public override bool Equals(object obj)

    public override int GetHashCode()

    // Rotation around the X axis (radians).
    public double Rx { get; set; }

    // Rotation around the Y axis (radians).
    public double Ry { get; set; }

    // Rotation around the Z axis (radians).
    public double Rz { get; set; }

    public override string ToString()

    // X translation component (m).
    public double X { get; set; }

    // Y translation component (m).
    public double Y { get; set; }

    // Z translation component (m).
    public double Z { get; set; }
}
```