Repository navigation
[Core] Refactor and cleanup core subpackage for 3.0 [14/N] - #8100
Conversation
|
| dispatchers = [_resolve_func(cfg) for cfg in fragments] | ||
|
|
||
| # match revolute/prismatic joints not excluded by a backend-registered skip predicate; | ||
| # non-joint matches (creation_candidates) are ignored silently since a subtree expression | ||
| # matches every descendant | ||
| # non-joint matches are ignored silently since a subtree expression matches every descendant | ||
| targets, _, any_skipped = _match_fragment_targets( | ||
| prim_path_expr, | ||
| lambda p: (p.IsA(UsdPhysics.RevoluteJoint) or p.IsA(UsdPhysics.PrismaticJoint)) and not _skip_joint_drive(p), | ||
| stage, | ||
| prim_path_expr, lambda p: _drive_instance_name(p) is not None and not _skip_joint_drive(p), stage | ||
| ) |
There was a problem hiding this comment.
No-target calls can raise If a joint-drive fragment names a function in an unavailable module, this line raises before checking whether any joints match. Previously, a call with no matching joints returned
False with a warning. This can turn an otherwise harmless asset spawn into an exception; resolve the functions only when there are targets.
| dispatchers = [_resolve_func(cfg) for cfg in fragments] | |
| # match revolute/prismatic joints not excluded by a backend-registered skip predicate; | |
| # non-joint matches (creation_candidates) are ignored silently since a subtree expression | |
| # matches every descendant | |
| # non-joint matches are ignored silently since a subtree expression matches every descendant | |
| targets, _, any_skipped = _match_fragment_targets( | |
| prim_path_expr, | |
| lambda p: (p.IsA(UsdPhysics.RevoluteJoint) or p.IsA(UsdPhysics.PrismaticJoint)) and not _skip_joint_drive(p), | |
| stage, | |
| prim_path_expr, lambda p: _drive_instance_name(p) is not None and not _skip_joint_drive(p), stage | |
| ) | |
| # non-joint matches are ignored silently since a subtree expression matches every descendant | |
| targets, _, any_skipped = _match_fragment_targets( | |
| prim_path_expr, lambda p: _drive_instance_name(p) is not None and not _skip_joint_drive(p), stage | |
| ) | |
| dispatchers = [_resolve_func(cfg) for cfg in fragments] if targets else [] |
There was a problem hiding this comment.
Isaac Lab Review Bot
Reviewed the sim-authoring deduplication across schema fragment dispatch, joint-drive authoring, mesh conversion, material-path resolution, and spawner creation paths. The patch consistently preserves the existing anchors, ordering, unit conversions, and legacy-writer routing shown in the changed code.
- Design and architecture: The shared
_apply_api_fragments,apply_schema_props, drive-writing, mesh-approximation, and tetrahedralization helpers consolidate duplicated behavior without introducing a new public abstraction or changing backend ownership. Reusing_drive_instance_nameandto_camel_casewithin the schema package is consistent with the existing utility layer. - API: Public signatures and defaults remain intact. The fragment writers retain target matching,
create_if_missing, warning, and result-aggregation behavior; joint-drive paths retain angular unit conversion anddrive_typemapping. The internal geometry helpers now return their created prims, and their changed callers consume those returns consistently. - Implementation: The changed producer and consumer paths for schema slots and material paths were traced across shape, mesh, file, and converter spawners. The proposed concern about omitting an explicit
to_camel_caseconvention does not demonstrate a changed attribute name or concrete failure under the utility's current deterministic default, so it does not warrant pre-merge action.
No blocking issues. No inline issue met the actionable-evidence threshold; the assessment above records the review feedback.
Automated review; human maintainers own approval decisions.
| apply_func(props_expr(anchor_path, pattern), fragments, create_if_missing=True, stage=stage) | ||
|
|
||
|
|
||
| def resolve_material_path(material_path: str, parent_path: str) -> str: |
There was a problem hiding this comment.
I will inline this the resolve here makes no sense
| return success | ||
|
|
||
|
|
||
| def _write_mesh_approximation(prim: Usd.Prim, name: str) -> None: |
There was a problem hiding this comment.
i will also inline this there is only 2 caller, and one of the caller is going to be deprecated , it doesn't worth to refactor out
|
run-ci |
|
run-ci |
…nto core-cleanup/14-sim-authoring
# Conflicts: # source/isaaclab_physx/benchmark/sensors/benchmark_contact_sensor.py # source/isaaclab_physx/benchmark/sensors/benchmark_frame_transformer.py
|
run-ci |
# Description Part 14 of the split of #7949. This PR cleans up sim authoring: the schema writers in `isaaclab.sim.schemas`, the spawners, and the mesh converter. It is rebased onto the current `develop` and ports only the parts of #7949 that still apply there. The authored USD is unchanged, and no public API changes. **Spawners and mesh converter** - `spawners.utils` (renamed from `spawners._utils`, see below) adds a helper: - `apply_schema_props` writes a spawner schema slot. It sends a fragment mapping to the fragment writer, one entry at a time and anchored at the spawned prim, and sends a legacy cfg to the legacy writer. The mesh and shape spawners, `spawn_from_mesh`, and `MeshConverter` repeated this branch for their collision, mass, and rigid-body slots; they now call the helper. - Material paths are resolved inline at each call site (absolute paths are kept; relative names go under the spawned prim), replacing `from_files._resolve_material_path`. - Existing-prim checks are left to `create_prim`, which already raises the same `ValueError`. The spawner bodies are shorter, and `spawn_geom_from_prim_type` / `_spawn_mesh_geom_from_mesh` return the prim they create. - Mesh spawners share `_axis_transform` for the cylinder, capsule, and cone axis rotation. - Light, sensor, ground plane, and multi-USD spawners: - The ground plane hides its light with `set_prim_visibility`. - `spawn_multi_usd_file` builds `MultiAssetSpawnerCfg` in one call and no longer runs a `hasattr` check that was always true. - `AssetConverterBase` has a shorter USD-extension and hash-file check, and writes the `config.yaml` generation stamp with a single `datetime.now()` call. The stamp format is the same. **Schema writers** - `apply_rigid_body_properties`, `apply_collision_properties`, and `apply_mass_properties` now share `_apply_api_fragments`. Target matching, `create_if_missing`, the zero-target warning, and result aggregation are unchanged. - The joint-drive writers share `_write_drive_attributes`, which converts angular stiffness and damping from per-radian to per-degree and maps `drive_type` to the USD `type` attribute. It is used by `apply_drive`, `_ensure_drive_exists`, `apply_joint_drive_properties`, and `modify_joint_drive_properties`. Joint-type detection reuses `drive_instance_name`, including in `schemas_actuators`. - Other shared helpers: - `_write_mesh_approximation` writes and validates the `physics:approximation` token. - `_tetrahedralize_surface` holds the pytetwild call and the tet-winding fix, moved out of `define_deformable_body_properties`. - Smaller cleanups: - `activate_contact_sensors` counts descendants with `Usd.PrimRange`. - `schemas_actuators` uses `to_camel_case` instead of a private camel-case regex. - Redundant `pass` statements are removed from the fragment marker classes. - Fragment appliers are called directly as `cfg.func(cfg, prim_path, stage)`. `@configclass` already turns the `func` import string into a callable `ResolvableString`, so the `callable(...) else string_to_callable(...)` fallback (four schema writers and the physics-material spawner) never ran. **Reflection** - Replaced avoidable `getattr`/`setattr`/`hasattr` with direct attribute access or an `isinstance` check wherever the attribute is always defined for the configs that reach that code (actuator authoring, the USD-file and shape spawners, the camera spawner's intrinsics, the fragment annotation lookup). The remaining uses are dynamic by design: iterating dataclass fields, the deprecated alias forwarding, optional class metadata, and mixed config types in the multi-asset wrapper. **No underscore module names or cross-file private helpers in core** - Renamed the underscore modules: `sim/spawners/_utils.py` → `utils.py`, `sim/schemas/_backend_hooks.py` → `backend_hooks.py`, `actuators/_compat.py` → `actuator_compat.py`, `benchmark/_cli.py` → `cli.py`, `cloner/_fabric_notices.py` → `fabric_notices.py`, `utils/_device.py` → `device.py`. All importers in `isaaclab`, `isaaclab_physx`, `isaaclab_newton`, `isaaclab_ov`, the benchmark scripts, tests, and docs are updated. - Dropped the `_` prefix from module-level functions used from other files: `limits_equal`, `resolve_limit_aliases`, `skip_joint_drive`, `articulation_root_companion_namespace`, `apply_namespaced_schemas`, `drive_instance_name`, `validate_newton_native_actuator_cfgs`, `author_actuator_prims`, `resave_checkpoint_with_metadata`, `deprecate_field_alias`, `deprecated_schema_cfg`, `spawn_from_usd_file`, `spawn_geom_from_prim_type`. They are not added to the package exports. **Not ported from #7949** - The forwarding-shim refactors in `schemas/__init__.py` and `schemas_cfg.py`, the `usd_api` / `physx_api` deprecation properties, and the empty `_usd_*` metadata on deprecated cfgs. These are deprecation-only and will be removed. - The `_OVERRIDABLE_PROPS` constant in the wrappers, a single-use constant. - The import-only edits. `develop` already uses relative imports. ## Type of change - Refactor (no functional change). The only visible difference is that the `ValueError` for an unsupported deformable type is now one line, instead of a triple-quoted string with embedded indentation. ## Verification - USD authoring equivalence, comparing `develop` sources with this branch in Kit, one fresh stage per case. All 57 cases produce identical exported USDA, return values, and raised errors: - Sphere, cuboid, cylinder, capsule, and cone shapes; and sphere, cuboid, cylinder, capsule, cone, and rectangle meshes. Each is spawned plain, with legacy cfgs, and with fragments (including dict targets and absolute material paths). - The cable spawner, `MeshFileCfg` from a trimesh object and from an `.obj` file, and all five lights. - Pinhole and fisheye cameras, and the sensor frame. - `UsdFileCfg` with legacy cfgs and with fragments (articulation root, joint drives, contact sensors, semantics, materials), the compliant-contact spawner, and a ground plane asset. - `MultiAssetSpawnerCfg` and `MultiUsdFileCfg`, and a surface deformable. - The legacy `define_`/`modify_` writers and the fragment `apply_*` writers, including `ensure_drives_exist`, the no-target case, mesh collision with an invalid approximation name, and fixed tendons. - A `MeshConverter` run with collision, mesh-collision, mass, and rigid props and `make_instanceable`, comparing the generated USD layers and `config.yaml`. - Tests, run one file at a time; all pass: - Spawners: `test_spawn_shapes`, `test_spawn_meshes`, `test_spawn_lights`, `test_spawn_sensors`, `test_spawn_from_files`, `test_spawn_wrappers`, `test_spawn_cable`, `test_spawn_materials`, `test_default_ground_plane`, `test_visual_materials_kitless`. - Schemas: `test_schemas`, `test_schemas_deprecation`, `test_schemas_shim`, `test_schemas_kitless_fixed_joint`, `test_schema_fragments`, `test_schema_fragment_parity`, `test_schema_writer_nested_targets`, `test_joint_drive_fragments`, `test_collision_fragments`, `test_mass_fragments`, `test_mesh_collision_fragments`, `test_articulation_fragments`, `test_material_fragments`, `test_tendon_fragments`, `test_tendon_fragments_codeless`, `test_deformable_backend_split`. - Converter: `test_mesh_converter`. - Actuator authoring: `source/isaaclab/test/actuators`, `test_newton_actuator_manager_authoring`, `test_newton_actuators_newton`, `test_newton_actuators_physx`. - After the renames, reflection pass, and review fixes, the 57-case USD comparison was rerun against the latest `develop` (0 differences), and the spawner, schema, fragment, converter, cloner (`isaaclab` and `isaaclab_physx`), benchmark CLI, device, Newton schema, and actuator authoring tests were rerun; all pass. Every renamed module and its importers in `isaaclab_physx`, `isaaclab_newton`, and `isaaclab_ov` import cleanly. - One-line helpers are kept inline rather than wrapped in functions (e.g. the drive get-or-apply, the passive-drive check, the dataclass-field dict, material paths). - After merging the latest `develop` (including #8102), the tests above were rerun and pass. `isaaclab_physx/test/sim/test_spawn_meshes.py` was run with the `tetrahedralization` extra, which covers `_tetrahedralize_surface`; it passes on this branch and on `develop`. - `ruff check` and `ruff format` are clean. ## Checklist - [x] I have read and understood the [contribution guidelines](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html) - [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `./isaaclab.sh --format` - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] I have added a changelog fragment under `source/<package>/changelog.d/` for each changed package (see [Changelog](https://isaac-sim.github.io/IsaacLab/main/source/refs/contributing.html#changelog)) - [x] If this is a user-visible change, the fragment clearly describes it ## Release backport - [x] <!-- backport-active-release --> Backport this pull request to the active release branch after it merges into `develop` (cherry picked from commit d11f811)
|
Backported to |
Description
Part 14 of the split of #7949. This PR cleans up sim authoring: the schema writers in
isaaclab.sim.schemas, the spawners, and the mesh converter. It is rebased onto the currentdevelopand ports only the parts of #7949 that still apply there. The authored USD is unchanged, and no public API changes.Spawners and mesh converter
spawners.utils(renamed fromspawners._utils, see below) adds a helper:apply_schema_propswrites a spawner schema slot. It sends a fragment mapping to the fragment writer, one entry at a time and anchored at the spawned prim, and sends a legacy cfg to the legacy writer. The mesh and shape spawners,spawn_from_mesh, andMeshConverterrepeated this branch for their collision, mass, and rigid-body slots; they now call the helper.from_files._resolve_material_path.create_prim, which already raises the sameValueError. The spawner bodies are shorter, andspawn_geom_from_prim_type/_spawn_mesh_geom_from_meshreturn the prim they create._axis_transformfor the cylinder, capsule, and cone axis rotation.set_prim_visibility.spawn_multi_usd_filebuildsMultiAssetSpawnerCfgin one call and no longer runs ahasattrcheck that was always true.AssetConverterBasehas a shorter USD-extension and hash-file check, and writes theconfig.yamlgeneration stamp with a singledatetime.now()call. The stamp format is the same.Schema writers
apply_rigid_body_properties,apply_collision_properties, andapply_mass_propertiesnow share_apply_api_fragments. Target matching,create_if_missing, the zero-target warning, and result aggregation are unchanged._write_drive_attributes, which converts angular stiffness and damping from per-radian to per-degree and mapsdrive_typeto the USDtypeattribute. It is used byapply_drive,_ensure_drive_exists,apply_joint_drive_properties, andmodify_joint_drive_properties. Joint-type detection reusesdrive_instance_name, including inschemas_actuators._write_mesh_approximationwrites and validates thephysics:approximationtoken._tetrahedralize_surfaceholds the pytetwild call and the tet-winding fix, moved out ofdefine_deformable_body_properties.activate_contact_sensorscounts descendants withUsd.PrimRange.schemas_actuatorsusesto_camel_caseinstead of a private camel-case regex.passstatements are removed from the fragment marker classes.cfg.func(cfg, prim_path, stage).@configclassalready turns thefuncimport string into a callableResolvableString, so thecallable(...) else string_to_callable(...)fallback (four schema writers and the physics-material spawner) never ran.Reflection
getattr/setattr/hasattrwith direct attribute access or anisinstancecheck wherever the attribute is always defined for the configs that reach that code (actuator authoring, the USD-file and shape spawners, the camera spawner's intrinsics, the fragment annotation lookup). The remaining uses are dynamic by design: iterating dataclass fields, the deprecated alias forwarding, optional class metadata, and mixed config types in the multi-asset wrapper.No underscore module names or cross-file private helpers in core
sim/spawners/_utils.py→utils.py,sim/schemas/_backend_hooks.py→backend_hooks.py,actuators/_compat.py→actuator_compat.py,benchmark/_cli.py→cli.py,cloner/_fabric_notices.py→fabric_notices.py,utils/_device.py→device.py. All importers inisaaclab,isaaclab_physx,isaaclab_newton,isaaclab_ov, the benchmark scripts, tests, and docs are updated._prefix from module-level functions used from other files:limits_equal,resolve_limit_aliases,skip_joint_drive,articulation_root_companion_namespace,apply_namespaced_schemas,drive_instance_name,validate_newton_native_actuator_cfgs,author_actuator_prims,resave_checkpoint_with_metadata,deprecate_field_alias,deprecated_schema_cfg,spawn_from_usd_file,spawn_geom_from_prim_type. They are not added to the package exports.Not ported from #7949
schemas/__init__.pyandschemas_cfg.py, theusd_api/physx_apideprecation properties, and the empty_usd_*metadata on deprecated cfgs. These are deprecation-only and will be removed._OVERRIDABLE_PROPSconstant in the wrappers, a single-use constant.developalready uses relative imports.Type of change
ValueErrorfor an unsupported deformable type is now one line, instead of a triple-quoted string with embedded indentation.Verification
developsources with this branch in Kit, one fresh stage per case. All 57 cases produce identical exported USDA, return values, and raised errors:MeshFileCfgfrom a trimesh object and from an.objfile, and all five lights.UsdFileCfgwith legacy cfgs and with fragments (articulation root, joint drives, contact sensors, semantics, materials), the compliant-contact spawner, and a ground plane asset.MultiAssetSpawnerCfgandMultiUsdFileCfg, and a surface deformable.define_/modify_writers and the fragmentapply_*writers, includingensure_drives_exist, the no-target case, mesh collision with an invalid approximation name, and fixed tendons.MeshConverterrun with collision, mesh-collision, mass, and rigid props andmake_instanceable, comparing the generated USD layers andconfig.yaml.test_spawn_shapes,test_spawn_meshes,test_spawn_lights,test_spawn_sensors,test_spawn_from_files,test_spawn_wrappers,test_spawn_cable,test_spawn_materials,test_default_ground_plane,test_visual_materials_kitless.test_schemas,test_schemas_deprecation,test_schemas_shim,test_schemas_kitless_fixed_joint,test_schema_fragments,test_schema_fragment_parity,test_schema_writer_nested_targets,test_joint_drive_fragments,test_collision_fragments,test_mass_fragments,test_mesh_collision_fragments,test_articulation_fragments,test_material_fragments,test_tendon_fragments,test_tendon_fragments_codeless,test_deformable_backend_split.test_mesh_converter.source/isaaclab/test/actuators,test_newton_actuator_manager_authoring,test_newton_actuators_newton,test_newton_actuators_physx.develop(0 differences), and the spawner, schema, fragment, converter, cloner (isaaclabandisaaclab_physx), benchmark CLI, device, Newton schema, and actuator authoring tests were rerun; all pass. Every renamed module and its importers inisaaclab_physx,isaaclab_newton, andisaaclab_ovimport cleanly.develop(including [Core] Make tests backend-agnostic and start them with launch_test_simulation (3/3) #8102), the tests above were rerun and pass.isaaclab_physx/test/sim/test_spawn_meshes.pywas run with thetetrahedralizationextra, which covers_tetrahedralize_surface; it passes on this branch and ondevelop.ruff checkandruff formatare clean.Checklist
pre-commitchecks with./isaaclab.sh --formatsource/<package>/changelog.d/for each changed package (see Changelog)Release backport
develop