-
Notifications
You must be signed in to change notification settings - Fork 10
draft: import usd #127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
draft: import usd #127
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds initial USD import support to the simulation stack, including an option to keep physics/drive properties authored in USD instead of overriding them from config, plus a tutorial demonstrating usage (single-env only).
Changes:
- Add
use_usd_propertiestoRigidObjectCfgandArticulationCfgto control whether config overrides USD-authored properties. - Implement USD loading paths for mesh rigid objects and for articulations/robots.
- Add a new tutorial script
scripts/tutorials/sim/import_usd.pydemonstrating USD import.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/tutorials/sim/import_usd.py | New tutorial showcasing importing rigid objects/articulations from USD. |
| embodichain/lab/sim/utility/sim_utils.py | Adds USD import handling for mesh rigid objects in load_mesh_objects_from_cfg. |
| embodichain/lab/sim/sim_manager.py | Adds USD import handling for add_articulation and add_robot. |
| embodichain/lab/sim/objects/rigid_object.py | Skips applying config physical attrs when use_usd_properties=True. |
| embodichain/lab/sim/objects/articulation.py | Skips applying config articulation settings/drive defaults when use_usd_properties=True. |
| embodichain/lab/sim/cfg.py | Introduces the new use_usd_properties configuration flags and docs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| action="store_true", | ||
| default=True, | ||
| help="Enable ray tracing for better visuals", | ||
| ) |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
--enable_rt is declared with action='store_true' but also default=True, which makes the flag impossible to disable from the CLI (it will always be True). Use default=False (store_true) or switch to a --disable_rt (store_false) pattern so users can actually control ray tracing.
| action="store_true", | |
| default=True, | |
| help="Enable ray tracing for better visuals", | |
| ) | |
| dest="enable_rt", | |
| action="store_true", | |
| help="Enable ray tracing for better visuals", | |
| ) | |
| parser.add_argument( | |
| "--disable_rt", | |
| dest="enable_rt", | |
| action="store_false", | |
| help="Disable ray tracing", | |
| ) | |
| parser.set_defaults(enable_rt=True) |
scripts/tutorials/sim/import_usd.py
Outdated
| usdpath="/home/xiemh/model/004_sugar_box/004_sugar_box_xmh.usda" | ||
| sugar_box: RigidObject = sim.add_rigid_object( | ||
| cfg=RigidObjectCfg( | ||
| uid="sugar_box", | ||
| shape=MeshCfg(fpath=usdpath), | ||
| body_type="dynamic", | ||
| init_pos=[0.2, 0.2, 1.0], | ||
| use_usd_properties=True, | ||
| ) | ||
| ) | ||
|
|
||
| # Add objects to the scene | ||
| h1 :Articulation= sim.add_articulation( | ||
| cfg=ArticulationCfg( | ||
| uid="h1", | ||
| # fpath="/home/xiemh/model/Collected_ur10/ur10.usd", | ||
| fpath="/home/xiemh/model/Collected_h1/h1.usda", | ||
| build_pk_chain=False, |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This tutorial hard-codes absolute local filesystem paths for USD assets (e.g. under /home/...), which makes the script unusable for other users and in CI. Consider resolving assets via the project’s data/resources path helpers (e.g. get_data_path/get_resources_data_path) and/or exposing the USD paths as CLI arguments.
|
|
||
| rigidbodys_found=[] | ||
| for key,value in results.items(): | ||
| if isinstance(value, dexsim.cuda.pybind.models.MeshObject): |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The USD import path filters returned objects using isinstance(value, dexsim.cuda.pybind.models.MeshObject). This can break on CPU-only installs/builds where dexsim.cuda may not exist. Since this module already imports MeshObject from dexsim.models, prefer checking against MeshObject (or another CPU-safe base type) instead of a CUDA-specific pybind class.
| if isinstance(value, dexsim.cuda.pybind.models.MeshObject): | |
| if isinstance(value, MeshObject): |
| # TODO: currently not supporting multiple arenas for USD | ||
| _env:dexsim.environment.Env = dexsim.default_world().get_env() | ||
| results = _env.import_from_usd_file(fpath,return_object=True) | ||
| print(f"import usd result: {results}") | ||
|
|
||
| rigidbodys_found=[] | ||
| for key,value in results.items(): | ||
| if isinstance(value, dexsim.cuda.pybind.models.MeshObject): | ||
| rigidbodys_found.append(value) | ||
| if len(rigidbodys_found)==0: | ||
| logger.log_error(f"No rigid body found in USD file: {fpath}") | ||
| elif len(rigidbodys_found)>1: | ||
| logger.log_error(f"Multiple rigid bodies found in USD file: {fpath}.") | ||
| elif len(rigidbodys_found)==1: |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
USD import currently ignores the provided env_list and always imports into dexsim.default_world().get_env(), then returns a single object. If env_list contains multiple arenas/envs, SimulationManager.add_rigid_object() will receive an obj_list whose length doesn’t match the number of envs. Since the code explicitly says multiple arenas aren’t supported, add an explicit guard (e.g., raise via logger.log_error when len(env_list) != 1) and import into env_list[0] to avoid silently creating mismatched batches.
| # TODO: currently not supporting multiple arenas for USD | |
| _env:dexsim.environment.Env = dexsim.default_world().get_env() | |
| results = _env.import_from_usd_file(fpath,return_object=True) | |
| print(f"import usd result: {results}") | |
| rigidbodys_found=[] | |
| for key,value in results.items(): | |
| if isinstance(value, dexsim.cuda.pybind.models.MeshObject): | |
| rigidbodys_found.append(value) | |
| if len(rigidbodys_found)==0: | |
| logger.log_error(f"No rigid body found in USD file: {fpath}") | |
| elif len(rigidbodys_found)>1: | |
| logger.log_error(f"Multiple rigid bodies found in USD file: {fpath}.") | |
| elif len(rigidbodys_found)==1: | |
| # TODO: currently not supporting multiple arenas for USD | |
| if len(env_list) != 1: | |
| logger.log_error( | |
| f"USD import currently supports exactly one environment, " | |
| f"but got {len(env_list)}." | |
| ) | |
| _env: dexsim.environment.Env = env_list[0] | |
| results = _env.import_from_usd_file(fpath, return_object=True) | |
| print(f"import usd result: {results}") | |
| rigidbodys_found = [] | |
| for key, value in results.items(): | |
| if isinstance(value, dexsim.cuda.pybind.models.MeshObject): | |
| rigidbodys_found.append(value) | |
| if len(rigidbodys_found) == 0: | |
| logger.log_error(f"No rigid body found in USD file: {fpath}") | |
| elif len(rigidbodys_found) > 1: | |
| logger.log_error(f"Multiple rigid bodies found in USD file: {fpath}.") | |
| elif len(rigidbodys_found) == 1: |
| if not cfg.use_usd_properties: | ||
| # Set articulation configuration in DexSim | ||
| set_dexsim_articulation_cfg(entities, self.cfg) | ||
|
|
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Articulation.__init__ now skips set_dexsim_articulation_cfg(...) when cfg.use_usd_properties is True, regardless of whether the asset was actually loaded from USD. This contradicts ArticulationCfg.use_usd_properties docstring (“ignored for URDF files”) and can lead to URDF-loaded articulations missing expected config application. Consider forcing use_usd_properties=False for non-USD fpath (similar to what load_mesh_objects_from_cfg does for non-USD meshes) or gating this behavior on file extension.
embodichain/lab/sim/sim_manager.py
Outdated
| is_usd = cfg.fpath.endswith((".usd", ".usda", ".usdc")) | ||
| if is_usd: | ||
| # TODO: currently not supporting multiple arenas for USD | ||
| env= self._env |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The USD import path explicitly notes it doesn’t support multiple arenas, but it doesn’t enforce that constraint: it always imports into self._env even when self._arenas is populated. This can produce batch-size mismatches and downstream indexing errors. Add an explicit check (e.g., raise when len(self._arenas) > 0) so multi-env configurations fail fast with a clear error.
| env= self._env | |
| if len(self._arenas) > 0: | |
| raise RuntimeError( | |
| "USD articulations currently support only a single arena, " | |
| f"but {len(self._arenas)} arenas are configured. " | |
| "Please use a single environment or a non-USD asset format." | |
| ) | |
| env = self._env |
| """Whether to use physical properties from USD file instead of config. | ||
|
|
||
| When True: Keep all physical properties (drive, physics attrs, etc.) from USD file. | ||
| When False (default): Override USD properties with config values (URDF behavior). | ||
| Only effective for USD files, ignored for URDF files. |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RigidObjectCfg.use_usd_properties docstring mentions “URDF behavior” and “drive” properties, but rigid objects are mesh-based and don’t have URDF or joint drives in this codepath. Consider rewording to avoid confusion (e.g., “Only effective for USD mesh files; ignored for non-USD meshes” and remove “drive” wording).
| """Whether to use physical properties from USD file instead of config. | |
| When True: Keep all physical properties (drive, physics attrs, etc.) from USD file. | |
| When False (default): Override USD properties with config values (URDF behavior). | |
| Only effective for USD files, ignored for URDF files. | |
| """Whether to use physical properties stored in the USD asset instead of config values. | |
| When True: keep physics-related attributes (e.g., collision, mass, physical materials) defined in the USD file. | |
| When False (default): override physics-related attributes from the USD file with values from this config. | |
| Only effective when loading USD mesh assets; ignored for non-USD mesh formats. |
| is_usd = cfg.fpath.endswith((".usd", ".usda", ".usdc")) | ||
| if is_usd: | ||
| # TODO: currently not supporting multiple arenas for USD | ||
| env= self._env | ||
| results = env.import_from_usd_file(cfg.fpath, return_object=True) | ||
| print("USD import results:", results) |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to add_articulation(), the USD import path in add_robot() doesn’t support multiple arenas but doesn’t enforce it: it always imports into self._env even if self._arenas is populated. Add an explicit guard (raise when len(self._arenas) > 0) to prevent creating robots with a batch size that doesn’t match the simulation’s number of envs.
| # Print FPS every second | ||
| if step_count % 100 == 0: | ||
| current_time = time.time() | ||
| elapsed = current_time - last_time | ||
| fps = ( | ||
| sim.num_envs * (step_count - last_step) / elapsed | ||
| if elapsed > 0 | ||
| else 0 | ||
| ) | ||
| # print(f"[INFO]: Simulation step: {step_count}, FPS: {fps:.2f}") |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable fps is not used.
| # Print FPS every second | |
| if step_count % 100 == 0: | |
| current_time = time.time() | |
| elapsed = current_time - last_time | |
| fps = ( | |
| sim.num_envs * (step_count - last_step) / elapsed | |
| if elapsed > 0 | |
| else 0 | |
| ) | |
| # print(f"[INFO]: Simulation step: {step_count}, FPS: {fps:.2f}") | |
| # Periodically update timing counters (FPS computation removed) | |
| if step_count % 100 == 0: | |
| current_time = time.time() |
| from embodichain.lab.sim.cfg import RigidBodyAttributesCfg | ||
| from embodichain.lab.sim.shapes import CubeCfg, MeshCfg | ||
| from embodichain.lab.sim.objects import RigidObject, RigidObjectCfg,ArticulationCfg,Articulation | ||
| from dexsim.utility.path import get_resources_data_path |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import of 'get_resources_data_path' is not used.
| from dexsim.utility.path import get_resources_data_path |
| for entity in entities: | ||
| entity.set_body_scale(*cfg.body_scale) | ||
| entity.set_physical_attr(cfg.attrs.attr()) | ||
| if not cfg.use_usd_properties: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also check whether the fpath is USD file.
| set_dexsim_articulation_cfg(entities, self.cfg) | ||
|
|
||
| # Init joint drive parameters. | ||
| num_entities = len(entities) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These parts must be set and should not be placed inside the if condition. self._set_default_joint_drive() could be placed here
|
|
||
| is_usd = fpath.endswith((".usd", ".usda", ".usdc")) | ||
| if is_usd: | ||
| # TODO: currently not supporting multiple arenas for USD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add log_error here to check the num_envs number
| is_usd = fpath.endswith((".usd", ".usda", ".usdc")) | ||
| if is_usd: | ||
| # TODO: currently not supporting multiple arenas for USD | ||
| _env:dexsim.environment.Env = dexsim.default_world().get_env() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just use the first arena from env_list
| # ---------------------------------------------------------------------------- | ||
|
|
||
| """ | ||
| This script demonstrates how to create a simulation scene using SimulationManager. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change description
scripts/tutorials/sim/import_usd.py
Outdated
| ) | ||
| ) | ||
|
|
||
| usdpath="/home/xiemh/model/004_sugar_box/004_sugar_box_xmh.usda" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add to huggingface when this PR is ready to merged.
| @@ -0,0 +1,164 @@ | |||
| # ---------------------------------------------------------------------------- | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also add docs for usd
Description
Support importing USD file
This pull request adds support for importing and configuring simulation objects from USD files, allowing users to choose whether to use physical properties defined in the USD file or override them with configuration values.
Only one env is supported now.
Documentation and Tutorial:
import_usd.pydemonstrating how to set up a simulation scene, import objects from USD files, and use the new configuration options.Type of change
Screenshots
Please attach before and after screenshots of the change if applicable.
Checklist