Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
61001a7
Add a new feature: gen_sim/scene_engine
MuziWong Jul 28, 2026
ad708e8
Using vhacd by default in the simulation environment
MuziWong Jul 28, 2026
b664562
RAN black
MuziWong Jul 29, 2026
fe6c1af
style(geometry-generation): fix CI formatting
MuziWong Jul 29, 2026
4c0cfc7
Updated geometry generation client
MuziWong Jul 30, 2026
a67ac77
Modified the gym export to scene export
MuziWong Jul 30, 2026
c630f16
Make the 2D AABB optimization more robust
MuziWong Jul 30, 2026
8ae888d
Add optional --config in cli
MuziWong Jul 30, 2026
c38c0fc
Register scene-engine and preview-scene in embodichain.__main__.COMMANDS
MuziWong Jul 30, 2026
b86c3b5
Fixed with the suggestion from Copilot
MuziWong Jul 30, 2026
c99182c
Added __init__.py and ran black.
MuziWong Jul 30, 2026
e7f3fbe
Merge branch 'main' of github.com:DexForce/EmbodiChain into muzi/feat…
XuanchaoPENG Jul 31, 2026
79442f5
Fix import bug
MuziWong Jul 31, 2026
a0f6797
Add Viser support
XuanchaoPENG Jul 31, 2026
db438e7
Merge branch 'muzi/feat_scene_engine' of github.com:DexForce/EmbodiCh…
XuanchaoPENG Jul 31, 2026
d1b363a
test(scene_engine): add unit coverage
MuziWong Jul 31, 2026
23947e5
Add test for the newly-modified scene-preview
MuziWong Jul 31, 2026
b0774a4
docs(scene_engine): add usage documentation
MuziWong Jul 31, 2026
ede8172
Change logger
MuziWong Jul 31, 2026
73e285e
Correct the table id verification comment, make it more clear
MuziWong Jul 31, 2026
244ab1b
Delete a bad comment line in scene_segmentation_utils.py
MuziWong Jul 31, 2026
930af9b
Align the doc with the scene_engine_config
MuziWong Jul 31, 2026
05f8a1a
Align the scene_engine config setup with the simready_pipeline
MuziWong Jul 31, 2026
d0d39ca
fix(scene_engine): validate geometry output object IDs
MuziWong Jul 31, 2026
114734d
fix(scene_engine): restrict preview mesh paths
MuziWong Jul 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/source/features/generative_sim/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ Generative Simulation collects EmbodiChain features for generating simulation-re
:maxdepth: 2

SimReady Asset Pipeline <simready_pipeline.md>
Scene Engine <scene_engine.md>
156 changes: 156 additions & 0 deletions docs/source/features/generative_sim/scene_engine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Scene Engine

The Scene Engine converts one tabletop-scene image into a scene-only export. It
identifies a table and visible assets, generates their meshes, refines their
layout, settles them under gravity, and writes an EmbodiChain scene export.

## Quick Start

Install EmbodiChain with the generative-simulation dependencies. See
[Installation (gensim extra)](../../quick_start/install.md#optional-generative-simulation-gensim).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] The gensim extra currently declares only bpy and pyrender, while Scene Engine directly imports requests, Pillow, SciPy, trimesh, Open3D, and matplotlib. A clean embodichain[gensim] installation therefore relies on undeclared transitive dependencies. Please declare these dependencies directly, possibly under a dedicated scene-engine extra, and exercise that installation path in CI.


Prepare a Scene Engine JSON config, then run:

```bash
embodichain scene-engine \
--image /path/to/scene.png \
--output_root /path/to/scene_output \
--config /path/to/scene_engine_config.json
```

Preview the result:

```bash
embodichain preview-scene --output_root /path/to/scene_output
```

Use `--viser` for a browser-based preview, or `--headless` to validate the
export without opening a window:

```bash
embodichain preview-scene \
--output_root /path/to/scene_output \
--viser
```

The equivalent module commands are:

```bash
python -m embodichain.gen_sim.scene_engine.cli.start --help
python -m embodichain.gen_sim.scene_engine.cli.preview --help
```

## Requirements and Configuration

The input must be one `.jpg`, `.jpeg`, or `.png` image with one main table and
visible, separate tabletop assets. The pipeline requires an OpenAI-compatible
VLM, an image-segmentation service, and a geometry-generation service.

Without `--config`, Scene Engine reads the official template at
`embodichain/gen_sim/scene_engine/configs/scene_engine_config.json`. The
checked-in template intentionally has empty service URLs and credentials.
Provide a complete user-owned JSON file with `--config`, or provide the
settings through environment variables. `--config` is an optional complete
JSON override; do not add credentials to the checked-in template.

Keep credentials outside version control. `OPENAI_API_KEY`, `OPENAI_MODEL`,
`OPENAI_BASE_URL`, and `OPENAI_MAX_ATTEMPTS` override the corresponding LLM
settings. For example:

```bash
export OPENAI_API_KEY="<api-key>"
export OPENAI_MODEL="<vision-model>"
export OPENAI_BASE_URL="https://example.com/v1"
export OPENAI_MAX_ATTEMPTS="3"

export SCENE_ENGINE_IMAGE_SEGMENTATION_BASE_URL="http://segmentation-host:port"
export SCENE_ENGINE_IMAGE_SEGMENTATION_PATH="/predict"
export SCENE_ENGINE_GEOMETRY_GENERATION_BASE_URL="http://geometry-host:port"
export SCENE_ENGINE_GEOMETRY_GENERATION_PATH="/generate_multiple_objects"
```

`SCENE_ENGINE_IMAGE_SEGMENTATION_TIMEOUT_S`,
`SCENE_ENGINE_IMAGE_SEGMENTATION_MAX_ATTEMPTS`,
`SCENE_ENGINE_IMAGE_SEGMENTATION_HEALTH_PATH`,
`SCENE_ENGINE_GEOMETRY_GENERATION_TIMEOUT_S`,
`SCENE_ENGINE_GEOMETRY_GENERATION_MAX_ATTEMPTS`, and
`SCENE_ENGINE_GEOMETRY_GENERATION_HEALTH_PATH` override the remaining service
fields when needed.

```json
{
"llm": {
"openai_compatible": {
"api_key": "<api-key>",
"model": "<vision-model>",
"base_url": "https://example.com/v1",
"default_query": {},
"max_attempts": 3
}
},
"image_segmentation": {
"base_url": "http://segmentation-host:port",
"timeout_s": 120,
"max_attempts": 3,
"health_path": "/health",
"segment_single_object_path": "/predict"
},
"geometry_generation": {
"base_url": "http://geometry-host:port",
"timeout_s": 600,
"max_attempts": 3,
"health_path": "/health",
"generate_objects_path": "/generate_multiple_objects"
}
}
```

The endpoint paths above match the packaged template, but remain
service-specific placeholders: change them when the deployed services expose
different routes. Geometry uses one ordered multi-object request for all masks;
a single-object scene uses the same request with one mask.

## Output

Each run refreshes the intermediate stage directories and writes the final
portable export:

```text
<output_root>/
|-- scene_understanding/
|-- scene_segmentation/
|-- scene_generation/
`-- scene_export/
|-- scene_config.json
`-- mesh_assets/
|-- <table-id>/<table-id>.glb
`-- <asset-id>/<asset-id>.glb
```

`scene_export/scene_config.json` has format
`"embodichain.scene-export/v1"`. It contains the table under `background` and
the settled assets under `rigid_object`; mesh paths are relative to
`scene_export/`.

The internal scene layout is y-up. The exporter copies GLBs unchanged and
converts final positions and rotations to the simulator's z-up convention.
This is a scene-only export, not a `run-env` configuration: it does not define
a robot or task.

## Python API

Use `generate_scene_from_image` to run the full pipeline:

```python
from embodichain.gen_sim.scene_engine.pipeline.generate import (
generate_scene_from_image,
)

scene = generate_scene_from_image(
image_path="scene.png",
output_root="scene_output",
llm_config_path="scene_engine_config.json",
image_segmentation_config_path="scene_engine_config.json",
geometry_generation_config_path="scene_engine_config.json",
)
```
56 changes: 56 additions & 0 deletions docs/source/guides/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,62 @@ The generated output contains the canonical source mesh under ``asset_source/``,

---

## Scene Engine

Generate a table-top scene from one image. Configure the VLM,
image-segmentation, and geometry-generation services with either a Scene Engine
JSON config or the documented environment variables.

```bash
embodichain scene-engine \
--image /path/to/scene.png \
--output_root /path/to/scene_output \
--config /path/to/scene_engine_config.json
```

The generated scene-only export is written to
``<output_root>/scene_export/scene_config.json``. It is intended for
``preview-scene`` and downstream scene consumers; it is not a complete
``run-env`` configuration because it does not choose or configure a robot.

Preview the gravity-settled table and assets:

```bash
embodichain preview-scene --output_root /path/to/scene_output
```

Use Viser for a browser-based preview:

```bash
embodichain preview-scene \
--output_root /path/to/scene_output \
--viser
```

### Arguments

``scene-engine``:

| Argument | Default | Description |
|---|---|---|
| ``--image`` | *(required)* | Input ``.jpg``, ``.jpeg``, or ``.png`` scene image |
| ``--output_root`` | *(required)* | Directory that receives intermediate artifacts and ``scene_export/`` |
| ``--config`` | packaged template | Optional complete Scene Engine JSON override. Without it, supply the documented service environment variables; the packaged JSON is only a template. |

``preview-scene``:

| Argument | Default | Description |
|---|---|---|
| ``--output_root`` | *(required)* | Scene Engine output root containing ``scene_export/`` |
| ``--device`` | ``cpu`` | Simulation device, such as ``cpu`` or ``cuda`` |
| ``--headless`` | ``False`` | Load and validate the export without a native window |
| ``--viser`` | ``False`` | Publish the scene through Viser instead of a native window |

For configuration, output layout, remote Viser access, and Python API usage,
see [Scene Engine](../features/generative_sim/scene_engine.md).

---

## Preview Asset

Preview a USD or mesh asset in the simulation without writing code.
Expand Down
10 changes: 10 additions & 0 deletions embodichain/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ class Command:
target="embodichain.gen_sim.simready_pipeline.cli.start:main",
help="Convert a raw asset directory into a SimReady asset.",
),
Command(
name="scene-engine",
target="embodichain.gen_sim.scene_engine.cli.start:main",
help="Generate a scene export from an input image.",
),
Command(
name="preview-scene",
target="embodichain.gen_sim.scene_engine.cli.preview:main",
help="Preview a generated Scene Engine scene export.",
),
Command(
name="preview-asset",
target="embodichain.lab.scripts.preview_asset:cli",
Expand Down
19 changes: 19 additions & 0 deletions embodichain/gen_sim/scene_engine/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ----------------------------------------------------------------------------
# Copyright (c) 2021-2026 DexForce Technology Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------

from __future__ import annotations

__all__: list[str] = []
19 changes: 19 additions & 0 deletions embodichain/gen_sim/scene_engine/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# ----------------------------------------------------------------------------
# Copyright (c) 2021-2026 DexForce Technology Co., Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------

from __future__ import annotations

__all__: list[str] = []
Loading
Loading