Give megan-tk an objective and milestones, then step or perceive it for a continue/adapt decision.
A token session is megan-tk pursuing one objective across an ordered chain of
milestones. You open it once, then drive it each control cycle. It hands back a
Decision: continue or adapt, and the
milestone its attention is on.There are two ways to drive a session:
reached and every obstacle’s milestone are indices into the milestone list
you opened the session with. An out-of-range index is rejected by the server (HTTP
422 → MeganTKError).
The whole point is the adapt branch — that’s megan-tk telling you the current
plan won’t carry the frontier and your change-doer should intervene here:
For grounded navigation you can let the token reason about distance instead of
discrete “reached” flags. Open the session with one shrinking ring radius per
milestone, then report raw position/goal/obstacles.
s = tk.session( objective="navigate to the dock", milestones=["approach", "dock"], ring_radii=[1.0, 0.3], # one radius per milestone, shrinking obstacle_block_radius=0.8, # how close an obstacle must be to block)assert s.perception is Trued = s.perceive( position=[0.0, 0.0], # robot world position (xy or xyz) goal=[2.0, 0.0], # goal world position obstacles=[{"id": "cone", "position": [1.0, 0.0]}],)print(d.route, d.frontier)
Perception obstacles take a dict or an (id, position) tuple:
ring_radii must have exactly one radius per milestone and must shrink as
milestones advance (each ring tighter than the last). Calling perceive on a
session opened withoutring_radii is a 422 — use step there instead.
The server holds the live token object (its knowledge graph accumulates across
steps), so close sessions you’re done with. The with form does this for you;
if you manage a session by hand, call close() in a finally.
from cadenza_cli import MeganTKtk = MeganTK()with tk.session("pick up the red cube", ["reach", "grasp", "lift"]) as s: reached = [] for obs in perception_stream(): # your sensor loop reached = update_reached(reached, obs) d = s.step(reached=reached, obstacles=blocking(obs)) if d.adapt: change_doer.intervene(at=d.frontier) if len(reached) == len(s.milestones): break