Volumes & Assets
A job reads its inputs and writes its files through three kinds of handle:
| Writable | What it names | Use it for | |
|---|---|---|---|
Volume |
Yes | A named folder on the GPU machine | Scratch files a job writes while it runs. |
Asset |
No | A catalog reference, pinned to one version | Validated robots, worlds, and props. |
AssetSource |
No | A file path, with no catalog identity | A USD or URDF file that isn’t published. |
What a training job produces does not go in any of these. Its checkpoints are saved to its policy automatically; see Policies and checkpoints.
Volumes: writable folders on the GPU machine
Section titled “Volumes: writable folders on the GPU machine”Declare a volume, mount it on the app, and write to its path inside the job:
scratch = simulo.Volume.from_name("scratch", create_if_missing=True)
app = simulo.App("my-app", mounts={"scratch": scratch})
@app.job(type="train", system=simulo.SystemType.TIER_1)def train() -> dict: with open(f"{scratch.path}/notes.txt", "w") as f: ...Constructing a Volume only declares it. scratch.path exists only inside a
running job; reading it while simulo run imports your file raises an error
instead of pretending the folder exists on your machine.
A volume lives on the disk of the GPU machine that runs the job. It belongs to your organization, and a later job from your organization sees its contents only if it runs on that same machine. GPU machines are started and replaced as demand changes, so a volume’s contents can disappear between jobs. Treat a volume as scratch space for one run, and keep anything you need later in one of the ways below.
To keep a file after the job ends:
- register it with
simulo.save_output. When the job completes, Simulo uploads it andsimulo outputscan download it. A job that fails, is cancelled, or times out does not deliver these files. See Retrieve job outputs. - or return small values in the job’s result dict.
An MCAP file a job writes into a mounted volume during the run is uploaded as one of the job’s recordings; see Recordings & live view.
Assets: versioned, read-only inputs
Section titled “Assets: versioned, read-only inputs”simulo.Asset.from_registry(ref) declares a catalog input:
cartpole = simulo.Asset.from_registry("simulo/robot/cartpole:v1")my_arm = simulo.Asset.from_registry("robot/my-arm:v3")A reference is [publisher/]kind/name[:vN]. With no publisher it names your
organization’s catalog; simulo/ names the Simulo catalog. Leaving out :vN
picks the latest published version at submit, and the job records that exact
version.
Pass a robot handle straight to Robot:
self.robot = simulo.Robot(asset=my_arm, initial_pose=simulo.Pose.identity())Create handles at module level so simulo run sees them and pins them. On the
GPU machine the handle becomes a read-only folder holding the exact,
digest-checked package. Its .path works only inside a running job.
Asset catalogs & version pinning covers
publishing, the two catalogs, --frozen, --strict-assets, and deleting.
Asset or AssetSource?
Section titled “Asset or AssetSource?”simulo.AssetSource is a model file named by its path, with no catalog
identity, no version, and no validation:
source = simulo.AssetSource.usd("/models/gripper.usd") # a simulo.USDAssetarm = simulo.AssetSource.urdf("/models/arm.urdf") # a simulo.URDFAsset
source.path # "/models/gripper.usd"simulo.Asset.from_registry(ref) |
simulo.AssetSource.usd(path) |
|
|---|---|---|
| What it names | A catalog entry, by reference | A file, by path |
| Version pinned with the job | Yes | No |
| Validated when published | Yes | No |
| Checks the kind (robot or world) | Yes | No |
Reading .path |
Only inside a running job | Always; it is the path you passed |
Use Asset.from_registry(...) in job code. It pins a version, records
the exact input with the job, and refuses a world where a robot belongs
instead of loading the wrong thing.
Use AssetSource when you need the model-file value itself: a type
annotation on a helper, an isinstance check against simulo.USDAsset or
simulo.URDFAsset, or plain library code with no job around it.
If you have a file and want it versioned and reproducible, publish it and use
Asset.from_registry(...).
Asset.usd() and AssetSource.usd()
Section titled “Asset.usd() and AssetSource.usd()”simulo.Asset also has .usd(path) and .urdf(path). Inside a running job
they return the same simulo.USDAsset or simulo.URDFAsset that
AssetSource does. The difference is only on your machine during
simulo run, where Asset.usd() returns an inert placeholder so the import
stays fast. That is why it is typed as returning Any, while
AssetSource.usd() returns a simulo.USDAsset everywhere. Neither pins or
validates the file.