The UR5e is a 6-axis collaborative arm from Universal Robots, part of the e-Series lineup that added a wrist-mounted force/torque sensor and freedrive hand-guiding to the earlier CB-series line. It shows up constantly in robot-learning work for reasons that have little to do with performance and everything to do with logistics: it is a common shop-floor and lab arm, its safety-rated speed and force limiting means it can share space with an operator without a fence, and its control stack — RTDE, URScript, and a maintained ROS 2 driver — is well documented enough that getting clean, synchronized data off it is a solved problem rather than a research project.
That last point is what this page is actually about. The UR5e is not a research arm built for compliant manipulation the way a Franka is; it is an industrial cobot that happens to have interfaces good enough for teleoperation and demonstration recording. Knowing which interface to use for which purpose — and where the arm's control architecture creates friction for data collection — is most of what you need to run it well.
- Degrees of freedom
- 6 rotating joints
- Payload
- 5 kg (11 lb)
- Reach
- 850 mm (33.5 in)
- RTDE streaming rate
- Up to 500 Hz, TCP/IP port 30004
Control interfaces that matter for data collection
Three interfaces cover essentially everything you need.
RTDE (Real-Time Data Exchange) is a TCP/IP protocol, served on port 30004, for streaming state out of the controller and setpoints in, without breaking the controller's real-time guarantees. On e-Series arms it can output at up to 500 Hz — the same rate as the arm's internal control loop — and it exposes joint positions, velocities, currents, and estimated torques, TCP pose, TCP velocity and force, digital/analog I/O, and safety and robot-mode status. For recording, RTDE is almost always the right channel: it is read-only-friendly, low-overhead, and does not require writing a URScript program to get data out.
URScript is Universal Robots' native scripting language — the language PolyScope programs compile down to, and the language you write directly if you're driving the arm at the socket level rather than through the teach pendant. It handles motion primitives (movej, movel, speedj), I/O, and control flow, and it runs on the controller at the same 500 Hz cycle. You mostly touch URScript when you need to issue motion commands programmatically; for pure logging, RTDE is sufficient and less invasive.
The ROS 2 driver. Universal_Robots_ROS2_Driver, maintained by Universal Robots, wraps RTDE, URScript, and the dashboard server behind a standard ROS 2 controller interface, publishing /joint_states and exposing MoveIt 2 integration out of the box. It supports the full e-Series and CB3 lineup and lists passing builds against current distributions. If your capture stack is already ROS 2, this driver is the path of least resistance — it turns RTDE's raw TCP stream into topics you can record with any ROS 2-native tool.
A minimal RTDE read loop, outside of ROS, looks like this:
import rtde_receive
rtde_r = rtde_receive.RTDEReceiveInterface("192.168.1.100")
while True:
q = rtde_r.getActualQ() # joint positions, rad
tcp_pose = rtde_r.getActualTCPPose() # [x, y, z, rx, ry, rz]
wrench = rtde_r.getActualTCPForce() # wrist F/T, N and NmTeleoperation options
The realistic ways to drive a UR5e for demonstration collection, roughly in order of how much they're actually used:
- Freedrive (hand-guiding). Every e-Series arm supports freedrive natively — press an enabling control and back-drive the arm by hand while it compensates for gravity and its own dynamics. This is kinesthetic teaching, not teleoperation in the remote-operator sense, but it's the lowest-friction way to collect single-arm manipulation demonstrations on a UR5e, since it needs no leader device and no retargeting.
- Leader-arm teleoperation. A kinematically dissimilar leader device (or a second UR arm) streams a target pose or joint configuration that the UR5e tracks via RTDE input registers or a URScript
servoj/speedjloop. This gives you remote operation, but because the UR5e is position-controlled rather than joint-torque-controlled, the follower has no native compliance of its own — any "give" the operator feels has to come from the leader side or from software-limited stiffness, not from the follower arm reflecting real joint torques back. - VR and hand-tracking retargeting. A headset or camera-based hand pose is retargeted to a target end-effector pose and streamed to the arm the same way. Works well for reach-and-grasp tasks; contact-rich tasks expose the same compliance gap as leader-arm teleop.
- Space mouse. A rate-control device mapped to TCP velocity. Coarse and low-cognitive-load, useful for positioning and inspection tasks, not well suited to fine manipulation.
The thread running through all of these: don't expect true bilateral force-reflecting teleoperation on a UR5e. You can display the wrist F/T reading to an operator, and you can build a software force-limiting or virtual-fixture layer on top of it, but the arm cannot render per-joint torque the way a torque-controlled arm like the Franka FR3 can, because it doesn't have per-joint torque sensing to render in the first place.
What a clean dataset looks like on this platform
For a UR5e session, the signals worth recording are:
- Joint states — position, velocity, current, and estimated torque per joint, via RTDE, at the highest rate your pipeline can sustain (up to 500 Hz; most demonstration datasets subsample to something in the tens-of-Hz range to match camera rate).
- TCP pose and velocity — RTDE's actual TCP pose output, useful as a redundant, easily-interpretable action representation alongside joint space.
- Wrist force/torque — the built-in 6-axis sensor's wrench output, essential for anything contact-rich (insertion, wiping, assembly).
- Gripper state, if one is mounted — not part of RTDE at all, since grippers are third-party UR+ accessories with their own driver and their own clock.
- Camera streams, on whatever mounting and rate your task calls for.
Sync is the part that actually takes work. RTDE gives you controller-side time synchronization for arm state, but cameras and a third-party gripper are on separate clocks entirely, so you need a shared reference — hardware trigger, PTP, or timestamped logging on receipt — to line them up after the fact. This is exactly the gap the bring-your-own-rig SDK path is meant to close: one adapter layer that handles ROS 2 and vendor-API sync so you're not hand-rolling a clock alignment scheme per robot.
Common pitfalls
Recording RTDE at the safety-monitoring rate, not the control rate. RTDE can be configured to output at any rate up to 500 Hz, and it's easy to leave it at a default that's lower than what your policy will actually run at, silently under-sampling fast contact transients.
URScript and RTDE fighting for control. If a URScript program is issuing motion commands while an external process is also writing RTDE input setpoints, you get command conflicts that manifest as jerky or rejected motion. Pick one channel to be the source of truth for control during a session and use the other purely for readback.
Treating the gripper as part of the arm's data stream. Because grippers are not a UR-native component, their state doesn't appear in RTDE at all. Datasets that forget this end up with an arm trajectory and no record of when the gripper actually closed, which is often the single most important event in a manipulation episode.
Confusing freedrive demonstrations with teleoperated ones. Freedrive recordings have no transport latency and no operator-display lag, so a policy trained only on freedrive data can behave differently from one trained on remotely teleoperated demonstrations of the same task — worth tracking as metadata, not just discarding.