Bring your own robot
The reusable cloud workflow is publish, inspect, reference, run. You upload a self-contained USD or URDF package once; Simulo validates it and assigns an immutable catalog version that any later job can pin.
1. Prepare the package
Section titled “1. Prepare the package”Keep the entry and every referenced mesh, texture, or USD layer under one package root. The client never collects a dependency from outside that root.
my-arm/├── robot.usda├── geometry.usda└── textures/ └── arm.pngmy-arm/├── robot.urdf└── meshes/ ├── base.obj └── link.objURDF mesh references using package:// are normalized to portable,
package-relative paths before upload. The published source package therefore
contains normalized references rather than preserving that URI spelling byte
for byte.
If the directory contains more than one possible entry, name it explicitly
with --entry.
2. Publish and wait for validation
Section titled “2. Publish and wait for validation”simulo asset publish ./my-arm --kind robot --name my-arm --entry robot.usdasimulo asset publish ./my-arm --kind robot --name my-arm --entry robot.urdfURDF robots default to a fixed base. Pass --base floating for a mobile
or legged robot. Use --scale 0.001 only when the source units genuinely
need that global conversion.
The command packages the dependency closure, uploads it, and follows the
validation job unless you pass --detach. A version number is assigned only
after the package passes. To exercise the same cloud validator without
publishing a version first:
simulo asset validate ./my-arm --kind robot --entry robot.urdf3. Inspect what the platform measured
Section titled “3. Inspect what the platform measured”simulo asset inspect robot/my-arm:v1simulo asset inspect robot/my-arm:v1 --report my-arm.validation.jsonCheck the resolved entry, joint names, degree-of-freedom count, collision shapes, units, mass, and settle/actuation outcomes before adapting the task. See Asset Validation for report semantics.
4. Use the pinned version in your app
Section titled “4. Use the pinned version in your app”Define the handle at module level so discovery sees it while importing the app:
import simulo
my_arm = simulo.Asset.from_registry("robot/my-arm:v1")
class ReachTask(simulo.Task): observation_dim = 12 action_dim = 6
def build(self, scene: simulo.Scene) -> None: scene.add(simulo.Terrain.plane(name="ground"), at="/", per_environment=False) self.robot = simulo.Robot(asset=my_arm, initial_pose=simulo.Pose.identity()) scene.add(self.robot, at="/World/Robot")Nothing loads on your machine: Asset.from_registry(...) is a lightweight
handle during discovery. The submitted job resolves and mounts the validated
package in execution.
Run with the asset-integrity gates enabled:
simulo run app.py --frozen --strict-assets--frozen proves every asset ref includes :vN; --strict-assets refuses
deprecated or runtime-unvalidated versions instead of accepting their warning.
5. Adapt the task to the robot
Section titled “5. Adapt the task to the robot”Replacing the model is necessary but not sufficient. A cartpole task is written around cartpole’s joints and dimensions. Update at least:
on_start— resolve your robot’s real joint names withself.robot.find_joints(...).observation_dimandaction_dim— match the values your task produces and consumes.get_observations,apply_actions,get_dones, andreset_idx— use the new joints, limits, and termination rules.- Reward logic — score the behavior you actually want from this embodiment.
The facts from asset inspect are the reliable starting point; do not copy a
DOF count from an unrelated example.
Browse before publishing
Section titled “Browse before publishing”If a suitable robot already exists in the global catalog, use its explicit global ref instead:
simulo asset list --global --kind robotcartpole = simulo.Asset.from_registry("simulo/robot/cartpole:v1")For catalog discovery and lifecycle commands, see Browse & manage assets.