Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
80cf81f
adds newton tend props rando
nv-rgresia May 6, 2026
ceb6579
adds tendon buffers and bindings
nv-rgresia May 6, 2026
6834867
adds process tendon
nv-rgresia May 6, 2026
6e82fe5
adds fixed tendon props prim
nv-rgresia May 6, 2026
2cfebd9
Merge branch 'develop' of github.com:isaac-sim/IsaacLab into passive-…
nv-rgresia May 8, 2026
183022a
Merge branch 'develop' of github.com:isaac-sim/IsaacLab into passive-…
nv-rgresia May 8, 2026
27a551b
refactor tendon randomization event
nv-rgresia May 14, 2026
f5f43d4
articulation cleanup
nv-rgresia May 14, 2026
3a54517
cleanup
nv-rgresia May 14, 2026
2744b3e
tendon log cleanup
nv-rgresia May 14, 2026
aa87f5f
updates changelog
nv-rgresia May 14, 2026
e054aa2
Merge branch 'develop' into passive-tendons
nv-rgresia May 14, 2026
c7dd84d
Merge branch 'develop' into passive-tendons
nv-rgresia May 15, 2026
99b1a61
Merge branch 'develop' into passive-tendons
nv-rgresia May 15, 2026
614dbb6
Merge branch 'develop' into passive-tendons
nv-rgresia May 15, 2026
5b2f873
updates backend handling
nv-rgresia May 15, 2026
4b50d5f
adds tendon count
nv-rgresia May 15, 2026
997200d
Merge branch 'develop' into passive-tendons
kellyguo11 May 16, 2026
ad103b4
Merge branch 'develop' into passive-tendons
kellyguo11 May 16, 2026
40135b6
Merge branch 'develop' into passive-tendons
kellyguo11 May 16, 2026
f963a5a
Merge remote-tracking branch 'origin/develop' into passive-tendons
nv-rgresia May 18, 2026
fdf2197
updates shadowhand newton path
nv-rgresia May 18, 2026
a2ded62
Merge branch 'passive-tendons' of github.com:nv-rgresia/IsaacLab into…
nv-rgresia May 18, 2026
b8c6a88
Merge branch 'develop' into passive-tendons
kellyguo11 May 19, 2026
db60dfc
Merge remote-tracking branch 'origin/develop' into passive-tendons
nv-rgresia May 19, 2026
2c0ac85
Merge branch 'passive-tendons' of github.com:nv-rgresia/IsaacLab into…
nv-rgresia May 19, 2026
3d0a74f
Merge branch 'develop' into passive-tendons
kellyguo11 May 19, 2026
2512c92
Merge branch 'develop' into passive-tendons
kellyguo11 May 20, 2026
26b6e41
repositions cube
nv-rgresia May 20, 2026
f4f71f9
Merge branch 'develop' into passive-tendons
nv-rgresia May 20, 2026
2cc82be
shadow env cleanup
nv-rgresia May 20, 2026
d48b845
Merge branch 'passive-tendons' of github.com:nv-rgresia/IsaacLab into…
nv-rgresia May 20, 2026
29068bf
fixes hand rotation plus cleanup
nv-rgresia May 20, 2026
d32c593
Merge branch 'develop' into passive-tendons
nv-rgresia May 21, 2026
bda9004
Merge branch 'develop' into passive-tendons
nv-rgresia May 21, 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
4 changes: 4 additions & 0 deletions source/isaaclab/changelog.d/passive-tendons.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Added
^^^^^
* Updates tendon randomization events to support newton tendons
* Adds support to modify MJC usd schema
133 changes: 73 additions & 60 deletions source/isaaclab/isaaclab/envs/mdp/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -1565,6 +1565,8 @@ def __call__(
operation: Literal["add", "scale", "abs"] = "abs",
distribution: Literal["uniform", "log_uniform", "gaussian"] = "uniform",
):
_backend = env.sim.physics_manager.__name__.lower()

# resolve environment ids
if env_ids is None:
env_ids = torch.arange(env.scene.num_envs, device=self.asset.device)
Expand Down Expand Up @@ -1606,80 +1608,91 @@ def __call__(

# limit stiffness
if limit_stiffness_distribution_params is not None:
limit_stiffness = _randomize_prop_by_op(
self.asset.data.fixed_tendon_limit_stiffness.torch.clone(),
limit_stiffness_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
self.asset.set_fixed_tendon_limit_stiffness(
limit_stiffness[env_ids[:, None], tendon_ids], tendon_ids, env_ids
)
if _backend == "physx":
limit_stiffness = _randomize_prop_by_op(
self.asset.data.fixed_tendon_limit_stiffness.torch.clone(),
limit_stiffness_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
self.asset.set_fixed_tendon_limit_stiffness(
limit_stiffness[env_ids[:, None], tendon_ids], tendon_ids, env_ids
)
else:
raise NotImplementedError("Limit stiffness is not support in Newton.")

# position limits
if lower_limit_distribution_params is not None or upper_limit_distribution_params is not None:
limit = self.asset.data.fixed_tendon_pos_limits.torch.clone()
# -- lower limit
if lower_limit_distribution_params is not None:
limit[..., 0] = _randomize_prop_by_op(
limit[..., 0],
lower_limit_distribution_params,
if _backend == "physx":
limit = self.asset.data.fixed_tendon_pos_limits.torch.clone()
# -- lower limit
if lower_limit_distribution_params is not None:
limit[..., 0] = _randomize_prop_by_op(
limit[..., 0],
lower_limit_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
# -- upper limit
if upper_limit_distribution_params is not None:
limit[..., 1] = _randomize_prop_by_op(
limit[..., 1],
upper_limit_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)

# check if the limits are valid
tendon_limits = limit[env_ids[:, None], tendon_ids]
if (tendon_limits[..., 0] > tendon_limits[..., 1]).any():
raise ValueError(
"Randomization term 'randomize_fixed_tendon_parameters' is setting lower tendon limits that are"
" greater than upper tendon limits."
)
self.asset.set_fixed_tendon_position_limit_index(
limit=tendon_limits, fixed_tendon_ids=tendon_ids, env_ids=env_ids
)
else:
raise NotImplementedError("Position limits is not yet implemented with Newton.")

# rest length
if rest_length_distribution_params is not None:
if _backend == "physx":
rest_length = _randomize_prop_by_op(
self.asset.data.fixed_tendon_rest_length.torch.clone(),
rest_length_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
# -- upper limit
if upper_limit_distribution_params is not None:
limit[..., 1] = _randomize_prop_by_op(
limit[..., 1],
upper_limit_distribution_params,
self.asset.set_fixed_tendon_rest_length_index(
rest_length=rest_length[env_ids[:, None], tendon_ids], fixed_tendon_ids=tendon_ids, env_ids=env_ids
)
else:
raise NotImplementedError("Rest length is not yet implemented with Newton.")
# offset
if offset_distribution_params is not None:
if _backend == "physx":
offset = _randomize_prop_by_op(
self.asset.data.fixed_tendon_offset.torch.clone(),
offset_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)

# check if the limits are valid
tendon_limits = limit[env_ids[:, None], tendon_ids]
if (tendon_limits[..., 0] > tendon_limits[..., 1]).any():
raise ValueError(
"Randomization term 'randomize_fixed_tendon_parameters' is setting lower tendon limits that are"
" greater than upper tendon limits."
self.asset.set_fixed_tendon_offset_index(
offset=offset[env_ids[:, None], tendon_ids], fixed_tendon_ids=tendon_ids, env_ids=env_ids
)
self.asset.set_fixed_tendon_position_limit_index(
limit=tendon_limits, fixed_tendon_ids=tendon_ids, env_ids=env_ids
)

# rest length
if rest_length_distribution_params is not None:
rest_length = _randomize_prop_by_op(
self.asset.data.fixed_tendon_rest_length.torch.clone(),
rest_length_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
self.asset.set_fixed_tendon_rest_length_index(
rest_length=rest_length[env_ids[:, None], tendon_ids], fixed_tendon_ids=tendon_ids, env_ids=env_ids
)

# offset
if offset_distribution_params is not None:
offset = _randomize_prop_by_op(
self.asset.data.fixed_tendon_offset.torch.clone(),
offset_distribution_params,
env_ids,
tendon_ids,
operation=operation,
distribution=distribution,
)
self.asset.set_fixed_tendon_offset_index(
offset=offset[env_ids[:, None], tendon_ids], fixed_tendon_ids=tendon_ids, env_ids=env_ids
)
else:
raise NotImplementedError("Offset is not supported in Newton.")

# write the fixed tendon properties into the simulation
self.asset.write_fixed_tendon_properties_to_sim_index(env_ids=env_ids)
Expand Down
28 changes: 18 additions & 10 deletions source/isaaclab/isaaclab/sim/schemas/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,23 +882,31 @@ def modify_fixed_tendon_properties(

# get USD prim
tendon_prim = stage.GetPrimAtPath(prim_path)
# check if prim has fixed tendon applied on it
# check if prim has fixed tendon applied on it or if the mjc tendon prim exiss
applied_schemas = tendon_prim.GetAppliedSchemas()
if not any("PhysxTendonAxisRootAPI" in s for s in applied_schemas):
prim_type = tendon_prim.GetTypeName()
if not any("PhysxTendonAxisRootAPI" in s for s in applied_schemas) and prim_type != "MjcTendon":
return False

# resolve all available instances of the schema since it is multi-instance
cfg = cfg.to_dict()
for schema_name in applied_schemas:
if "PhysxTendonAxisRootAPI" not in schema_name:
continue
# set into PhysX API by attribute prefix schema_name: (e.g. PhysxTendonAxisRootAPI:default:stiffness)
if prim_type != "MjcTendon":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think MjcTendon is newton specific so it may need to be added to new newton schema. #5049 has example how physx setup is done. @ooctipus could you also help suggest here?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think there are other mujoco schema also got leaked into core schema. and also seems like we have not prepared a home for mujoco schema under isaaclab_newton properly. This check is no ideal but probably makes sense for this PR, and would require follow up work to split it.

for schema_name in applied_schemas:
if "PhysxTendonAxisRootAPI" not in schema_name:
continue
# set into PhysX API by attribute prefix schema_name: (e.g. PhysxTendonAxisRootAPI:default:stiffness)
for attr_name, value in cfg.items():
safe_set_attribute_on_usd_prim(
tendon_prim,
f"{schema_name}:{to_camel_case(attr_name, 'cC')}",
value,
camel_case=False,
)
else:
# only stiffness and damping in the cfg map to mjc attributes
for attr_name, value in cfg.items():
safe_set_attribute_on_usd_prim(
tendon_prim,
f"{schema_name}:{to_camel_case(attr_name, 'cC')}",
value,
camel_case=False,
tendon_prim, f"mjc:{to_camel_case(attr_name, 'cC')}", value, camel_case=False
)
# success
return True
Expand Down
3 changes: 3 additions & 0 deletions source/isaaclab_newton/changelog.d/passive-tendons.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Added
^^^^^
* Updates articulation to support passive tendons properties
Loading
Loading