FastSim 0.1.0a36 is an alpha release. This repository is the clean vNext
implementation: it intentionally does not accept legacy FastSim configuration or
provide legacy import aliases.
Why FastSim?
Isaac Lab, MuJoCo, and PyBullet are simulation engines or simulator frameworks. UniRoboSim normalizes their scene, entity, sensor, debug, and control capabilities. FastSim solves a different problem: it turns assets, runtime policy, a Scenario, and installed plugins into one inspectable and repeatable simulation application.
| Layer | Responsibility |
|---|---|
| Simulator backend | Native physics, rendering, devices, and backend-specific features |
| UniRoboSim | Backend discovery and a portable simulator contract |
| FastSim Core | Configuration, registry resolution, execution plans, locks, lifecycle, scoped services, and control arbitration |
| FastSim plugins | Rule-based, model, teleoperation, Agent, recording, replay, debug, TUI, Web, or server behavior |
Use UniRoboSim directly when an application only needs a thin, portable simulator API. Use FastSim when a run must be described as data, inspected before startup, locked to exact resources, extended without modifying the runtime, and driven by multiple kinds of control producers.
FastSim does not own task semantics. Concepts such as pick, place, grasp poses,
action lists, planners, model inference, and teleoperation devices belong to plugins.
Core only supplies the lifecycle, data, planning-read, and control boundaries those
plugins share.
Architecture

The CLI is part of FastSim Core, not a plugin. Feature interfaces such as a TUI, browser console, interactive debugger, or HTTP server are plugins so their code and runtime cost are absent unless installed and selected.
Installation
Version matrix
FastSim itself supports Python 3.11 and 3.12. Use the Python required by the selected backend provider.
| Package | Current compatible version | Python | Notes |
|---|---|---|---|
fastsim |
0.1.0a36 |
3.11, 3.12 | Pins unirobosim==0.10.5; kinematics remains optional |
unirobosim |
0.10.5 |
3.11, 3.12 | Portable core; no simulator is bundled |
unirobosim-isaaclab |
0.10.16 |
3.12 | Requires a compatible Isaac Lab 3.0 / Isaac Sim 6.0 installation |
unirobosim-mujoco |
0.9.4 |
3.12 | Provider currently pins MuJoCo 3.11.0 |
unirobosim-pybullet |
0.9.4 |
3.11 | Provider currently pins PyBullet 3.2.7 |
fastsim-kinematics-solver-spi |
0.1.0 |
3.11, 3.12 | Optional provider contract |
fastsim-kinematics-solver-portable |
0.1.0 |
3.11, 3.12 | Optional deterministic URDF provider |
FastSim 0.1.0a36 retains the opt-in, independently stamped observation-channel
stream introduced in 0.1.0a12 and used for camera recording. Pure numeric Record capture is snapshot-atomic, so one
simulation tick creates one queue item regardless of channel count. The existing snapshot query and subscription API
is preserved, while direct application state reads now return the WorldState and
Observation pair atomically from one committed tick. Live channel delivery and
ordered capture use separate sequences:
channel_sequence orders every due live item, while optional capture_sequence
orders only recorded items. Record 0.2.3 targets FastSim 0.1.0a8; the current
Record 0.3.12 and managed Replay 0.2.17 use the current FastSim
>=0.1.0a36,<0.2 release train. Do not combine
packages from different release trains. In ordered capture, a Run uses exactly
one observation lane. A data_consumer does not become a recorder merely by
reading observations: the installed Manifest must explicitly declare
semantics.plugin.recording_sources, and Core accepts at most one enabled
capture owner. Other data consumers keep ordinary live subscriptions and add no
global sequencing or recording-history overhead. Selecting observations
requires a non-empty compiled observation demand.
Primary recording publication now defaults to structural integrity, avoiding payload SHA-256 work while retaining FSR validation, pinned file identity, durability, atomic publication, and cleanup. Deployments that need same-size post-validation tamper detection can opt into strict SHA-256 integrity. See Run output integrity.
The repositories are currently installed from source; the commands below do not assume that packages are available from PyPI. For a PyBullet development setup:
git clone https://github.com/GitHofee/UniRoboSim.git
git clone https://github.com/GitHofee/UniRoboSim-pybullet.git
git clone https://github.com/FastSim-Benchmark/FastSim.git
python3.11 -m venv fastsim-dev
source fastsim-dev/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ./UniRoboSim
python -m pip install -e ./UniRoboSim-pybullet
python -m pip install -e './FastSim[dev]'
For MuJoCo, use Python 3.12 and install
UniRoboSim-mujoco instead. For
Isaac Lab, run pip through the Python environment that owns the compatible Isaac
Lab installation, then install
UniRoboSim-isaaclab and FastSim
into that same environment. Do not create a second Isaac installation only for
FastSim.
Confirm which FastSim installation is active:
fastsim --version
fastsim doctor --json
doctor reports package and Python information. Its backend_integration field is
currently conservative (unverified); it is not a native backend health check.
Quick start
The repository contains a minimal lifecycle Run at
examples/quickstart/run.yaml. It resolves one small
red cube from a local Registry, so configuration, resource integrity, and backend
startup can be checked without downloading a robot or installing a plugin.
schema: fastsim/2
name: quickstart
backend: pybullet
runtime:
launch_profile: headless
physics_hz: 60
control_hz: 30
seed: 7
scenario:
scene:
objects:
cube:
use: object://fastsim/quickstart-cube
pose:
xyz_m: [0.0, 0.0, 0.5]
quat_xyzw: [0.0, 0.0, 0.0, 1.0]
Validate and inspect it without opening a simulator:
fastsim config validate examples/quickstart/run.yaml --json
fastsim config expand examples/quickstart/run.yaml
fastsim config explain examples/quickstart/run.yaml runtime.physics_hz
Create and verify a content-addressed lock:
fastsim config lock examples/quickstart/run.yaml --output quickstart.lock --json
fastsim config verify-lock quickstart.lock --json
With the PyBullet provider installed, run the application for two wall-clock seconds:
fastsim run examples/quickstart/run.yaml --duration 2 --json
The top-level fields are intentionally small:
| Field | Meaning |
|---|---|
schema |
The clean authoring contract; currently fastsim/2 |
name |
Stable human-readable Run name |
backend |
UniRoboSim provider ID selected for this compilation |
runtime |
Physics, control, sensor-rate, and seed policy |
scenario |
Required scene and optional plugin-owned behavior/evaluation payloads |
control |
Default actor and precedence between control-producing plugin instances |
plugins |
Installed plugin instances selected for this Run |
overrides |
Explicit authoring-time overrides compiled with provenance |
Demo library
demo/fundamentals is the guided API course. Each
numbered case is self-contained and includes a Python program, a Run
configuration, an English README, and a Chinese README. The sequence begins with
configuration-only checks, then introduces lifecycle, control, sensors, scene and
planning queries, reproducibility, and advanced physical tracks. Start with
01_config_validation_and_compilation
if this is your first FastSim application.
demo/components is the component authoring course for
simulation users. It follows the real Project and Registry resolution chain and gives
copyable examples for environments, objects, articulations, robots, sensors, lights,
deformables, fluids, Scenarios, version selection, backend variants, defaults, and
resource integrity.
demo/official_plugins is reserved for
configuration-first application pipelines built from released official plugins.
Plugin demos are added only after their packages and native acceptance gates are
public; placeholders are not presented as working products.
Direct application API
Developers building a complete simulation application can use the asynchronous
FastSimApplication facade without implementing a plugin:
import asyncio
import fastsim
async def main() -> None:
async with fastsim.app("run.yaml") as simulation:
await simulation.start()
targets = await simulation.control.targets()
print([(item.entity_id, item.resource_group) for item in targets])
operation = await simulation.control.submit_joints(
actor="droid",
group="arm",
path=[
[0.0, -0.4, 0.0, -2.0, 0.0, 1.6, 0.8],
[0.2, -0.2, 0.1, -1.8, 0.1, 1.4, 0.6],
],
dt=1.0 / 60.0,
timeout=10.0,
)
print(await operation.status())
result = await operation.result()
await operation.release()
print(result.status)
moved = await simulation.scene.set_pose(
"objects.red_cube",
xyz_m=(0.55, -0.15, 0.72),
)
print(moved.status)
asyncio.run(main())
The facade provides async lifecycle operations, coherent world and observation state, opt-in scene/frame/planning-geometry reads, rigid-object pose and drag commands, packed RGB and particle-fluid queries, control-target discovery, joint paths, generic multi-resource physical tracks, and explicit operation status/result/cancel/release. It exposes no simulator-native handle and does not add task semantics such as pick, place, or planning.
The optional solve-only simulation.kinematics client resolves an end-effector pose
to ordered joints without executing them. It loads a verified URDF from the compiled
robot component, captures current joint state in the active generation, and runs an
installed provider off the Application loop. See the bilingual
Application kinematics guide.
Planning publication can be expensive and requires a complete collision scene. Use
fastsim.app("run.yaml", planning_reads=True) only when scene, frame, or planning
geometry APIs are needed. The default keeps planning disabled for control and sensor
runs; a planning call then fails explicitly instead of returning partial geometry.
The optional fastsim-plugin-server package exposes the same facade through
fastsim-http/1:
pip install fastsim-plugin-server
fastsim-server run.yaml --host 127.0.0.1 --port 8000
Control routes return 202 Accepted with an operation ID, so HTTP remains
asynchronous as well. Non-loopback listeners require both HTTPS and bearer-token
authentication. See the package's OpenAPI document at /api/v1/docs for the exact
transport schema.
For a persistent remote control plane, start an empty Server and authorize one trusted Project tree. The independent Web Client can then upload one standalone config or select a config below the named root and ask the Server to launch it:
fastsim-server \
--launch-root runs=/srv/fastsim-runs \
--browser-origin http://127.0.0.1:8080
Configuration model
Files and project discovery
Run and project documents can be YAML, JSON, or TOML. FastSim searches upward from
the Run file for exactly one .fastsim/project.yaml, .json, or .toml. The project
declares registry indexes, trusted resource roots, cache policy, offline mode, and
optional deployment ceilings for plugin access.
The quick-start project points at the component index shipped beside the example:
schema: fastsim-project/1
installed_packages: false
registries:
- name: quickstart
path: components/index.yaml
A larger project can discover installed component catalogs and layer additional indexes in a deterministic order:
schema: fastsim-project/1
installed_packages: true
registries:
- name: project-assets
path: assets/index.yaml
use values such as robot://franka, object://kitchen/cup,
scenario://house/heat-food, and plugin://example/controller are resolved by the
project's registries. Omitting a version selects the registry's stable release;
an exact version can be requested with @, for example
robot://franka@1.4.0. Compilation records the exact manifest and resource digests,
and a lock preserves them for a later run.
FastSim deliberately has no recursive include, $ref, or inherited configuration
language. Reusable products live in versioned registry components; a Run remains a
short description of what is selected and what is overridden.
Scenario
Every standalone Run has one Scenario. scene is required. behavior and
evaluation are optional opaque mappings: FastSim preserves them and only grants
them to plugins whose manifest requests those sections.
scenario:
scene:
environment:
use: scene://example/apartment
static: true
robots:
mobile_manipulator:
use: robot://example/mobile-manipulator
pose:
xyz_m: [0.0, 0.0, 0.0]
quat_xyzw: [0.0, 0.0, 0.0, 1.0]
scale: [1.0, 1.0, 1.0]
objects:
cup:
use: object://example/cup
pose:
xyz_m: [0.7, -0.2, 0.85]
quat_xyzw: [0.0, 0.0, 0.0, 1.0]
behavior:
program: heat-and-deliver
evaluation:
profile: household-success
environment.static defaults to true: the environment remains a collidable static
support world, while undeclared internal actors are not dynamically solved. Set it to
false when authored mechanisms inside the environment itself must remain interactive.
Explicit robots, objects, and articulations are unaffected.
The authoring schema has groups for environments, rigid objects, general articulations, robots, deformables, fluids, sensors, and lights. The current UniRoboSim runtime lowering runs enabled environment, object, articulation, robot, procedural surface-deformable, fluid, and supported sensor entities. Enabled lights and unsupported deformable forms fail closed at runtime composition; provider support alone is not sufficient.
Scene placement is physical data. A semantic relation such as
inside: refrigerator is not used as a substitute for a pose; the food and
refrigerator are authored with concrete transforms. A task plugin may interpret its
own semantic annotations in behavior, but Core does not turn them into scene state.
Instead of an inline Scenario, a Run may select one registry component:
scenario:
use: scenario://example/heat-food
fastsim config materialize expands a referenced Scenario back into portable,
runnable authoring.
Runtime rates and backend selection
backend: isaaclab
runtime:
launch_profile: headless
physics_hz: 60
control_hz: 30
sensor_hz: {}
rate_policy: exact
seed: 7
The launch profile is one of visible, headless, or headless-physics:
| Launch profile | Native window | Camera sensor rendering |
|---|---|---|
visible |
Enabled | Enabled |
headless |
Disabled | Available on demand |
headless-physics |
Disabled | Disabled |
The default is headless; existing Run files therefore keep their current no-window,
camera-capable behavior. The remaining defaults are 60 Hz physics, 30 Hz control,
exact rate policy, and seed 0.
With exact, physics frequency must be an integer multiple of every control or
sensor frequency. accumulate permits non-integer ratios.
Named sensor_hz entries are accepted by the configuration compiler, but the
current UniRoboSim runtime lowering requires this mapping to remain empty. Every
physical entity that can be scaled accepts a positive XYZ scale. Rigid objects and
static scenes may use non-uniform values; standalone articulations require uniform
values. Isaac Lab composite USD scenes may use uniform scale with embedded dynamic
entities, while non-uniform scale is admitted only when the authored result is static
and its collision representation supports it. Unsupported asset/scale combinations
fail before simulation starts instead of silently ignoring the configured value.
The author selects the backend in the Run. During unlocked inspection it can be overridden without editing the file:
fastsim config validate examples/quickstart/run.yaml --backend mujoco --json
fastsim run examples/quickstart/run.yaml --backend mujoco --launch-profile visible --duration 2 --json
--backend and --launch-profile are compilation overrides. Neither may be used
with --lock, because changing either value changes the execution plan and requires
a regenerated lock.
Backend switching is not format conversion by itself. The same Run is portable only when every selected component provides a compatible variant or resource and the provider reports the required capabilities. Native rendering, contacts, soft matter, fluids, sensor output, and controller behavior may differ between engines; FastSim does not claim numerical identity merely because the provider ID changed.
For the current physical runtime slice, a PyBullet or MuJoCo entity must resolve to
exactly one simulation resource in model/vnd.urdf+xml; an Isaac Lab entity must
resolve to exactly one simulation resource in model/vnd.usd. MuJoCo's native
provider can expose additional formats, but FastSim's current locked profile still
admits URDF only. Asset conversion is an explicit preprocessing step, not an
automatic side effect of changing backend.
An articulation component may carry a backend-specific articulation_drive
profile in the matching variant defaults. This is physical calibration owned by the
component, not a Run-level tuning knob: MuJoCo accepts per-joint position stiffness
and damping, while PyBullet accepts position and optional velocity gains. FastSim
validates the profile against the selected backend and the component's declared
stable joints, preserves it in the lock, and projects only this typed field to the
adapter. Omission preserves the adapter's previous behavior. Backend-native drive
calibration is excluded from the portable Replay compatibility digest only after
this exact validation succeeds.
Plugins: simple by default, explicit when needed
One plugin instance has five authoring blocks:
plugins:
controller:
use: plugin://example/controller
bindings:
robot: mobile_manipulator
access: all
session:
freshness:
max_observation_age_sim_s: 0.25
lease:
timeout_s: 5.0
heartbeat:
timeout_s: 2.0
config:
model_endpoint: http://model.example.test/v1/action
| Block | Owner and purpose | May be omitted? |
|---|---|---|
use |
Registry identity of the installed plugin | No |
bindings |
Maps plugin-local actor names to Scenario entities | Yes; compatible Scenario entities are derived deterministically |
access |
Narrows services, observations, and control groups | Yes; omission and all both mean the exact manifest/Run/deployment intersection |
session |
Core-enforced freshness, lease, and heartbeat timeouts | Yes; manifest defaults apply |
config |
Plugin-private settings validated by its manifest | Yes when its schema/defaults permit it |
The plugin manifest is the complete declaration of role, runtime entry point,
Scenario inputs, service dependencies, binding policy, control capability, session
defaults, and private configuration schema. Normal users therefore usually write
only use and config. Deployment owners may add a project-level
plugin_access_limits allowlist; this is a compile-time capability ceiling, not an
operating-system sandbox.
The four plugin roles are control_producer, data_consumer, extension, and
interface. Rule-based, model, teleoperation, and Agent controllers are all
ordinary control_producer plugins. Recording/replay are data consumers; debug and
external interfaces use the appropriate extension or interface role. These names do
not add behavior to Core—the corresponding distribution must be installed and
selected.
Control precedence contains plugin instance names, not package identities:
control:
default_robot: mobile_manipulator
precedence: [teleop, model]
Precedence resolves authority between overlapping resources. It does not invoke a
task or decide which action should happen next. default_robot is derived when the
Scenario has one enabled robot and may be authored for a multi-robot Run; plugin
actors are still selected by bindings, not silently redirected by that default.
Control and planning-data flow
FastSim uses one control path regardless of where commands originate:
plugin capture/query -> plugin computation -> ControlChunk
-> Control service -> ControlChunkExecutor -> UniRoboSim -> simulator
- A rule-based plugin reads its private behavior program, captures a coherent robot state and world geometry, runs IK or a planner in its own thread/process, then submits a joint trajectory.
- A model plugin reads observations, requests inference locally or remotely, and submits the next joint or end-effector-derived chunk.
- A teleoperation plugin samples a device or network stream and submits short, replaceable chunks.
- An Agent plugin uses the same scoped query and control services; it has no hidden simulator access.
The beginner-facing plugin facade is fastsim.plugins.easy.PluginClient. It is not a
second simulator EasyAPI. It combines public scoped services into a coherent planning
capture and a joint-path submission:
import asyncio
from fastsim.plugins.easy import PluginClient
async def run_rulebased_step(context, planner):
async with PluginClient(context) as client:
source = await client.capture(
actor="robot",
group="arm",
ee="tool0",
geometry=True,
timeout=5.0,
)
# The planner belongs to the plugin. CPU/GPU work must not block the
# FastSim application loop.
joint_path = await asyncio.to_thread(planner.solve, source.view)
result = await client.control.joints(
joint_path,
source=source,
dt=1.0 / 30.0,
timeout=30.0,
)
if not result.ok:
raise RuntimeError(f"control failed: {result.status}: {result.message}")
The capture contains the selected control target, ordered joint IDs, positions, velocities, units, limits, optional end-effector transform, scene/frame snapshots, and optionally a geometry catalog. Mesh/SDF resources are resolved on demand under a bounded lease. Heavy world geometry is not copied into every observation frame. Before control admission, FastSim revalidates the capture against the current world generation and declared expected motion.
Advanced rule-based planners may submit already projected physical tracks without
constructing a ControlChunk:
async def submit_projected_trajectory(client, source, planner_trajectory):
base_capability = source.projection_capabilities.resolve_projection(base_resource)
embedded_base = base_capability.embedded_base_joints[0]
projection = VirtualJointProjection(
ProjectionBinding(
virtual_base=virtual_axes,
arm_joint_names=arm_joint_names,
arm_joint_units=arm_joint_units,
base_resource=base_resource,
arm_resource=arm_resource,
embedded_base_joints=embedded_base,
),
capabilities=source.projection_capabilities,
)
tracks = projection.project(planner_trajectory)
return await client.control.physical_tracks(
(tracks.base_track, tracks.arm_track),
source=source,
timeout=30.0,
)
The capability comes from the capture's immutable, authorized target catalog. An
embedded base is available only when its component manifest declares the exact
physical x/y/yaw joints, (m, m, rad) units, controller and supported kinematic
models. physical_tracks() rejects caller-only capability claims and unadvertised
base-pose command spaces before consuming the capture.
The exact manifest and admission contract is recorded in
Embedded base-joint capabilities.
PluginControlClient.joints() waits until its chunk reaches a terminal state. A
rule-based producer gets sequential behavior by awaiting each result before
submitting the next chunk. The underlying ChunkExecutionPolicy defaults to
all_frames_applied, hold at the terminal frame, and preemption allowed. A servo
producer can submit a newer overlapping chunk through the low-level control service;
the executor terminates the displaced chunk as PREEMPTED and starts the admitted
successor at a control-tick boundary. Plugins that need stricter behavior can use the
public low-level contracts in fastsim.control.
physical_tracks() is the sequential rule-based path: concurrent calls are admitted
in FIFO order and overlapping physical resources cannot preempt the earlier call.
The simpler joints()/joints_many() path retains preemptive servo behavior.
Planner or model latency does not implicitly block physics. The plugin decides what to do while computing—pause the Run through an operator workflow, hold the previous valid target, or let the world continue under the configured idle policy. Recording plugins should use control and lifecycle events to omit or label idle intervals instead of assuming every physics tick is training data.
Public Python APIs
Application lifecycle
The stable synchronous application facade is exported from fastsim and
fastsim.api:
import fastsim
with fastsim.open("examples/quickstart/run.yaml", launch_profile="visible") as run:
running = run.start(timeout=30.0)
paused = run.pause(timeout=30.0)
stepped = run.single_step(timeout=30.0)
resumed = run.resume(timeout=30.0)
status = run.snapshot()
plugins = run.plugin_status()
run.stop(timeout=30.0)
FastSimRun also exposes prepare, reset, and idempotent close. One Run owns one
application-loop thread and one UniRoboSim runtime. Plugins must not call this facade;
they receive asynchronous scoped services in PluginRuntimeContext.
The asynchronous path API accepts the same compilation override:
import fastsim
app = fastsim.app(
"examples/quickstart/run.yaml",
launch_profile="headless-physics",
)
fastsim.open_plan(plan) and fastsim.application_plan(plan) intentionally have no
launch-profile argument. An immutable ExecutionPlan is the sole authority at that
boundary. When using a lock, author the desired profile before creating the lock;
path APIs reject a second launch_profile override.
Compilation and plans
from fastsim.config import load_project
context = load_project("examples/quickstart/run.yaml")
compiled = context.compiler().compile_file("examples/quickstart/run.yaml")
plan = compiled.execution_plan
print(plan.backend, plan.digest)
fastsim.config exports the strict codecs, project/registry/compiler contracts, and
structured diagnostics. fastsim.plan exports immutable ExecutionPlan,
ScenarioPlan, lock verification, diff/explanation, and freeze/thaw helpers.
Plugin SPI and scoped runtime services
fastsim.plugins exports the plugin factory/runtime protocols, immutable binding,
lifecycle states, installed-plugin discovery, and conformance runner. A plugin only
sees services granted in its compiled binding. Current public service keys are:
| Service key | Purpose |
|---|---|
run.info |
Run identity and immutable runtime metadata |
scenario.read |
Manifest-declared Scenario sections |
scene.query |
Entity catalogs and coherent scene state |
frame.query |
Frame catalogs, transforms, and deltas |
scene.geometry |
Planning geometry catalogs, transforms, deltas, and leased resources |
scene.command |
Revocable scene pose, drag, attach, and detach commands when the selected backend declares a matching public command capability |
planning.capture |
Coherent scene/frame/geometry/control-target capture plus revalidation |
observations |
Authorized observation snapshots and subscriptions |
fluid.emitters |
Live particle-fluid reservoir and emitter control |
fluid.audit |
Compact post-acceptance emission batches for a data_consumer recorder |
fluid.replay |
Startup-only immutable emission schedule loading for a control_producer replay plugin |
control.targets |
Authorized actors, resource groups, axes, command spaces, and controllers |
control |
Sessions, chunk submission, cancellation, and status |
artifact.read |
Bounded reads of manifest-declared plugin artifacts |
event.publish |
Bounded plugin events |
Direct backend handles, Runtime authority objects, and another plugin's private configuration are deliberately not exposed.
CLI reference
There is no fastsim config compile command. Compilation occurs inside the commands
below.
| Command | Purpose |
|---|---|
fastsim doctor [--json] |
Inspect this installation |
fastsim config validate RUN |
Resolve and validate a Run |
fastsim config expand RUN |
Print canonical effective configuration |
fastsim config materialize RUN --output PATH |
Write authoring with an inline Scenario |
fastsim config explain RUN PATH |
Explain the origin of one effective field |
fastsim config diff BEFORE AFTER |
Compare two effective configurations |
fastsim config lock RUN [--output PATH] |
Write a content-addressed lock |
fastsim config verify-lock LOCK |
Verify lock structure and every local resource digest |
fastsim config convert INPUT --to yaml|json|toml [--output PATH] |
Convert portable authoring syntax |
fastsim plugins list RUN |
List compiled plugin metadata without importing plugin code |
fastsim plugins inspect RUN INSTANCE |
Inspect one compiled instance without importing it |
fastsim plugins diagnose RUN |
Import and verify only the factories selected by the Run |
fastsim settings path|list|get|describe|set|unset|validate|export|import|reset |
Manage optional workstation preferences |
fastsim outputs root|list|stats|inspect|verify|open|remove|clean |
Manage bounded Run output artifacts |
fastsim server status [--url URL] |
Check liveness and readiness of a separate FastSim Server |
fastsim run RUN |
Compile and execute one application |
All compile-based commands accept --project PATH, repeatable --registry PATH,
--offline or --online, --cache-root PATH, --network-timeout SECONDS, --backend ID,
--launch-profile {visible,headless,headless-physics}, and --json, except that
verify-lock has no compilation overrides and convert only converts syntax. run
additionally accepts:
--lock PATH— verify and use a previously written lock;--duration SECONDS— stop after a non-negative wall-clock duration;--timeout SECONDS— positive lifecycle-operation timeout, default 30 seconds;--output-root PATH— trusted local root for output-producing plugins;--gpus IDS— comma-separated visible GPU IDs for this Run.
User settings are deliberately absent by default and are never part of a Run or lock. See user settings for precedence and the complete key catalog. See outputs CLI for FSR discovery, validation, Viewer launch and bounded cleanup.
Examples:
fastsim config convert run.yaml --to json --output run.json
fastsim plugins list run.yaml --json
fastsim plugins inspect run.yaml controller --json
fastsim plugins diagnose run.yaml --json
fastsim settings list --effective --json
fastsim outputs list --status complete --json
fastsim server status --url http://127.0.0.1:8010 --json
fastsim run run.yaml --launch-profile headless-physics --duration 60 --timeout 30 --json
fastsim run run.yaml --lock run.lock --duration 60 --timeout 30 --json
Developing plugins
Official and shared plugin packages live in the separate
FastSim-Plugins
repository. It contains packaging conventions, a minimal plugin template, producer
utilities, and conformance tooling. A plugin is a normal Python distribution with:
- a
fastsim-component/2manifest and registry index; - a factory registered in the
fastsim.pluginsentry-point group, with the exact name andmodule:attributevalue declared by that manifest; - lifecycle hooks implementing the
fastsim-plugin-runtime/1SPI; - focused tests plus FastSim conformance checks.
Start with the repository's
Adding a plugin
guide and copy its minimal template rather than creating packaging metadata by hand.
The standalone
FastSim-RuleBased-TestRepo
contains the three-level Chinese developer guide, the general Agent skill for plugin
authoring, a real installable reference plugin, and Rule-based acceptance code. It
demonstrates coherent geometry/joint capture, plugin-owned planning, and joint-chunk
submission; it is not the production Rule-based task implementation.
Development and verification
python -m pip install -e '.[dev]'
python -m pytest
python -m ruff check src tests
python -m ruff format --check src tests
python -m build
Useful focused checks while editing configuration or documentation:
python -m pytest tests/unit/config tests/unit/test_cli.py tests/architecture/test_readme.py
fastsim config validate examples/quickstart/run.yaml --json
Real-backend tests are separate from SDK-only tests and require the corresponding provider, native simulator, GPU/display when applicable, and explicit opt-in. A unit test passing does not imply that every backend capability has been exercised.
Release checklist
Before publishing an alpha revision:
- Run the full source test suite on supported Python versions.
- Build wheel and source distribution, install the wheel in a clean environment, and rerun package/CLI smoke tests.
- Run the relevant real backend gates visibly unless the gate is explicitly a headless performance test.
- Verify lock/resource integrity and plugin conformance for release candidates.
- Record exact FastSim, UniRoboSim core, provider, simulator, driver, asset, and seed versions with the evidence.
Current limitations
- This is an alpha contract, not a stable 1.0 API.
- Legacy FastSim configuration and imports are intentionally unsupported.
- FastSim Core does not include task/action semantics, a planner, model inference, teleoperation device drivers, recording/replay, TUI, Web, debug, HTTP, or MCP implementations. Each requires an installed plugin; consult that plugin's own release status rather than inferring it from Core support.
- The current application facade owns one world per process. Environment-level vectorization is not a Core feature.
- Backend selection is unified; asset support, physics fidelity, rendering, sensors, fluids, deformables, and performance remain provider capabilities.
- Current Runtime lowering accepts environment, rigid-object, articulation, robot, procedural surface-deformable, particle-fluid, and supported camera-sensor entities. Volume-deformable and light lowering, plus named sensor rates, are not implemented yet; scale constraints depend on the entity kind, asset form, and provider capability.
fastsim doctordoes not yet probe native backend health.- License metadata is currently
LicenseRef-Pending; public source availability is not a declaration of an open-source license.