Skip to main content

A CLI, library, and local server for interacting with the Tektonian backend.

Project description

Simulac

⚡️ Full-stack robot framework


Simulac is a full-stack robot framework for robotics engineers who want a unified API for robot simulation, scene building, and hosted robot benchmarks.

Simulac supports:

  1. Integrated physics engines
    • Simulac provides an abstraction layer over industry-standard physics engines
    • Mujoco is default local runtime. Mujoco Warp, Newton and Genesis will be added in the future
  2. Digital twin building
    • Simulac provides fully curated assets for digital twin
    • Use assets with simple entity constructors Stuff("Robocasa/mug/mug_01")
    • Export and load environment definitions as JSON for reuse, review, and experiment setup
  3. Robot benchmark
    • Run hosted robot benchmarks without manually reproducing benchmark infrastructure
    • Reduce setup frictions and speed up iteration

Contents

Installation

Simulac requires Python 3.12 or later.

Install with pip:

pip install simulac

Or install with uv:

uv add simulac

Robot Framework

Simulac's local Environment API separates scene definition from runtime mutation:

  1. Create an Environment.
  2. Add entities such as Stuff, Robot, Camera, and lights.
  3. Mutate build-time properties before creating a runner.
  4. Create a Runner, which freezes the scene definition.
  5. Use runtime handles for live simulation changes.
from simulac import Camera, Environment, Robot, Runner, Stuff

env = Environment(default_engine="mujoco")

table = env.add_entity(
    Stuff("path/to/table.xml"),
    entity_id="table",
    pos=(0.0, 0.0, 0.0),
    fixed=True,
)

cube = env.add_entity(
    Stuff("path/to/cube.xml"),
    entity_id="cube",
    pos=(0.4, 0.0, 0.8),
)

robot = env.add_entity(
    Robot("path/to/franka_panda.xml"),
    entity_id="panda",
)

camera = env.add_entity(
    Camera(type="rgb"),
    entity_id="front_rgb",
    pos=(0.8, -0.8, 1.2),
)

cube.set_mass(0.12)
cube.set_friction(1.0)

runner = Runner(env, 0, 5, runtime_engine="mujoco")
state = runner.reset(seed=0)

Build-time object handles include:

Handle Common operations
StuffObject set_pos, set_rot, set_size, set_mass, set_fixed, set_friction, collider, joint, anchor
RobotObject set_pos, set_rot, set_joint_pos, collider, joint, anchor
CameraObject set_pos, set_rot, set_fov, look_at, attach_to, follow

Save a scene

env.save_env("scene.json", overwrite=True)

Load a scene

loaded_env = Environment("scene.json", default_engine="mujoco")

Local World Building

Local world building uses entity definitions and object handles.

from simulac import AreaLight, Camera, Environment, Robot, Stuff

env = Environment(default_engine="mujoco")

table = env.add_entity(Stuff("path/to/table.xml"), entity_id="table", fixed=True)
robot = env.add_entity(Robot("path/to/robot.xml"), entity_id="robot")
camera = env.add_entity(Camera(type="rgb"), entity_id="front_rgb")
light = env.add_entity(AreaLight(intensity=0.8), entity_id="main_light")

camera.look_at(table.anchor("workspace_center"))
camera.attach_to(robot.anchor("camera_mount"))

Objects can expose named references for placement, constraints, and runtime lookup:

top = table.collider("top")
mount = table.anchor("robot_mount")
joint = robot.joint("joint1")

Environment definitions can be exported as JSON:

scene_json = env.dump_env_json(indent=2)
env.save_env("scene.json", overwrite=True)

Runtime API

After a runner is created, use runtime handles for live simulation state.

cube_rt = runner.get_runtime_object(cube)
robot_rt = runner.get_runtime_object(robot)
camera_rt = runner.get_runtime_object(camera)

cube_rt.change_pos((0.42, 0.05, 0.82))
cube_rt.change_mass(0.20)
cube_rt.change_friction(0.9)

robot_rt.change_joint_pos([0.0] * 7)
robot_rt.set_control([0.0] * 7)

livcamera_rte_camera.change_fov(60.0)

state = runner.tick()
image = runner.render(camera, width=640, height=480)

Runtime robot handles expose robot state by joint, site, link, and sensor name:

joint = robot_rt.joint("joint1")
site = robot_rt.site("gripper")
link = robot_rt.link("link7")
sensor = robot_rt.sensor("force_sensor")

For engine-specific work, access the native context:

ctx = runner.context("mujoco")
model = ctx.model
data = ctx.data

Randomization and Constraints

Randomization specs are sampled during reset. Constraints are used to reject invalid reset candidates.

from simulac import Constraint, Environment, Randomize, Stuff

env = Environment(default_engine="mujoco")

block = env.add_entity(Stuff("path/to/block.xml"), entity_id="block")
goal = env.add_entity(
    Stuff("path/to/goal_marker.xml"),
    entity_id="goal",
    fixed=True,
)

block.set_pos(
    Randomize.uniform(
        (0.25, -0.20, 0.80),
        (0.55, 0.20, 0.80),
        constraints=[
            Constraint.distance("block", "goal", min=0.15, max=0.50),
        ],
    )
)

block.set_mass(Randomize.choice(0.08, 0.12, 0.16))

Randomization helpers:

  • Randomize.uniform(min, max)
  • Randomize.normal(mean, std, clip_min=None, clip_max=None)
  • Randomize.choice(*values)

Constraint helpers:

  • Constraint.distance(a, b, min=None, max=None)
  • Constraint.bbox(target, lower, upper, mode="inside")
  • Constraint.nonpenetration(*between)

Hosted Benchmark

Run a Benchmark

from simulac.gym_style import init_bench

env = init_bench(
    "Tektonian/Libero",
    "libero_90/KITCHEN_SCENE2_put_the_black_bowl_at_the_back_on_the_plate",
    0,
    {"control_mode": "OSC_POSE"},
)

obs, info = env.reset(seed=0)
obs, reward, done, info = env.step([0.0] * 7)
env.close()

init_bench() accepts:

Parameter Description
benchmark_id Benchmark owner and name, for example Tektonian/Libero
env_id Benchmark scene or task id
seed Initial seed used to build the remote environment
benchmark_specific Benchmark-specific options such as controller mode

Visit our website to see all available benchmarks

Authentication

Remote benchmark execution requires a Tektonian API key.

Go to our website and get an API key.

Store your API key with CLI command:

simulac auth login

You can also provide the key through an environment variable:

export SIMULAC_API_KEY=<your_api_key>

Note: API keys can only be viewed once when created

Check the active credential:

simulac auth whoami

Remove the locally stored API key:

simulac auth logout

List Available Environments

simulac benchmark list Tektonian/Libero
from simulac.gym_style import get_env_list

env_ids = get_env_list("Tektonian/Libero")

Visit the Tektonian benchmark page to see available benchmarks:

https://tektonian.com/benchmark

Step Multiple Environments

make_vec() steps multiple hosted environments concurrently and returns results in the same order as the input environment list.

from simulac.gym_style import init_bench, make_vec

args = (
    "Tektonian/Libero",
    "libero_90/KITCHEN_SCENE2_put_the_black_bowl_at_the_back_on_the_plate",
    0,
)
options = {"benchmark_specific": {"control_mode": "OSC_POSE"}}

envs = [init_bench(*args, **options) for _ in range(3)]
vec_env = make_vec(envs)

reset_results = vec_env.reset([0, 1, 2])
step_results = vec_env.step([[0.0] * 7 for _ in envs])
vec_env.close()

CLI

Configuration

Simulac reads configuration from environment variables when present:

  • SIMULAC_API_KEY: use an API key without running simulac auth login
  • SIMULAC_BASE_URL: override the default Tektonian API endpoint
  • SIMULAC_LOG_LEVEL: set log verbosity. choose one of off, trace, debug, info, warning, error
  • SIMULAC_TELEMETRY=off: disable telemetry

Development

For development, start with:

  1. See CONTRIBUTING.md
  2. Read docs/README.md
  3. Read docs in docs/internal

Project Status

Simulac is currently alpha software.

  • - The remote benchmark client is the most complete public surface. (with version 0.1.0 at 01-06-2026 )
  • - Local world-building and runner APIs are still evolving. (with version 0.1.0 at 01-06-2026)
  • - Support parallel Runner
  • - GUI for build Environment
  • - Add more physics engine adapters
    • - Mujoco Warp
    • - Newton
    • - Genesis

License

Apache-2.0

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simulac-0.1.0.tar.gz (114.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simulac-0.1.0-py3-none-any.whl (154.5 kB view details)

Uploaded Python 3

File details

Details for the file simulac-0.1.0.tar.gz.

File metadata

  • Download URL: simulac-0.1.0.tar.gz
  • Upload date:
  • Size: 114.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for simulac-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2d0603dfeeb09cd5a9e4598cd947b80bfdf0661618a95e3bf5b854b804f18159
MD5 8a8bd0257a53d788081b469b91ed8da1
BLAKE2b-256 80ffde0501008dd75c7e3168bd6eef858bda81ef9fc05b25e5a6697469406a02

See more details on using hashes here.

File details

Details for the file simulac-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: simulac-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 154.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for simulac-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9d37b33553cfc3b828afa1685eac90c520c34fd5e6b32e90d2cfb2bee46ba0ee
MD5 a53c56a7ca43b7ec2af4e48fed816ddc
BLAKE2b-256 dca797bf9223a069b49f7a8fe0a00082b460234cae955699d84229b08592d978

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page