embodichain.lab.sim.scene

Contents

embodichain.lab.sim.scene#

Scene services share composition, geometric layout, physical state operations and measured validation between GenSim, explicit recipes and execution hosts. They consume existing entity configurations and UIDs; Spawn and SimulationManager remain the owners of native resources and topology.

Public poses are arena-local Z-up transforms in metres. Seven-component physical poses use position followed by xyzw quaternion. Array geometry already includes asset scale and orientation. GenSim adapts its Y-up editing model at its existing boundary; shared services never load prompts or assets from generation directories.

Robot-aware workspace proposals#

The reusable workspace adapter combines Robot cache sampling with object-local grasp geometry. sample_object_poses returns proposed object poses and joint seeds; check_object_pose independently checks actual pose IK, joint limits and complete FK position/orientation residuals. It returns SceneCheckReport. These checks do not establish support, collision-free motion or task success. The legacy Task Program import converts reports to ValidationResult.

RobotSceneWorkspace

Adapt current-base workspace sampling to object-local manipulation poses.

SceneWorkspaceCandidate

An object proposal derived from one valid cached joint configuration.

class embodichain.lab.sim.scene.RobotSceneWorkspace[source]#

Adapt current-base workspace sampling to object-local manipulation poses.

Parameters:
  • robot (Robot) – Live robot with workspace sampling and IK support.

  • control_part (str) – Explicit solver/workspace control-part name.

  • position_tolerance_m (float) – Maximum FK position residual for pose acceptance.

  • orientation_tolerance_rad (float) – Maximum FK orientation residual in radians.

The initial integration supports B=1. All transforms use the local arena frame; replication offsets must not be added to Robot FK/IK or object poses.

Methods:

__init__(robot, *, control_part[, ...])

check_object_pose(pose_change, ...[, joint_seed])

Run actual pose IK and verify joint limits and full-pose FK residuals.

sample_object_poses(entity_uid, ...[, ...])

Propose object poses from valid TCP samples and local grasp geometry.

__init__(robot, *, control_part, position_tolerance_m=0.001, orientation_tolerance_rad=0.01)[source]#
check_object_pose(pose_change, object_grasp_pose, *, joint_seed=None)[source]#

Run actual pose IK and verify joint limits and full-pose FK residuals.

Parameters:
  • pose_change (ScenePoseChange) – Actual or proposed local-arena object pose.

  • object_grasp_pose (Tensor | Sequence[Sequence[float]]) – Transform from TCP into the object frame.

  • joint_seed (Sequence[float] | Tensor | None) – Optional selected-control-part seed, width solver DOF.

Return type:

SceneCheckReport

Returns:

Mandatory workspace.pose_ik evidence. Passing certifies this manipulation pose only, independently of motion and task acceptance.

sample_object_poses(entity_uid, object_grasp_pose, *, num_samples, seed, position_bounds=None, max_attempts=64)[source]#

Propose object poses from valid TCP samples and local grasp geometry.

Parameters:
  • entity_uid (str) – Physical object UID used by the scene host.

  • object_grasp_pose (Tensor | Sequence[Sequence[float]]) – Transform from TCP into the object frame.

  • num_samples (int) – Requested maximum number of returned proposals.

  • seed (int) – Nonnegative seed for an isolated device-local generator.

  • position_bounds (Sequence[Sequence[float]] | Tensor | None) – Optional object-origin arena bounds of shape (2,3).

  • max_attempts (int) – Sampling budget when filtering object-origin bounds.

Return type:

tuple[SceneWorkspaceCandidate, ...]

Returns:

Up to num_samples valid proposals. Exhausting sampling bounds returns fewer samples and does not certify other poses unreachable.

Raises:
  • ValueError – For invalid arguments or malformed workspace results.

  • Exception – Cache loading and robot configuration errors propagate.

class embodichain.lab.sim.scene.SceneWorkspaceCandidate[source]#

An object proposal derived from one valid cached joint configuration.

Parameters:
  • pose_change (ScenePoseChange) – Proposed object pose in the local arena frame.

  • joint_seed (tuple[float, ...]) – Owned joint values for the explicitly selected control part.

  • cache_index (int) – Corresponding valid workspace sample index.

  • score (float | None) – Optional cached reachability/manipulability score.

Kinematic sampling does not establish object support, collision-free motion or task success. Modified proposals require a fresh pose IK check.

Methods:

__init__(pose_change, joint_seed, ...)

__init__(pose_change, joint_seed, cache_index, score)#

Implementation module: embodichain.lab.sim.scene.workspace

RobotSceneWorkspace

Adapt current-base workspace sampling to object-local manipulation poses.

SceneWorkspaceCandidate

An object proposal derived from one valid cached joint configuration.

The implemented layout is fixed-orientation XY placement using AABB proxies. It does not establish exact mesh collision freedom, vertical support, robot reachability or task success. Physical state services currently reject worlds other than B=1 and selections other than env_ids=(0,) before writing.

Installation and runnable recipe#

Use the normal EmbodiChain installation, then run the model-free example. DexSim supplies SciPy and Trimesh; EmbodiChain requires Shapely 2 or newer:

pip install -e .
PYTHONPATH=. python scripts/tutorials/scene/tabletop_recipe.py --seed 7

The example declares a workbench, two containers built from five panels each, six parts and a keep-out region. It generates a proposal, prepares the existing manager, settles through the caller-owned physics loop, checks measured layout and restores a physical snapshot. It requires a working native simulator. Browser visualization is explicitly disabled with VisualizationCfg(backend="none"), and the renderer is "no-render". Use --output /path/to/report.json to save the measured checks. Successful execution reports layout_status="solved", stable=true, measured_xy_layout_valid=true and state_restored=true. These checks qualify this tabletop preparation; they do not establish robot reachability or task success.

GenSim integration and current scope#

GenSim’s established entry points adapt the shared services while retaining their editing conventions and lifecycle. The following capabilities already use a single shared implementation:

Capability

GenSim entry point

Shared implementation

Main horizontal support detection

TableSupportSurfaceDetector

Scene CPU support detection, also used by detect_support_region.

Group height alignment and planar placement

AssetsGroupTableAligner and AssetsGroupSupportClamp

Scene CPU group-offset and support-containment strategies.

Independent AABB separation

AssetsSupportLayoutOptimizer

Scene CPU packing strategy, also used by separate_aabbs.

Tabletop and parent-surface constraints

TableSurfaceLayoutOptimizer and ParentSurfaceLayoutOptimizer

LayoutProblem and solve_layout with the existing GenSim policy.

Physical settling and pose readback

GravitySettler

settle_scene and SceneView.pose; convergence is explicit opt-in.

See GenSim scene adapters for the adapter APIs. GenSim owns image/text understanding, model clients, asset preparation, visual orientation decisions, the editable scene graph, hierarchy traversal, Y-up conversion, diagnostics and export. Its temporary simulation remains caller-owned. SceneFragment and SceneRecipe provide a separate explicit construction path; the existing image/edit pipelines do not run through that recipe interface or use the physical snapshot-restoration workflow.

Physical mutation and restoration currently support B=1 with fixed topology. Parallel tensor geometry does not extend that runtime scope. Mesh support detection selects one main horizontal outer contour, and layout uses fixed- orientation XY AABBs. Changed orientations require measured footprints for post-settle layout checks. General room construction, batched physical writes, exact mesh collision and full solver checkpoints remain future work.

CPU strategies and tensor kernels#

Scene layout, support selection and placement retain their CPU algorithms and Shapely/Trimesh/SciPy dependencies. They call reusable Torch geometry kernels; this does not move SLSQP, polygon search or physical hosts to GPU.

Kernel batching distinguishes independent leading layouts B from the objects N within each layout. For example, (B, N, 2, 3) contains B sets of N 3D boxes. Object masks belong to that object axis; masking padding does not select simulation environments. Scene runtime services still require B=1.

See Geometry tensor kernels for tensor shape, mask, dtype and device contracts. The geometry kernel benchmark measures kernels separately from CPU strategy solving and simulator execution. Its results must be reported with the actual device, shapes and synchronization policy.

Public facade#

The facade resolves implemented services lazily. Expansion contracts have a separate scene.expansion namespace. Importing through lab.sim retains that package’s normal simulation dependency requirements.

SceneFragment

Own existing entity configurations and named local anchor transforms.

compose

Combine fragments and map an optional anchor into an arena frame.

declare_fragment

Declare a complete fragment through an existing simulation manager.

SceneRecipe

Own resolved asset configurations and an explicit planar layout recipe.

GeneratedScene

One recipe attempt with separate proposal and geometry evidence.

generate

Sample a bounded recipe and solve it without creating a simulator.

check_layout

Measure actual poses against a recipe's arena-local XY constraints.

SupportSurfaceConfig

Parameters for conservative single-level table-top detection.

SupportRegion

A horizontal support identified by an existing scene entity UID.

detect_support_region

Detect one main horizontal support from explicit arena-local geometry.

AABBLayoutConfig

Controls for support-constrained pairwise AABB separation.

GroupSupportClampConfig

Numerical controls for rigid group placement on a support region.

clamp_group

Propose one planar group translation retaining all relative positions.

separate_aabbs

Propose independent XY translations resolving projected AABB overlaps.

align_group_height

Propose one Z translation aligning the group's lowest point to support.

LayoutCfg

Budgets and metric tolerances for fixed-orientation planar layout.

PlanarRelation

Axis-aligned spatial relation in an explicitly named reference frame.

LayoutProblem

A horizontal support problem with fixed orientations and AABB geometry.

LayoutSolution

Proposed centers and measured violations; never a physical-validity claim.

solve_layout

Generate an arena-local XY proposal using the CPU SLSQP scene strategy.

SceneView

Select supported entities without creating another resource registry.

EntityState

Immutable single-arena rigid or articulated physical state in Z-up/xyzw.

SceneState

Fixed-topology physical state with an explicit environment dimension.

capture_state

Capture all physical fields without stepping or retaining live buffers.

restore_state

Restore a captured state without stepping, after complete preflight.

SceneChangeSet

Owned rigid-body pose changes with an explicit movable-entity allowlist.

SceneChangeResult

Changed entities and host-owned caches that need invalidation.

apply_changes

Apply allowed poses and clear dynamics, without advancing physics.

SceneCheck

One measured required check; missing evidence is unverified.

SceneCheckReport

Fail-closed required-check collection.

SettlingCfg

Caller-driven settling budget and optional measured convergence thresholds.

validate_scene

Evaluate explicit checks of actual state without stepping physics.

compare_states

Compare physical fields with quaternion sign equivalence.

settle_scene

Run caller-owned physics steps and measure optional velocity convergence.

embodichain.lab.sim.scene.composition#

Fragments copy existing configurations and optional anchor transforms. Composition transforms poses and namespaces UIDs without changing body scales or physics ownership. declare_fragment declares through an existing manager; the caller still invokes prepare(). Native declaration failures do not promise rollback.

SceneFragment

Own existing entity configurations and named local anchor transforms.

compose

Combine fragments and map an optional anchor into an arena frame.

declare_fragment

Declare a complete fragment through an existing simulation manager.

Owned configuration fragments and deterministic frame composition.

Classes:

SceneFragment

Own existing entity configurations and named local anchor transforms.

Functions:

compose(fragments, *[, namespace, ...])

Combine fragments and map an optional anchor into an arena frame.

declare_fragment(sim, fragment)

Declare a complete fragment through an existing simulation manager.

class embodichain.lab.sim.scene.composition.SceneFragment[source]#

Own existing entity configurations and named local anchor transforms.

Parameters:
  • entities (Sequence[RigidObjectCfg | ArticulationCfg]) – Rigid-object or articulation configurations with unique UIDs. Their existing init_local_pose takes precedence over Euler fields.

  • anchors (Mapping[str, object] | None) – Optional named 4x4 anchor-to-fragment rigid transforms.

Configurations are copied on entry and readback. The fragment owns no native resources and does not override the deployment’s physics configuration.

Methods:

__init__(entities, *[, anchors])

Attributes:

anchors

Return copied anchor names and immutable local transforms.

entities

Return owned copies of the entity configurations.

__init__(entities, *, anchors=None)[source]#
property anchors: dict[str, tuple[tuple[float, ...], ...]]#

Return copied anchor names and immutable local transforms.

property entities: tuple[RigidObjectCfg | ArticulationCfg, ...]#

Return owned copies of the entity configurations.

embodichain.lab.sim.scene.composition.compose(fragments, *, namespace='', arena_from_fragment=None, anchor=None)[source]#

Combine fragments and map an optional anchor into an arena frame.

Parameters:
  • fragments (Sequence[SceneFragment]) – Fragments already expressed in the same composition frame.

  • namespace (str) – Prefix added to entity and anchor names as prefix__name.

  • arena_from_fragment (object | None) – Desired root transform, or desired anchor transform when anchor is supplied. Defaults to identity.

  • anchor (str | None) – Existing anchor to align with arena_from_fragment.

Return type:

SceneFragment

Returns:

New fragment with transformed poses and unchanged body scales. Duplicate entity or anchor names are rejected before any simulation mutation.

embodichain.lab.sim.scene.composition.declare_fragment(sim, fragment)[source]#

Declare a complete fragment through an existing simulation manager.

Parameters:
  • sim (SimulationManager) – Caller-owned simulation manager. The caller invokes prepare().

  • fragment (SceneFragment) – Owned object and articulation configurations to declare.

Return type:

tuple[str, ...]

Returns:

Declared UIDs. Existing UIDs are rejected before declaration. Native failures propagate and do not promise rollback of earlier declarations.

embodichain.lab.sim.scene.procedural#

Recipes consume resolved assets, a versioned recipe identity and explicit geometry. generate derives candidates from seed and logical ordinal, independently of physical slots. Failed attempts return no fragment or variant. check_layout remeasures XY constraints from actual poses. Callers may supply actual_aabbs_xy_by_uid measured in arena coordinates to update proxies after rotation. Without updated geometry, changed orientation is unverified; changed support remains unverified. Moving a fixed entity fails validation.

SceneRecipe

Own resolved asset configurations and an explicit planar layout recipe.

GeneratedScene

One recipe attempt with separate proposal and geometry evidence.

generate

Sample a bounded recipe and solve it without creating a simulator.

check_layout

Measure actual poses against a recipe's arena-local XY constraints.

Seeded tabletop recipes using the same layout and proposal contracts as hosts.

Classes:

GeneratedScene

One recipe attempt with separate proposal and geometry evidence.

SceneRecipe

Own resolved asset configurations and an explicit planar layout recipe.

Functions:

check_layout(recipe, poses_by_uid, *[, cfg, ...])

Measure actual poses against a recipe's arena-local XY constraints.

generate(recipe, *[, seed, ordinal, cfg])

Sample a bounded recipe and solve it without creating a simulator.

class embodichain.lab.sim.scene.procedural.GeneratedScene[source]#

One recipe attempt with separate proposal and geometry evidence.

Failed layout attempts have no fragment or variant. Even a passed geometry report is not physical stability, reachability, or task acceptance.

Methods:

__init__(fragment, variant, layout, checks)

__init__(fragment, variant, layout, checks)#
class embodichain.lab.sim.scene.procedural.SceneRecipe[source]#

Own resolved asset configurations and an explicit planar layout recipe.

Parameters:
  • recipe_id (str) – Versioned scene/asset identity supplied by the recipe author.

  • fragment (SceneFragment) – Existing entity configurations. Asset generation is upstream.

  • layout (LayoutProblem) – Geometry-center seeds and AABBs at the fragment’s initial poses. Fixed virtual entities without configurations represent keep-out zones. All movable entities must have matching configurations.

Geometry proxies already include asset scale and initial orientation. The first implementation changes XY translation only; objects retain their authored height and rotation. A recipe supplies the physical support height rather than inferring it from a filename or semantic category.

A layout UID may represent a whole-group AABB whose center differs from the configured root origin. Generation translates that root by the solved center displacement; it does not traverse support graphs or move members absent from the layout. The caller must expand group transforms and movable permissions to every member before applying a complete group proposal.

Methods:

__init__(recipe_id, fragment, layout)

Attributes:

fragment

Return a detached copy of the original configuration fragment.

layout

Return an owned copy of the original proxy geometry and constraints.

recipe_id

Return the author-supplied versioned asset/scene identity.

__init__(recipe_id, fragment, layout)[source]#
property fragment: SceneFragment#

Return a detached copy of the original configuration fragment.

property layout: LayoutProblem#

Return an owned copy of the original proxy geometry and constraints.

property recipe_id: str#

Return the author-supplied versioned asset/scene identity.

embodichain.lab.sim.scene.procedural.check_layout(recipe, poses_by_uid, *, cfg=None, actual_aabbs_xy_by_uid=None)[source]#

Measure actual poses against a recipe’s arena-local XY constraints.

Parameters:
  • recipe (SceneRecipe) – Original asset poses and geometry-center proxy layout.

  • poses_by_uid (dict[str, object]) – Measured 4x4 arena-local transforms for every configured layout entity and its support. Virtual obstacles retain their fixed recipe positions, even when their seed positions differ.

  • cfg (LayoutCfg | None) – The same constraint clearances used during generation.

  • actual_aabbs_xy_by_uid (Mapping[str, object] | None) – Optional measured arena-frame AABB minimum and maximum XY corners, shaped (2, 2), for configured entities. These update centers and half extents and permit orientation changes of movable objects. For group proxies, supply the union of all members’ measured AABBs under the root UID. The caller owns geometry measurement and separately checks member poses, fixed members and preservation of the internal group structure. Without measurements, a root translation only shifts the authored proxy; it cannot prove that every group member followed the root.

Return type:

SceneCheckReport

Returns:

Measured layout evidence. Missing poses, changed support or orientation changes without measured AABBs are unverified. Moving a fixed entity fails even when updated AABBs are supplied. This check does not establish vertical support, physical stability or task success.

embodichain.lab.sim.scene.procedural.generate(recipe, *, seed=0, ordinal=0, cfg=None)[source]#

Sample a bounded recipe and solve it without creating a simulator.

Parameters:
  • recipe (SceneRecipe) – Resolved configurations and planar constraints.

  • seed (int) – Nonnegative proposal seed.

  • ordinal (int) – Logical candidate index, independent of slots and scheduling.

  • cfg (LayoutCfg | None) – Shared solver controls.

Return type:

GeneratedScene

Returns:

A fresh fragment and an existing-scene-compatible pose variant when solved, or a failed attempt with the original solver status and checks.

embodichain.lab.sim.scene.geometry#

Support regions identify a supporting entity and its arena-local polygon. Direct polygon inputs may include holes and disconnected components. Mesh detection currently selects one main horizontal outer contour and its inscribed optimization rectangle, preserving the legacy GenSim selection policy.

SupportSurfaceConfig

Parameters for conservative single-level table-top detection.

SupportRegion

A horizontal support identified by an existing scene entity UID.

detect_support_region

Detect one main horizontal support from explicit arena-local geometry.

Explicit Z-up support geometry for scene placement services.

Classes:

SupportRegion

A horizontal support identified by an existing scene entity UID.

SupportSurfaceConfig

Parameters for conservative single-level table-top detection.

Functions:

detect_support_region(support_uid, vertices, ...)

Detect one main horizontal support from explicit arena-local geometry.

class embodichain.lab.sim.scene.geometry.SupportRegion[source]#

A horizontal support identified by an existing scene entity UID.

Geometry is measured in metres in arena-local Z-up coordinates. Polygon holes and disconnected regions are supported by placement; mesh detection selects one largest contour, retaining openings when preserve_holes is enabled in SupportSurfaceConfig. This descriptor neither owns nor creates simulation resources.

Methods:

__init__(support_uid, top_z, support_polygon)

__init__(support_uid, top_z, support_polygon, optimization_rectangle=None, frame='arena')#
class embodichain.lab.sim.scene.geometry.SupportSurfaceConfig[source]#

Parameters for conservative single-level table-top detection.

preserve_holes retains openings in the selected mesh component and constrains the inscribed rectangle to its actual support. Its default preserves the legacy outer-contour detection contract.

Methods:

__init__([normal_z_min, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(normal_z_min=<factory>, min_surface_area_m2=<factory>, max_face_height_span_m=<factory>, height_level_tolerance_m=<factory>, preserve_holes=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

embodichain.lab.sim.scene.geometry.detect_support_region(support_uid, vertices, faces, *, config=None)[source]#

Detect one main horizontal support from explicit arena-local geometry.

Parameters:
  • support_uid (str) – UID of the existing supporting entity.

  • vertices (ndarray) – Already transformed Z-up vertices in metres, shape (N, 3).

  • faces (ndarray) – Triangle indices, shape (M, 3).

  • config (SupportSurfaceConfig | None) – Geometric support selection thresholds.

Return type:

SupportRegion

Returns:

Support descriptor in the same frame, without applying asset scale again.

embodichain.lab.sim.scene.placement#

Group clamping preserves relative positions; AABB separation moves entities independently; height alignment returns one shared Z offset. These operations only propose numeric changes. A failed bounded search is not a proof of infeasibility.

AABBLayoutConfig

Controls for support-constrained pairwise AABB separation.

GroupSupportClampConfig

Numerical controls for rigid group placement on a support region.

clamp_group

Propose one planar group translation retaining all relative positions.

separate_aabbs

Propose independent XY translations resolving projected AABB overlaps.

align_group_height

Propose one Z translation aligning the group's lowest point to support.

Pure placement proposals for explicit scene support geometry.

Classes:

AABBLayoutConfig

Controls for support-constrained pairwise AABB separation.

GroupSupportClampConfig

Numerical controls for rigid group placement on a support region.

Functions:

align_group_height(region, bounds_by_uid, *)

Propose one Z translation aligning the group's lowest point to support.

clamp_group(region, aabbs_by_uid, *[, config])

Propose one planar group translation retaining all relative positions.

separate_aabbs(region, aabbs_by_uid, *[, config])

Propose independent XY translations resolving projected AABB overlaps.

class embodichain.lab.sim.scene.placement.AABBLayoutConfig[source]#

Controls for support-constrained pairwise AABB separation.

Methods:

__init__([margin_m, aabb_clearance_m, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(margin_m=<factory>, aabb_clearance_m=<factory>, max_rounds=<factory>, split_samples=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

class embodichain.lab.sim.scene.placement.GroupSupportClampConfig[source]#

Numerical controls for rigid group placement on a support region.

Methods:

__init__([margin_m, grid_resolution_m])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(margin_m=<factory>, grid_resolution_m=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

embodichain.lab.sim.scene.placement.align_group_height(region, bounds_by_uid, *, clearance_m=0.02)[source]#

Propose one Z translation aligning the group’s lowest point to support.

Parameters:
  • region (SupportRegion) – Horizontal support descriptor in arena coordinates.

  • bounds_by_uid (dict[str, ndarray]) – Per-entity minima/maxima with shape (2, 3).

  • clearance_m (float) – Non-negative gap above support, in metres.

Return type:

float

Returns:

Shared vertical translation. Positions and orientations are unchanged.

embodichain.lab.sim.scene.placement.clamp_group(region, aabbs_by_uid, *, config=None)[source]#

Propose one planar group translation retaining all relative positions.

Parameters:
  • region (SupportRegion) – Supporting entity and allowed arena-local XY region.

  • aabbs_by_uid (dict[str, ndarray]) – Four XY corners per entity in arena coordinates.

  • config (GroupSupportClampConfig | None) – Boundary clearance and raster-search resolution.

Return type:

ndarray | None

Returns:

Shared XY offset, or None if the raster search found no placement. Failure does not establish mathematical infeasibility.

embodichain.lab.sim.scene.placement.separate_aabbs(region, aabbs_by_uid, *, config=None)[source]#

Propose independent XY translations resolving projected AABB overlaps.

Parameters:
  • region (SupportRegion) – Supporting entity and allowed arena-local XY region.

  • aabbs_by_uid (dict[str, ndarray]) – Four XY corners per entity in arena coordinates.

  • config (AABBLayoutConfig | None) – Boundary margin, pair clearance and iteration budget.

Return type:

dict[str, ndarray]

Returns:

Translation per logical entity UID; no simulation is modified.

Raises:

ValueError – Invalid geometry or no solution found within the budget.

Attention

This checks planar AABBs, not exact mesh collisions or physical stability.

embodichain.lab.sim.scene.layout#

Layout problems name fixed and movable entities, full-box bounds, displacement preferences and arena-frame planar relations. Solutions distinguish solved, no_solution, budget_exhausted and unsupported. Residuals describe the checked linear, fixed-position and AABB constraints; failed proposals must not be applied.

LayoutCfg

Budgets and metric tolerances for fixed-orientation planar layout.

PlanarRelation

Axis-aligned spatial relation in an explicitly named reference frame.

LayoutProblem

A horizontal support problem with fixed orientations and AABB geometry.

LayoutSolution

Proposed centers and measured violations; never a physical-validity claim.

solve_layout

Generate an arena-local XY proposal using the CPU SLSQP scene strategy.

UID-based horizontal layout proposals independent of simulation execution.

Classes:

LayoutCfg

Budgets and metric tolerances for fixed-orientation planar layout.

LayoutProblem

A horizontal support problem with fixed orientations and AABB geometry.

LayoutSolution

Proposed centers and measured violations; never a physical-validity claim.

PlanarRelation

Axis-aligned spatial relation in an explicitly named reference frame.

Functions:

solve_layout(problem[, cfg])

Generate an arena-local XY proposal using the CPU SLSQP scene strategy.

class embodichain.lab.sim.scene.layout.LayoutCfg[source]#

Budgets and metric tolerances for fixed-orientation planar layout.

enforce_all_clearances=False is a legacy compatibility option: only intersecting boxes are repaired, with the requested collision margin.

Methods:

__init__([relation_clearance_m, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(relation_clearance_m=<factory>, collision_margin_m=<factory>, max_slsqp_iterations=<factory>, slsqp_ftol=<factory>, max_collision_rounds=<factory>, max_added_collision_pairs=<factory>, imported_seed_weight=<factory>, feasibility_tolerance=<factory>, enforce_all_clearances=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

class embodichain.lab.sim.scene.layout.LayoutProblem[source]#

A horizontal support problem with fixed orientations and AABB geometry.

Bounds contain minimum and maximum corners for each complete AABB, not center bounds. Missing bounds mean unbounded placement (e.g. obstacles). Fixed positions override seeds. The support UID identifies the support only; it is not a reserved entity name. Callers own support height, mesh measurement, grouping and hierarchical solve order.

Methods:

__init__(support_uid, seed_xy_by_uid, ...[, ...])

__init__(support_uid, seed_xy_by_uid, half_extents_xy_by_uid, bounds_xy_by_uid, fixed_xy_by_uid=<factory>, relations=(), preferred_uids=None, frame='arena', skip_fixed_collisions=False)#
class embodichain.lab.sim.scene.layout.LayoutSolution[source]#

Proposed centers and measured violations; never a physical-validity claim.

no_solution describes the numerical search outcome, not a proof that all possible layouts are infeasible. Failure candidates must not be applied.

Methods:

__init__(status, xy_by_uid, residuals, message)

__init__(status, xy_by_uid, residuals, message, geometry='fixed_orientation_aabb')#
class embodichain.lab.sim.scene.layout.PlanarRelation[source]#

Axis-aligned spatial relation in an explicitly named reference frame.

Arena XY means left=-X, right=+X, behind=-Y and front=+Y. Unsupported frames are reported instead of silently interpreting local axes as arena.

Methods:

__init__(source_uid, relation, target_uid[, ...])

__init__(source_uid, relation, target_uid, frame='arena')#
embodichain.lab.sim.scene.layout.solve_layout(problem, cfg=None)[source]#

Generate an arena-local XY proposal using the CPU SLSQP scene strategy.

This policy does not read or change physics. Shared tensor geometry kernels support other devices independently; this search remains CPU-only.

Parameters:
Return type:

LayoutSolution

Returns:

Candidate centers and residuals. Unsupported coordinate frames return unsupported; malformed inputs raise ValueError.

embodichain.lab.sim.scene.query#

A view reads existing physical bindings and cloned poses while retaining the environment dimension. It rejects unsupported entities and changed bindings. It is not a second scene registry or a general raycast/contact-query API.

SceneView

Select supported entities without creating another resource registry.

Thin fixed-topology view over existing simulation entities.

Classes:

SceneView

Select supported entities without creating another resource registry.

class embodichain.lab.sim.scene.query.SceneView[source]#

Select supported entities without creating another resource registry.

Parameters:
  • sim (SimulationManager) – Existing prepared simulation manager.

  • env_ids (Sequence[int]) – Explicit arena selection. Only a B=1 world is supported initially.

Methods:

__init__(sim, *[, env_ids])

check_topology()

Reject changed bindings before reads or writes.

describe_entities()

Return topology and binding identities without reading dynamic state.

entities()

Return current supported physical bindings, ordered by kind and UID.

pose(uid, *[, to_matrix])

Read a cloned arena-local pose, retaining the environment dimension.

sync_render_state()

Publish direct state edits without stepping when the backend supports it.

__init__(sim, *, env_ids=(0,))[source]#
check_topology()[source]#

Reject changed bindings before reads or writes.

Return type:

None

describe_entities()[source]#

Return topology and binding identities without reading dynamic state.

Return type:

tuple[tuple[object, ...], ...]

entities()[source]#

Return current supported physical bindings, ordered by kind and UID.

Return type:

tuple[tuple[str, str, object], ...]

pose(uid, *, to_matrix=True)[source]#

Read a cloned arena-local pose, retaining the environment dimension.

Parameters:
  • uid (str) – Existing entity UID.

  • to_matrix (bool) – Return (B,4,4), otherwise (B,7) with xyzw quaternion.

Return type:

Tensor

Returns:

Independent pose tensor in meters and Z-up.

sync_render_state()[source]#

Publish direct state edits without stepping when the backend supports it.

Return type:

None

embodichain.lab.sim.scene.state#

Snapshots own immutable arena-local physical state, including velocities, joints, controller targets and efforts. Restore preflights ownership, backend, binding, topology and current joint limits before writes. By default saved joint positions or targets outside those limits are rejected. Callers may explicitly pass qpos_tolerance to allow small measured-position excursions to be clipped and then verify the actual round trip; controller targets remain strict. Restore does not step and cannot be used as a full backend checkpoint. Native failures may leave partial writes.

EntityState

Immutable single-arena rigid or articulated physical state in Z-up/xyzw.

SceneState

Fixed-topology physical state with an explicit environment dimension.

capture_state

Capture all physical fields without stepping or retaining live buffers.

restore_state

Restore a captured state without stepping, after complete preflight.

Immutable physical state services, independent of Gym and Task Program.

Classes:

EntityState

Immutable single-arena rigid or articulated physical state in Z-up/xyzw.

SceneState

Fixed-topology physical state with an explicit environment dimension.

Functions:

capture_state(view)

Capture all physical fields without stepping or retaining live buffers.

restore_state(view, snapshot, *[, ...])

Restore a captured state without stepping, after complete preflight.

class embodichain.lab.sim.scene.state.EntityState[source]#

Immutable single-arena rigid or articulated physical state in Z-up/xyzw.

Methods:

__init__(kind, uid, body_type, joint_names, ...)

__init__(kind, uid, body_type, joint_names, pose, velocity, qpos=(), qvel=(), target_qpos=(), target_qvel=(), qf=())#
class embodichain.lab.sim.scene.state.SceneState[source]#

Fixed-topology physical state with an explicit environment dimension.

Parameters:
  • physics_backend (str) – Backend identity, required for restore.

  • env_ids (tuple[int, ...]) – Arena selection corresponding to each batch.

  • batches (tuple[tuple[EntityState, ...], ...]) – Immutable numeric entity rows, one tuple per selected arena.

This is a portable physical-state representation, not a backend checkpoint. The owner and binding tokens restrict restoration to the original simulation.

Methods:

__init__(physics_backend, env_ids, batches, ...)

__init__(physics_backend, env_ids, batches, _owner, _topology)#
embodichain.lab.sim.scene.state.capture_state(view)[source]#

Capture all physical fields without stepping or retaining live buffers.

Parameters:

view (SceneView) – Fixed-topology B=1 scene selection.

Return type:

SceneState

Returns:

Immutable arena-local poses, velocities, joints, targets and efforts.

embodichain.lab.sim.scene.state.restore_state(view, snapshot, *, qpos_tolerance=0.0)[source]#

Restore a captured state without stepping, after complete preflight.

Parameters:
  • view (SceneView) – Original scene selection with unchanged bindings.

  • snapshot (SceneState) – Owned state captured from the same simulation.

  • qpos_tolerance (float) – Maximum allowed measured joint-position limit excursion. Defaults to strict rejection. An explicit tolerance permits the articulation writer to clip measured positions by that amount; controller targets remain strict. Callers must verify the actual restored state against their acceptance tolerances.

Raises:
  • ValueError – For unsupported topology, foreign state, or saved joint positions/targets outside current limits, before any writes.

  • RuntimeError – For native writes that failed; partial writes are not rolled back.

Return type:

None

embodichain.lab.sim.scene.operations#

Change sets require an explicit movable-entity allowlist. Application preflights all rigid-body changes, clears their dynamics and publishes render state. Returned invalidations must be handled by the host; observations and planner bindings cannot be reused solely because simulation time is unchanged.

SceneChangeSet

Owned rigid-body pose changes with an explicit movable-entity allowlist.

SceneChangeResult

Changed entities and host-owned caches that need invalidation.

apply_changes

Apply allowed poses and clear dynamics, without advancing physics.

Preflighted deterministic arena-local scene changes.

Classes:

SceneChangeResult

Changed entities and host-owned caches that need invalidation.

SceneChangeSet

Owned rigid-body pose changes with an explicit movable-entity allowlist.

Functions:

apply_changes(view, changes)

Apply allowed poses and clear dynamics, without advancing physics.

class embodichain.lab.sim.scene.operations.SceneChangeResult[source]#

Changed entities and host-owned caches that need invalidation.

Methods:

__init__(changed_uids[, refresh_required])

__init__(changed_uids, refresh_required=('geometry', 'planning', 'observations'))#
class embodichain.lab.sim.scene.operations.SceneChangeSet[source]#

Owned rigid-body pose changes with an explicit movable-entity allowlist.

Parameters:
  • poses (Mapping[str, tuple[tuple[float, ...], ...]]) – UID to proper 4x4 entity-to-arena transforms, in meters and Z-up.

  • movable_uids (tuple[str, ...]) – Entities the calling policy permits to move.

Methods:

__init__(poses, movable_uids)

__init__(poses, movable_uids)#
embodichain.lab.sim.scene.operations.apply_changes(view, changes)[source]#

Apply allowed poses and clear dynamics, without advancing physics.

Parameters:
  • view (SceneView) – Fixed-topology B=1 scene selection.

  • changes (SceneChangeSet) – Fully specified arena-local poses and movable permissions.

Return type:

SceneChangeResult

Returns:

Changed UIDs and required host cache invalidations; render state is synced.

Raises:
  • ValueError – For unsupported changes before any entity is modified.

  • RuntimeError – For failed native writes; earlier writes remain applied.

embodichain.lab.sim.scene.validation#

A report passes only when its nonempty required checks all pass. Fixed-step settling returns unverified stability; optional convergence mode measures velocity thresholds over consecutive samples. The caller owns stepping and advances the entire world. State comparison treats quaternion signs equivalently and retains the existing restore tolerances.

SceneCheck

One measured required check; missing evidence is unverified.

SceneCheckReport

Fail-closed required-check collection.

SettlingCfg

Caller-driven settling budget and optional measured convergence thresholds.

validate_scene

Evaluate explicit checks of actual state without stepping physics.

compare_states

Compare physical fields with quaternion sign equivalence.

settle_scene

Run caller-owned physics steps and measure optional velocity convergence.

Measured scene checks and caller-driven settling without task dependencies.

Classes:

SceneCheck

One measured required check; missing evidence is unverified.

SceneCheckReport

Fail-closed required-check collection.

SettlingCfg

Caller-driven settling budget and optional measured convergence thresholds.

Functions:

compare_states(expected, actual)

Compare physical fields with quaternion sign equivalence.

settle_scene(view, step, cfg)

Run caller-owned physics steps and measure optional velocity convergence.

validate_scene(checks)

Evaluate explicit checks of actual state without stepping physics.

class embodichain.lab.sim.scene.validation.SceneCheck[source]#

One measured required check; missing evidence is unverified.

Methods:

__init__(name, status[, message, metrics])

__init__(name, status, message='', metrics=<factory>)#
class embodichain.lab.sim.scene.validation.SceneCheckReport[source]#

Fail-closed required-check collection.

Methods:

__init__(checks)

Attributes:

passed

Return true only when nonempty evidence passes every required check.

__init__(checks)#
property passed: bool#

Return true only when nonempty evidence passes every required check.

class embodichain.lab.sim.scene.validation.SettlingCfg[source]#

Caller-driven settling budget and optional measured convergence thresholds.

Fixed steps deliberately produce unverified stability evidence. Convergence requires consecutive measurements below all velocity thresholds.

Methods:

__init__([mode, max_steps, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

__init__(mode=<factory>, max_steps=<factory>, linear_threshold=<factory>, angular_threshold=<factory>, joint_threshold=<factory>, consecutive_steps=<factory>)#
copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

embodichain.lab.sim.scene.validation.compare_states(expected, actual)[source]#

Compare physical fields with quaternion sign equivalence.

Parameters:
  • expected (SceneState) – Original physical snapshot.

  • actual (SceneState) – Snapshot measured after restoration.

Return type:

SceneCheckReport

Returns:

Restore check using absolute qpos tolerance 1e-4 and all others 1e-5.

embodichain.lab.sim.scene.validation.settle_scene(view, step, cfg)[source]#

Run caller-owned physics steps and measure optional velocity convergence.

Parameters:
  • view (SceneView) – B=1 scene; no temporary simulation is created here.

  • step (Callable[[int], None]) – Host callback advancing the supplied number of physics substeps.

  • cfg (SettlingCfg) – Fixed-step or convergence policy. This advances the whole world.

Return type:

SceneCheckReport

Returns:

Stability evidence, failed on timeout and unverified for fixed steps.

embodichain.lab.sim.scene.validation.validate_scene(checks)[source]#

Evaluate explicit checks of actual state without stepping physics.

Parameters:

checks (Iterable[SceneCheck | Callable[[], SceneCheck]]) – Measured results or zero-argument measurement callbacks.

Return type:

SceneCheckReport

Returns:

Required evidence; an empty report cannot accept a candidate.