Chapter 4 - xgolib Robot Control

Chapter 4: xgolib Robot Control

To make the robot move, you call the xgolib motion library. This chapter covers the most-used basic motions, then wheel-legged (Rider/RA) advanced control, with per-model parameter ranges and model-compatibility tips so your motion code runs correctly on every model.

In this chapter:

SectionWhat it coversDifficulty
4.1 Basic Motionmove_x / turn / attitude / translation etc. + per-model parameter ranges★☆☆
4.2 Advanced ControlWheel-legged XGO-RIDER / RA ra_* / rider_* interfaces★★★
4.3 Model CompatibilityXGO() auto-detect, model alias table, per-model branching★★☆
4.4 Debugging & VerificationLow-speed try, suspend test, state printing, per-model branch testing, etc.★☆☆

Reading path: lite3 / mini2S / mini2SW use the quadruped interface in 4.1; Rider2 / Ranger use the wheeled-legged interface in 4.2. Read 4.3 before sharing code across models. SDK aliases are not product-generation names.

Prerequisites:

  • Done Chapter 1, you can SSH into the robot;
  • The robot is powered on and idle (motion commands directly drive the hardware);
  • You know your model (Mini / Lite / Rider / RA).

4.1 Basic Motion (Quadruped Models)

Why xgolib: The robot's servos, IMU and battery all connect through a single UART, so you can't drive each servo directly. xgolib wraps that serial protocol into an object — creating an XGO() instance is like “holding the whole robot's controls”; after that, one line of code makes it move forward, turn or perform an action, saving you from handling serial framing, checksums and per-model differences yourself.

xgolib is the XGO motion-control library. Current Luwu-OS provides the unified from xgolib import XGO entry point; XGO() detects the connected model. The image may bundle its own version under /opt/luwu-os/libs/xgolib/. Check xgolib.__file__ and xgolib.__version__ on the device rather than assuming a fixed bundled release. The current education library is xgoedu-luwuos; the legacy xgoedu removal does not remove that newer package.

4.1.1 Minimal Run-It Script (see the robot move first)

Save this as test_move.py and run python3 test_move.py:

from xgolib import XGO
import time

dog = XGO()          # auto-detect the model and open the serial port
print("Connected model:", dog.read_firmware())

dog.forward(18)      # speed 18, start moving forward
time.sleep(2)        # keep moving forward for 2 seconds
dog.stop()           # stop
print("Done: the robot should move forward ~2 s then stop")

✅ Expected result: The terminal prints Connected model: M... (firmware) first, then the robot moves forward ~2 s and stops, finally printing the done message. If it errors out or the dog doesn't move, see 4.1.9 Common Errors.

⚠️ Before the first run make sure the robot is charged, idle and clear of obstacles; try a small value like 10 first, confirm the direction is correct, then increase it.

4.1.2 Connecting & Basic Motion

XGO() is the single entry point — it opens the serial port, probes the model and connects:

from xgolib import XGO
dog = XGO()          # auto-detect the model (scans /dev/ttyAMA5, /dev/ttyAMA0)
# or set it manually: XGO("xgomini") / XGO("xgolite") ...

Motion methods take a speed command: pass the speed value, and with runtime>0 they run for that many seconds then stop; pass 0 to stop.

dog.move_x(10, runtime=2)   # forward speed, stops after ~2 s (xgomini: -25~25)
dog.move_y(5, runtime=2)    # lateral speed (-18~18)
dog.turn(10, runtime=1)     # in-place turn speed (-100~100)
dog.move_x(0)               # manual stop

4.1.3 Directional Semantics (Forward / Back / Left / Right)

Don't bother with axes — use the semantic methods, which are equivalent to move_x / move_y:

dog.move('x', 10)   # generic direction: 'x' / 'y'
dog.forward(10)     # forward (same as move_x)
dog.back(10)        # backward
dog.left(10)        # strafe left
dog.right(10)       # strafe right

4.1.4 Attitude & Translation (Quadruped Body)

  • Attitude attitude: control the body's pitch / roll / yaw angle (xgomini: Roll ±20° / Pitch ±22° / Yaw ±16°)
  • Translation translation: position & height of the body on the X / Y / Z axes (xgomini: X ±35 / Y ±19.5 / Z 75~120mm)
dog.attitude('p', 15)                # pitch, single axis
dog.attitude(['y', 'p'], [5, 10])    # yaw + pitch

dog.translation('x', 10)    # forward/backward (-35~35)
dog.translation('y', 5)     # left/right (-19.5~19.5)
dog.translation('z', 90)    # body height (75~120)

4.1.5 Gaits, Actions & Performance

dog.gait_type('trot')       # gaits: trot / walk / high_walk / slow_trot

dog.action(13, wait=True)   # play a preset action (ID 1~255, wait=True blocks until done)

dog.perform(1)              # start cyclic performance (auto-rotates actions); perform(0) stops

dog.pace(0)                 # mark time in place (0 stop / 1 start)
dog.mark_time(10)           # mark-time height (xgomini: 10~35)

💡 Action IDs depend on the firmware action table and differ by model/version, so try a small ID first to confirm.

4.1.6 Arm (models with an arm, e.g. XGO-MINI)

dog.arm(120, 150)           # cartesian control (x, z)
dog.arm_polar(200, 130)     # polar control (angle theta, distance r)
dog.arm_mode(1)             # arm mode switch
dog.arm_speed(50)           # arm speed (0~100)
dog.claw(245)               # gripper (0=open, 255=closed)

4.1.7 Reading State

batt = dog.read_battery()    # battery 0~100
fw = dog.read_firmware()     # firmware version string, e.g. 'M107'
roll = dog.read_roll()       # current roll angle

Other general commands: dog.stop() stops all motion, dog.imu(1) toggles self-balance (1=on, 0=off), dog.reset() resets to the initial pose.

4.1.8 Parameter Range Table (model-dependent, from changePara() in xgolib_dog.py)

Parameterxgominixgolite
Forward speed move_x±25±25
Lateral speed move_y±18±18
Turn speed turn±100±100
Translation X / Y±35 / ±19.5±25 / ±18
Body height Z75~120mm60~110mm
Attitude Roll / Pitch / Yaw±20 / ±22 / ±16±20 / ±10 / ±12
Mark-time height mark_time10~3510~25

4.1.9 Common Errors

SymptomCauseFix
PermissionError: [Errno 13] opening serial portThe port is held by another process (e.g. the launcher is running)Close the process holding the port, run as sudo, or quit the launcher first
Could not open port ...Probe scanned the wrong port, or the robot isn't powered onConfirm the robot is on; to force a port use XGO(port="/dev/ttyAMA5")
Connects but the dog doesn't moveruntime not set, speed too low / wrong directionUse the 4.1.1 run-it script to confirm basic motion, then tune the speed

Unrecognized model alias

Aliases depend on the installed xgolib version

Use auto-detection, inspect the loaded library, and verify the reported firmware/model before moving. Current releases support the mini3w / xgomini2sw names; the old blanket claim that xgomini3w is invalid is obsolete.

4.2 Advanced Control (XGO-RIDER / RA wheel-foot)

Ranger and Rider2 are different hardware models. In the documented library they share the XGO_RIDER driver class. Ranger uses the RA / xgora path and ra_* methods; Rider2 uses the Rider / xgorider path. Sharing a class does not make their actuator counts, modes or action tables interchangeable.

from xgolib import XGO

dog = XGO("ra")   # returns an XGO_RIDER instance (internally version="xgorider")

# --- RA interface (ranges -87~+87 etc., see method docstrings) ---
dog.ra_mode(0)       # mode switch: 0=wheel-foot mode, 1=car mode
dog.ra_move_x(87)    # move forward/backward, speed -87~+87
dog.ra_turn(87)      # rotate, speed -87~+87
dog.ra_height(50)    # chassis height, range 0~100
dog.ra_roll(10)      # roll angle, -87~+87
dog.ra_pitch(10)     # pitch angle, -87~+87
dog.ra_action(1)     # preset actions: 1=sway L/R, 2=raise/lower, 3=forward/back,
                     # 4=snake, 5=lift+rotate, 6=swing, 255=reset
dog.ra_perform(1)    # start/stop performance mode (action rotation)
dog.ra_imu(1)        # self-balance on/off
dog.ra_led(0, [255, 0, 0])   # LED strip color (index, RGB list)
dog.ra_reset()       # reset
# --- Rider native interface (rider_*) ---
dog.rider_move_x(1.0)        # forward speed (VX ±1.5)
dog.rider_turn(90)           # turn speed (VYAW ±360)
dog.rider_height(90)         # chassis height (Z 60~120mm)
dog.rider_roll(10)           # roll angle (Roll ±17°)
dog.rider_action(1)          # preset action (1~255)
dog.rider_perform(1)         # performance mode on/off
dog.rider_balance_roll(1)    # self-balance on/off (IMU)
dog.rider_reset_odom()       # reset odometry
dog.rider_led(0, [0, 255, 0])        # LED strip
dog.rider_read_battery()     # battery level
dog.rider_read_roll()        # read roll angle
dog.rider_read_pitch()       # read pitch angle
dog.rider_read_yaw()         # read yaw angle

XGO_RIDER also inherits all generic motion methods (move_x/move_y/turn/translation/attitude/action, etc.), but parameter ranges follow the xgorider table (VX ±1.5 / VY ±1.0 / VYAW ±360 / Z 60~120mm / Roll ±17°).

4.3 Model Compatibility

Use XGO() for the installed library’s default port and baud detection. Constructor defaults vary by release; current device builds may use baud=0 for automatic baud detection. Inspect the installed implementation before forcing a port, model or baud rate.

  • version: when omitted, the serial ports are scanned automatically (SCAN_PORTS = ["/dev/ttyAMA5", "/dev/ttyAMA0"]) and the firmware is probed
  • Supported model aliases (short / full name):
Short NameFull NameModel
"mini""xgomini"XGO-MINI
"lite""xgolite"XGO-LITE
"mini3w""xgomini2sw"XGO-mini2SW
"rider""xgorider"XGO-RIDER (two-wheel)

"ra"

"xgora"

XGO-Ranger; uses the XGO_RIDER driver with RA methods

The old xgolib 1.1.6 restriction on XGO("xgomini3w") is not a current general rule: the Chinese guide documents support in 1.1.10, and the inspected Ranger image also recognizes that alias. Use the installed release’s aliases and verify the detected model. Names such as mini3w remain software identifiers for compatibility; the current product name is XGO-mini2SW.

from xgolib import XGO, XGO_RIDER

dog = XGO()          # auto-detect the model
# You can also specify: XGO("xgomini") / XGO("xgolite") / XGO("mini3w") / XGO("rider") / XGO("ra")

# Branch by model type
if isinstance(dog, XGO_RIDER):
    dog.rider_roll(10)          # wheel-foot: use rider_*/ra_* interfaces
else:
    dog.attitude('r', 10)       # four-legged: use attitude/translation etc.

# Firmware version check
fw = dog.read_firmware()        # returns an ASCII firmware string, e.g. 'M107' / 'RA100' / 'MW300'
if fw.upper().startswith('RA'):
    pass  # RA-specific logic

For model detection at the system level, call configs/detect_device.py (the launcher uses it too):

python3 /opt/luwu-os/configs/detect_device.py
# prints one model string: xgomini / xgolite / xgomini2sw / xgorider / unknown
# priority: live serial probe > configs/device.ini manual override > unknown

4.4 Debugging & Verification Tips

The worst thing when writing motion code is a “one-run full-body” — the dog may run into someone or trip itself. I recommend:

TipHow
Start slowStart from a small value like 10 (the scale in the 4.1.8 table), confirm the direction, then increase
Test suspendedHold the dog over a table edge or on a stand; first check whether the servos target the right angle, then test on the ground
Print state step by stepBetween steps do print(dog.read_battery(), dog.read_roll()) to confirm state before/after motion
Timeout fallbackAdd time.sleep() and dog.stop() around critical motion so an instruction can't hang
Test per modelRun the same code on a Mini and a Lite to feel the parameter-range differences (4.1.8)

⚠️ For any motion test, first confirm enough battery, clear surroundings and the dog is idle; if anything looks wrong, press dog.stop() or power off immediately.