Skip to content

Robot State

A robot can publish named state that operators read — on demand or live. The robot owns the value; operators read it. State is held in memory by the robot process, so it resets when the robot restarts.

Two APIs build on this:

  • Shared state — a key/value store the robot updates and operators read.
  • Task runs — a pedal-driven sequence of subtasks with progress and rep counting, shown in the web Tasks widget.

State values live under {robot}/state/{key}. The robot sets a value; operators read the latest with a one-shot query (request/response) or subscribe for live updates. Values are bytes — the SDK helpers below send JSON.

import adamo
session = adamo.connect(api_key="ak_...")
state = session.state_store("my-arm")
state.set("fork_height", {"current": 1.4}) # dict / list -> JSON
state.set("mode", "manual")
# state.delete("mode")

Read it from an operator program (or another robot):

import adamo
from adamo.operate import state_topic, state_topic_all
session = adamo.connect(api_key="ak_...")
# one-shot read
for s in session.get(state_topic("my-arm", "fork_height")):
print(s.payload) # b'{"current": 1.4}'
# live updates for every state key
session.subscribe(state_topic_all("my-arm"), callback=lambda s: print(s.key, s.payload))

For data collection a robot often runs an ordered list of subtasks over and over — flatten, fold the left side, fold the right side — advancing on a foot pedal, then looping. A task runner owns that cursor: it tracks the active subtask, counts reps, and returns to an idle gap when the set completes. It publishes the run on {robot}/state/task_run.

Each pedal press is one advance:

idle → subtask 1 → subtask 2 → … → subtask N → idle (rep++) → subtask 1 → …

select loads a set and parks at idle. Completing the last subtask returns to idle and increments the rep, so there is always a gap between runs. Wire your pedal to advance — the runner does the rest.

import adamo
session = adamo.connect(api_key="ak_...")
runner = session.task_runner("my-arm")
runner.select("fold-set", "Fold clothes", [
{"id": "s1", "name": "Flatten"},
{"id": "s2", "name": "Fold left"},
{"id": "s3", "name": "Fold right"},
])
# Wire your pedal (USB HID, GPIO, …) to advance:
def on_pedal():
runner.advance()

The web Tasks widget reads {robot}/state/task_run and renders the subtask list with the active one highlighted and the rep count — the operator picks which set to run there. You can also read the document directly.

{robot}/state/task_run is UTF-8 JSON:

{
"task_set_id": "fold-set",
"name": "Fold clothes",
"current_index": 2,
"rep": 7,
"subtasks": [
{ "id": "s1", "name": "Flatten", "status": "done" },
{ "id": "s2", "name": "Fold left", "status": "done" },
{ "id": "s3", "name": "Fold right","status": "active" }
]
}

current_index is null when idle (between reps). Each subtask status is pending, active, or done.