Lite 6 Arm & SDK Guide
Last Updated: Sep 02, 2026
The arm at your station is a UFACTORY Lite 6, and you talk to it over the network with the xArm Python SDK. This page summarizes the hardware limits you have to design around and the SDK calls you will actually use.
In this lab you will normally go through the wrapper in src/lite6arm.py rather than calling the SDK directly. Read this page anyway — the wrapper is thin, and every error message you see comes from the layer described here.
Contents
- Contents
- The arm
- Connecting
- The startup sequence
- Modes
- States
- Units and conventions
- Reading the arm’s state
- Commanding motion
- The gripper
- Errors
- Reference
The arm
The Lite 6 is a 6-DOF collaborative arm with the control electronics built into its base. Its specifications, joint limits and payload are on the Hardware page — this page covers only how you talk to it.
Two hardware facts drive most of the software problems you will hit:
- The joint limits are asymmetric, and J5 (±124°) and J3 (−3.5° to 300°) are tight. A mathematically valid IK solution can still be unreachable, which surfaces as error 23 in the error table.
- The payload is 600 g including the gripper, so a grasp can fail for reasons that have nothing to do with your code.
Connecting
The arm is on the network, not USB. The SDK connects to an IP address:
from xarm.wrapper import XArmAPI
arm = XArmAPI('192.168.1.xxx') # the IP on the label at the back of your arm
This is the address you set as XARM_IP during setup.
If the connection fails, ping the address from a terminal before touching your code. No reply means a cable, IP or arm problem, not a Python problem. See Linux Command Line Tools.
The startup sequence
The arm will not move until you have enabled motion, chosen a mode, and put it in a ready state. This three-step sequence is the single most important thing on this page:
arm.motion_enable(enable=True)
arm.set_mode(0) # position control
arm.set_state(0) # ready to move
You must repeat this sequence every time you clear an error, and after an emergency stop. Clearing the error alone does not make the arm ready again — a very common “my code stopped working and I don’t know why” bug.
Modes
set_mode() selects how the arm interprets commands.
| Mode | Meaning | Use in this lab |
|---|---|---|
| 0 | Position control | The default. Point-to-point moves |
| 1 | Servo motion | High-frequency small steps, streamed by you |
| 2 | Joint teaching | Free-drive. Arms hand-guiding — the button on the arm then releases it |
| 3 | Cartesian teaching | Not available |
| 4 | Joint velocity control | Velocity commands per joint |
| 5 | Cartesian velocity control | Velocity commands on the TCP |
| 6 | Joint online trajectory planning | Retarget a joint move while it runs |
| 7 | Cartesian online trajectory planning | Retarget a Cartesian move while it runs |
Mode 2 is how you do teach-and-repeat. Put the arm in joint teaching mode, press the button on the arm to release it, physically guide it to a pose, read the joint angles back with get_servo_angle(), and store them. Switch back to mode 0 to replay them.
set_mode(2) only arms hand-guiding — the arm becomes back-driveable when the button on it is pressed. It stays under gravity compensation throughout, so it holds its own weight rather than dropping.
Mode 1 is a trap for beginners: it executes each command immediately at maximum speed, so it only behaves sensibly if you are streaming small increments at a high, steady rate. Stay in mode 0 unless you know you need otherwise.
States
Confusingly, the values you write with set_state() are not the same as the values you read back from get_state().
set_state(n) | Meaning |
|---|---|
| 0 | Ready to move |
| 3 | Pause |
| 4 | Stop |
get_state() returns | Meaning |
|---|---|
| 1 | Moving |
| 2 | Idle / sleeping |
| 3 | Paused |
| 4 | Stopped |
So after a successful set_state(0), a healthy idle arm reads back as state 2, not 0.
Units and conventions
The SDK works in millimetres and degrees by default. Not metres, not radians. Mixing units is the most common source of bugs in this lab, and a factor-of-1000 error will drive the arm into the board.
- Cartesian positions:
x,y,zin mm - Orientation:
roll,pitch,yawin degrees - Joint angles: degrees
- Speeds: mm/s for Cartesian moves, °/s for joint moves
Most methods take an is_radian argument, and you can set the default for the whole session when you construct the object:
arm = XArmAPI('192.168.1.xxx', is_radian=True)
Pick one convention and apply it consistently. If your kinematics code works in radians — and it probably should — decide early whether you convert at the boundary or set is_radian=True everywhere, and write it down for your teammates.
Reading the arm’s state
Both getters return a (code, value) tuple — the code first, then the data:
code, pose = arm.get_position() # [x, y, z, roll, pitch, yaw]
code, angles = arm.get_servo_angle() # [j1, j2, j3, j4, j5, j6]
Forgetting that these return a tuple, and treating the result as a plain list, produces a confusing error one or two lines later. Unpack both values.
Commanding motion
Joint space
arm.set_servo_angle(angle=[0, 20, 30, 0, 40, 0], speed=30, wait=True)
Cartesian space
arm.set_position(x=200, y=0, z=150, roll=180, pitch=0, yaw=0,
speed=100, wait=True)
Go home
arm.move_gohome(wait=True)
Common arguments:
| Argument | Meaning |
|---|---|
speed | mm/s for Cartesian moves, °/s for joint moves |
mvacc | Acceleration limit |
wait | True blocks until the move finishes; False returns immediately |
relative | Treat the position as an offset from the current one |
wait=True is what you want while you are learning — without it your next command is issued while the arm is still moving, and a sequence of waypoints will blur together or be dropped. Use wait=False deliberately, not by accident.
The gripper
The gripper is custom-built for this lab (see Hardware) but is driven by the standard Lite 6 gripper calls:
arm.open_lite6_gripper()
arm.close_lite6_gripper()
arm.stop_lite6_gripper() # de-energize and hold where it is
Each returns a code like any other SDK call. open and close drive the gripper; stop cuts the drive.
The gripper is binary — no width, no force, no feedback about whether it grasped anything. Your state machine has to verify a grasp some other way, such as looking at it with the camera, and should aim for a repeatable approach pose rather than a closed loop on grip force.
Give the gripper time to finish moving before the arm drives away. The call returns as soon as the command is sent, not when the jaws have finished travelling.
Errors
Every SDK call returns a code. 0 means success; anything else means the command did not do what you asked. Ignoring return codes turns a clear failure into a mysterious one.
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | There are errors that have not been cleared |
| 2 | There are warnings that have not been cleared |
| 9 | State is not ready to move |
| −2 | Arm not ready — motion not enabled, or state not set |
| −9 | Emergency stop active |
To inspect and clear a controller error:
code, (err, warn) = arm.get_err_warn_code()
arm.clean_error()
arm.clean_warn()
# the arm is NOT ready yet — redo the startup sequence
arm.motion_enable(enable=True)
arm.set_mode(0)
arm.set_state(0)
Controller error codes worth recognizing:
| Error | Meaning |
|---|---|
| 1, 2, 3 | Emergency stop (button, control-box IO, three-state switch) |
| 10 | Servo motor error |
| 21 | Kinematics solution failed — the pose you asked for has no IK solution |
| 22 | Self-collision detected |
| 23 | Joint angle exceeds limit — check against the joint limit table above |
| 24 | Commanded speed exceeds the maximum |
| 31 | Abnormal current, consistent with a collision |
| 35 | Safety boundary limit triggered |
Errors 21 and 23 are the ones you will meet while writing IK. Both mean the target was unreachable, not that the arm is broken.
Reference
- xArm Python SDK on GitHub — source, and the
example/wrapper/lite6/folder of runnable examples - Full API documentation — every method on
XArmAPI - API return and error codes
- UFACTORY developer documentation
- Lite 6 product page and specifications
- Lite 6 user manual (PDF)