Skip to main content

PhysicalAI LeKiwi Plugin

Third-party LeKiwi mobile manipulator plugin for PhysicalAI.

Provides a concrete implementation of the Robot protocol for:

Class Robot Motors Protocol
LeKiwi 6-DOF SO-ARM100 arm + 3-wheel holonomic base Feetech STS3215 (via scservo_sdk) POSITION / VELOCITY

Installation

uv add physicalai-lekiwi-plugin

scservo_sdk (Feetech servo serial SDK) is included as a core dependency.

No calibration JSON is bundled. You must provide your own calibration file (LeRobot format) or use uncalibrated/ticks mode.

Usage

Basic follower (with calibration file)

import numpy as np
from physicalai.robot import connect
from physicalai_lekiwi_plugin import LeKiwiCalibration, LeKiwi

robot = LeKiwi(
    port="/dev/ttyACM0",
    role="follower",
    calibration=LeKiwiCalibration.from_path("calibration.json"),
)

with connect(robot) as robot:
    obs = robot.get_observation()
    action = obs.joint_positions.copy()
    robot.send_action(action)

In Studio catalog payloads, calibration_id is optional. When provided, the plugin loads that calibration and runs in normalized units. When omitted, the driver falls back to explicit uncalibrated ticks mode.

Calibration from a dict

cal = LeKiwiCalibration.from_dict({
    "arm_shoulder_pan":  {"id": 1, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "arm_shoulder_lift": {"id": 2, "drive_mode": 0, "homing_offset": -512, "range_min": 512,  "range_max": 3583},
    "arm_elbow_flex":    {"id": 3, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "arm_wrist_flex":    {"id": 4, "drive_mode": 1, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "arm_wrist_roll":    {"id": 5, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "arm_gripper":       {"id": 6, "drive_mode": 0, "homing_offset": 0,    "range_min": 2048, "range_max": 3072},
    "base_left_wheel":   {"id": 7, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "base_back_wheel":   {"id": 8, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
    "base_right_wheel":  {"id": 9, "drive_mode": 0, "homing_offset": 0,    "range_min": 0,    "range_max": 4095},
})

robot = LeKiwi(port="/dev/ttyACM0", role="follower", calibration=cal)

Uncalibrated bringup mode

robot = LeKiwi.uncalibrated(port="/dev/ttyACM0", role="follower")

Observations and actions use raw servo ticks (0–4095). No calibration file needed.

Leader (read-only teleoperation)

robot = LeKiwi.uncalibrated(port="/dev/ttyACM0", role="leader")

with connect(robot) as robot:
    while True:
        obs = robot.get_observation()
        print(obs.joint_positions)

Leader mode disables torque on all motors so the arm can be moved manually.

Keyboard WASD base control

import numpy as np
from physicalai.robot import connect
from physicalai_lekiwi_plugin import LeKiwi

robot = LeKiwi.uncalibrated(port="/dev/ttyACM0", role="follower")

with connect(robot) as robot:
    print("WASD drive: W=forward, S=backward, A=rotate left, D=rotate right, Q=strafe left, E=strafe right")
    try:
        while True:
            key = input("cmd> ").strip().lower()
            vx = vy = vtheta = 0.0
            if key == "w":
                vx = 0.15
            elif key == "s":
                vx = -0.15
            elif key == "a":
                vtheta = 0.5
            elif key == "d":
                vtheta = -0.5
            elif key == "q":
                vy = 0.15
            elif key == "e":
                vy = -0.15
            elif key in ("", "x"):
                break

            action = np.zeros(9, dtype=np.float32)
            action[6:] = [vx, vy, vtheta]
            robot.send_action(action)
    except KeyboardInterrupt:
        pass

    robot.send_action(np.zeros(9, dtype=np.float32))

URDF Model

from physicalai_lekiwi_plugin import get_urdf_path

urdf_path = get_urdf_path()
URDF Model Use
lekiwi/LeKiwi.urdf LeKiwi mobile manipulator Kinematics & gravity compensation

The URDF references original STL mesh files from the SIGRobotics-UIUC/LeKiwi project.

Kinematics Model

The base uses a three-wheel holonomic drive with wheels at 240°, 0°, and 120°:

# Body-frame velocities -> individual wheel raw speeds
wheel_raw = robot._body_to_wheel_raw(vx, vy, vtheta)

# Individual wheel raw speeds -> body-frame velocities
body_vel = robot._wheel_raw_to_body(left_raw, back_raw, right_raw)
Parameter Value
Wheel angles 240°, 0°, 120°
Wheel radius 0.05 m
Base radius 0.125 m
Max raw wheel 3000

Acknowledgments

The URDF model for the LeKiwi is from the SIGRobotics-UIUC/LeKiwi project.

Download files

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

Source Distribution

physicalai_lekiwi_plugin-0.1.0.tar.gz (22.0 MB view details)

Uploaded Source

Built Distribution

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

physicalai_lekiwi_plugin-0.1.0-py3-none-any.whl (22.1 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: physicalai_lekiwi_plugin-0.1.0.tar.gz
  • Upload date:
  • Size: 22.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for physicalai_lekiwi_plugin-0.1.0.tar.gz
Algorithm Hash digest
SHA256 bc50e08cd8cc5528139479d877306635775b4697326cc48d7a4d6be1073033a5
MD5 2e04827565f24e6c881f790c6f6edf9e
BLAKE2b-256 33774281eb0a86ae8dad03620bebba4cd03b3e8a4b3a12ae36edb0b5d4255864

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for physicalai_lekiwi_plugin-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e892fe90b4097394911d9c023cc31d8a5d26af59e68cf3d7a150697547f6039d
MD5 856da1bd02bb19f477e241db424f5a54
BLAKE2b-256 4fe801c8e3d7023d9681e56ad290721d3d27be233230b5c51a8fdf9608910355

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Supported by

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