Skip to content

Commit cc3b2fc

Browse files
Merge pull request #15 from andrewkaufman/articulation-root
Body : Remove ArticulationRootAPI from non-jointed bodies
2 parents e238092 + 57afb3a commit cc3b2fc

File tree

3 files changed

+18
-2
lines changed

3 files changed

+18
-2
lines changed

mujoco_usd_converter/_impl/body.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def convert_body(parent: Usd.Prim, name: str, body: mujoco.MjsBody, data: Conver
7676
safe_names = data.name_cache.getPrimNames(body_prim, [x.name for x in body.bodies])
7777
for child_body, safe_name in zip(body.bodies, safe_names):
7878
child_body_prim = convert_body(parent=body_prim, name=safe_name, body=child_body, data=data)
79-
if child_body_prim and body == data.spec.worldbody:
79+
if child_body_prim and body == data.spec.worldbody and has_articulated_children(child_body):
8080
child_body_over = data.content[Tokens.Physics].OverridePrim(child_body_prim.GetPath())
8181
UsdPhysics.ArticulationRootAPI.Apply(child_body_over)
8282

@@ -91,6 +91,16 @@ def is_kinematic(body: mujoco.MjsBody, physics_prim: Usd.Prim) -> bool:
9191
return kinematic_attr and kinematic_attr.Get()
9292

9393

94+
def has_articulated_children(body: mujoco.MjsBody) -> bool:
95+
# Check if this body has child bodies with non-free joints
96+
for child_body in body.bodies:
97+
if child_body.joints:
98+
for joint in child_body.joints:
99+
if joint.type != mujoco.mjtJoint.mjJNT_FREE:
100+
return True
101+
return False
102+
103+
94104
def extract_inertia(fullinertia: np.ndarray) -> tuple[Gf.Quatf, Gf.Vec3f]:
95105
mat = np.zeros((3, 3))
96106
mat[0, 0] = fullinertia[0]

tests/data/bodies.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<geom type="box" size="0.1 0.1 0.1"/>
55
<body name="nested_body" pos="0 1 0">
66
<geom type="box" size="0.1 0.1 0.1"/>
7+
<joint type="hinge"/>
78
</body>
89
</body>
910

tests/testBodies.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def setUp(self):
1818
self.stage: Usd.Stage = Usd.Stage.Open(asset.path)
1919
self.assertIsValidUsd(self.stage)
2020

21-
def test_bodies(self):
21+
def test_articulation_roots(self):
2222
# Root body is an Articulation Root
2323
prim = self.stage.GetPrimAtPath("/bodies/Geometry/root_body")
2424
self.assertTrue(prim.HasAPI(UsdPhysics.ArticulationRootAPI))
@@ -29,6 +29,11 @@ def test_bodies(self):
2929
self.assertFalse(prim.HasAPI(UsdPhysics.ArticulationRootAPI))
3030
self.assertTrue(prim.HasAPI(UsdPhysics.RigidBodyAPI))
3131

32+
# Kinematic Body is not an articulation root as there are no joints to its child bodies
33+
prim = self.stage.GetPrimAtPath("/bodies/Geometry/kinematic_body")
34+
self.assertFalse(prim.HasAPI(UsdPhysics.ArticulationRootAPI))
35+
self.assertTrue(prim.HasAPI(UsdPhysics.RigidBodyAPI))
36+
3237
def test_kinematic_body(self):
3338
# mocap body is kinematic
3439
prim = self.stage.GetPrimAtPath("/bodies/Geometry/kinematic_body")

0 commit comments

Comments
 (0)