Skip to content

Quickstart

Get a robot streaming video to operate.adamohq.com in under five minutes. Pick the language you want to write your robot in — Python, Rust, or C — install the SDK, write a short program that opens a camera, run it.

You don’t need to write an operator — operate.adamohq.com provides a gamepad, VR teleop, recording, and replay against any robot you’ve started. The Building Your Own Operator page covers the case when you want a custom one.

Terminal window
pip install adamo

Requires Python 3.10+. On the robot host you’ll also want the video extras:

Terminal window
pip install 'adamo[video]'

Sign up at operate.adamohq.com and go to Settings → API Keys. Create a key (it starts with ak_) and copy it. The SDK uses this key to find the right router for your organisation.

You can pass the key inline or read it from the ADAMO_API_KEY environment variable.

A robot program does two things: declares the cameras it streams, then blocks driving the pipeline. That’s it.

import adamo
robot = adamo.Robot(api_key="ak_...", name="my-arm")
robot.attach_video("main", device="/dev/video0")
robot.run()

The default transport is QUIC, which runs over UDP. Some corporate networks, lab firewalls, VPNs, and hotel Wi-Fi block outbound UDP even when normal HTTPS works. If the SDK logs connection timeouts or the robot never appears in the operator UI, retry with TCP.

robot = adamo.Robot(api_key="ak_...", name="my-arm", protocol="tcp")

TCP is usually a little less latency-efficient than QUIC, but it is the right choice when the network blocks UDP. For LAN or unreliable-tolerant traffic, you can explicitly choose UDP with protocol="udp" (Python), Protocol::Udp (Rust), or adamo_protocol_t_ADAMO_PROTOCOL_UDP (C).

Run your program. On startup the SDK fetches your router endpoint and opens a session.

[adamo] connecting to router as my-arm…
[adamo] connected (org: my-org)
[adamo] streaming main: 1280x720 @ 30 fps, 4000 kbps (nvh264enc)

Open operate.adamohq.com and log in. Your robot appears in the grid with its live camera feed already playing. Click it to open the teleoperation view.

From there you have:

  • Gamepad control — plug in a USB or Bluetooth controller; the web app publishes Joy messages that your robot can subscribe to. See Receiving Control.
  • VR teleop — for stereo camera tracks, “View Stereo” launches a WebXR view with head + controller pose forwarded to the robot.
  • Recording & replay — every session can be recorded and replayed later.
  • Layouts — multi-camera grids you can configure once and reuse.

See The operate.adamohq.com Platform for the full tour.

To make the robot respond to gamepad or VR input, see Receiving Control.

When you are not sure what is flowing through the network, subscribe to a wildcard and print the keys that arrive. This is the live equivalent of “list topics”: it observes traffic, so quiet topics appear only after they publish a sample.

import adamo
session = adamo.connect(api_key="ak_...")
seen = set()
with session.subscribe("my-arm/**") as sub:
for sample in sub:
if sample.key not in seen:
seen.add(sample.key)
print(sample.key)

Use my-arm/** for one robot, **/control/** for control traffic, or ** when you really want to see every sample in your org. See Robot and Topic Discovery for Python, Rust, C, and TypeScript versions.

Most robots have more than one camera. Just call the attach method again — once per track.

import adamo
robot = adamo.Robot(api_key="ak_...", name="my-arm")
robot.attach_video("wrist_left", device="/dev/video0")
robot.attach_video("wrist_right", device="/dev/video1")
robot.attach_video("head", shm="head_cam") # iceoryx2 SHM
robot.run()

For the full set of input methods (V4L2 and shared memory), see Adding Cameras.