Skip to content

feat(lekiwi): add the lekiwi mobile base extension - #322

Draft
QuanluZhang wants to merge 6 commits into
RLinf:mainfrom
QuanluZhang:feat/lekiwi
Draft

QuanluZhang wants to merge 6 commits into
RLinf:mainfrom
QuanluZhang:feat/lekiwi

Conversation

@QuanluZhang

Copy link
Copy Markdown
Collaborator

Description

Add LeKiwi, a three-wheel omnidirectional mobile base built from three Feetech STS3215 wheel servos and a front UVC camera, as an RPent robot extension.

Environment server. robots/lekiwi/env_server.py owns an RLinf RealWorldEnv in its own process and serves the env.* RPC methods. There is no Ray cluster on the robot's onboard computer: on a small board the scheduler processes would use more memory than the robot has. robots/lekiwi/env_client.py attaches from the agent machine over HTTP and never imports RLinf.

Control. drive(velocity, duration_s) steps the wheels for a bounded duration and stops them before it returns, so an interrupted run, a crashed client, or a dropped network cannot leave the base rolling. hold keeps a velocity until it expires or a stop arrives and is what Dashboard teleoperation uses. The Dashboard refreshes it while a button is held, so it lapses one second after the last refresh; the server caps any hold at two seconds. Requested velocities are clipped to the site limits.

Site YAML. robots/lekiwi/config/example.yaml carries the serial port, the camera serials, and the velocity limits. robots/lekiwi/runtime_config.py validates it against the RLinf dataclasses, so an unknown key fails at startup instead of being ignored, and applies RPent's developer defaults as override_cfg rather than restating them in the YAML. python -m robots.lekiwi.detect writes that YAML from the hardware it finds: it scans the servo bus without commanding motion and opens each camera once.

Dashboard. The LeKiwi dashboard spec marks the environment external, so a Session attaches to --env-endpoint and never spawns one. rpent/dashboard/teleop.py adds the teleoperation panel with hold-based driving, video recording (teleop_NNN.mp4), and an action log (teleop_actions.jsonl).

Tasks. Two tasks are registered in robots/lekiwi/tasks.py: drive_smoke_test (task 0) and room_survey (task 1).

Dependency. This needs the RLinf LeKiwi environment layer, which is not in a released RLinf yet; the lekiwi extra's comment and the new documentation page both say so. The robots.lekiwi package data now ships config/example.yaml.

Testing

Run on a CPU-only machine against the unit-test fakes:

  • pytest tests/unit_tests/robots/lekiwi tests/unit_tests/rpent/dashboard tests/unit_tests/rpent/cli tests/unit_tests/robots/test_tool_schema_contracts.py tests/unit_tests/robots/test_toolkit_contracts.py — 212 passed.
  • ruff check --preview . and ruff format --check . — clean on tracked files.
  • sphinx-build -W --keep-going source-en build/html-en and source-zh build/html-zh — both builds succeed with warnings treated as errors.

Manual verification

No LeKiwi was attached while this change was prepared, so the robot, the camera, and the Dashboard teleoperation panel are not verified on hardware. Everything was exercised against the fakes that tests/unit_tests/robots/lekiwi loads for the RLinf environment. A first run on a real base should follow the new page: rlinf-lekiwi-test-wheels and rlinf-lekiwi-check-camera on the robot computer, then task 0 with the wheels off the ground.

Checklist

  • My code follows the code style of this project.
  • I have updated related documentation when needed.
  • I have added tests to cover my changes when needed.
  • All new and existing tests passed.
    🤖 Generated with Claude Code

@read-the-docs-community

read-the-docs-community Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

@read-the-docs-community

read-the-docs-community Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

RLinf-bot and others added 2 commits October 27, 2026 10:01
Add LeKiwi, a three-wheel omnidirectional base, as an RPent robot
extension. The environment server owns an RLinf RealWorldEnv in its own
process and exposes env.drive, env.stop, and env.hold, so the robot's
onboard computer runs no Ray cluster. The client attaches over RPC and
never imports RLinf.

A drive call steps the wheels for a bounded duration and stops them
before it returns; hold keeps a velocity until it expires, which is what
Dashboard teleoperation uses. The site YAML carries the serial port,
camera serials, and velocity limits, and is validated against the RLinf
dataclasses so a typo fails at startup. robots.lekiwi.detect writes that
YAML from the hardware it finds.

The Dashboard gains a teleoperation panel with hold-based driving, video
recording, and an action log, and the LeKiwi dashboard spec marks the
environment external so a Session never spawns one.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
Add an English and Chinese page that takes a LeKiwi base from a working
robot to a running task: prepare the robot computer, write the site YAML
from the detection output, start the environment server, and attach from
the agent machine or a Dashboard Session. List LeKiwi with the other real
robots in the overview and the sidebar.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
The extra now pins the RLinf revision that has the LeKiwi environment
layer, so `uv pip install -e '.[lekiwi]'` installs both and the guide no
longer clones RLinf or passes a second -e path. Drop the hardware
bring-up block that repeats the RLinf LeKiwi guide, and run detection
through the new rpent-lekiwi-detect script instead of python -m.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
Expose robots.lekiwi.env_server.main as rpent-lekiwi-server so the guide
starts the server with a command next to rpent-lekiwi-detect instead of a
python -m invocation.

The site YAML section now tells readers to edit the generated file where
it does not fit and to copy it to the agent machine, and calls the two
machines the robot computer and the agent machine rather than server and
client.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
Comment thread robots/lekiwi/config/example.yaml Resolved
"Plan a short route from the camera view, one bounded segment at a time.",
"Drive one segment, then inspect the result before moving again.",
"Finish only when the task's evidence is visible and consistent with state.",
)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this file content necessary for manual control mode?

Comment thread robots/lekiwi/detect.py Resolved
Comment thread robots/lekiwi/detect.py Resolved
Comment thread robots/lekiwi/detect.py Resolved
Comment thread robots/lekiwi/env_client.py Resolved
"default": 30.0,
"env.reset": 60.0,
# A drive holds for up to the server's max duration, then reports.
"env.drive": 60.0,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this field mean? 60.0 is 60.0 seconds?

Comment thread robots/lekiwi/env_server.py Resolved
Comment thread robots/lekiwi/runtime_config.py Resolved
Remove the Dashboard teleoperation section; manual mode is described in
one paragraph on the LeKiwi page. Drop the Troubleshooting and Safety
sections, replace the "site" vocabulary with LeKiwi YAML, and default
the generated file to lekiwi.yaml.

Write camera_max_age: 0.05 in the example and generated YAML so a step
follows the 15 fps camera rather than RLinf's 0.5 s default, which caps
distinct frames at two per second.

Inline the single-use detector helpers, rename build_site_config to
build_yaml_config, and cut the LeKiwi unit tests from 29 to 20 by merging
cases that cover the same contract.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
RLinf now accepts 0, where a step waits for a fresh frame, so the page
no longer claims the value must be positive.

Co-Authored-By: Claude Code <[email protected]>
Signed-off-by: QuanluZhang <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants