UnderAutomation
有问题吗?

[email protected]

联系我们
UnderAutomation
⌘Q
本页面仅提供英文版本。

Get started with Python

Install the Universal Robots SDK from PyPI and write a first Python program. Python 3.7 to 3.13 on Windows, Linux and macOS, with pythonnet.

  • How it works
  • Install the package
  • From PyPI
  • From the sources
  • Use the SDK with an AI agent
  • First program
  • How the names are written
  • Events
  • Errors
  • Limits of the Python package
  • What to read next

This page shows how to install the Universal Robots SDK for Python and write a first program for a UR cobot. The Python package has the same functions as the .NET library, with Python names.

How it works

The package UnderAutomation.UniversalRobots contains the .NET library UnderAutomation.UniversalRobots.dll and a Python layer that calls it through pythonnet. pythonnet runs .NET code in the Python process. Nothing is installed on the robot.

ItemSupported
Python3.7 to 3.13
pythonnet3.0.5, installed with the package
Operating systemWindows, Linux, macOS
RobotsCB-Series, e-Series, UR8 Long, UR15, UR18, UR20, UR30, with PolyScope or PolyScope X, and URSim
  • Windows: the DLL runs on the .NET Framework 4.x of Windows. Nothing else to install.
  • Linux and macOS: install the .NET runtime (for example .NET 8), then select it for pythonnet before you start Python. Without this, pythonnet uses Mono, its default runtime on Linux and macOS.
Bash
sudo apt-get install -y dotnet-runtime-8.0
export PYTHONNET_RUNTIME=coreclr

Always write the export: a variable set without it does not reach the Python process. The same choice can be made in code, before the first import of the package:

# Linux and macOS: use the .NET runtime instead of Mono.
# Same effect as "export PYTHONNET_RUNTIME=coreclr", before the first import of the SDK
from pythonnet import load
load("coreclr")
from underautomation.universal_robots.ur import UR

Install the package

From PyPI

Install the package in a virtual environment:

Bash
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux and macOS
source .venv/bin/activate
pip install UnderAutomation.UniversalRobots

Package page: pypi.org/project/UnderAutomation.UniversalRobots

From the sources

Bash
git clone https://github.com/underautomation/UniversalRobots.py.git
cd UniversalRobots.py
pip install -e .

The repository also holds runnable examples, one folder per interface: examples/dashboard, examples/primary_interface, examples/rtde, examples/rest, examples/sftp, examples/kinematics and examples/license. Run python examples/launcher.py to choose one from a menu. The first run asks the address of the robot and saves it in examples/robot_config.json.

Use the SDK with an AI agent

An AI agent such as Claude Code, Codex, GitHub Copilot or Cursor can write your Python code with the SDK. Without help, it does not know which protocol to use, which controller option is needed, or the exact names of the API, so it can invent members that do not exist. The UnderAutomation skill gives it the documentation of this version of the SDK: protocols, controller settings, API in Python, errors and safety rules for robot motion.

With the skill installed, you can ask for example:

Install the skill in your project:

Bash
npx skills add underautomation/skills --skill underautomation-universal-robots-python

With Claude Code, you can also install it as a plugin:

Bash
claude plugin marketplace add underautomation/skills
claude plugin install universal-robots-python@underautomation

Or paste this prompt to your agent: "Install the UnderAutomation Universal Robots skill: follow https://underautomation.com/universal-robots/documentation/ai-skills.md". The other installation modes are in AI agent skills.

First program

Import UR, connect and read a value.

import time
from underautomation.universal_robots.ur import UR
# Only after the 30 day trial: register your license key
# UR.register_license("YourCompanyName", "YOUR_LICENSE_KEY")
robot = UR()
# Connect with the default services: Primary Interface and Dashboard Server
robot.connect("192.168.0.1")
# The Primary Interface receives the state of the robot at 10 Hz
time.sleep(0.5)
# Cartesian position of the tool, in meters and radians
pose = robot.primary_interface.cartesian_info.as_pose()
print(f"X={pose.x} Y={pose.y} Z={pose.z}")
# Mode of the robot, read with the Dashboard Server
mode = robot.dashboard.get_robot_mode()
print(f"Robot mode: {mode.value}")
robot.disconnect()
Click to see the full code

The SDK runs for 30 days without a key. After that, register_license is needed: see Licensing.

How the names are written

The Python package follows the .NET API, with Python names:

.NETPython
robot.PrimaryInterface.JointDatarobot.primary_interface.joint_data
robot.Dashboard.GetProgramState()robot.dashboard.get_program_state()
parameters.Rtde.OutputSetup.Add(...)parameters.rtde.output_setup.add(...)
UR.RegisterLicense(...)UR.register_license(...)
pose.X, pose.Rxpose.x, pose.rx
values.InputIntRegisters.X24values.input_int_registers.x24
RtdeOutputData.ActualTcpPoseRtdeOutputData.ActualTcpPose
SingularityType.NoneSingularityType.None_
robot.Rtde.OutputDataReceived += handlerrobot.rtde.output_data_received(handler)
A callback, like Action<ulong> of UploadFileA Python function: upload_file(local, remote, lambda sent: print(sent))
double[], double[][] returneda .NET array: index it, iterate it, or copy it with list(...)

Methods and properties become snake_case. Enumerations are Python IntEnum classes that keep the .NET value names, except the Python keywords (None_). Each type is in a module named after it, in the folder of its .NET namespace. A method that takes a .NET array accepts a Python list:

# Main class and connection settings
from underautomation.universal_robots.ur import UR
from underautomation.universal_robots.connect_parameters import ConnectParameters
# One module per type, in the folder of its .NET namespace
from underautomation.universal_robots.common.pose import Pose
from underautomation.universal_robots.rtde.rtde_input_data import RtdeInputData
from underautomation.universal_robots.rtde.rtde_output_data import RtdeOutputData
from underautomation.universal_robots.rtde.rtde_input_values import RtdeInputValues
from underautomation.universal_robots.kinematics.kinematics_utils import KinematicsUtils
from underautomation.universal_robots.files.ur_program import URProgram

Events

An event of the .NET API is a method in Python: call it with your function. The function receives two arguments, the sender and the event arguments. Read the new values in the properties of the client, or wrap the arguments in their Python class:

static void Main(string[] args)
{
var robot = new UR();
var parameters = new ConnectParameters("192.168.0.1");
// The socket server is disabled by default
parameters.SocketCommunication.Enable = true;
parameters.SocketCommunication.Port = 50001;
robot.Connect(parameters);
// URScript: socket_open("192.168.0.10", 50001)
robot.SocketCommunication.SocketClientConnection += (sender, e) =>
{
e.Client.SocketWrite("Welcome");
};
// URScript: socket_send_string("Hello")
robot.SocketCommunication.SocketRequest += (sender, e) =>
{
Console.WriteLine(e.Client.EndPoint.Address + " says " + e.Message);
};
// URScript: value := socket_get_var("COUNTER")
robot.SocketCommunication.SocketGetVar += (sender, e) =>
{
if (e.Name == "COUNTER") e.Value = 12; // integer only
};
// URScript: socket_close()
robot.SocketCommunication.SocketClientDisconnection += (sender, e) =>
{
Console.WriteLine(e.Client.EndPoint + " disconnected");
};
// Send a message to every connected robot
robot.SocketCommunication.SocketWrite("Start");
// Or to one robot
foreach (SocketClient client in robot.SocketCommunication.ConnectedClients)
client.SocketWrite("Hello " + client.EndPoint.Address);
}
}
Click to see the full code

The function runs in a thread of the SDK, not in the main thread of Python.

Errors

An error raised by the SDK comes from the .NET runtime. Import the exception class from its .NET namespace, after the import of the package. Its members keep their .NET names: Message, Service, LicenseInfo.

{
var robot = new UR();
try
{
robot.Connect("192.168.0.1");
}
catch (InvalidLicenseException ex)
{
// The trial is over or the license key is not valid
Console.WriteLine(ex.LicenseInfo);
}
catch (ConnectException ex)
{
// One service did not connect: the other services are closed
Console.WriteLine($"{ex.Service} of {ex.RobotIp}: {ex.Message}");
}
catch (Exception ex)
{
// For example, the robot does not answer the ping
Console.WriteLine(ex.Message);
}
// Errors that happen after the connection, in a background thread
robot.InternalErrorOccured += (sender, e) =>
{
Console.WriteLine($"{e.Status}: {e.Message}");
};
}
}
Click to see the full code

Limits of the Python package

  • A .NET method with an out parameter, like Pose.TryParse and Pose.FromRotationVectorToQuaternion, is not usable from Python.
  • GlobalVariable.ToMatrix has no Python twin.
  • The SDK has no asynchronous methods.

What to read next

  • Connect to the robot: the settings of the robot, the connection parameters, the errors.
  • RTDE and Primary Interface: every code sample has a Python tab.
  • Licensing: the 30 day trial and the license key.
  • AI agent skills: install the Python skill of the SDK in Claude Code, Codex, GitHub Copilot or Cursor.

轻松将 Universal Robots、Fanuc、Yaskawa、ABB 或 Staubli 机器人集成到您的 .NET、Python、LabVIEW 或 Matlab 应用程序中

UnderAutomation
联系我们Legal

© All rights reserved.