@@ -1629,27 +1629,49 @@ def modify_joint_drive_properties(
16291629"""
16301630
16311631
1632- def _applied_schema_instance (applied_schema , schema_type : str ) -> str | None :
1633- """Return an applied multiple-apply schema's instance when its type matches exactly."""
1634- applied_type , instance = Usd .SchemaRegistry .GetTypeNameAndInstance (str (applied_schema ))
1635- return instance if applied_type == schema_type and instance else None
1632+ _FIXED_TENDON_SCHEMAS = ("PhysxTendonAxisRootAPI" , "PhysxTendonAxisAPI" )
1633+ _SPATIAL_TENDON_SCHEMAS = ("PhysxTendonAttachmentRootAPI" ,)
16361634
16371635
1638- def _is_fixed_tendon_target (prim : Usd .Prim ) -> bool :
1639- """Whether a prim carries a fixed-tendon representation."""
1640- if prim .GetTypeName () == "MjcTendon" :
1641- return True
1642- fixed_types = {"PhysxTendonAxisRootAPI" , "PhysxTendonAxisAPI" }
1643- return any (
1644- _applied_schema_instance (schema , schema_type )
1645- for schema in prim .GetAppliedSchemas ()
1646- for schema_type in fixed_types
1647- )
1636+ def _write_tendon_properties (prim , values , schema_type ):
1637+ authored = False
1638+ for schema in prim .GetAppliedSchemas ():
1639+ applied_type , instance = Usd .SchemaRegistry .GetTypeNameAndInstance (str (schema ))
1640+ if applied_type != schema_type or not instance :
1641+ continue
1642+ authored = True
1643+ for name , value in values .items ():
1644+ attribute = f"physxTendon:{ instance } :{ to_camel_case (name , 'cC' )} "
1645+ safe_set_attribute_on_usd_prim (prim , attribute , value , camel_case = False )
1646+ return authored
16481647
16491648
1650- def _is_spatial_tendon_target (prim : Usd .Prim ) -> bool :
1651- """Whether a prim carries a spatial-tendon root instance."""
1652- return any (_applied_schema_instance (schema , "PhysxTendonAttachmentRootAPI" ) for schema in prim .GetAppliedSchemas ())
1649+ def _apply_tendon_fragments (prim_path_expr , fragments , schema_types , prim_types , family , stage ):
1650+ fragments = list (fragments )
1651+ if stage is None :
1652+ stage = get_current_stage ()
1653+ if not fragments :
1654+ return True
1655+ targets , _ , any_skipped = _match_fragment_targets (
1656+ prim_path_expr ,
1657+ lambda prim : prim .GetTypeName () in prim_types
1658+ or any (
1659+ Usd .SchemaRegistry .GetTypeNameAndInstance (str (schema ))[0 ] in schema_types
1660+ for schema in prim .GetAppliedSchemas ()
1661+ ),
1662+ stage ,
1663+ )
1664+ if not targets :
1665+ logger .warning ("No %s-tendon targets matched expression '%s'; nothing was authored." , family , prim_path_expr )
1666+ return False
1667+ success = not any_skipped
1668+ for cfg in fragments :
1669+ func = cfg .func if callable (cfg .func ) else string_to_callable (cfg .func )
1670+ fragment_hit = False
1671+ for target in targets :
1672+ fragment_hit |= bool (func (cfg , target .GetPath ().pathString , stage ))
1673+ success = fragment_hit and success
1674+ return success
16531675
16541676
16551677def apply_fixed_tendon_properties (
@@ -1684,26 +1706,7 @@ def apply_fixed_tendon_properties(
16841706 Returns:
16851707 True if every fragment tuned at least one target and no instanced prim was skipped.
16861708 """
1687- fragments = list (fragments )
1688- if stage is None :
1689- stage = get_current_stage ()
1690- if not fragments :
1691- return True
1692- targets , _ , any_skipped = _match_fragment_targets (prim_path_expr , _is_fixed_tendon_target , stage )
1693- if not targets :
1694- logger .warning ("No fixed-tendon targets matched expression '%s'; nothing was authored." , prim_path_expr )
1695- return False
1696- # per-fragment any-target aggregation: a fragment fails only when it tuned no target at all,
1697- # since each backend's func legitimately no-ops on the other backend's tendon prims.
1698- success = not any_skipped
1699- for cfg in fragments :
1700- func = cfg .func if callable (cfg .func ) else string_to_callable (cfg .func )
1701- fragment_hit = False
1702- for target in targets :
1703- if func (cfg , target .GetPath ().pathString , stage ):
1704- fragment_hit = True
1705- success = fragment_hit and success
1706- return success
1709+ return _apply_tendon_fragments (prim_path_expr , fragments , _FIXED_TENDON_SCHEMAS , ("MjcTendon" ,), "fixed" , stage )
17071710
17081711
17091712@apply_nested
@@ -1744,42 +1747,12 @@ def modify_fixed_tendon_properties(
17441747 if stage is None :
17451748 stage = get_current_stage ()
17461749
1747- # get USD prim
17481750 tendon_prim = stage .GetPrimAtPath (prim_path )
1749- # check if prim has fixed tendon applied on it or if the mjc tendon prim exiss
1750- applied_schemas = tendon_prim .GetAppliedSchemas ()
1751- prim_type = tendon_prim .GetTypeName ()
1752- if (
1753- not any (_applied_schema_instance (schema , "PhysxTendonAxisRootAPI" ) for schema in applied_schemas )
1754- and prim_type != "MjcTendon"
1755- ):
1756- return False
1757-
1758- # resolve all available instances of the schema since it is multi-instance
1759- cfg = cfg .to_dict ()
1760- if prim_type != "MjcTendon" :
1761- for schema_name in applied_schemas :
1762- instance_name = _applied_schema_instance (schema_name , "PhysxTendonAxisRootAPI" )
1763- if instance_name is None :
1764- continue
1765- for attr_name , value in cfg .items ():
1766- template = f"physxTendon:__INSTANCE_NAME__:{ to_camel_case (attr_name , 'cC' )} "
1767- attribute = Usd .SchemaRegistry .MakeMultipleApplyNameInstance (template , instance_name )
1768- safe_set_attribute_on_usd_prim (
1769- tendon_prim ,
1770- attribute ,
1771- value ,
1772- camel_case = False ,
1773- )
1774- else :
1775- # NOTE: ``mjc:*`` branch (``MjcTendon`` prim) kept inline; future split candidate into isaaclab_newton.
1776- # only stiffness and damping in the cfg map to mjc attributes
1777- for attr_name in ("stiffness" , "damping" ):
1778- value = cfg .get (attr_name )
1779- safe_set_attribute_on_usd_prim (
1780- tendon_prim , f"mjc:{ to_camel_case (attr_name , 'cC' )} " , value , camel_case = False
1781- )
1782- # success
1751+ values = cfg .to_dict ()
1752+ if tendon_prim .GetTypeName () != "MjcTendon" :
1753+ return _write_tendon_properties (tendon_prim , values , "PhysxTendonAxisRootAPI" )
1754+ for name in ("stiffness" , "damping" ):
1755+ safe_set_attribute_on_usd_prim (tendon_prim , f"mjc:{ name } " , values .get (name ), camel_case = False )
17831756 return True
17841757
17851758
@@ -1819,26 +1792,7 @@ def apply_spatial_tendon_properties(
18191792 Returns:
18201793 True if every fragment tuned at least one target and no instanced prim was skipped.
18211794 """
1822- fragments = list (fragments )
1823- if stage is None :
1824- stage = get_current_stage ()
1825- if not fragments :
1826- return True
1827- targets , _ , any_skipped = _match_fragment_targets (prim_path_expr , _is_spatial_tendon_target , stage )
1828- if not targets :
1829- logger .warning ("No spatial-tendon targets matched expression '%s'; nothing was authored." , prim_path_expr )
1830- return False
1831- # per-fragment any-target aggregation: a fragment fails only when it tuned no target at all,
1832- # since each backend's func legitimately no-ops on the other backend's tendon prims.
1833- success = not any_skipped
1834- for cfg in fragments :
1835- func = cfg .func if callable (cfg .func ) else string_to_callable (cfg .func )
1836- fragment_hit = False
1837- for target in targets :
1838- if func (cfg , target .GetPath ().pathString , stage ):
1839- fragment_hit = True
1840- success = fragment_hit and success
1841- return success
1795+ return _apply_tendon_fragments (prim_path_expr , fragments , _SPATIAL_TENDON_SCHEMAS , (), "spatial" , stage )
18421796
18431797
18441798@apply_nested
@@ -1878,30 +1832,8 @@ def modify_spatial_tendon_properties(
18781832 # obtain stage
18791833 if stage is None :
18801834 stage = get_current_stage ()
1881- # get USD prim
18821835 tendon_prim = stage .GetPrimAtPath (prim_path )
1883- # check if prim has spatial tendon applied on it
1884- applied_schemas = tendon_prim .GetAppliedSchemas ()
1885- has_spatial = any (_applied_schema_instance (schema , "PhysxTendonAttachmentRootAPI" ) for schema in applied_schemas )
1886- if not has_spatial :
1887- return False
1888-
1889- cfg = cfg .to_dict ()
1890- for schema_name in applied_schemas :
1891- instance_name = _applied_schema_instance (schema_name , "PhysxTendonAttachmentRootAPI" )
1892- if instance_name is None :
1893- continue
1894- for attr_name , value in cfg .items ():
1895- template = f"physxTendon:__INSTANCE_NAME__:{ to_camel_case (attr_name , 'cC' )} "
1896- attribute = Usd .SchemaRegistry .MakeMultipleApplyNameInstance (template , instance_name )
1897- safe_set_attribute_on_usd_prim (
1898- tendon_prim ,
1899- attribute ,
1900- value ,
1901- camel_case = False ,
1902- )
1903- # success
1904- return True
1836+ return _write_tendon_properties (tendon_prim , cfg .to_dict (), "PhysxTendonAttachmentRootAPI" )
19051837
19061838
19071839"""
0 commit comments