Back to Robot Platforms
/ ROBOT PLATFORM · Collaborative arms

UFACTORY xArm

How to drive and record data on the UFACTORY xArm 5/6/7 and Lite 6: SDK control modes, teleoperation options, and dataset gotchas for this arm family.

Updated Aug 20266 min read
SHORT ANSWER

The UFACTORY xArm family (xArm 5, 6, 7, and the smaller Lite 6) is a line of collaborative arms sold direct with an open Python/C++/ROS 2 SDK, which makes it a common choice in academic and early-stage robot-learning labs. This page covers how to drive it for demonstration collection and what to watch for when recording clean, synchronized episodes.

UFACTORY sells the xArm line direct, as a table-top collaborative arm with an open SDK rather than a closed vendor controller you integrate through a systems house. The family covers xArm 5 (5-DoF), xArm 6 (6-DoF), xArm 7 (7-DoF), and the smaller Lite 6 (6-DoF) — the same control software and Python/C++/ROS 2 SDK across all four, with payload and DoF as the main differentiators. That combination — priced well below industrial arms, sold without a distributor sales cycle, and controllable from a laptop within an afternoon — is why the xArm shows up so often in university labs, robotics startups bootstrapping a demo, and hobbyist robot-learning projects that sit alongside cheaper community rigs like SO-101.

None of that makes it a research toy. The xArm 6 carries a 5 kg payload at 700 mm reach with ±0.1 mm repeatability, comparable on paper to arms costing several times more, and the same teleoperation and recording concerns that apply to a Franka or UR arm apply here — they are just easier to get to, because the SDK and drivers are public and free to read.

Control interfaces that matter for data collection

Everything downstream — teleoperation latency, joint-state fidelity, dataset sync — is bounded by what the control stack exposes.

xArm-Python-SDK (pip install xarm-python-sdk) wraps the arm's TCP/IP protocol in a Python API, XArmAPI, that you point at the controller's IP address. It exposes several control modes selected with set_mode():

  • Mode 0 — position control. set_position() / set_servo_angle() for point-to-point cartesian or joint moves.
  • Mode 1 — servo motion mode. set_servo_cartesian() / set_servo_angle_j() accept a continuous stream of small pose or joint deltas, which is the mode you use to drive the arm from an external controller (a leader arm, a VR pose stream, a policy). The controller's maximum receive rate in this mode is 250 Hz on current firmware; sending faster than that drops commands, and UFACTORY's own guidance is to stream at 100–200 Hz for smooth trajectories.
  • Mode 2 — joint teaching mode. Hand-guiding: back-drive the arm by hand with an adjustable "teach sensitivity," used for kinesthetic demonstrations or quick waypoint capture.
  • Modes 4/5 — joint and cartesian velocity control, for rate-controlled input devices like a space mouse.
from xarm.wrapper import XArmAPI
 
arm = XArmAPI("192.168.1.113")
arm.motion_enable(True)
arm.set_mode(1)      # servo motion mode: stream pose deltas
arm.set_state(0)
 
# called at 100-200 Hz from your teleop loop
arm.set_servo_cartesian([x, y, z, roll, pitch, yaw], speed=100, mvacc=2000)

For teams already on ROS 2, xarm_ros2 (GitHub, xArm-Developer org) wraps the same functionality as controllers and topics, ships a MoveIt2 configuration for planning and simulation, and is maintained as distro-specific branches (Foxy, Galactic, Humble, Jazzy, Rolling) rather than a single rolling master — UFACTORY explicitly retired master as guidance-only and directs users to the branch matching their installed distro. This is the more natural entry point if your capture stack already speaks ROS 2, and it is the path assumed by Telemanual's bring-your-own-rig integration, which connects customer-owned arms through ROS 2 and vendor-API adapters rather than a bespoke driver per robot.

Teleoperation options

What actually drives an xArm during a collection session depends on how much fidelity the task needs.

  • Leader–follower teleop. A second, kinematically similar arm (or a lightweight leader device) streams joint targets into servo mode on the follower. This gives direct joint-space correspondence and is the highest-fidelity option for contact-rich tasks, at the cost of owning a second arm.
  • VR / hand-tracking retargeting. A controller or tracked hand pose is retargeted to an end-effector pose and streamed through set_servo_cartesian(). Cheaper to set up than a leader arm and portable across the xArm 5/6/7 variants without re-tooling, but retargeting error and the lack of native force feedback make it weaker on insertion and other tight-tolerance contact work — see the trade-offs in VR vs. leader-follower teleoperation.
  • Space mouse / rate control. Mode 4/5 velocity control suits coarse repositioning and inspection-style tasks, not fine manipulation.
  • Hand-guiding (mode 2). Genuinely useful for quick kinesthetic waypoints, but a 5 kg-class arm has enough mass and gearing friction that fine-grained contact demonstrations recorded this way tend to be noisier than servo-mode teleop.

DoF matters here beyond the spec sheet: xArm 7's extra joint gives redundant configurations to avoid self-collision and singularities in cluttered scenes, which is useful if your teleop interface fights the arm for elbow position; xArm 5 has no such redundancy and is more prone to hitting joint limits at extreme wrist orientations. For comparison against arms of similar class, see the Franka FR3 and Kinova Gen3 platform pages.

What a clean dataset looks like on this platform

Record at least: joint positions and velocities, commanded and achieved end-effector pose, gripper state, and every camera stream, all stamped to one clock. The xArm-specific gotcha is state reporting: the SDK only streams state over its socket connection when enable_report=True, and the depth of that state depends on report_type — the default 'normal' mode gives you the basics, while 'rich' mode adds fields like joint torque, load, and speed/acceleration limits that some pipelines assume are always present. Teams that never set report_type explicitly get a state stream quietly missing fields their downstream code expects. UFACTORY does not publish a single documented ceiling for how fast that report stream actually updates, so measure your effective proprioception rate on the bench — the same discipline you'd apply to the 250 Hz servo-command ceiling — rather than assuming a number from a forum post or an old firmware's behavior.

xArm 5
5-DoF, 3 kg payload, 700 mm reach
xArm 6
6-DoF, 5 kg payload, 700 mm reach
xArm 7
7-DoF, 3.5 kg payload, 700 mm reach
Lite 6
6-DoF, 0.6 kg payload, 440 mm reach
Servo-mode max command rate
250 Hz (100 Hz on SDK/firmware before v1.4.0)
State report modes
'normal' (basic) vs 'rich' (adds torque, load, speed/accel limits), set via report_type

Multi-camera rigs need their own calibration discipline independent of the arm — see the multi-camera calibration guide — since none of the camera-to-base extrinsics come from the xArm controller itself.

Common pitfalls

Other things that bite teams new to this family:

  • Using master on xarm_ros2. UFACTORY froze the master branch for guidance only; real fixes land on the distro-specific branches. Building against master silently gets you a stale driver.
  • Confusing Lite 6 with the xArm 5/6/7 line. Lite 6 shares the SDK but not the payload or reach class — 0.6 kg and 440 mm versus 3–5 kg and 700 mm. Demonstrations collected on one do not transfer assumptions (grasp force, workspace bounds) to the other.
  • Streaming servo commands faster than the controller accepts. Above the 250 Hz ceiling, commands are silently dropped rather than queued, which shows up as jittery motion that looks like a network problem but is a rate-limit problem.
  • Leaving report_type at its default. As above — the SDK's default 'normal' report mode omits torque, load, and speed/acceleration-limit fields that 'rich' mode includes; a pipeline written against the richer fields silently gets stale or missing values if nobody switched the mode.
  • Treating hand-guiding as free labeling. Mode 2 demonstrations skip the servo-mode command path entirely, so if your logging pipeline only captures commanded servo targets, hand-guided episodes need a separate tap into achieved joint state to be recorded at all.

If you already run xArm hardware and want the capture, sync, and export pipeline handled without building the logging stack described above yourself, that is the bring-your-own-rig path — the SDK and ROS 2 details above are exactly what its adapter layer targets.

KEY FACTS

VARIANTS
xArm 5 (5-DoF), xArm 6 (6-DoF), xArm 7 (7-DoF), Lite 6 (6-DoF)
PAYLOAD
3 kg / 5 kg / 3.5 kg (xArm 5/6/7); 0.6 kg (Lite 6)
REACH & REPEATABILITY
700 mm, ±0.1 mm (xArm 5/6/7); 440 mm, ±0.5 mm (Lite 6)
SDK / ROS 2
xArm-Python-SDK (pip install xarm-python-sdk); xarm_ros2 driver with MoveIt2 config

/ QUESTIONS

Frequently asked

Put this into practice.

Tell us what your robots need to learn. We will scope the rig, the operators, the protocol, and the first datasets — usually in one call.