The world state file
A world's scene definition: placed objects, planner configuration, and its sidecar files.
A world is a folder at worlds/<id>/. The required file is world_state.json; worlds built from a camera scan carry sidecar files beside it.
You author worlds in the World Builder, not by hand. This page is for reading the file and understanding what the fields mean.
Hand-authoring an entry in
objectsis the one edit to avoid. The loader reads most of an object's fields by direct key access, so an entry missing any one of them fails with aKeyErrorrather than a helpful message. Add objects through the World Builder and edit the result.
Minimal example
A fresh world from zeon new world my_world:
{
"version": "2.0",
"config": {
"tensor_device": "cuda",
"enable_blox": false,
"create_workspace_boundaries": false
},
"objects": {},
"metadata": {
"name": "my_world",
"description": "",
"source": "manual"
}
}Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
version | string | yes | World schema version. See the note below; "2.0" and "3.0" are both in circulation. |
config | object | yes | Planner and simulator configuration. |
objects | map | yes | Objects placed in the scene, keyed by instance name. |
metadata | object | no | Display metadata. Read by the world list to label the world; the scene loader ignores it. |
Two schema versions are in circulation. Worlds created by
zeon new world, and older worlds generally, carry"2.0". A World Builder save writes"3.0". The two differ in how object geometry is serialized. See the note undergeometry. Loading a world during normal use does not check the version, so both work; you mainly need to know which shape you are looking at when reading a file.
config
configSet by the World Builder. You rarely edit these by hand.
| Field | Type | Description |
|---|---|---|
tensor_device | string | Where the planner runs its computations. "cuda" on GPU-equipped installs. |
collision_cache | object | Planner cache sizing, as {"obb": 20, "mesh": 10}. |
enable_blox | boolean | Whether the world carries a voxelized geometry layer, typically from a camera scan. |
blox_layer_name | string | Name of the voxel layer. "world" in practice. |
blox_voxel_size | float | Voxel size in metres. |
blox_integrator | string | Voxel integration algorithm. "tsdf" in practice. |
create_workspace_boundaries | boolean | Whether the planner treats the workspace AABB as invisible walls. |
workspace_aabb_min | [x, y, z] | Workspace AABB minimum corner. |
workspace_aabb_max | [x, y, z] | Workspace AABB maximum corner. |
map_saved | boolean | true once a voxel grid has been persisted to .npz. |
mesh_saved | boolean | true if a visualization mesh has been persisted to blox_mesh.ply. |
tsdf_saved | boolean | true once the block-sparse TSDF has been persisted to blox_tsdf.npz. Written by newer exports; the shipped 2.0 worlds omit it. |
voxel_count | integer | Number of occupied voxels in the saved grid. |
voxel_export_region | object | The exported region, as {"aabb_min": [...], "aabb_max": [...]}. |
include_objects_in_voxels | boolean | Whether placed objects were baked into the voxel grid. |
voxel_spec | object | null | Voxel reconstruction spec. null when unused. |
objects
objectsA map of the objects placed in the scene. Each key is the instance name. Objects the World Builder places are keyed <type>_<uuid>, so the same object type can appear several times in one scene. Fixtures added by hand tend to keep plain names like table.
A placed project object. The pose values are shortened for readability. Real files carry full double precision, and the instance key carries a full UUID:
"fixture_plate_9e3b532c-…": {
"geometry": {
"type": "articulated",
"yaml_path": "objects/fixture_plate/fixture_plate.object_model.yaml"
},
"mount": {
"type": "FixedMount",
"world_P_body_fixed": {
"xyz": [0.605, 0.403, 0.0],
"wxyz": [1.0, 0.0, 0.0, 0.0],
"stamp_s": null
}
},
"enabled": true,
"filter_from_depth": true,
"collide_in_planner": true,
"attachment_spec": {
"fit_type": "voxel_volume_sample_surface",
"surface_sphere_radius": 0.001,
"voxelize_method": "ray"
},
"metadata": {
"name": "fixture_plate",
"location": "fixture_plate",
"type": "fixture_plate"
},
"joint_config": {}
}Object fields
| Field | Required | Description |
|---|---|---|
geometry | yes | What this object is (see below). |
mount | yes | How it is anchored. |
enabled | yes | false leaves the object defined but out of the scene. |
filter_from_depth | yes | true excludes the object from depth-based perception, and is used for objects whose pose is already known. |
collide_in_planner | yes | true makes the planner avoid it. |
attachment_spec | yes | How the object is fitted when picked up. |
metadata | yes | Free-form per-object metadata. May be {}. |
joint_config | for articulated | Joint name → value. Present on articulated geometry. |
Every field above except joint_config is read by direct key access. Omitting one is a load error, not a defaulted value.
geometry
geometryTwo shapes appear, distinguished by the type tag:
A project object, from your objects/ folder or the mesh database:
{ "type": "articulated", "yaml_path": "objects/fixture_plate/fixture_plate.object_model.yaml" }The yaml_path points at the object's object_model.yaml. It is stored in this portable, project-relative form on purpose; the absolute path is worked out at load time and never written back to the file, so a world stays valid on another machine. Older worlds instead have an absolute container path baked in, like /app/storage/mesh_database/<name>/<name>.object_model.yaml. Both resolve.
A primitive, a synthetic shape used for tables, filters, and workspace walls:
{ "type": "Cuboid", "name": "x_min", "pose": { "xyz": [-1.36, -0.36, 0.35], "wxyz": [1, 0, 0, 0], "stamp_s": null }, "dims": [0.02, 2.9, 1.7] }The registered primitive types are Cuboid, Sphere, Cylinder, Capsule, Mesh, and VoxelGrid. An unrecognized type is a load error.
This flat,
type-tagged form is the"3.0"shape. A"2.0"world serializes its primitives the older way, as{"class": "Cuboid", "kwargs": {...}}. If you open an existing world and seeclass/kwargs, that is what you are looking at.
mount
mountFixedMount is the only mount type a saved world may contain. Any other value raises an error on load. It carries world_P_body_fixed with three keys: xyz (metres), wxyz (quaternion, scalar first), and stamp_s (null in every saved world).
Workspace boundaries
When create_workspace_boundaries is on, the World Builder adds six primitives named x_min, x_max, y_min, y_max, z_min, and z_max, invisible cuboids at the AABB faces. Those six names are reserved and special-cased by the loader, which can skip them on request. Don't edit them by hand; they're regenerated when the AABB changes.
metadata
metadata| Field | Type | Description |
|---|---|---|
name | string | Display name. Usually matches the folder name. |
description | string | Free text. |
created_at | string (ISO 8601) | When the world was created. |
source | string | "manual" or "execution". |
source is shown in the world list as Created manually or From execution.
Sidecar files
A world built from a camera scan carries binary sidecars beside world_state.json:
| File | Purpose |
|---|---|
blox_voxels.npz | The voxel grid from the scan. Loaded when enable_blox is true. |
blox_tsdf.npz | A block-sparse TSDF snapshot. Preferred over blox_voxels.npz when present, because it lets depth integration resume rather than start over. |
blox_mesh.ply | A visualization mesh. Written only when the export asks for one; mesh_saved records whether it exists. |
nvblox_map.bin | NVBlox map data. |
One more sidecar appears on any world, scanned or not:
| File | Purpose |
|---|---|
live_state.yaml | A text file holding what genuinely changes at run time and so does not belong in a frozen scene export: per-object calibration offsets and the tipbox tip pointer, keyed by object UUID. |
Commit all of them like any other file. Don't edit the binaries: they are written by the platform and have no hand-editable form.
live_state.yaml is the exception: it is meant to be hand-edited during calibration. A YAML typo there fails with a clear error naming the file rather than an opaque parser error inside a skill.
When the file is wrong
Malformed JSON does not surface as a clean "this world is broken" message. The world list swallows the parse error and still shows the world, labelled with a title-cased version of the folder name (my_world appears as "My World") and an object count of 0. The raw folder name survives as the world's id. The failure surfaces when you load it: the path resolver logs a warning and hands the file to the loader, which fails on the same malformed JSON.
A referenced object that doesn't exist is more forgiving: the path resolver catches per-object failures and logs a warning, so one missing mesh doesn't fail the whole world load. The world opens without that object.
See also
Updated 3 days ago