Menlo
Python SDKGuides

Connection Modes

UDP, Hybrid and LiveKit: what each carries, what it needs, and how the SDK picks one.

The SDK reaches the robot through Asimov Edge, the service on the robot, in one of three connection modes. The Robot object and every verb are the same in all three; the mode decides what the connection carries and where it works from.

ModeControl and stateCamera and audioWorks from
udpUDP on the robot's networknonethe robot's network
hybridUDP on the robot's networka LiveKit roomthe robot's network
livekita LiveKit rooma LiveKit roomwherever Asimov Manager is reachable

A saved robot carries a mode, so Robot().connect() needs no argument. Pass one to override it for a session: connect("udp").

UDP

Commands go to the robot on UDP port 8850 and state comes back on port 8851. There is no media and no sign-in: anyone on the robot's network who can reach port 8850 can command it, so trust the network before you turn it on.

Asimov Edge sends UDP state to one host. On the robot, set the Asimov Edge parameters udp-control to on and udp-state-host to your computer's address, in the Asimov Manager settings.

examples/01_connect_udp.pyView on GitHub ↗
config = ConnectionConfig(udp=UdpConfig(host=args.host))

with Robot(config).connect("udp") as robot:
    state = robot.state
    print(robot.info)
    print(f"robot mode {state.mode.name}, armed {robot.armed}")
    if state.battery is not None:
        print(f"battery {state.battery.soc_percent:.0f} %")
    print(f"latest state is {state.age_s * 1000:.0f} ms old")

The full script is 01_connect_udp.py.

One client per state port: a second script on the same computer binds UdpConfig(state_bind=("0.0.0.0", <port>)) and the robot's udp-state-port matches it.

Hybrid

Control and state travel as in udp, so a velocity command does not cross the internet. The camera, microphone and speaker travel over the robot's LiveKit room, which the SDK joins with an SDK credential from Asimov Manager. Use hybrid on the robot's network when a script needs the camera or sound.

It needs the robot's address, its Asimov Manager URL and an SDK credential. Issue the credential on the Developer page of Asimov Manager (Developer Credentials). The credential's role applies to the LiveKit room: a Control credential can talk through the speaker, an Observe credential watches and listens only. Commands in hybrid travel over UDP, which has no sign-in, so the role does not limit driving.

examples/02_connect_hybrid.pyView on GitHub ↗
config = ConnectionConfig(
    udp=UdpConfig(host=args.host),
    livekit=ManagerConfig(url=args.manager, credential=credential),
)

with Robot(config).connect("hybrid") as robot:
    print(robot.info.endpoint)
    print(f"camera {robot.has('camera')}, microphone {robot.has('microphone')}")
    print(f"robot mode {robot.state.mode.name}")

The full script is 02_connect_hybrid.py.

LiveKit

Everything, commands included, goes through the robot's LiveKit room. Commands travel on the data topic commands and state on the data track state, at about 10 Hz. Use livekit away from the robot's network, or when an agent framework joins the same room and the SDK is one more participant in it.

It needs the Asimov Manager URL and an SDK credential. The SDK asks Asimov Manager for a room token, joins, and reports robot.info.endpoint as room@url.

examples/03_connect_livekit.pyView on GitHub ↗
config = ConnectionConfig(livekit=ManagerConfig(url=args.manager, credential=credential))

with Robot(config).connect("livekit") as robot:
    print(robot.info.endpoint)  # room@url as the identity Asimov Manager issued
    print(f"robot mode {robot.state.mode.name}")
    print(f"camera {robot.has('camera')}, microphone {robot.has('microphone')}")

The full script is 03_connect_livekit.py.

The Asimov Manager URL is the one you open in the browser: http://192.168.22.32, http://asimov.local:8080 or a bare host name. The LiveKit URL Asimov Manager hands out is the one Asimov Edge uses on the robot; when it says localhost, the SDK substitutes the manager's host. A manager that redirects is reported as a ConnectError, not followed.

Every SDK session joins the room as its own participant, sdk-<credential id>-<host>-<6 hex>. ManagerConfig(label="...") fixes the suffix so a restarted script replaces its previous session instead of joining beside it. To join with a token you minted yourself, pass LiveKitConfig(url, room, token) instead of ManagerConfig; one token is one participant.

How the SDK Picks a Connection

Robot() with no argument builds its connection from the environment or a saved robot, in this order:

  1. Environment variables: MENLO_UDP_HOST, or MENLO_MANAGER_URL and MENLO_CREDENTIAL, or both pairs. They are not merged with a saved robot.
  2. A saved robot from ~/.menlo/robots.toml: the one named by MENLO_ROBOT, else the file's default, else the only one.
  3. Otherwise ConnectError, naming menlo setup and the variables.

MENLO_MODE sets the mode connect() uses with no argument and MENLO_LIMITS the velocity limits, whichever source supplied the connection. MENLO_HOME moves the store directory.

A saved robot holds everything one mode needs, and can hold more than one mode's fields:

~/.menlo/robots.toml
default = "lab"

[robots.lab]
mode = "hybrid"
udp_host = "192.168.22.32"
manager_url = "http://192.168.22.32"
credential = "..."
room = "robot-menlo-0001"

[robots.lab.limits]
vx = 0.3

udp needs udp_host; hybrid needs udp_host, manager_url and credential; livekit needs manager_url and credential. A mode whose field is missing raises ConnectError naming the field and the menlo robots add command that fills it. Save and change robots with the command line; the file is created with mode 0600 because it holds SDK credentials.

To build the connection in code instead, pass a ConnectionConfig to Robot(...), as the examples above do.

What Connect Waits For

connect() returns once the robot has reported state, so robot.state is valid on the next line. It raises ConnectError after timeout (5 s by default) without state. On hybrid and livekit the media tracks are awaited for media_timeout (3 s); the capabilities the SDK claims are the tracks that arrived.

connect(require_state=False) opens the room without waiting for the firmware: camera, microphone and speaker work at once, and state and the motion verbs unlock when the first state frame arrives.

A protocol version other than the one the SDK speaks raises ProtocolMismatchError. allow_version_skew=True connects anyway, for a robot whose firmware is one version ahead or behind.

A lost link stops the robot

After 2 s without state the SDK raises LinkLostError, sends zero velocity if it holds one, and every verb raises until you close() and connect() again. On udp and hybrid, Asimov Edge also zeroes a velocity 2 s after the last command it received. See Safety.

  • Quickstart: save a robot and run the first script
  • Command Line: menlo setup and menlo robots
  • Asimov Manager: credentials and Asimov Edge parameters
  • Reference: ConnectionConfig, UdpConfig, ManagerConfig, LiveKitConfig

How is this guide?

On this page