ABB Robot Communication SDK for Python
UnderAutomation.ABB is a Python package that talks to ABB industrial robot controllers over Robot Web Services (RWS). The same code runs on IRC5 (RobotWare 6) and on OmniCore (RobotWare 7). Nothing is installed on the controller. No RobotStudio, no PC SDK, no ABB runtime.
Use it to read and write RAPID variables, control I/O, read positions, jog the robot, manage programs, files and backups, and follow the state of the controller, from a Python script. It works with real controllers and with the virtual controllers of RobotStudio.
- Product page: underautomation.com/abb
- Documentation: underautomation.com/abb/documentation/get-started-python
- Also available for .NET: ABB.NET
What you can do
- RAPID variables and programs: read and write variables, persistents and constants, start and stop tasks, move the program pointer, load and save modules.
- Inputs / Outputs: list, read and write digital, analog and group signals, pulse, invert or simulate a signal, browse I/O devices and networks.
- Position and kinematics: read the current
robtargetandjointtarget, convert between Cartesian pose and joint values, jog the robot. - Controller and state: identity, options, operation mode, controller state, speed ratio, clock, language and network.
- Backup and restore: create a full backup, check it, restore it.
- File system: browse the controller file system, download and upload files, create, copy, rename and delete files and directories.
- Event log: read the event log by domain, in the language you ask, and clear it.
- System and energy: system product list, options and energy counters.
- Mastership: request and release the edit and motion mastership.
- Discovery: find the ABB controllers of the local network and the virtual controllers of this machine, without a license and without a known address.
- One API for both controller generations: IRC5 (RWS 1.0) and OmniCore (RWS 2.0), only one connection parameter changes.
No ABB option is required on the controller. Robot Web Services is part of a standard system.
How it works
The package wraps the .NET library UnderAutomation.ABB.dll with pythonnet.
The DLL is inside the package: pip install installs everything, including pythonnet.
-
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 tell pythonnet to use it before you start Python:
export PYTHONNET_RUNTIME=coreclr
Without this variable, pythonnet uses Mono, its default runtime on Linux and macOS. You can also choose the runtime in your code, before the first import of the package:
from pythonnet import load load("coreclr")
Installation
Python 3.7 to 3.13 is supported (the limit of pythonnet 3.0.5). Install the package in a virtual environment:
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux and macOS
source .venv/bin/activate
pip install UnderAutomation.ABB
Or install it from the sources of this repository:
git clone https://github.com/underautomation/ABB.py.git
cd ABB.py
pip install -e .
Getting started
from underautomation.abb.abb_controller import AbbController
# The SDK runs in trial mode for 30 days. Register your key to remove the trial limit.
# AbbController.register_license("Your Company", "your-license-key")
robot = AbbController()
robot.connect("192.168.125.1")
identity = robot.rws.controller.get_identity()
print(identity.name)
robot.disconnect()
Choose the controller generation
The default is OmniCore (RWS 2.0). For an IRC5 controller, set the version to RwsVersion.Irc5_V1_0.
The rest of your code does not change.
from underautomation.abb.abb_controller import AbbController
from underautomation.abb.connection_parameters import ConnectionParameters
from underautomation.abb.rws.rws_version import RwsVersion
params = ConnectionParameters("192.168.125.1")
params.rws.username = "Default User"
params.rws.password = "robotics"
params.rws.use_https = True # OmniCore is reached over HTTPS
params.rws.version = RwsVersion.OmniCore_V2_0 # or RwsVersion.Irc5_V1_0 for IRC5
robot = AbbController()
robot.connect(params)
Without the license layer
RwsClient is a standalone RWS client that you can use without AbbController:
from underautomation.abb.rws.rws_client import RwsClient
from underautomation.abb.rws.rws_version import RwsVersion
client = RwsClient()
client.connect("192.168.125.1", useHttps=True, version=RwsVersion.OmniCore_V2_0)
print(client.controller.get_identity().name)
From .NET names to Python names
The Python API is the .NET API with Python names. The .NET documentation applies to Python.
| .NET | Python |
|---|---|
Method GetIdentity() |
get_identity() |
Property Rws.Controller |
rws.controller |
Static method AbbController.RegisterLicense(...) |
AbbController.register_license(...) |
Enum value RwsVersion.OmniCore_V2_0 |
RwsVersion.OmniCore_V2_0 |
Array IoSignalItem[] |
list-like object, use list(...) to copy it |
Nullable<int> |
int | None |
Each type is in the module named after it, in snake case:
UnderAutomation.ABB.Rws.Data.MastershipDomain is underautomation.abb.rws.data.mastership_domain.MastershipDomain.
The async methods of the .NET API (...Async) have no Python equivalent: use the synchronous methods.
Features
Everything is reached through robot.rws, grouped by service:
controller, io, rapid, motion_system, panel, system, file, elog, mastership.
RAPID variables and programs
from underautomation.abb.rws.data.mastership_domain import MastershipDomain
# Read a RAPID symbol, the value comes back the way RAPID writes it
reg1 = robot.rws.rapid.get_symbol_value("RAPID/T_ROB1/user/reg1")
print(reg1.value)
# Write a symbol (needs the edit mastership in automatic mode)
robot.rws.mastership.request(MastershipDomain.Edit)
robot.rws.rapid.set_symbol_value("RAPID/T_ROB1/user/reg1", "42")
robot.rws.mastership.release(MastershipDomain.Edit)
# Start and stop the program
robot.rws.rapid.start()
robot.rws.rapid.stop()
# Load a program, list tasks, follow the execution state
robot.rws.rapid.load_program("T_ROB1", "HOME:/myprogram.pgf")
tasks = robot.rws.rapid.get_tasks()
state = robot.rws.rapid.get_execution_state()
Inputs / Outputs
# List every signal
signals = robot.rws.io.get_signals()
# Read one signal
di1 = robot.rws.io.get_signal("EtherNetIP", "d652", "DI_01")
print(di1.logical_value)
# Write, pulse or invert an output
robot.rws.io.set_signal_value("EtherNetIP", "d652", "DO_01", 1)
robot.rws.io.pulse_signal("EtherNetIP", "d652", "DO_01", 1, pulses=3)
robot.rws.io.invert_signal("EtherNetIP", "d652", "DO_01", 1)
# Simulate a signal so a value can be forced without hardware
robot.rws.io.set_signal_state("EtherNetIP", "d652", "DI_01", simulated=True)
Position and kinematics
from underautomation.abb.common.robot_joints import RobotJoints
# Current Cartesian and joint position of a task
rob_target = robot.rws.rapid.get_rob_target("T_ROB1")
joint_target = robot.rws.rapid.get_joint_target("T_ROB1")
print(f"X={rob_target.x} Y={rob_target.y} Z={rob_target.z}")
print(f"J1={joint_target.robot_axes.axis1} J2={joint_target.robot_axes.axis2}")
# Jog the robot
robot.rws.motion_system.set_jogging_mechanical_unit("ROB_1")
robot.rws.motion_system.jog(RobotJoints(5, 0, 0, 0, 0, 0), 0)
Discover controllers
# Finds the controllers of the local network and the virtual controllers of this machine.
# No connection is opened and no license is needed.
found = AbbController.discover()
for controller in found:
print(f"{controller.system_name} at {controller.address}:{controller.port}")
# to_connection_parameters carries the address, the port, the scheme and the RWS version found
robot = AbbController()
robot.connect(found[0].to_connection_parameters())
Controller and state
from datetime import datetime
identity = robot.rws.controller.get_identity()
info = robot.rws.controller.get_info()
mode = robot.rws.panel.get_operation_mode()
state = robot.rws.panel.get_controller_state()
speed_ratio = robot.rws.panel.get_speed_ratio()
robot.rws.panel.set_speed_ratio(50)
robot.rws.controller.set_clock(datetime.now())
has_option = robot.rws.controller.has_option("RobotWare-OS")
Backup and restore
robot.rws.controller.create_backup("HOME:/backups/2026-01-15")
check = robot.rws.controller.check_restore("HOME:/backups/2026-01-15")
if check.is_accepted:
robot.rws.controller.restore_backup("HOME:/backups/2026-01-15")
File system
listing = robot.rws.file.list_directory("HOME:/")
for d in listing.directories:
print(d.name)
for f in listing.files:
print(f"{f.name} ({f.size} bytes)")
robot.rws.file.upload_file_from_path("HOME:/myprogram.mod", r"C:\rapid\myprogram.mod")
robot.rws.file.get_file_to_destination("HOME:/myprogram.mod", r"C:\backup\myprogram.mod")
robot.rws.file.delete_file("HOME:/old.mod")
Event log
messages = robot.rws.elog.get_messages(domain=0, language="en")
for m in messages:
print(f"{m.timestamp} {m.title}")
robot.rws.elog.clear_all_messages()
Mastership
from underautomation.abb.rws.data.mastership_domain import MastershipDomain
robot.rws.mastership.request(MastershipDomain.Motion)
# ... jog or move the robot ...
robot.rws.mastership.release(MastershipDomain.Motion)
Examples
The folder examples contains scripts ready to run, one folder per RWS service.
examples/__init__.py holds the shared helpers: Python path, connection settings and license
registration. The first run asks the address of the controller, the RWS credentials and the protocol
version, and saves them in examples/robot_config.json (ignored by git). Press Enter to accept the value
between brackets.
Run a script from the root of the repository:
python examples/system/system_info.py
Or choose a script in a menu. The launcher runs it in the same process, so a breakpoint set in an example file is hit:
python examples/launcher.py
| Script | What it does |
|---|---|
license/license_info.py |
License state and every license property, no connection needed. |
controller/controller_identity.py |
Name, serial id, type, MAC address, installed systems, options and network interfaces. |
controller/controller_clock.py |
Reads the controller clock, its time zone and its time server, and sets the clock. |
controller/controller_backup.py |
Reads the backup state and the content of a backup, and creates a new one under $temp. |
system/system_info.py |
RobotWare version, options, robot types, installed products and energy counters. |
panel/panel_state.py |
Controller state, operation mode, mode selector lock and collision detection. |
panel/panel_speed_ratio.py |
Reads and writes the speed ratio, switches the motors on and off. |
io/io_list_signals.py |
Lists every signal with its value and its state, and searches signals by name. |
io/io_read_signal.py |
Reads one signal in detail: values, states, quality, timestamps, configuration. |
io/io_write_signal.py |
Writes, inverts, pulses and simulates an output signal, then restores it. |
io/io_networks_devices.py |
Browses the I/O topology: fieldbus networks, devices and their signals. |
rapid/rapid_tasks.py |
Lists the tasks, reads one in detail, its program, its pointers and the execution state. |
rapid/rapid_read_symbol.py |
Searches the RAPID symbols of a task and reads the value and properties of one. |
rapid/rapid_write_symbol.py |
Takes the edit mastership, writes a variable, restores it and releases the mastership. |
rapid/rapid_modules.py |
Lists the modules of a task, prints the source code and searches a text in it. |
rapid/rapid_start_stop.py |
Resets the program pointer, starts the execution, follows its state and stops it. |
motion/motion_mechanical_units.py |
Lists the mechanical units, their axes, their base frame and their calibration. |
motion/motion_current_position.py |
Reads the current robtarget in each coordinate system, the jointtarget and the axes. |
motion/motion_kinematics.py |
Forward and inverse kinematics on the controller, and every joint solution of a pose. |
file/file_browse.py |
Walks the controller file system, enters directories and reads the content of a file. |
file/file_transfer.py |
Uploads a local file under $temp, downloads it back and deletes it. |
elog/elog_messages.py |
Lists the event log domains and reads their messages with causes and actions. |
mastership/mastership_info.py |
Lists the mastership domains, shows who holds them, takes one and releases it. |
Notes:
- An example that only reads is safe on any controller. The examples that write ask before each change and put the original value back.
- A virtual controller does not implement every resource of a real one. When it answers 404, the example prints the reason and continues.
- A controller refuses a write when the mode selector is on manual and the FlexPendant keeps the ownership. The example prints the 403 answer instead of stopping.
- The certificate of an OmniCore controller is signed by the controller itself.
examples/__init__.pyaccepts it before the connection, seeallow_self_signed_certificates().
IRC5 and OmniCore, one API
ABB controllers expose Robot Web Services in two versions. This SDK covers both. The same code runs on an IRC5 and on an OmniCore. Only the connection parameters change.
| Controller | RobotWare | Robot Web Services | RwsVersion value |
|---|---|---|---|
| IRC5 | RobotWare 6 and earlier | RWS 1.0 | RwsVersion.Irc5_V1_0 |
| OmniCore | RobotWare 7 and later | RWS 2.0 | RwsVersion.OmniCore_V2_0 |
HTTP or HTTPS is a separate setting (use_https), independent of the controller generation.
Compatibility
- Python: 3.7 to 3.13, with pythonnet 3.0.5.
- Operating systems: Windows (.NET Framework), Linux and macOS (.NET runtime and
export PYTHONNET_RUNTIME=coreclr). - Controllers: IRC5, OmniCore, and their virtual controllers in RobotStudio.
License
This SDK needs a commercial license. A 30-day trial starts at the first use, no key needed. After the trial, register your key in your code:
from underautomation.abb.abb_controller import AbbController
license_info = AbbController.register_license("Your Company", "your-license-key")
print(license_info.state)
- License agreement: underautomation.com/abb/eula and License.md
- Trial key: underautomation.com/license
- Prices and quote: underautomation.com/abb
Support
- Documentation: underautomation.com/abb/documentation
- Issues: GitHub Issues
- Contact: underautomation.com/contact
Metadata
Release files for UnderAutomation.ABB 1.1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| underautomation_abb-1.1.0.0.tar.gz | 245.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| underautomation_abb-1.1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 577.8 kB
Release files / underautomation_abb-1.1.0.0.tar.gz
| Download URL | underautomation_abb-1.1.0.0.tar.gz |
|---|---|
| Size | 245.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1c1b12e8e2204a91a7a8a1d67f7726ab53f603ac8bd3cff2689da56877d73aa7
|
|
BLAKE2b-256 checksum How to use checksums |
911cfbaaec4fee425e0111ce2d6f5132ccb4e9c0ba6b39519671b1706e04d6ab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / underautomation_abb-1.1.0.0-py3-none-any.whl
| Download URL | underautomation_abb-1.1.0.0-py3-none-any.whl |
|---|---|
| Size | 332.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
81749e06c215faa749b51f409743830ff3774d2c9032b8418b392850a0c190d5
|
|
BLAKE2b-256 checksum How to use checksums |
ad8003a1ffdbc1111bb13cedc8e76e260d7c8b1b9b1e5202a1becc102ba416da
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|