UFACTORY xArm 6#

The UFACTORY xArm 6 is a 6-axis articulated robotic arm. PyLabRobot supports it with the xArm bio-gripper. It supports:

The device communicates over Ethernet using the xarm-python-sdk. Install the optional dependency group with pip install PyLabRobot[xarm].

Model

PLR Name

Notes

xArm 6

XArm6

6-DOF articulated arm + bio-gripper

Setup#

Construct XArm6 with the controller IP (and optional TCP offset/load), then call setup().

from pylabrobot.ufactory.xarm6 import XArm6

xarm = XArm6(
  ip="192.168.1.220",
  tcp_offset=(0, 0, 0, 0, 0, 0),  # adjust for your gripper mount (x, y, z, roll, pitch, yaw)
)
await xarm.setup()

setup() connects to the controller, clears any pending errors, enables motion, and initializes the bio-gripper. To skip the gripper init, pass skip_gripper_init=True to setup().

Gripper control#

Gripper widths are in millimeters. The bio-gripper range is 71 mm (fully closed) to 150 mm (fully open); override with gripper_min_mm / gripper_max_mm on the constructor.

Open and close by moving to the ends of the range:

await xarm.move_gripper(width=xarm.max_gripper_width)
await xarm.move_gripper(width=xarm.min_gripper_width)
await xarm.is_gripper_closed()

Cartesian movement#

Move the arm to a Cartesian location with a full 3D rotation. speed (mm/s) and mvacc (mm/s^2) override the defaults.

from pylabrobot.resources import Coordinate
from pylabrobot.resources.rotation import Rotation

await xarm.move_to_location(
  location=Coordinate(x=300, y=0, z=200),
  rotation=Rotation(x=180, y=0, z=0),  # roll, pitch, yaw (degrees)
  speed=150,
  mvacc=2500,
)

Joint movement#

Move in joint space using the XArm6Axis enum. speed is in deg/s and mvacc in deg/s^2. Axes you omit keep their current angle.

Warning

Moving to arbitrary joint positions can cause the arm to collide with its base, the gripper, or nearby equipment. Verify coordinates carefully in a safe workspace first.

from pylabrobot.ufactory.xarm6 import XArm6Axis

position = {
  XArm6Axis.J1: 0.0,
  XArm6Axis.J2: -30.0,
  XArm6Axis.J3: -60.0,
  XArm6Axis.J4: 0.0,
  XArm6Axis.J5: 90.0,
  XArm6Axis.J6: 0.0,
}
await xarm.move_to_joint_position(position, speed=40)

Querying position#

Get the current joint angles or Cartesian end-effector pose:

await xarm.request_joint_position()
await xarm.request_gripper_pose()

Pick and place#

pick_up_at_location moves the arm to the target pose and closes the gripper to resource_width. drop_at_location moves to the target and fully opens the gripper. Approach and retract motions are the caller’s responsibility — wrap these calls with your own pre- and post-moves as needed.

pick = Coordinate(x=300, y=100, z=50)
place = Coordinate(x=300, y=-100, z=50)
above = Coordinate(x=0, y=0, z=80)
down = Rotation(x=180, y=0, z=0)

Approach the pick position from 80 mm above, descend, close the gripper, and retract:

await xarm.move_to_location(pick + above, down)
await xarm.pick_up_at_location(location=pick, rotation=down, resource_width=80)
await xarm.move_to_location(pick + above, down)

Travel to the place position, descend, release, and retract:

await xarm.move_to_location(place + above, down)
await xarm.drop_at_location(location=place, rotation=down, resource_width=80)
await xarm.move_to_location(place + above, down)

Freedrive (teaching mode)#

Enter freedrive mode to manually position the arm by hand, then read coordinates for use in your protocol. The xArm SDK frees all axes simultaneously; the free_axes argument is accepted for API compatibility but ignored.

await xarm.start_freedrive_mode(free_axes=[0])
# Manually guide the arm to the desired pose, then read it:
taught = await xarm.request_gripper_pose()
print(taught)
await xarm.stop_freedrive_mode()

Park, halt, and error recovery#

Park the arm (SDK home by default, or a user-supplied park_location), emergency-stop all motion, or clear an error state:

await xarm.park()
await xarm.halt()
await xarm.clear_errors()

Teardown#

await xarm.stop()