botblocks
projectsgalleryworkspacedocsprofile
introdashboardclipython

full python api

this is a list of classes and methods that actually exist at present:

# --- envs

class Env:
    def __init__(self, things: list[Thing], providers: list[type[Provider]] = [])
    def time(self) -> float
    def log(self, msg, clear=False, level='log')
    def start(self, wait=True, view=True, loop=True) -> Env  # wait=True blocks and runs the loop
    def reset(self, wait=False)
    def quit()

class MujocoEnv(Env):
    def drive(self, on: bool = True)
    def step_sim(self, n: int = 1, ctrl=None, timeout: float = 10.)

# kinematic, physics-free preview (servos snap to target, no falling/collisions)
class ViewerEnv(Env)

# provider-driven, for real hardware (LocalEnv([robot], providers=[ServoSTS]))
class LocalEnv(Env)

# --- things

# a Thing in the world
# program via @Thing.ready and @Thing.loop decorators
class Thing:
    def __init__(self, pos: Xyz = (0, 0, 0), rot: Xyz = (0, 0, 0), name: str = None, **props)
    def ready()
    def loop()
    pose  # -> (pos, rot), live from the sim
    def set_pos(self, pos: Xyz)

class Plane(Thing):
    def __init__(self, size: float = 100., color='#222', **kw)

class Box(Thing):
    def __init__(self, size: float = .1, color='#64a', **kw)

# keyable as robot['my_subsystem']
# Robot().load('path') downloads a robot, e.g. 'menagerie/unitree_go2' or 'public/so101'
class Robot(Thing):
    def __getitem__(self, name: str) -> Subsystem
    def load(self, path: str) -> Robot

# --- subsystems

class Subsystem:
    pose  # -> (pos, rot), world pose of a joint-mounted subsystem's body

class Motor(Subsystem):
    def power(self, v: float)  # v in [-1, 1]

class Servo(Subsystem):
    def target(self, pos: float)  # radians
    def read(self) -> float
    def velocity(self) -> float

class Encoder(Subsystem):
    def read(self) -> float
    def velocity(self) -> float

class Camera(Subsystem):
    def snap(self) -> BytesId
    def snap_img(self) -> PIL.Image

class IMU(Subsystem):
    def gravity(self) -> np.ndarray  # body-frame; also .vel() .accel() .ang_vel() .ang() .pos() .quat()

class Command(Subsystem):  # obs-only goal vector for RL, randomized each reset
    def set(self, v=None, norm=False)
    def read(self) -> np.ndarray

class DiffDrive(Subsystem):
    def power(self, fwd: float, turn: float = 0)

class Arm(Subsystem):
    def move(self, pos=(0, 0, 0), aim=None)  # ik move relative to tip, max 6cm/call
    def goto(self, pos=(0, 0, 0), rpy=None)  # absolute world pose; rpy in radians
    def fk(self)
    def describe(self)

# --- providers

class Provider

class CameraUSB(Provider):
    provides = Camera
    def __init__(self, cam_id: int = 0)

# feetech sts-compatible servo; servo_id/port auto-assign if omitted
class ServoSTS(Provider):
    provides = Servo
    def __init__(self, servo_id: int = None, port: str = None)

# --- rl

class GymEnv:  # gymnasium.Env; things+subsys define obs/action spaces
    def __init__(self, things: list[Thing], subsys: list[Subsystem | Robot] = [])
    def train(self, steps=50_000_000, save='scratch/policy', shards=8) -> None  # sharded PPO

class Policy:
    def __init__(self, path: str, subsys: list[Subsystem | Robot] = [], vecnorm: str = None)
    def step()  # observe -> act, one call