Copyright (c) 2025, b-robotized. All rights reserved. Author: Nikola Banovic
This package provides a ros2_control SystemInterface for communicating with Beckhoff TwinCAT PLCs. It acts as a transport layer, allowing ros2_control controllers to read from and write to PLC variables (e.g., joint states, GPIOs, sensor values) over the network.
The core of this hardware interface is in using ADS Sum-Commands. This allows us to read/write multiple PLC variables in a single network transaction, bringing the total network transactions per update loop to only 2 (one read and one write).
This package is built upon the official beckhoff/ADS library, which handles the low-level ADS protocol communication.
ros2_controlIntegration: Seamlessly integrate your PLC application with theros2_controlframework.- Efficient Communication: Utilizes ADS Sum-Commands to bundle multiple variable requests, ensuring high-performance communication suitable for real-time control loops.
- URDF-Based Configuration: All hardware connections and variable mappings are configured directly within your robot's URDF file.
- ROS 2 (Jazzy Jalisco or newer recommended)
- ads_vendor package
Configuration is managed entirely within the <ros2_control> tag of your robot's URDF file. You must specify the PLC connection parameters and map each hardware interface (state or command) to a specific variable on the PLC.
These parameters define the connection to the target PLC.
| Parameter | Type | Description |
|---|---|---|
plc_ip_address |
string |
The IP address of the Beckhoff PLC. |
plc_ams_net_id |
string |
The AMS NetID of the target PLC (e.g., "192.168.1.1.1.1"). |
local_ams_net_id |
string |
The AMS NetID of the computer running ROS. |
plc_ams_port |
string |
The AMS Port of the PLC runtime (e.g., "851"). |
For each <state_interface> and <command_interface>, you must provide parameters that link it to a PLC variable.
| Parameter | Type | Description |
|---|---|---|
PLC_symbol |
string |
The full symbolic name of the variable in the PLC (e.g., "MAIN.Joint_Pos_State"). |
PLC_type |
string |
The data type of the PLC variable (e.g., "LREAL", "BOOL", "DINT"). Case-insensitive. |
n_elements |
integer |
(Optional) The number of elements if the symbol is an array. Defaults to 1. |
index |
integer |
(Optional) The index within the PLC array that this interface corresponds to. Defaults to 0. |
initial_value |
double |
(Optional, Command Only) The initial value for a command interface before the first command is received. |
The following PLC data types are supported and are automatically converted to and from double values.
LREAL,REALBOOLDINT,UDINTINT,UINTSINT,USINTBYTE
[In this accompanying package]is an example of how to configure the hardware interface in a URDF file for a 6-axis robot and a digital output. Here we also provide a sample PLC project with this hardware interface, along with an example URDF
First, load and compile the sample PLC project in your TwinCAT XAE environment. TwinCAT XAE is available for non-commercial use with a trial license
- Import the PLC Project: Import the from the
PLC-TestProjectdirectory. - Import the Library: The PLC program requires the
tc3_interfaceslibrary provided with the project. In the Solution Explorer, right-click on References, select Add Library, and add the provided.compiled-libraryfile. This will allow the program to compile successfully.
For ADS communication to work, your TwinCAT system needs a static IP and a route to the ROS 2 machine.
- Set a Static IP: Assign a static IP address to the network adapter on your Windows machine that you'll use for ADS. This IP must match the
plc_ip_addressin your URDF. - Configure Firewall: Ensure your Windows firewall allows traffic on the ADS port (TCP 851 is the default) or is disabled on the private network for testing. Verify connectivity by pinging the Windows machine from the ROS 2 host.
- Set Local AMS Net ID: In the TwinCAT systray icon, go to Router -> Change AMS NetID... and set it to match the
plc_ams_net_idin your URDF. Restart TwinCAT when prompted. This is the address of your virtual PLC device. - Add Static Route: In your project's SYSTEM -> Routes tab, add a Static route that points to your ROS 2 machine.
- AMS Net ID:
local_ams_net_idfrom the URDF. - IP Address: The IP address of the machine running the ROS 2 hardware interface.
- AMS Net ID:
- Activate Configuration: Click the "Activate Configuration" button in the toolbar to download the hardware setup to the runtime.
- Login and Run: Select the PLC project, click Login to download the program, and then click Start to run it. The TwinCAT icon in the systray should turn green.
With the PLC running and waiting for a connection, launch the ros2_control system.
A successful connection will produce log output similar to this, showing the interface linking to the PLC symbols and establishing communication:
[controller_manager]: Loading hardware 'beckhoff_bot'
[BeckhoffADSHardwareInterface]: Exporting state interfaces...
[BeckhoffADSHardwareInterface]: sensor 'robot_sensor/currentPos_0' | hw_states_[2] <-- MAIN.currentPos[0]
...
[BeckhoffADSHardwareInterface]: Exporting command interfaces...
[BeckhoffADSHardwareInterface]: gpio 'robot_io/joggingEnabled' | hw_commands_[0] --> MAIN.joggingEnabled
...
[BeckhoffADSHardwareInterface]: Configuring ADS device...
[BeckhoffADSHardwareInterface]: ADS Device configured for PLC: 192.168.122.2, Port: 851
[BeckhoffADSHardwareInterface]: Requesting Device state...
[BeckhoffADSHardwareInterface]: Communication successful! ADS State: 5, DeviceState: 0
[BeckhoffADSHardwareInterface]: Fetching ADS handles for configured PLC variables...
[BeckhoffADSHardwareInterface]: Handles acquired
[resource_manager]: Successful 'configure' of hardware 'beckhoff_bot'
[resource_manager]: 'activate' hardware 'beckhoff_bot'
You can then inspect the live values from the PLC in another terminal and compare them with those in the TwinCAT XAE:
ros2 topic echo /controller_manager/introspection_data/full
For troubleshooting network connection with TwinCAT 3 XAE, refer to the documentation, especially chapters 7. and 8.
Feel free to contribute on any of these!
The ADS protocol supports asynchronous callbacks, where the PLC can push a variable update to the client ("notifications"). We plan to add a mechanism to register for these notifications directly from the URDF. This will allow state interfaces for rarely updated variables to be updated via callbacks instead of being polled in every read() cycle, further optimizing the main control loop.
We plan to add support for reading PLC STRING variables. As ros2_control state interfaces are numeric, this would likely be exposed through a separate mechanism, such as publishing to a ROS topic, for monitoring purposes.
We may investigate adding support for reading and writing to user-defined structures (DUTs) on the PLC. This would allow for more complex data to be exchanged in a single, structured block. However, this is a complex feature and is considered a low-priority research item.
This ads_vendor package was created by B-Robotized GmbH and is provided under the Apache 2.0 License.
The vendored Beckhoff ADS library is subject to its own license, which can be found in its repository.