PincOpen LeKiwi (STS3250 heavy arm joints + PincOpen gripper) as a LeRobot third-party robot plugin
Project description
lerobot_robot_lekiwi_pincopen
My LeKiwi runs STS3250 servos on the big arm joints and a PincOpen gripper. This plugin lets the original, unmodified LeRobot (0.6.0 or newer) drive that hardware, zero source edits.
I wrote up the hardware build in Mobile Manipulation with LeKiwi + PincOpen. This package is that integration as installable code.
▶ click for the clip: autonomous SmolVLA rollout, pick up the chocolate bar from the basket and place it on the ground
vs the original lekiwi robot:
- STS3250 on the heavy arm joints, set by
sts3250_joints(default: joints 2-4; shoulder_pan, wrist_roll and gripper are STS3215) - load-based tuning via
heavy_joints, independent of which servo is fitted - PincOpen gripper: fixed EPROM calibration, skipped during interactive calibration
- tuned servo params written on every connect, all exposed as config fields:
tuning is a yaml/CLI edit (
--robot.heavy_p_coefficient=10), never a code change - camera capture pinned to MJPG — the stock default sets no
fourcc, so OpenCV auto-negotiates uncompressed YUYV (~147 Mbps/camera) and saturates the Pi's USB2 bus; MJPG is ~16× lighter for identical frames
Install
pip install -e .
Use
LeRobot auto-discovers the plugin by its package name (the official third-party conventions):
# calibrate (gripper is skipped, its EPROM calibration is applied)
lerobot-calibrate --robot.type=lekiwi_pincopen --robot.id=my_lekiwi
# host (the original lekiwi_host skips plugin discovery, hence the wrapper; same CLI, same yaml)
python -m lerobot_robot_lekiwi_pincopen.lekiwi_host --config_path=host.yaml
The client side (teleop/record/eval) needs nothing from this package:
lekiwi_client never touches motors.
Calibration files live under
~/.cache/huggingface/lerobot/calibration/robots/lekiwi_pincopen/.
Driving LeKiwi from the record / teleoperate CLIs
LeKiwi is a mobile manipulator, so it takes two devices to drive: a leader arm for
the arm and a keyboard for the holonomic base. Stock lerobot-teleoperate cannot
express that, and stock lerobot-record cannot talk to a LeKiwi client at all. The
package ships two laptop-side types that close both gaps without patching lerobot:
--robot.type=lekiwi_pincopen_client— the ZMQ client. Stock lerobot never registerslekiwi_clientin the record/teleoperate scripts, so it is not a selectable choice there; andLeKiwiClientexposes no.cameras, so recording dies onlen(robot.cameras)while sizing its image writer. This registers the client and reports the configured cameras.--teleop.type=lekiwi_pincopen_leader— one teleoperator wrapping the sprung SO-101 leader plus a keyboard for the base, the waybi_so_leaderwraps two arms. The CLIs see a single ordinary teleoperator. WASD moves, Z/X rotate, R/F change speed.
robot:
type: lekiwi_pincopen_client
remote_ip: 192.168.0.42
id: my_kiwi
teleop:
type: lekiwi_pincopen_leader
id: my_leader
# See the note below: use an ABSOLUTE path.
calibration_dir: /home/<you>/.cache/huggingface/lerobot/calibration/teleoperators/so101_leader
arm_config:
port: /dev/ttyACM0
# Optional; these are the defaults.
# teleop_keys: {forward: w, backward: s, left: a, right: d, rotate_left: z, rotate_right: x, speed_up: r, speed_down: f, quit: q}
# speed_levels: [{xy: 0.1, theta: 30}, {xy: 0.2, theta: 60}, {xy: 0.3, theta: 90}]
Notes:
- Nothing changes on the robot/host side, so there is no need to redeploy the Pi.
- The arm keeps the teleoperator's own
idunsuffixed, so an existing leader calibration keeps resolving. Migrating from--teleop.type=so101_leader_sprungis a type swap plus movingportunderarm_config. - The keyboard is best effort.
pynputcannot capture keys on Wayland or on a headless machine; there the base holds still and the arm stays teleoperable rather than the session failing. - Both are proposed upstream in huggingface/lerobot#3741.
Optional: sprung gripper trigger for the SO-101 leader
The package also ships --teleop.type=so101_leader_sprung: a stock SO-101
leader whose gripper trigger pushes back progressively when squeezed and
springs back to fully open when released — the SO-arm analogue of the Koch
leader's current-based-position trigger, emulated in the STS3215's position
mode (soft P gain + low torque cap). Works with any SO-101/SO-100 leader, not
just PincOpen setups.
teleop:
type: so101_leader_sprung
port: /dev/ttyACM0
id: my_leader
# calibration files are stored per teleoperator type; reuse an existing
# so101_leader calibration instead of recalibrating. Use an ABSOLUTE path:
# lerobot does not expand `~` in calibration_dir.
calibration_dir: /home/<you>/.cache/huggingface/lerobot/calibration/teleoperators/so101_leader
Notes:
- Position reads are unchanged — recorded gripper actions are identical apart from a consistent open rest position between grasps.
- The spring's
P_Coefficientwrite persists in the servo's EPROM (harmless; the servo behaves identically when used as a stock passive leader, since torque is off outside this teleoperator). - Hand-tuned on real hardware; holding the trigger fully squeezed for 8 continuous minutes raised the servo temperature by 1 °C, and the factory overload protection stays armed above the configured torque cap.
Tuning
| Field | Default |
|---|---|
arm_p_coefficient |
14 |
heavy_p_coefficient |
10 |
heavy_acceleration |
200 |
gripper_acceleration |
200 |
gripper_overload_torque |
65 (percent) |
gripper_protective_torque |
5 (percent) |
gripper_protection_time |
7 (x10 ms) |
P=10 on the big joints is the load-bearing fix. The original writes P=16, which gave me jitter and servo overload shutdowns on this hardware.
Tests
pip install -e .[dev]
python -m pytest tests
No hardware needed, everything stops short of bus.connect().
Related
- Mobile Manipulation with LeKiwi + PincOpen: the hardware story
- lekiwi-tui: my terminal control center, ships and drives this plugin automatically
License
Apache-2.0. calibrate()/configure() derive from LeRobot (Apache-2.0,
The HuggingFace Inc. team); see the file headers.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz.
File metadata
- Download URL: lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cdd2166f111e231c7a1db7a56166e3acd7b1e58c22528e18bd69bac521f5e2a
|
|
| MD5 |
3d3c51c51444d2a42b932d30b608db81
|
|
| BLAKE2b-256 |
0672a9b61c1ea6ca35a18c1cbb40c1db89083aa57ec29c4f49911fd7ff9c4c7c
|
Provenance
The following attestation bundles were made for lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz:
Publisher:
publish.yml on zuoxingdong/lerobot_robot_lekiwi_pincopen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz -
Subject digest:
4cdd2166f111e231c7a1db7a56166e3acd7b1e58c22528e18bd69bac521f5e2a - Sigstore transparency entry: 2312301159
- Sigstore integration time:
-
Permalink:
zuoxingdong/lerobot_robot_lekiwi_pincopen@135d2f34943caac6f057d57dcd003fbe3f2025d4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/zuoxingdong
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@135d2f34943caac6f057d57dcd003fbe3f2025d4 -
Trigger Event:
release
-
Statement type:
File details
Details for the file lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl.
File metadata
- Download URL: lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
93122aff6e4e525509cc9ab50890a80dcf9d97ed5f08fbfcd0d830525ac44ed8
|
|
| MD5 |
6e08b1596727b5cef78bf18b5730257b
|
|
| BLAKE2b-256 |
76a22b51d95bc3dafa719e7385214b033672786c131e98f108d0e99e4790b499
|
Provenance
The following attestation bundles were made for lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on zuoxingdong/lerobot_robot_lekiwi_pincopen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl -
Subject digest:
93122aff6e4e525509cc9ab50890a80dcf9d97ed5f08fbfcd0d830525ac44ed8 - Sigstore transparency entry: 2312301349
- Sigstore integration time:
-
Permalink:
zuoxingdong/lerobot_robot_lekiwi_pincopen@135d2f34943caac6f057d57dcd003fbe3f2025d4 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/zuoxingdong
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@135d2f34943caac6f057d57dcd003fbe3f2025d4 -
Trigger Event:
release
-
Statement type: