Skip to content

Commit 54d0eca

Browse files
committed
Fold rename fix into 0.5.26 — single version bump per PR
The PR previously had two changelog headings (0.5.26 for the original tendon-replication work and 0.5.27 for the per-env rename) and two extension.toml bumps. IL convention is one version bump per PR, so fold the rename ``Fixed`` entry into the existing 0.5.26 ``Fixed`` section and revert ``extension.toml`` to ``0.5.26``.
1 parent 9c51f72 commit 54d0eca

4 files changed

Lines changed: 64 additions & 88 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
Added
2+
^^^^^
3+
4+
* Added MuJoCo tendon parsing to Newton physics replication.
5+
:func:`~isaaclab_newton.cloner.newton_replicate._build_newton_builder_from_mapping`
6+
now calls ``SolverMuJoCo.register_custom_attributes`` on each proto builder so that
7+
``MjcTendon`` prims (e.g. Shadow Hand fixed tendons) are parsed during ``add_usd``
8+
and propagated into the main builder via ``add_builder``. Per-world parameter
9+
randomization (stiffness, damping, range) is supported; heterogeneous tendon topology
10+
across worlds is not (Newton limitation). The schema-resolver chain is unchanged
11+
(``SchemaResolverNewton`` + ``SchemaResolverPhysx``); tendons are driven by the
12+
registered ``mujoco:*`` custom frequencies, independent of resolver order.
13+
14+
Fixed
15+
^^^^^
16+
17+
* Fixed MuJoCo tendon handling in Newton physics replication. Two interlocking issues
18+
prevented tendons from being included in the replicated model:
19+
20+
1. Calling ``SolverMuJoCo.register_custom_attributes`` on the main builder triggered
21+
a stage-wide custom-frequency traversal (independent of ``ignore_paths``) that
22+
tried to resolve ``MjcTendon`` joint paths against the main builder's empty
23+
``joint_label``, silently dropping all tendons. Fixed by registering MJC custom
24+
attributes only on proto builders.
25+
26+
2. In heterogeneous clone plans (multiple MJCF sources on the same stage), Newton's
27+
custom-frequency traversal ignores ``root_path``, causing proto builder A to also
28+
match ``MjcTendon`` prims from source B. Fixed by patching ``usd_prim_filter`` on
29+
each proto builder's registered custom frequencies to restrict traversal to its
30+
own source path (``_scope_custom_frequencies``).
31+
32+
* Fixed per-environment string identifiers (e.g. ``mujoco:tendon_label``) keeping
33+
the source proto path after replication. :func:`~isaaclab_newton.cloner.newton_replicate._rename_builder_labels`
34+
now also walks string-typed custom-attribute columns whose frequency declares a
35+
``references="world"`` companion, rewriting their per-row source-path prefix to
36+
the destination world root in the same pass that handles built-in label arrays.
37+
Adds ``constraint_mimic`` to that built-in pass for completeness. The prefix
38+
match uses a path-separator boundary so a source path that is a string prefix
39+
of another (e.g. ``/Sources/protoA`` vs ``/Sources/protoAB``) does not
40+
cross-contaminate during the rename.

source/isaaclab_newton/config/extension.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22

33
# Note: Semantic Versioning is used: https://semver.org/
4-
version = "0.5.27"
4+
version = "0.5.25"
55

66
# Description
77
title = "Newton simulation interfaces for IsaacLab core package"

source/isaaclab_newton/docs/CHANGELOG.rst

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,6 @@
11
Changelog
22
---------
33

4-
0.5.27 (2026-05-01)
5-
~~~~~~~~~~~~~~~~~~~
6-
7-
Fixed
8-
^^^^^
9-
10-
* Fixed per-environment string identifiers (e.g. ``mujoco:tendon_label``) keeping
11-
the source proto path after replication. :func:`~isaaclab_newton.cloner.newton_replicate._rename_builder_labels`
12-
now also walks string-typed custom-attribute columns whose frequency declares a
13-
``references="world"`` companion, rewriting their per-row source-path prefix to
14-
the destination world root in the same pass that handles built-in label arrays.
15-
Adds ``constraint_mimic`` to that built-in pass for completeness. The prefix
16-
match uses a path-separator boundary so a source path that is a string prefix
17-
of another (e.g. ``/Sources/protoA`` vs ``/Sources/protoAB``) does not
18-
cross-contaminate during the rename.
19-
20-
21-
0.5.26 (2026-04-29)
22-
~~~~~~~~~~~~~~~~~~~
23-
24-
Added
25-
^^^^^
26-
27-
* Added MuJoCo tendon parsing to Newton physics replication.
28-
:func:`~isaaclab_newton.cloner.newton_replicate._build_newton_builder_from_mapping`
29-
now calls ``SolverMuJoCo.register_custom_attributes`` on each proto builder so that
30-
``MjcTendon`` prims (e.g. Shadow Hand fixed tendons) are parsed during ``add_usd``
31-
and propagated into the main builder via ``add_builder``. Per-world parameter
32-
randomization (stiffness, damping, range) is supported; heterogeneous tendon topology
33-
across worlds is not (Newton limitation). The schema-resolver chain is unchanged
34-
(``SchemaResolverNewton`` + ``SchemaResolverPhysx``); tendons are driven by the
35-
registered ``mujoco:*`` custom frequencies, independent of resolver order.
36-
37-
Fixed
38-
^^^^^
39-
40-
* Fixed MuJoCo tendon handling in Newton physics replication. Two interlocking issues
41-
prevented tendons from being included in the replicated model:
42-
43-
1. Calling ``SolverMuJoCo.register_custom_attributes`` on the main builder triggered
44-
a stage-wide custom-frequency traversal (independent of ``ignore_paths``) that
45-
tried to resolve ``MjcTendon`` joint paths against the main builder's empty
46-
``joint_label``, silently dropping all tendons. Fixed by registering MJC custom
47-
attributes only on proto builders.
48-
49-
2. In heterogeneous clone plans (multiple MJCF sources on the same stage), Newton's
50-
custom-frequency traversal ignores ``root_path``, causing proto builder A to also
51-
match ``MjcTendon`` prims from source B. Fixed by patching ``usd_prim_filter`` on
52-
each proto builder's registered custom frequencies to restrict traversal to its
53-
own source path (``_scope_custom_frequencies``).
54-
55-
564
0.5.25 (2026-04-28)
575
~~~~~~~~~~~~~~~~~~~
586

source/isaaclab_newton/isaaclab_newton/cloner/newton_replicate.py

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -92,60 +92,48 @@ def _build_newton_builder_from_mapping(
9292
quaternions = torch.zeros((mapping.size(1), 4), device=mapping.device, dtype=torch.float32)
9393
quaternions[:, 3] = 1.0
9494

95-
# Main builder: loads only ground plane, lights, and scene-level prims.
96-
# /World/envs (and all source asset paths) are excluded via ignore_paths.
97-
#
98-
# ``SolverMuJoCo.register_custom_attributes`` is intentionally NOT called on
99-
# the main builder. Doing so would register the ``mujoco:*`` custom
100-
# frequencies, whose traversal uses ``stage.Traverse()`` and ignores
101-
# ``ignore_paths``. The traversal would find ``MjcTendon`` prims under
102-
# ``/World/envs/...`` and try to resolve their joint paths against the main
103-
# builder's empty ``joint_label`` (no joints loaded), emitting "unknown
104-
# joint path" warnings and silently dropping every tendon.
105-
main_resolvers = [SchemaResolverNewton(), SchemaResolverPhysx()]
95+
# ``SchemaResolverMjc`` is intentionally EXCLUDED from the resolver chain:
96+
# ``MjcTendon`` prims are parsed by the ``mujoco:*`` custom frequencies
97+
# (registered via ``SolverMuJoCo.register_custom_attributes`` on each proto
98+
# below), not by the schema-resolver chain. Adding ``SchemaResolverMjc``
99+
# would change which schema wins for non-tendon properties (shape margins/
100+
# gaps, joint limit ke/kd, armature, material stiffness/damping) on MJCF-
101+
# derived USDs that also carry ``physx:``/``newton:`` authoring — those
102+
# should keep their current Newton/PhysX precedence.
103+
schema_resolvers = [SchemaResolverNewton(), SchemaResolverPhysx()]
106104
builder = NewtonManager.create_builder(up_axis=up_axis)
107105
stage_info = builder.add_usd(
108106
stage,
109107
ignore_paths=["/World/envs"] + sources,
110-
schema_resolvers=main_resolvers,
108+
schema_resolvers=schema_resolvers,
111109
)
112110

113-
# Proto resolvers match the main builder. SchemaResolverMjc is intentionally
114-
# EXCLUDED: MjcTendon prims are parsed by the ``mujoco:*`` custom frequencies
115-
# (registered via ``SolverMuJoCo.register_custom_attributes`` below), not by
116-
# the schema-resolver chain. Adding ``SchemaResolverMjc`` would change which
117-
# schema wins for non-tendon properties (shape margins/gaps, joint limit
118-
# ke/kd, armature, material stiffness/damping) on MJCF-derived USDs that
119-
# also carry ``physx:``/``newton:`` authoring — those should keep their
120-
# current Newton/PhysX precedence.
121-
# Both resolver classes are stateless (no instance fields); sharing one set
122-
# across proto builders is safe.
123-
proto_resolvers = [SchemaResolverNewton(), SchemaResolverPhysx()]
124-
125111
# The prototype is built from env_0 in absolute world coordinates.
126112
# add_builder xforms are deltas from env_0 so positions don't get double-counted.
127113
env0_pos = positions[0]
128114
protos: dict[str, ModelBuilder] = {}
129115
for src_path in sources:
130-
# ``register_custom_attributes`` registers the ``mujoco:*`` custom
131-
# frequencies on this builder, which is what drives MjcTendon parsing
132-
# (the resolver chain does not). It must run before ``add_usd`` so the
133-
# custom-frequency traversal can resolve MjcTendon joint paths against
134-
# this proto's fully populated joint_label.
116+
# ``register_custom_attributes`` is what drives ``MjcTendon`` parsing
117+
# (not the resolver chain). It must run before ``add_usd`` so the
118+
# custom-frequency traversal can resolve ``MjcTendon`` joint paths
119+
# against this proto's fully populated ``joint_label``. It is NOT
120+
# called on the main builder above: the traversal ignores
121+
# ``ignore_paths`` and would find ``MjcTendon`` prims under
122+
# ``/World/envs/...`` and silently drop them against the main
123+
# builder's empty ``joint_label``.
135124
p = NewtonManager.create_builder(up_axis=up_axis)
136125
solvers.SolverMuJoCo.register_custom_attributes(p)
137-
# Newton's custom-frequency traversal uses stage.Traverse() unconditionally,
138-
# ignoring root_path. In heterogeneous plans with multiple MJCF sources that
139-
# each have tendons, proto A's traversal would also find source B's MjcTendon
140-
# prims. Patch the filters to restrict them to src_path so only this proto's
141-
# own tendons are resolved.
126+
# Newton's custom-frequency traversal uses ``stage.Traverse()``
127+
# unconditionally, ignoring ``root_path``. Without scoping, proto A's
128+
# traversal would also match source B's ``MjcTendon`` prims in
129+
# heterogeneous-source plans.
142130
_scope_custom_frequencies(p, src_path)
143131
p.add_usd(
144132
stage,
145133
root_path=src_path,
146134
load_visual_shapes=True,
147135
skip_mesh_approximation=True,
148-
schema_resolvers=proto_resolvers,
136+
schema_resolvers=schema_resolvers,
149137
)
150138
if simplify_meshes:
151139
p.approximate_meshes("convex_hull", keep_visual_shapes=True)

0 commit comments

Comments
 (0)