Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

8 Commits

Repository files navigation

CommandAGI · Control your SO-101 arm

A simple, direct example: a Python script that runs on your computer with the SO-101 (LeRobot) arm plugged into a USB port. Your computer becomes the command proxy — it registers the arm as a robot on CommandAGI, streams a webcam view, and writes every control action it receives straight to the servo bus. Anyone with the session link — you in the web UI, an AI agent, or another developer's SDK client — can then watch and drive it.

No microcontroller and no extra firmware: this talks to the SO-101's stock Feetech USB bus-servo adapter directly at 1 Mbps, the same path LeRobot uses.

Want the arm online over Wi-Fi with no computer attached (an ESP32 as the brain)? That lives in the separate firmware repo — ask the CommandAGI team.

Run it

pip install -r requirements.txt
export COMMANDAGI_API_KEY=cagi_... # create one in your dashboard (operator scope)
python so101_arm.py # auto-detects the SO-101 USB driver

It prints a session URL — open it to watch the arm's camera and drive it. Press Ctrl-C to take it offline.

  • Plug the SO-101's USB driver into your computer. The script auto-detects the port (/dev/ttyACM*, /dev/ttyUSB*, /dev/tty.usb*); override with SO101_PORT (e.g. COM5 on Windows). A USB webcam, if present, becomes the arm's camera view (SO101_CAMERA picks the index); otherwise it streams a placeholder.

How it works

fromcommandagiimportCommandAGIcagi=CommandAGI() # COMMANDAGI_API_KEY from the environmentbridge=cagi.register_robot("so101-arm") # registers a robot device, returns a bridgeprint("watch + drive at:", bridge.session_url)
bridge.run(
camera=cam.frame, # () -> JPEG bytes (the arm's observation)on_action=arm.on_action, # (action, payload) -> writes joint goals to the busfps=10,
)

so101_arm.py speaks the Feetech STS3215 protocol directly over the USB driver. The six follower joints are shoulder_pan, shoulder_lift, elbow_flex, wrist_flex, wrist_roll, gripper at servo IDs 1..6.

Control vocabulary

actionpayloadeffect
joint{name, value}set one joint (value −1..1; gripper 0..1)
pose{shoulder_pan: .., elbow_flex: .., ...}set several joints at once
gripper{value}0 = closed, 1 = open
home / resetgo to the rest pose
stophold current targets
move / back{speed}jog shoulder_lift ± (default drive buttons)
turn{dir, rate}jog shoulder_pan ±

Safety

The arm boots de-energized. Torque enables only when the first motion command arrives and is released on exit. Goals are always clamped to the per-joint limits in JOINTSrun the LeRobot calibration for your build and tighten those before trusting it under torque.

Learn more

MIT licensed.

About

Control a physical SO-101 (LeRobot) arm from an ESP32 — streams to CommandAGI via the recommended Python SDK route.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages