teleop / docs /python-fallback.md
ebubar's picture
feat: launch browser-first expressive gamepad teleop
f8430d1
|
Raw History Blame Contribute Delete
7.55 kB
metadata
title: Reachy_Mini_Teleop
emoji: 🎮
colorFrom: blue
colorTo: indigo
sdk: static
pinned: false
short_description: Local gamepad puppeteering with independent antenna control.
tags:
  - reachy_mini
  - reachy_mini_python_app

Reachy Mini Teleop

Local, expressive gamepad control for Reachy Mini Lite. Control the head, body, height, and both antennas independently. A browser panel shows app/controller status, switches Precision/Turbo mode, and provides Stop.

The controller connects to this Windows computer. The browser panel is local; it does not provide remote robot access or camera/audio streaming.

Start here

  1. Power/connect Reachy Mini and open Reachy Mini Control. Connect the robot and wait until it is ready. Close other apps that command its movements.
  2. Connect your Xbox or DualSense controller by USB or Bluetooth. Center the sticks and release the triggers before starting.
  3. Double-click start-local.cmd in this folder. It checks the locked Python environment, starts Teleop, and opens http://127.0.0.1:8042.
  4. Keep the terminal open. Use the gamepad to move the robot.
  5. Click Stop in the browser, or press Ctrl+C in the terminal. Allow about three seconds for the neutral return. Motors remain enabled to support the head.

Closing the browser tab does not stop Teleop. Force-closing the terminal, losing power, or a broken daemon connection cannot guarantee a neutral return. The browser Stop button is a normal software stop, not an emergency hardware stop.

First-time setup

Requires Windows, Python 3.12, and uv. The launcher creates/updates the environment using the committed lock file. Initial setup needs internet access; a prepared environment can run offline. No Hugging Face login is required for this local app.

From PowerShell in this folder:

uv sync --locked --python 3.12
uv run --no-sync python -m teleop.main --check

The check connects to the daemon's WebSocket and reads telemetry. It sends no motion commands and does not initialize camera/audio. For normal operation:

.\start-local.cmd

For offline operation after setup, bypass the launcher's environment check:

.\.venv\Scripts\python.exe -m teleop.main --open-browser

The app also retains its reachy_mini_apps entry point for discovery by Reachy Mini Control. The launcher is the supported Windows workflow tested here.

Controls

Input Action
Left stick Head yaw and pitch relative to the body
Right stick horizontal Body rotation; head follows while preserving relative yaw
Right stick vertical Head height
L2 / LT Left antenna outward
R2 / RT Right antenna outward
L1 / LB Left antenna inward
R1 / RB Right antenna inward
D-pad up Turbo
D-pad down Precision
Browser mode switch Same Precision/Turbo state
Browser Stop / terminal Ctrl+C Smooth neutral return, then exit

Both antenna channels remain enabled. The SDK receives antennas in right, left order. SDL's controller mapping handles Xbox/DualSense layout differences. Unknown controllers are rejected rather than assigned guessed button indices; configure SDL_GAMECONTROLLERCONFIG if your controller needs a custom mapping.

The app streams one atomic head/body/antenna target at approximately 60 Hz, with elapsed-time integration, smoothing, and per-channel speed limits. Turbo doubles rates but retains pose bounds. Conservative limits are head/body relative yaw +/-45 degrees, pitch +/-20 degrees, body +/-90 degrees, height -20 to +30 mm, and antennas +/-60 degrees. Height-dependent yaw/pitch limits narrow near either height extreme. These are conservative heuristics, not collision detection; the daemon also applies its own limits. Startup begins at measured pose, then converges gradually into app limits if necessary. Sticks hold the last position when released; they do not automatically recenter the head.

Controller loss stops the loop and requests a three-second neutral return. A lost daemon connection stops commands and logs an error; it cannot send a return move.

Pollen Telepresence or this app?

Pollen's current Telepresence app is the easier choice for remote viewing, phone/touch control, robot camera, and two-way audio. It also supports physical gamepads: its current source reads whichever stick has the larger deflection and uses that to steer head yaw/pitch, with body yaw taking over beyond the head's relative yaw limit.

This app remains useful for local expressive puppeteering: separate sticks for head versus body/height, independent trigger/shoulder antenna control, Precision/Turbo modes, and holding poses when controls are released. The reviewed Pollen Telepresence code does not provide those antenna/height controls. Its motion loop is 20 Hz; ours targets 60 Hz with explicit smoothing, but that alone does not prove smoother hardware movement. An attended comparison is still needed.

We recommend Pollen Telepresence for general remote teleoperation and keeping this app for the richer local performance controls. There is no need to rebuild Pollen's camera/audio stack here.

Sources reviewed October 24, 2026:

Troubleshooting

  • Zenoh / port 7447: an old Python environment is being used. This app pins SDK 1.11.0 to match the installed daemon. Run the launcher from this folder; there is another Teleop copy at Desktop\teleop that was not updated.
  • Port 8000 / connection refused: open Reachy Mini Control and connect the robot. The new --check command explains missing/unsupported daemon readiness.
  • GStreamer 1.28.8 / cp312 installation error: Windows media components are constrained to the Desktop-compatible 1.28.7 wheels. Use the committed lock and Python 3.12; do not install GStreamer independently into this environment.
  • exclude-newer = "7 days" warning: this project's own uv settings isolate it from the parent SDK checkout's newer uv configuration format.
  • Waiting for controller: ensure the pad is connected to the same computer, not just the robot or another Bluetooth host. Restart after pairing if needed.
  • Port 8042 already in use: stop the existing Teleop instance before starting another. Do not run two robot-control apps simultaneously.
  • Antenna motion looks choppy: the earlier hardware issue may still need attention. Software keeps both channels available; do not force the mechanism.

The browser status and extension bar show commanded app state, not independently verified physical movement. Watch the terminal for errors.

Development checks

uv run --no-sync python -m unittest discover -s tests -v
uv run --no-sync python -m teleop.main --check

Tests use fake robot/controller input. Physical controls, direction, feel, antenna behavior, and Stop/disconnect acceptance still require an attended hardware trial.