Scenes & Viewer Handles
simview.scene is the main authoring API: SimulationScene builds a model
incrementally (terrain, bodies, static objects) and accumulates states, then
saves/loads JSON or launches a viewer. ViewerHandle is the non-blocking handle
returned by SimulationScene.show().
simview.scene
SimulationScene
SimulationScene(
batch_size: int,
scalar_names: list[str],
dt: float,
collapse: bool = False,
terrain: SimViewTerrain | None = None,
bodies: dict[str, SimViewBody] | None = None,
static_objects: dict[str, SimViewStaticObject]
| None = None,
batch_names: list[str] | None = None,
metadata: dict[str, Any] | None = None,
)
Initializes the simulation data container. Manages the SimViewModel and the time-series states.
metadata is free-form, JSON-serializable run provenance (e.g. engine
name, checkpoint path, git commit, CLI args) with no meaning to the
viewer -- it's carried through to simview info and the browser so a
saved scene stays self-describing. Can also be set/updated later via
self.model.metadata.
add_body_object
Adds a pre-configured SimViewBody object to the model. See
create_body for the meaning of body.parent/body.local_transform.
add_state
add_state(
time: float,
body_states: list[SimViewBodyState],
scalar_values: dict[str, Tensor | ndarray | list]
| None = None,
) -> None
Adds a new state (snapshot in time) to the simulation data.
add_static_object_instance
Adds a pre-configured SimViewStaticObject to the model.
add_terrain_object
Adds a pre-configured SimViewTerrain object to the model.
add_trajectory
add_trajectory(
times,
trajectories: list[BodyTrajectory],
scalar_values: dict[str, Tensor | ndarray | list]
| None = None,
binary: bool = True,
) -> None
Append an entire time-series in one call.
Equivalent to looping add_state over T frames, but converts each
body's pose/vector tensors once (vectorised) instead of per frame, which
is dramatically faster for long trajectories. With binary=True the
numeric per-body fields (bodyTransform and any provided vectors) are
packed as float32 __b64__ blobs, shrinking the output file and the
parse cost; the viewer and :func:merge_simulation_files decode these
transparently. Set binary=False to emit plain JSON lists. A body's
contacts (if provided on its :class:BodyTrajectory) are ragged and
always emitted as plain JSON per frame, using the same encoding as
SimViewBodyState / add_state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
times
|
sequence of length |
required | |
trajectories
|
list[BodyTrajectory]
|
one :class: |
required |
scalar_values
|
dict[str, Tensor | ndarray | list] | None
|
for a scene with |
None
|
create_body
create_body(
body_name: str,
shape_type: BodyShapeType,
available_attributes: list[
OptionalBodyStateAttribute | str
]
| None = None,
parent: str | None = None,
local_transform: LocalTransformLike | None = None,
**kwargs,
) -> None
Creates and adds a dynamic body to the simulation model.
parent/local_transform attach this body to another body already
in the model, instead of it moving in world space:
- Rigid attachment (e.g. a wheel bolted to a chassis): pass both
parentandlocal_transform(a constant[x, y, z, w, qx, qy, qz]offset). Never calladd_state/add_trajectoryfor this body afterwards -- its world pose is derived by the viewer every frame from the parent's current pose plus this fixed offset. - Articulated attachment (e.g. an arm joint): pass only
parent. Keep supplying this body's pose every frame viaadd_state/add_trajectoryas usual -- it's just interpreted as local to the parent's current-frame pose instead of world space.
create_pointcloud
create_pointcloud(
body_name: str,
points: Tensor,
color: Tensor | None = None,
embedding: Tensor | None = None,
**kwargs,
) -> None
Creates and adds a pointcloud body to the simulation model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
body_name
|
str
|
Unique name for this body. |
required |
points
|
Tensor
|
(N, 3) point positions. |
required |
color
|
Tensor | None
|
Optional (N, 3) per-point RGB in [0, 1] for static vertex-colored rendering. |
None
|
embedding
|
Tensor | None
|
Optional (N, K) per-point feature vector (e.g. a reduced-dim PCA projection) enabling the viewer's click-to-similarity color mode. |
None
|
create_static_object_batched
create_static_object_batched(
name: str,
shape_type: BodyShapeType,
shapes_kwargs: list[dict[str, Any]],
) -> None
Creates and adds a batched static object to the simulation model.
create_static_object_singleton
Creates and adds a singleton static object to the simulation model.
create_terrain
create_terrain(
heightmap: Tensor,
normals: Tensor | None = None,
x_lim: tuple[float, float] | None = None,
y_lim: tuple[float, float] | None = None,
grid_res: float | None = None,
properties: dict[str, Tensor] | None = None,
embedding_map: Tensor | None = None,
) -> None
Adds terrain to the simulation model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
heightmap
|
Tensor
|
2D or 3D tensor of terrain heights. |
required |
normals
|
Tensor | None
|
3D or 4D tensor of terrain normals. If None, normals are automatically computed from the heightmap gradients. |
None
|
x_lim
|
tuple[float, float] | None
|
(min, max) coordinates for the X axis. |
None
|
y_lim
|
tuple[float, float] | None
|
(min, max) coordinates for the Y axis. |
None
|
grid_res
|
float | None
|
Grid resolution. If x_lim and y_lim are omitted, they will be automatically inferred assuming the grid is centered at 0. |
None
|
properties
|
dict[str, Tensor] | None
|
Optional arbitrary named
per-cell scalar maps (2D or 3D, like |
None
|
embedding_map
|
Tensor | None
|
Optional per-cell K-wide feature map
(3D channels-first |
None
|
from_dict
classmethod
Reconstruct a SimulationScene from the dict produced by save/to_json
(i.e. the parsed {"model": ..., "states": ...} document).
Binary __b64__-encoded fields inside states (e.g. from
add_trajectory(binary=True)) are left as-is, matching the on-disk
wire format, so a subsequent save() reproduces the same bytes for
those fields without a decode/re-encode round trip.
load
classmethod
Load a SimulationScene previously written by save.
Transparently reads gzip-compressed files (detected by magic bytes,
regardless of extension) as well as plain JSON. Enables round-tripping
from Python: SimulationScene.load(p).save(p2).
save
Exports the complete simulation data (model and states) to a JSON file. Uses a streaming approach to reduce memory spikes for large simulations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filepath
|
str | Path
|
Destination path. If it ends in |
required |
compress
|
bool
|
If True, gzip-compress the output (useful for large
simulations, which can reach 100+ MB as plain JSON). If
|
False
|
show
show(
host: str = "127.0.0.1",
preferred_port: int = 5420,
open_browser: bool = False,
) -> ViewerHandle
Serve a snapshot of this scene on a background thread and return
immediately, instead of blocking like SimViewLauncher/SimViewServer.run.
Intended for Jupyter notebooks and scripts that want to keep running
(or keep the cell interactive) while the viewer is up: the returned
ViewerHandle renders inline via _repr_html_ when it's a cell's
result, and its stop() (or exiting it as a context manager) shuts
the server down. The scene itself is left untouched -- unlike
SimViewLauncher, show doesn't clear self.states/self.model, so
the same scene can still be save()d or shown again afterwards.
Multiple concurrent show() calls (on the same or different scenes)
are fine -- each gets its own server thread and port (via
find_free_port).
ViewerHandle
A running, non-blocking SimView server for a snapshot of a scene.
Returned by SimulationScene.show. Holds the background server thread
started for that snapshot; stop() (also called automatically on
context-manager exit) shuts it down. _repr_html_ lets Jupyter render the
viewer inline in an iframe just by evaluating the handle in a cell.