Universal Robots Trigger Node
Start a pipeline with an RTDE sample of a Universal Robots cobot once per publish interval, with readable modes and the controller's own time.
- Starts on
- Each publish interval (100 ms to 1 h)
- Function
- Monitor RTDE
- Output
- One event per interval
- Dedup
- None: every sample starts a run
Overview
The Universal Robots Trigger Node starts a MaestroHub pipeline with an RTDE sample of the variables a Monitor RTDE function lists (joint positions, TCP pose, I/O, robot and safety modes, runtime state…). Unlike the Read RTDE node, which reads one sample inside an already-running pipeline, the trigger starts a new execution once per publish interval.
The robot streams RTDE at 125 Hz (CB3) or 500 Hz (e-Series). The trigger asks it for twice the publish rate (at most 10 Hz) and starts a pipeline with the first sample at least one publish interval after the previous one, on the robot's own clock, so a 1 s interval is one run per second however fast the robot runs.
Reconnection Handling
- If no sample arrives for 5 seconds, or the RTDE link drops, the trigger fires once with
_metadata.qualitybadand the reason under_metadata.error. Itsresultis the last sample delivered (an empty object if none had arrived yet). - The stream then reconnects on its own (after 1 s, backing off to 30 s) while the connection is up, and the next sample is
goodagain. - When the whole connection reconnects, every trigger's stream is started again; nothing needs re-enabling.
Configuration Options
| Field | Meaning |
|---|---|
| Connection | A Universal Robots connection |
| Function | A Monitor RTDE function on it |
| Enabled | Off keeps the node but never subscribes |
The function sets RTDE Variables (comma-separated, at most 64) and Publish Interval (100ms to 1h, default 1s). See Monitor RTDE.
Output Data Structure
Output Format
{
"_metadata": {
"type": "universalrobots_trigger",
"protocol": "universalrobots",
"connectionId": "bf29be94-fc0a-4dc4-8e5c-092f1b74eb4b",
"functionId": "aef374c3-aa2b-454e-aabc-5657faac5950",
"controllerTime": "12345.678",
"serverTimestamp": "2026-10-20T10:14:03.221Z",
"quality": "good",
"timestamp": "2026-10-20T10:14:03.221123456Z"
},
"result": {
"values": { "actual_q": [0, -1.5708, 1.5708, -1.5708, -1.5708, 0], "robot_mode": 7, "runtime_state": 2 },
"labels": { "robot_mode": "RUNNING", "runtime_state": "PLAYING" },
"controllerTime": 12345.678,
"quality": "good",
"serverTimestamp": "2026-10-20T10:14:03.221Z"
}
}
result Fields
| Field | Type | Description |
|---|---|---|
values | object | One entry per variable, by name: numbers, booleans, or arrays for vectors. |
labels | object | Readable names for robot_mode, safety_mode, safety_status and runtime_state when they are in the recipe; UNKNOWN for a code this release does not know. |
controllerTime | number | The controller's clock, seconds since it started. Not wall-clock time. |
quality | string | good for a sample the robot sent. |
serverTimestamp | string | When MaestroHub received the sample, UTC. |
_metadata Fields
| Field | Type | Description |
|---|---|---|
type | string | Always "universalrobots_trigger". |
protocol | string | Always "universalrobots". |
connectionId | string | The connection profile ID. |
functionId | string | The Monitor RTDE function ID. |
controllerTime | string | The controller's clock, as a string. |
serverTimestamp | string | RFC 3339, UTC; when MaestroHub received the sample. |
quality | string | good, or bad on the once-per-outage failure event. |
quality_reason | string | Only on a failure event: comm_error. |
error | string | Only on a failure event: why the stream was lost. |
timestamp | string | RFC 3339 (nanoseconds); when the trigger event was created, UTC. |
Referencing in Downstream Nodes
$trigger.result.values.actual_q: the joint positions$trigger.result.labels.robot_mode: e.g.RUNNING$trigger.result.controllerTime: the robot's clock$trigger.result.qualityand$trigger._metadata.quality:badon the failure event$trigger.result.serverTimestamp: when the sample arrived$trigger._metadata.connectionId,$trigger._metadata.functionId: the connection and function used
Best Practices
- Choose the longest publish interval that answers your question: one event per second per robot is plenty for dashboards and downtime tracking.
- List only the variables you use; each is decoded and carried in every event.
- Branch on
labelsrather than numeric codes, so a pipeline readslabels.safety_status == "PROTECTIVE_STOP".