Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 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
b61ef2f
Add Gradio UI with managed Viser previews
XuanchaoPENG Aug 3, 2026
693e1eb
add conda support
XuanchaoPENG Aug 3, 2026
ab2ad30
add scene engine
XuanchaoPENG Aug 3, 2026
93096a5
add .env
XuanchaoPENG Aug 3, 2026
93abb7a
add clean process
XuanchaoPENG Aug 3, 2026
a6a3219
Changed support region detection algo + Changed the 2d-aabbs-optimiza…
MuziWong Aug 3, 2026
3b1abc2
Reformatted the gravity settlement
MuziWong Aug 3, 2026
dd66de8
Reformatted assets group table aligner + Reformatted simready tools
MuziWong Aug 3, 2026
e4bc9e3
add env config
XuanchaoPENG Aug 4, 2026
bbf2a06
Modified the scene segmentation: 1. Bold the asset outline 2. Avoid t…
MuziWong Aug 4, 2026
c45be97
Reformatted the scene export
MuziWong Aug 4, 2026
fbe72ee
add reset
XuanchaoPENG Aug 4, 2026
c3f672d
Merge branch 'muzi/feat_scene_engine' into xuanchao/gradio
XuanchaoPENG Aug 4, 2026
2436a37
Update the datastructure + Reformatted the pipeline
MuziWong Aug 4, 2026
5eb9134
Read .env for now
MuziWong Aug 4, 2026
2c9477d
Deleted all docs and all tests
MuziWong Aug 4, 2026
2d64a80
Deleted json config in setup.py
MuziWong Aug 4, 2026
f51bc5d
Merge remote-tracking branch 'origin/main' into muzi/feat_scene_engin…
MuziWong Aug 4, 2026
82acb65
Added md + rst in docs/
MuziWong Aug 4, 2026
8979f68
Modified help, description and epilog
MuziWong Aug 4, 2026
4f4102b
Added test files
MuziWong Aug 4, 2026
d710331
Added extra dependencies in gen_sim: scene_engine + Added CI
MuziWong Aug 4, 2026
4347d6e
Merge remote-tracking branch 'origin/muzi/feat_scene_engine' into xua…
XuanchaoPENG Aug 4, 2026
44539f3
fix bug
XuanchaoPENG Aug 5, 2026
9b0c5eb
run black
XuanchaoPENG Aug 5, 2026
3ef309e
Merge branch 'main' into xuanchao/gradio
XuanchaoPENG Aug 6, 2026
3e3c50b
add log
XuanchaoPENG Aug 6, 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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,9 @@ scripts/benchmark/rl/reports/*
.worktrees/
# Local gym project workspace
/gym_project/
.debug_engine/

# Local Gradio UI dependencies, generated Articraft records, and bytecode
/embodichain/gen_sim/gradio_ui/.articraft/
/embodichain/gen_sim/gradio_ui/.debug_engine/
/embodichain/gen_sim/gradio_ui/__pycache__/
5 changes: 0 additions & 5 deletions embodichain/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,6 @@ class Command:
target="embodichain.workspace_cache_cli:main",
help="Inspect and clean workspace analyzer caches.",
),
Command(
name="analyze-workspace",
target="embodichain.lab.scripts.analyze_workspace:cli",
help="Analyze a robot's reachable workspace from a URDF/USD asset.",
),
)


Expand Down
39 changes: 39 additions & 0 deletions embodichain/gen_sim/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Shared GenSim configuration
# Copy this file to .env and set deployment-specific values. Values exported
# by the shell, container, or CI environment take precedence over this file.

# Common OpenAI-compatible LLM endpoint used by Scene Engine.
OPENAI_API_KEY=""
OPENAI_MODEL=""
OPENAI_BASE_URL=""
SCENE_ENGINE_OPENAI_DEFAULT_QUERY="{}"
OPENAI_MAX_ATTEMPTS=3

# Scene Engine services.
SCENE_ENGINE_IMAGE_SEGMENTATION_BASE_URL=""
SCENE_ENGINE_IMAGE_SEGMENTATION_TIMEOUT_S=30
SCENE_ENGINE_IMAGE_SEGMENTATION_MAX_ATTEMPTS=3
SCENE_ENGINE_IMAGE_SEGMENTATION_HEALTH_PATH="/health"
SCENE_ENGINE_IMAGE_SEGMENTATION_SINGLE_OBJECT_PATH="/predict"
SCENE_ENGINE_GEOMETRY_GENERATION_BASE_URL=""
SCENE_ENGINE_GEOMETRY_GENERATION_TIMEOUT_S=600
SCENE_ENGINE_GEOMETRY_GENERATION_MAX_ATTEMPTS=3
SCENE_ENGINE_GEOMETRY_GENERATION_HEALTH_PATH="/health"
SCENE_ENGINE_GEOMETRY_GENERATION_OBJECTS_PATH="/generate_multiple_objects"

# Gradio application and local workbench settings. The EmbodiChain repository
# root is derived automatically from the installed source tree.
GRADIO_SERVER_NAME="0.0.0.0"
GRADIO_SERVER_PORT=7860
SCENE_ENGINE_VISER_PORT=8080
ARTICRAFT_VISER_PORT=8081
ARTICRAFT_ROOT=""
ARTICRAFT_REPOSITORY_URL="https://github.com/mattzh72/articraft.git"
ARTICRAFT_CONDA_ENV="articraft"
ARTICRAFT_OUTPUT_ROOT=""

# Optional SimReady endpoint. These values are mapped to OPENAI_* only for
# SimReady subprocesses, leaving Scene Engine settings unchanged.
SIMREADY_OPENAI_API_KEY=""
SIMREADY_OPENAI_MODEL=""
SIMREADY_OPENAI_BASE_URL=""
105 changes: 105 additions & 0 deletions embodichain/gen_sim/env.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# ----------------------------------------------------------------------------
# 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.
# ----------------------------------------------------------------------------

"""Load the shared GenSim environment configuration."""

from __future__ import annotations

import os
from pathlib import Path
from typing import MutableMapping

__all__ = ["find_gen_sim_env_file", "get_embodichain_root", "load_gen_sim_env"]


def get_embodichain_root() -> Path:
"""Return the repository containing the installed GenSim source tree.

The Gradio app always launches its local tools from this directory. It is
derived from this module instead of a machine-specific dotenv value, so a
checkout continues to work after it is moved or cloned elsewhere.
"""
return Path(__file__).resolve().parents[2]


def find_gen_sim_env_file() -> Path:
"""Return the configured shared ``.env`` file path.

``EMBODICHAIN_ENV_FILE`` is useful for deployments that keep secrets outside
the source tree. Otherwise GenSim uses ``embodichain/gen_sim/.env``. The
repository-root ``.env`` remains a backward-compatible fallback.
"""
configured_path = os.environ.get("EMBODICHAIN_ENV_FILE")
if configured_path:
return Path(configured_path).expanduser().resolve()
default_path = Path(__file__).resolve().parent / ".env"
if default_path.is_file():
return default_path


def load_gen_sim_env(env: MutableMapping[str, str] | None = None) -> Path | None:
"""Load missing variables from the shared GenSim ``.env`` file.

Existing process environment variables are never overwritten so container,
CI, and shell-provided settings retain precedence over the local file.

Args:
env: Environment mapping to populate. Defaults to :data:`os.environ`.

Returns:
The loaded path, or ``None`` when no local ``.env`` file exists.

Raises:
ValueError: If the file contains an invalid ``KEY=VALUE`` entry.
"""
target_env = os.environ if env is None else env
env_path = find_gen_sim_env_file()
if not env_path.is_file():
return None
Comment on lines +69 to +71

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Missing dotenv crashes startup

When neither EMBODICHAIN_ENV_FILE nor the optional local .env exists, find_gen_sim_env_file() returns None and the loader calls .is_file() on it, causing the Gradio workspace to fail during import with an AttributeError.

Suggested change
env_path = find_gen_sim_env_file()
if not env_path.is_file():
return None
env_path = find_gen_sim_env_file()
if env_path is None or not env_path.is_file():
return None
Prompt To Fix With AI
This is a comment left during a code review.
Path: embodichain/gen_sim/env.py
Line: 69-71

Comment:
**Missing dotenv crashes startup**

When neither `EMBODICHAIN_ENV_FILE` nor the optional local `.env` exists, `find_gen_sim_env_file()` returns `None` and the loader calls `.is_file()` on it, causing the Gradio workspace to fail during import with an `AttributeError`.

```suggestion
    env_path = find_gen_sim_env_file()
    if env_path is None or not env_path.is_file():
        return None
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex Fix in Claude Code


for line_number, raw_line in enumerate(
env_path.read_text(encoding="utf-8").splitlines(), start=1
):
parsed = _parse_env_line(raw_line)
if parsed is None:
continue
key, value = parsed
if not key.isidentifier():
raise ValueError(
f"Invalid environment variable name at {env_path}:{line_number}: {key!r}"
)
target_env.setdefault(key, value)
return env_path


def _parse_env_line(line: str) -> tuple[str, str] | None:
"""Parse one conventional dotenv line without requiring a third-party package."""
stripped = line.strip()
if not stripped or stripped.startswith("#"):
return None
if stripped.startswith("export "):
stripped = stripped.removeprefix("export ").lstrip()
if "=" not in stripped:
raise ValueError(f"Expected KEY=VALUE entry, got: {line!r}")

key, value = stripped.split("=", maxsplit=1)
key = key.strip()
value = value.strip()
if len(value) >= 2 and value[0] == value[-1] and value[0] in {"'", '"'}:
value = value[1:-1]
elif " #" in value:
value = value.split(" #", maxsplit=1)[0].rstrip()
return key, value
Loading
Loading