Skip to main content

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.

PincOpen LeKiwi running an autonomous SmolVLA rollout, click to play

▶ 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 registers lekiwi_client in the record/teleoperate scripts, so it is not a selectable choice there; and LeKiwiClient exposes no .cameras, so recording dies on len(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 way bi_so_leader wraps 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 id unsuffixed, so an existing leader calibration keeps resolving. Migrating from --teleop.type=so101_leader_sprung is a type swap plus moving port under arm_config.
  • The keyboard is best effort. pynput cannot 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_Coefficient write 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

License

Apache-2.0. calibrate()/configure() derive from LeRobot (Apache-2.0, The HuggingFace Inc. team); see the file headers.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz (22.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl (24.8 kB view details)

Uploaded Python 3

File details

Details for the file lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz.

File metadata

File hashes

Hashes for lerobot_robot_lekiwi_pincopen-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4cdd2166f111e231c7a1db7a56166e3acd7b1e58c22528e18bd69bac521f5e2a
MD5 3d3c51c51444d2a42b932d30b608db81
BLAKE2b-256 0672a9b61c1ea6ca35a18c1cbb40c1db89083aa57ec29c4f49911fd7ff9c4c7c

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lerobot_robot_lekiwi_pincopen-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 93122aff6e4e525509cc9ab50890a80dcf9d97ed5f08fbfcd0d830525ac44ed8
MD5 6e08b1596727b5cef78bf18b5730257b
BLAKE2b-256 76a22b51d95bc3dafa719e7385214b033672786c131e98f108d0e99e4790b499

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page