> For the complete documentation index, see [llms.txt](https://docs.cybus.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cybus.io/2-4-2/guides/machine-connectivity/robots-sensors-shop-floor-devices/connecting-a-universal-robots-cobot.md).

# Connecting a Universal Robots Cobot

This guide shows you how to read state data from a Universal Robots (UR) cobot with the Connectware [Modbus/TCP connector](/2-4-2/connectors/shop-floor-connectors/modbus-tcp.md) and map it into an ISA-95 style MQTT topic hierarchy. Every UR control box ships with a built-in Modbus/TCP server, so you do not need to install anything on the robot. The values collected here (robot mode, safety status, joint angles, TCP position, and a program-defined cycle counter) are the typical input for cell dashboards, utilization monitoring, and condition monitoring. In more detail, the following topics are covered:

* The built-in Modbus/TCP server of the UR control box
* Identifying the Modbus registers for robot state, joint angles, and TCP position
* Decoding signed values with the `int16BE` data type
* Converting milli-radians to degrees with a transform rule
* Creating the [service commissioning file](/2-4-2/data-flows/service-commissioning-files.md)
* Mapping the values into an ISA-95 style MQTT topic hierarchy
* Verifying data in the [Data Explorer](/2-4-2/monitoring/data-explorer.md)

This guide focuses on the UR specifics. For a general introduction to the Modbus/TCP connector, including function codes and write operations, see [Connecting & Integrating a Modbus/TCP Server](/2-4-2/guides/machine-connectivity/gateways-generic-protocols/connecting-and-integrating-a-modbus-tcp-server.md).

A complete example file is available at the end of this guide.

## Prerequisites

To follow this guide, you will need the following:

* A running instance of Cybus Connectware.
* A Universal Robots cobot that is reachable over Ethernet from Connectware. The register map in this guide applies to e-Series robots (for example, a UR10e) and CB-Series robots alike. The Modbus/TCP server is available on all CB3 and e-Series controllers, and on CB2 controllers from software 1.6 on.
* Access to the [Admin UI](/2-4-2/access/admin-ui.md) with sufficient [user permissions](/2-4-2/access/user-management.md).
* Basic knowledge of MQTT and the Connectware [services](/2-4-2/data-flows/services.md) concept (for example, [service commissioning files](/2-4-2/data-flows/service-commissioning-files.md), [connections](/2-4-2/data-flows/service-commissioning-files/resources/cybus-connection.md), and [endpoints](/2-4-2/data-flows/service-commissioning-files/resources/cybus-endpoint.md)).

## The Built-In Modbus/TCP Server

The UR control box acts as a Modbus/TCP server on the standard port 502. Configure the network settings in PolyScope so that the robot has an IP address that Connectware can reach; the registers are then available without further configuration on the robot. The server supports the standard Modbus function codes for reading (1 to 4) and writing (5, 6, 15, and 16). This guide reads all values with function code 3.

UR controllers also offer the Real-Time Data Exchange (RTDE) interface, which streams the same robot state at higher rates in a proprietary format; Connectware does not support RTDE out of the box, so this guide uses the Modbus/TCP server.

## Identifying the Modbus Registers

The register map of the server is fixed and identical across robot generations. It is documented in the Universal Robots support article [Modbus server](https://www.universal-robots.com/articles/ur/interface-communication/modbus-server/), which includes the complete register table as a download. Each value occupies exactly one 16-bit register. The following registers are used in this guide:

| Address | Name                 | Unit         |
| ------: | -------------------- | ------------ |
|     258 | Robot mode           | enum         |
|     260 | `isPowerOnRobot`     | 0 or 1       |
|     261 | `isSecurityStopped`  | 0 or 1       |
|     262 | `isEmergencyStopped` | 0 or 1       |
|     270 | Base joint angle     | mrad         |
|     271 | Shoulder joint angle | mrad         |
|     272 | Elbow joint angle    | mrad         |
|     273 | Wrist 1 joint angle  | mrad         |
|     274 | Wrist 2 joint angle  | mrad         |
|     275 | Wrist 3 joint angle  | mrad         |
|     400 | TCP x (base frame)   | tenth of mm  |
|     401 | TCP y (base frame)   | tenth of mm  |
|     402 | TCP z (base frame)   | tenth of mm  |
| 128-255 | General purpose      | user-defined |

On CB3 and e-Series controllers, the robot mode register reports the following values: 0 = Disconnected, 1 = Confirm safety, 2 = Booting, 3 = Power off, 4 = Power on, 5 = Idle, 6 = Backdrive, 7 = Running. CB2 controllers use a different value set for this register, which is listed in the same UR article. The `isSecurityStopped` register indicates a protective stop, `isEmergencyStopped` an emergency stop.

The register map provides more values that follow the same pattern as the endpoints in this guide: joint speeds (280 to 285, mrad/s), joint currents (290 to 295, mA), joint temperatures (300 to 305, °C), TCP orientation rx, ry, rz (403 to 405, mrad), and TCP speed (410 to 415). Register 266 reports the safety mode with the values documented in the UR Primary Interface manual, but is only available from PolyScope 5.14 on.

### General Purpose Registers

Registers 128 to 255 are general purpose registers that the robot program can read and write with the URScript functions `read_port_register()` and `write_port_register()`. The fixed register map has no dedicated program state register, so use a general purpose register to expose program-level information, for example a cycle counter or the number of the active program step. A single line in the robot program, such as `write_port_register(128, cycle_count)`, makes the value readable for Connectware. Because these registers are also writable over Modbus with function code 6, you can use them for data flowing towards the robot as well; see [Connecting & Integrating a Modbus/TCP Server](/2-4-2/guides/machine-connectivity/gateways-generic-protocols/connecting-and-integrating-a-modbus-tcp-server.md) for write endpoints.

### Handling Signed 16-Bit Values

UR documents all register values as unsigned 16-bit integers and leaves the signed interpretation to the client. Joint angles and TCP coordinates are signed quantities: a base joint moved to -90° reports -1571 mrad, which arrives on the wire as the unsigned value 63965. Set `dataType: int16BE` and Connectware decodes the register as a signed two's complement integer, so negative angles and coordinates arrive as negative JSON numbers without manual conversion. For registers that only report 0, 1, or small positive values, this guide uses `uint16BE` to make the intent explicit. For all available data types, see [Modbus/TCP Endpoint Properties](/2-4-2/connectors/shop-floor-connectors/modbus-tcp/modbusendpoint.md).

## Writing the Service Commissioning File

The service commissioning file contains all connection and mapping details. Do not worry about copying the snippets together into one file, the complete example file is available at the end of this guide.

### Description and Metadata

These sections contain general information about the service commissioning file. Only the metadata name is required.

{% code lineNumbers="true" %}

```yaml
description: >
  Service commissioning file that reads robot mode, safety status, joint
  angles, and TCP position from a Universal Robots cobot over the built-in
  Modbus/TCP server and maps them into an ISA-95 style MQTT topic hierarchy
  (Example)

metadata:
  name: Universal Robots Cobot Example
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0
```

{% endcode %}

### Parameters and Definitions

We define the network address of the control box as parameters, so you can set them when you install the service. The default Modbus/TCP port is 502.

The MQTT topics in this guide follow an ISA-95 style equipment hierarchy with a `cobot` branch (`<enterprise>/<site>/<area>/<line>/cobot`). We define the prefix once in the `definitions` section and reuse it in every mapping with `!sub`.

{% code lineNumbers="true" %}

```yaml
parameters:
  cobotHost:
    description: Hostname or IP address of the Universal Robots control box
    type: string
    default: 192.168.1.100

  cobotPort:
    description: Modbus/TCP port of the Universal Robots control box
    type: integer
    default: 502

definitions:
  MQTT_TOPIC_PREFIX: enterprise/hamburg/assembly/line-1/cobot
```

{% endcode %}

### Cybus::Connection

The connection resource establishes the Modbus/TCP connection to the control box. The `connectionStrategy` object controls how Connectware retries failed connection attempts with increasing delays. For all connection properties, see [Modbus/TCP Connection Properties](/2-4-2/connectors/shop-floor-connectors/modbus-tcp/modbusconnection.md).

{% code lineNumbers="true" %}

```yaml
resources:
  cobotConnection:
    type: Cybus::Connection
    properties:
      protocol: Modbus
      targetState: connected
      connection:
        host: !ref cobotHost
        port: !ref cobotPort
        connectionStrategy:
          initialDelay: 1000
          maxDelay: 30000
          incrementFactor: 2
```

{% endcode %}

### Robot State Endpoints

Each endpoint polls one register. The register address becomes `address`, and since every value occupies one register, `length` is always 1. The robot mode is decoded as `int16BE` because CB2 controllers report -1 for "No controller". The safety flags at addresses 260 to 262 only report 0 or 1 and use `uint16BE`; the following snippet shows one of them, the other two differ only in the address.

{% code lineNumbers="true" %}

```yaml
robotMode:
  type: Cybus::Endpoint
  properties:
    protocol: Modbus
    connection: !ref cobotConnection
    subscribe:
      fc: 3
      address: 258
      length: 1
      dataType: int16BE
      interval: 1000

emergencyStop:
  type: Cybus::Endpoint
  properties:
    protocol: Modbus
    connection: !ref cobotConnection
    subscribe:
      fc: 3
      address: 262
      length: 1
      dataType: uint16BE
      interval: 1000
```

{% endcode %}

### Joint Angle Endpoints with a Transform Rule

The joint angle registers report milli-radians, which is rarely the unit you want on a dashboard. A [transform rule](/2-4-2/data-flows/rule-engine/data-processing-rules.md#transform) converts the value to degrees before Connectware publishes it: one milli-radian is 180 / (1000 × π) ≈ 0.0572957795 degrees. The JSONata expression keeps the message structure with `timestamp` and `value` intact and rounds the result to two decimal places.

{% code lineNumbers="true" %}

```yaml
jointAngleBase:
  type: Cybus::Endpoint
  properties:
    protocol: Modbus
    connection: !ref cobotConnection
    subscribe:
      fc: 3
      address: 270
      length: 1
      dataType: int16BE
      interval: 500
    rules:
      - transform:
          expression: |
            {
              "timestamp": timestamp,
              "value": $round(value * 0.0572957795, 2)
            }
```

{% endcode %}

The endpoints for the remaining five joints (addresses 271 to 275) are identical apart from the address and are included in the complete example file.

### TCP Position Endpoints

The TCP position registers report tenths of millimeters in the base frame. The same transform rule pattern converts them to millimeters. The following snippet shows the x coordinate; y and z (addresses 401 and 402) follow the same pattern.

{% code lineNumbers="true" %}

```yaml
tcpPositionX:
  type: Cybus::Endpoint
  properties:
    protocol: Modbus
    connection: !ref cobotConnection
    subscribe:
      fc: 3
      address: 400
      length: 1
      dataType: int16BE
      interval: 500
    rules:
      - transform:
          expression: |
            {
              "timestamp": timestamp,
              "value": value / 10
            }
```

{% endcode %}

{% hint style="info" %}
The joint angle registers 270 to 275 and the TCP position registers 400 to 402 are contiguous. If you poll many endpoints, enable [batch read processing](/2-4-2/connectors/shop-floor-connectors/modbus-tcp.md#batch-read-processing) on the connection. Connectware then combines reads of neighboring registers into a single request.
{% endhint %}

### Cycle Counter Endpoint

The last endpoint reads the general purpose register 128, which the robot program writes with `write_port_register(128, cycle_count)`. General purpose registers hold whatever the robot program stores in them; for a plain counter, `uint16BE` is the appropriate data type.

{% code lineNumbers="true" %}

```yaml
cycleCounter:
  type: Cybus::Endpoint
  properties:
    protocol: Modbus
    connection: !ref cobotConnection
    subscribe:
      fc: 3
      address: 128
      length: 1
      dataType: uint16BE
      interval: 1000
```

{% endcode %}

### Cybus::Mapping

The mapping publishes each endpoint on a topic of the ISA-95 hierarchy.

{% code lineNumbers="true" %}

```yaml
mapping:
  type: Cybus::Mapping
  properties:
    mappings:
      - subscribe:
          endpoint: !ref robotMode
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/state/robot-mode'
      - subscribe:
          endpoint: !ref powerOn
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/state/power-on'
      - subscribe:
          endpoint: !ref protectiveStop
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/state/protective-stop'
      - subscribe:
          endpoint: !ref emergencyStop
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/state/emergency-stop'
      - subscribe:
          endpoint: !ref jointAngleBase
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/base/angle'
      - subscribe:
          endpoint: !ref jointAngleShoulder
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/shoulder/angle'
      - subscribe:
          endpoint: !ref jointAngleElbow
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/elbow/angle'
      - subscribe:
          endpoint: !ref jointAngleWrist1
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-1/angle'
      - subscribe:
          endpoint: !ref jointAngleWrist2
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-2/angle'
      - subscribe:
          endpoint: !ref jointAngleWrist3
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-3/angle'
      - subscribe:
          endpoint: !ref tcpPositionX
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/x'
      - subscribe:
          endpoint: !ref tcpPositionY
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/y'
      - subscribe:
          endpoint: !ref tcpPositionZ
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/z'
      - subscribe:
          endpoint: !ref cycleCounter
        publish:
          topic: !sub '${MQTT_TOPIC_PREFIX}/program/cycle-counter'
```

{% endcode %}

With this mapping, the base joint angle is published on the topic `enterprise/hamburg/assembly/line-1/cobot/joint/base/angle`, and every other value follows the same pattern.

## Installing the Service Commissioning File

1. Install the service commissioning file. See [Installing Services](/2-4-2/data-flows/services/managing/installing.md).
2. Enable the service. See [Enabling Services](/2-4-2/data-flows/services/managing/enabling.md).

**Result:** The service is enabled. Connectware establishes the Modbus/TCP connection to the control box and polls the configured registers.

## Verifying the Data

Open the [Data Explorer](/2-4-2/monitoring/data-explorer.md) and subscribe to `enterprise/hamburg/assembly/line-1/cobot/#`. Each topic carries a JSON object with the keys `timestamp` and `value`, where the value is the decoded and converted measurement:

{% code lineNumbers="true" %}

```json
{
  "timestamp": 1784194200354,
  "value": -92.45
}
```

{% endcode %}

A few plausibility checks for the first readings:

* The topic `state/robot-mode` reports 7 (Running) on an e-Series or CB3 robot that is powered on with the brakes released.
* The joint angles match the values on the Move screen of PolyScope.
* The TCP position matches the TCP coordinates that PolyScope displays, in millimeters.
* When you press the emergency stop button, `state/emergency-stop` changes to 1 and the robot mode leaves 7.

If the connection does not reach the **Connected** state, verify that the robot has finished booting and that port 502 is reachable from Connectware. If angles or coordinates that should be negative arrive as large positive numbers around 65000, the endpoint decodes the register as unsigned: set `dataType` to `int16BE`. If values are off by a constant factor, check the unit conversion in the transform rule against the register table.

## Service Commissioning File Example

{% file src="/files/mGmgCaSs5nAI1mw1OFO5" %}

{% code title="universal-robots-example.yml" lineNumbers="true" expandable="true" %}

```yaml
---
# ----------------------------------------------------------------------------
# Service Commissioning File
# ----------------------------------------------------------------------------
# Copyright: Cybus GmbH
# Contact: support@cybus.io
# ----------------------------------------------------------------------------
# Connecting a Universal Robots Cobot (Example)
# ----------------------------------------------------------------------------

description: >
  Service commissioning file that reads robot mode, safety status, joint
  angles, and TCP position from a Universal Robots cobot over the built-in
  Modbus/TCP server and maps them into an ISA-95 style MQTT topic hierarchy
  (Example)

metadata:
  name: Universal Robots Cobot Example
  provider: cybus
  homepage: https://www.cybus.io
  version: 1.0.0

parameters:
  cobotHost:
    description: Hostname or IP address of the Universal Robots control box
    type: string
    default: 192.168.1.100

  cobotPort:
    description: Modbus/TCP port of the Universal Robots control box
    type: integer
    default: 502

definitions:
  # ISA-95 style topic prefix: <enterprise>/<site>/<area>/<line>/cobot
  MQTT_TOPIC_PREFIX: enterprise/hamburg/assembly/line-1/cobot

resources:
  # Connection to the Universal Robots control box (built-in Modbus/TCP
  # server on port 502)
  cobotConnection:
    type: Cybus::Connection
    properties:
      protocol: Modbus
      targetState: connected
      connection:
        host: !ref cobotHost
        port: !ref cobotPort
        connectionStrategy:
          initialDelay: 1000
          maxDelay: 30000
          incrementFactor: 2

  # Robot state registers. Register addresses from the register table of the
  # Universal Robots support article "Modbus server". Each value occupies
  # one 16-bit register.
  # Robot mode is decoded as int16BE because CB2 controllers report -1 for
  # "No controller".
  robotMode:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 258
        length: 1
        dataType: int16BE
        interval: 1000

  powerOn:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 260
        length: 1
        dataType: uint16BE
        interval: 1000

  protectiveStop:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 261
        length: 1
        dataType: uint16BE
        interval: 1000

  emergencyStop:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 262
        length: 1
        dataType: uint16BE
        interval: 1000

  # Joint angles: registers 270-275 report milli-radians as signed 16-bit
  # values. A transform rule converts them to degrees before publishing
  # (1 mrad = 180 / (1000 * pi) degrees = 0.0572957795 degrees).
  jointAngleBase:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 270
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  jointAngleShoulder:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 271
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  jointAngleElbow:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 272
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  jointAngleWrist1:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 273
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  jointAngleWrist2:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 274
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  jointAngleWrist3:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 275
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": $round(value * 0.0572957795, 2)
              }

  # TCP position: registers 400-402 report tenths of millimeters in the base
  # frame as signed 16-bit values. A transform rule converts them to
  # millimeters before publishing.
  tcpPositionX:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 400
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": value / 10
              }

  tcpPositionY:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 401
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": value / 10
              }

  tcpPositionZ:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 402
        length: 1
        dataType: int16BE
        interval: 500
      rules:
        - transform:
            expression: |
              {
                "timestamp": timestamp,
                "value": value / 10
              }

  # General purpose register 128: written by the robot program with
  # write_port_register(128, <value>), for example as a cycle counter.
  cycleCounter:
    type: Cybus::Endpoint
    properties:
      protocol: Modbus
      connection: !ref cobotConnection
      subscribe:
        fc: 3
        address: 128
        length: 1
        dataType: uint16BE
        interval: 1000

  mapping:
    type: Cybus::Mapping
    properties:
      mappings:
        - subscribe:
            endpoint: !ref robotMode
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/state/robot-mode'
        - subscribe:
            endpoint: !ref powerOn
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/state/power-on'
        - subscribe:
            endpoint: !ref protectiveStop
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/state/protective-stop'
        - subscribe:
            endpoint: !ref emergencyStop
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/state/emergency-stop'
        - subscribe:
            endpoint: !ref jointAngleBase
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/base/angle'
        - subscribe:
            endpoint: !ref jointAngleShoulder
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/shoulder/angle'
        - subscribe:
            endpoint: !ref jointAngleElbow
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/elbow/angle'
        - subscribe:
            endpoint: !ref jointAngleWrist1
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-1/angle'
        - subscribe:
            endpoint: !ref jointAngleWrist2
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-2/angle'
        - subscribe:
            endpoint: !ref jointAngleWrist3
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/joint/wrist-3/angle'
        - subscribe:
            endpoint: !ref tcpPositionX
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/x'
        - subscribe:
            endpoint: !ref tcpPositionY
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/y'
        - subscribe:
            endpoint: !ref tcpPositionZ
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/tcp/position/z'
        - subscribe:
            endpoint: !ref cycleCounter
          publish:
            topic: !sub '${MQTT_TOPIC_PREFIX}/program/cycle-counter'
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.cybus.io/2-4-2/guides/machine-connectivity/robots-sensors-shop-floor-devices/connecting-a-universal-robots-cobot.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
