-
Notifications
You must be signed in to change notification settings - Fork 9
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -582,41 +582,45 @@ def __init__( | |||||||||||||||||||||||||
| if self.cfg.init_qpos is None: | ||||||||||||||||||||||||||
| self.cfg.init_qpos = torch.zeros(self.dof, dtype=torch.float32) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| # Set articulation configuration in DexSim | ||||||||||||||||||||||||||
| set_dexsim_articulation_cfg(entities, self.cfg) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| # Init joint drive parameters. | ||||||||||||||||||||||||||
| num_entities = len(entities) | ||||||||||||||||||||||||||
| dof = self._data.dof | ||||||||||||||||||||||||||
| default_cfg = JointDrivePropertiesCfg() | ||||||||||||||||||||||||||
| self.default_joint_damping = torch.full( | ||||||||||||||||||||||||||
| (num_entities, dof), default_cfg.damping, dtype=torch.float32, device=device | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| self.default_joint_stiffness = torch.full( | ||||||||||||||||||||||||||
| (num_entities, dof), | ||||||||||||||||||||||||||
| default_cfg.stiffness, | ||||||||||||||||||||||||||
| dtype=torch.float32, | ||||||||||||||||||||||||||
| device=device, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| self.default_joint_max_effort = torch.full( | ||||||||||||||||||||||||||
| (num_entities, dof), | ||||||||||||||||||||||||||
| default_cfg.max_effort, | ||||||||||||||||||||||||||
| dtype=torch.float32, | ||||||||||||||||||||||||||
| device=device, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| self.default_joint_max_velocity = torch.full( | ||||||||||||||||||||||||||
| (num_entities, dof), | ||||||||||||||||||||||||||
| default_cfg.max_velocity, | ||||||||||||||||||||||||||
| dtype=torch.float32, | ||||||||||||||||||||||||||
| device=device, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| self.default_joint_friction = torch.full( | ||||||||||||||||||||||||||
| (num_entities, dof), | ||||||||||||||||||||||||||
| default_cfg.friction, | ||||||||||||||||||||||||||
| dtype=torch.float32, | ||||||||||||||||||||||||||
| device=device, | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| self._set_default_joint_drive() | ||||||||||||||||||||||||||
| if not cfg.use_usd_properties: | ||||||||||||||||||||||||||
| # Set articulation configuration in DexSim | ||||||||||||||||||||||||||
| set_dexsim_articulation_cfg(entities, self.cfg) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
Comment on lines
+585
to
+588
|
||||||||||||||||||||||||||
| # Init joint drive parameters. | ||||||||||||||||||||||||||
|
Comment on lines
+585
to
+589
|
||||||||||||||||||||||||||
| if not cfg.use_usd_properties: | |
| # Set articulation configuration in DexSim | |
| set_dexsim_articulation_cfg(entities, self.cfg) | |
| # Init joint drive parameters. | |
| # Always apply articulation configuration in DexSim so that visual and | |
| # robustness-related settings (e.g., compute_uv, inertia clamping) are | |
| # consistently honored, even when using USD-authored properties. | |
| set_dexsim_articulation_cfg(entities, self.cfg) | |
| if not cfg.use_usd_properties: | |
| # Init joint drive parameters when not using USD-authored 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.
These parts must be set and should not be placed inside the if condition. self._set_default_joint_drive() could be placed here
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -211,9 +211,10 @@ def __init__( | |||||||||||||||||
| self._visual_material: List[VisualMaterialInst] = [None] * len(entities) | ||||||||||||||||||
| self.is_shared_visual_material = False | ||||||||||||||||||
|
|
||||||||||||||||||
| for entity in entities: | ||||||||||||||||||
| entity.set_body_scale(*cfg.body_scale) | ||||||||||||||||||
| entity.set_physical_attr(cfg.attrs.attr()) | ||||||||||||||||||
| if not cfg.use_usd_properties: | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also check whether the fpath is USD file. |
||||||||||||||||||
| for entity in entities: | ||||||||||||||||||
| entity.set_body_scale(*cfg.body_scale) | ||||||||||||||||||
|
Comment on lines
+214
to
+216
|
||||||||||||||||||
| if not cfg.use_usd_properties: | |
| for entity in entities: | |
| entity.set_body_scale(*cfg.body_scale) | |
| for entity in entities: | |
| # Always apply configured body scale, even when using USD properties. | |
| entity.set_body_scale(*cfg.body_scale) | |
| # Only override physical attributes from cfg when not using USD properties. | |
| if not cfg.use_usd_properties: |
Copilot
AI
Feb 28, 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.
There are existing tests for rigid objects under tests/sim/objects/; this new use_usd_properties behavior isn’t covered. Add a unit test that verifies config-driven physical attributes are applied when use_usd_properties=False and are not overridden when True (can be done with a stub/mocked MeshObject).
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -1041,9 +1041,31 @@ def add_articulation( | |||||||||||||||||||
| env_list = [self._env] if len(self._arenas) == 0 else self._arenas | ||||||||||||||||||||
| obj_list = [] | ||||||||||||||||||||
|
|
||||||||||||||||||||
| for env in env_list: | ||||||||||||||||||||
| art = env.load_urdf(cfg.fpath) | ||||||||||||||||||||
| obj_list.append(art) | ||||||||||||||||||||
| is_usd = cfg.fpath.endswith((".usd", ".usda", ".usdc")) | ||||||||||||||||||||
| if is_usd: | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently add checking for num_envs when file is USD. After we support spawn via cloning, we can remove this. |
||||||||||||||||||||
| # TODO: currently not supporting multiple arenas for USD | ||||||||||||||||||||
|
||||||||||||||||||||
| # TODO: currently not supporting multiple arenas for USD | |
| # TODO: currently not supporting multiple arenas for USD | |
| if len(env_list) != 1: | |
| logger.log_error( | |
| "USD articulation import currently supports exactly one environment; " | |
| f"got {len(env_list)}. This can happen when using multiple arenas." | |
| ) | |
| return None |
Copilot
AI
Feb 28, 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.
Avoid print() in core library code; it will spam stdout in downstream applications. Use the project logger (or log at debug level) for USD import results, or remove the output entirely.
| print("USD import results:", results) | |
| logger.log_debug(f"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.
add_articulation() is annotated to return Articulation, but the new USD branch has return None after logger.log_error(...). Since logger.log_error raises, the return None is unreachable and also misleading for type/contract. Either remove the return None and rely on the exception (consistent with other error paths in this file) or change the API to return Articulation | None and avoid raising in this case.
| return None |
Copilot
AI
Feb 28, 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.
Same multi-arena issue as add_articulation: USD import always uses self._env, so in multi-arena simulations this will create a robot batch with only one instance. Add an explicit len(env_list) == 1 guard (or implement cloning into each arena) before allowing USD import.
| env = self._env | |
| if len(env_list) != 1: | |
| logger.log_error( | |
| "USD robot import currently supports only a single arena; " | |
| f"got {len(env_list)} arenas for file {cfg.fpath}." | |
| ) | |
| return None | |
| env = env_list[0] |
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.
Copilot
AI
Feb 28, 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.
Avoid print() in library code here as well; use the project logger (preferably debug level) or remove the output.
| print("USD import results:", results) | |
| logger.log_debug(f"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.
In add_robot(), the USD branch includes return None after logger.log_error(...). Because logger.log_error raises, this return None is dead code and makes the control flow harder to read. Prefer either raising without a return (consistent with existing patterns here) or replacing the error with a non-raising log if you truly want to return None.
| return None |
Copilot
AI
Feb 28, 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.
logger.log_error(...) raises, so the subsequent return None is unreachable. Since add_robot already returns Robot | None, consider either (a) returning None without raising (use logger.log_warning/log_info), or (b) remove the return None and consistently raise on failure.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -219,6 +219,28 @@ def load_mesh_objects_from_cfg( | |||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| compute_uv = cfg.shape.compute_uv | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| 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() | ||||||||||||||||||||||||
| results = _env.import_from_usd_file(fpath, return_object=True) | ||||||||||||||||||||||||
| print(f"import usd result: {results}") | ||||||||||||||||||||||||
|
Comment on lines
+224
to
+227
|
||||||||||||||||||||||||
| # 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}") | |
| # USD import currently supports exactly one arena/env. | |
| if len(env_list) != 1: | |
| raise ValueError( | |
| f"USD import currently supports exactly one arena/env, but got {len(env_list)}." | |
| ) | |
| _env = env_list[0] | |
| results = _env.import_from_usd_file(fpath, return_object=True) |
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): |
Copilot
AI
Feb 28, 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.
load_mesh_objects_from_cfg mutates the caller’s config (cfg.use_usd_properties = False) for non-USD meshes. This side effect can leak out to other code paths that reuse the same cfg instance. Prefer treating this as a local effective flag (e.g., use_usd_properties_effective = ...) rather than modifying cfg in-place.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,168 @@ | ||||||||||||||||||||||||||||||||
| # ---------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also add docs for usd |
||||||||||||||||||||||||||||||||
| # Copyright (c) 2021-2025 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. | ||||||||||||||||||||||||||||||||
| # ---------------------------------------------------------------------------- | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||
| This script demonstrates how to create a simulation scene using SimulationManager. | ||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Change description |
||||||||||||||||||||||||||||||||
| It shows the basic setup of simulation context, adding objects, and sensors. | ||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import argparse | ||||||||||||||||||||||||||||||||
| import time | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| from embodichain.lab.sim import SimulationManager, SimulationManagerCfg | ||||||||||||||||||||||||||||||||
| 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 | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
| from dexsim.utility.path import get_resources_data_path |
Copilot
AI
Feb 28, 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 always True and provides no way to disable ray tracing from the CLI. Set the default to False (consistent with other tutorials) or switch to a --disable_rt/store_false pattern.
| default=True, | |
| default=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.
--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) |
Copilot
AI
Feb 28, 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 comment says the window is opened after the scene is set up, but open_window() is called before adding any objects. Either move the window-opening block to after scene creation or adjust the comment to match the actual behavior.
| # Open window when the scene has been set up | |
| # Open window if not running in headless mode |
Copilot
AI
Feb 28, 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 tutorial hard-codes absolute local USD paths (e.g., /home/...). This will break for anyone else and for CI/doc builds. Prefer accepting these as CLI args and/or building paths from packaged assets (you already import get_resources_data_path, but it’s unused).
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() |
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_propertiesdocstring 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).