Menlo
Asimov API

Asimov API set up

End-to-end setup for running the Asimov API service on a Raspberry Pi.

Running the Asimov API on a Raspberry Pi

End-to-end setup for a Raspberry Pi running the Asimov API service. This walks through installing the service, finding your audio/video devices, and launching against a LiveKit server on your laptop.

Looking for the API itself (commands, telemetry, joint order)? See the Asimov API manual.

1. Prereqs

  • A Raspberry Pi running a recent Debian/Ubuntu image.
  • Python 3.12 or newer. Bookworm ships Python 3.11, which will fail the install — use uv or pyenv to get 3.12.
  • System libraries (Debian/Ubuntu):
    sudo apt update
    sudo apt install -y portaudio19-dev libgl1 libglib2.0-0
    # protobuf-compiler is only needed if you edit .proto files
  • A USB or CSI camera and a USB audio device (mic + speaker — same device or separate is fine).

2. Install

git clone <repo-url> ~/asimov-api
cd ~/asimov-api
make install               # creates .venv and installs the package

If python on your $PATH is not 3.12, create the venv explicitly with uv:

uv venv --python 3.12 ~/asimov-api/.venv
~/asimov-api/.venv/bin/pip install -e .

The protobuf files are committed, so you don't need make proto unless you've edited proto/*.proto.

3. Find your camera

# List video devices
v4l2-ctl --list-devices

# For each /dev/videoN, check whether it exposes a usable format
for N in $(ls /dev/video* | sed 's|/dev/video||'); do
    echo "=== /dev/video$N ==="
    v4l2-ctl -d /dev/video$N --list-formats 2>/dev/null | head -5
done

Note the index N of the device that lists at least one format (often MJPG or YUYV). You'll pass it as --camera-device N.

4. Find your audio devices

# Speakers / playback
aplay -l

# Microphones / capture
arecord -l

Note the human-readable name of your USB audio device (e.g. ReSpeaker, XVF3800, USB Audio). You'll pass that name — or a substring of it — to --mic-device and --speaker-device. ALSA's default device often doesn't work for USB capture, so it's safer to name the device explicitly.

Sample rate gotcha

Some cheap USB audio devices only accept 16 kHz output. If you hear [Errno -9997] Invalid sample rate when the speaker starts, pass --speaker-sample-rate 16000.

Software volume (optional)

If your USB device has no hardware mixer (check amixer -c <card>), add a software volume plugin in ~/.asoundrc:

pcm.your_softvol {
    type softvol
    slave.pcm "hw:CARD=YourDevice,DEV=0"
    control.name "SoftMaster"
    control.card "YourDevice"
}

Replace YourDevice with your card's ID (from aplay -l). Then use --speaker-device your_softvol and adjust with:

amixer -D your_softvol sset SoftMaster 80%

5. Launch

The service connects to a LiveKit server for video/audio/teleop and to the motor firmware over UDP.

On your laptop, start LiveKit and mint a viewer token. The LIVEKIT_ENABLE_DATA_TRACKS=true env var is required — telemetry rides on a LiveKit data track, which --dev mode doesn't enable by default:

LIVEKIT_ENABLE_DATA_TRACKS=true livekit-server --dev --bind 0.0.0.0
lk token create --api-key devkey --api-secret secret \
    --identity viewer --room robot --join --valid-for 24h

Note your laptop's LAN IP. On the Raspberry Pi:

env PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python PYTHONPATH=~/asimov-api/src \
    ~/asimov-api/.venv/bin/python -m edge.main \
        --firmware-host <robot-compute-ip-or-127.0.0.1> \
        --livekit-url ws://<laptop-lan-ip>:7880 \
        --livekit-key devkey --livekit-secret secret \
        --serial MENLO-0001 --force-cloud \
        --mic-device <your-mic-name> \
        --speaker-device <your-speaker-name> \
        --camera-device <N>

Use --firmware-host 127.0.0.1 if you aren't running the motor firmware yet — UDP goes nowhere, but the media pipeline (camera/mic/speaker) still works.

--force-cloud is required — it bypasses BLE provisioning and tells the service to start LiveKit immediately.

6. Verify

Tail the logs:

journalctl -t edge -f       # if running as a systemd service
# otherwise: just watch the terminal you launched it in

Look for these tags coming up cleanly:

  • [MAIN] startup banner
  • [CAMERA] opened your /dev/videoN with a non-zero resolution
  • [MICROPHONE] and [SPEAKER] opened at their sample rates
  • [CLOUD] connected to your LiveKit URL and joined the room
  • [FW_LINK] first RobotState arrived (only if firmware is up)

In a viewer connected to the same LiveKit room, you should see the camera feed, hear the mic audio, and be able to send audio back to the speaker.

7. Stop

pkill -f "edge.main"

Troubleshooting

SymptomLikely cause
pip install fails on requires-pythonPython 3.11 active — use uv venv --python 3.12 …
pyaudio build failsMissing portaudio19-dev
Camera opens but no framesWrong --camera-device index, or /dev/videoN is the metadata node — pick one that lists a video format
[Errno -9997] Invalid sample rateUSB audio device only supports 16 kHz — add --speaker-sample-rate 16000
No mic input but speaker worksDefault device has 0 input channels — pass --mic-device <name> explicitly
Viewer connects but no video/audio--force-cloud not passed, or LiveKit URL/key/secret wrong

How is this guide?

On this page