Skip to content

Loading search…

reactive

Guards and controllers that run at every control tick.

  • Layer: reactive
  • Needs: –
  • Requires: –
  • Conflicts with: –
  • Never dropped: no
  • Mixin: skills.reactive:Reactive
  • Manifest: skills/reactive/skill.toml
def run_controller(fn, until=None, max_seconds=None, region=None, hz=None, cameras=None, camera_hz=5.0)

Run fn(obs) -> command at hz (default: every tick) and hold the last command in between. The command is a dict with any of ‘left_arm’/‘right_arm’ (6 joint targets), ‘left_eef’/‘right_eef’ (link6 pose [x, y, z, qw, qx, qy, qz], solved by IK outside fn) and ‘left_gripper’/‘right_gripper’ (0 closed .. 1 open), or None to finish. With cameras, obs[“observation”] is an Observation of those cameras refreshed at camera_hz (images, intrinsics, camera_to_world), for visual servoing with pure image processing and pixel_to_plane / project. fn runs under the reactive budget; decoding the images does not count against it.

Also in the namespace: when, watch, clear_guards (constants and names the skill’s exports(session) provides).

From the RoboDojo prompt pack (prompts/robodojo/), with every skill and feature on:

when nothing is found, try the color, the material, or the holder it sits in.
watch(signal, low=None, high=None, event=None) signal: key of obs such as
"left_gripper", "left_ee.2", or a function of obs
clear_guards(names=None)
run_controller(fn, until=None, max_seconds=None, region=None, hz=None, cameras=None, camera_hz=5)
fn(obs) -> {"left_arm": 6 joints, "left_eef": link6 pose, "left_gripper": value, ...}
or None to stop; called at hz (default every tick), the last command is held in
between. "left_eef" is solved by IK for you. With cameras=["cam_head"], obs also
has "observation": the latest images of those cameras (refreshed at camera_hz)
with calibration, so fn can track something moving (e.g. a color mask, then
pixel_to_plane(obs["observation"], "cam_head", u, v, z)) and servo toward it.