Skip to main content
Every robot implements three methods:
obs = robot.observe()   # {"state": Tensor(1, N), "images": ...}
robot.act(action)       # Tensor(1, N)
robot.reset()
This contract is the seam between policy code and the world. A policy that works against a MockRobot works against a SimRobot works against a RealRobot — no changes to the policy.

Built-in robots

# Real hardware
robot = rfx.RealRobot(rfx.SO101_CONFIG)

# Simulation
robot = rfx.SimRobot.from_config("so101.yaml", backend="genesis", viewer=True)
robot = rfx.SimRobot.from_config("go2.yaml",   backend="mjx",     num_envs=4096)

# Mock (zero dependencies)
robot = rfx.MockRobot(state_dim=12, action_dim=6)

Contract guarantees

observe()

Returns a Dict[str, Tensor]. Keys are stable — state, images, and any sensor keys declared in the robot config. Shapes and dtypes follow the config.

act(action)

Accepts a Tensor in the action space declared by the robot config. Indexing by name (via MotorCommands) is supported for readable code.

reset()

Returns the robot to a known-safe home state. Called once per episode.

disconnect()

Releases hardware resources. Always call during cleanup, or use a context manager.

Custom robots

Implement observe() / act() / reset() directly, or supply a YAML config that declares joints, sensors, and control rate. Hardware adapters handle the transport layer; the contract stays the same.