Add support for querying of MjsTendon path from Python.

Fixes #2670

PiperOrigin-RevId: 822215254
Change-Id: Ice5a264e54f963776093511c6e4ac830aae6d4f8
This commit is contained in:
Sam Haves
2025-10-21 11:50:24 -07:00
committed by Copybara-Service
parent 2f65e23779
commit ac2cd5dfd6
9 changed files with 411 additions and 11 deletions
+54 -10
View File
@@ -1511,27 +1511,28 @@ class SpecsTest(absltest.TestCase):
body = spec.worldbody.add_body(name='body')
body.add_geom(name='body_geom', pos=[0, 0, 0], size=[.1, 0, 0])
body.add_site(name='site1', pos=[0, 0, 0])
body.add_site(name='site2', pos=[0, 0, -1])
body.add_site(name='site3', pos=[0, 0, -4])
body.add_site(name='site4', pos=[0, 1, -6])
site1 = body.add_site(name='site1', pos=[0, 0, 0])
site2 = body.add_site(name='site2', pos=[0, 0, -1])
site3 = body.add_site(name='site3', pos=[0, 0, -4])
sidesite = body.add_site(name='sidesite', pos=[2, 0, -5])
site4 = body.add_site(name='site4', pos=[0, 1, -6])
spec.worldbody.add_geom(name='sphere', size=[.2, 0, 0], pos=[0, 0, -2])
sphere = spec.worldbody.add_geom(name='sphere', size=[.2, 0, 0], pos=[0, 0, -2])
spec.worldbody.add_geom(
cylinder = spec.worldbody.add_geom(
name='cylinder',
type=mujoco.mjtGeom.mjGEOM_CYLINDER,
size=[0.1, 0.2, 0.3],
pos=[0, 0, -5]
)
body.add_joint(
joint1 = body.add_joint(
name='joint1', type=mujoco.mjtJoint.mjJNT_HINGE, axis=[0, 1, 0]
)
body2 = spec.worldbody.add_body(name='body2', pos=[2, 0, 0])
body2.add_geom(name='body2_geom', pos=[0, 0, 0], size=[.1, 0, 0])
body2.add_joint(
joint2 = body2.add_joint(
name='joint2', type=mujoco.mjtJoint.mjJNT_HINGE, axis=[0, 1, 0]
)
@@ -1546,11 +1547,50 @@ class SpecsTest(absltest.TestCase):
wrap_site4_1 = spatial_tendon.wrap_site('site4')
wrap_pulley2 = spatial_tendon.wrap_pulley(2.0)
wrap_site3_2 = spatial_tendon.wrap_site('site3')
wrap_cylinder = spatial_tendon.wrap_geom('cylinder', '')
wrap_cylinder = spatial_tendon.wrap_geom('cylinder', 'sidesite')
wrap_site4_2 = spatial_tendon.wrap_site('site4')
wrap_joint1 = fixed_tendon.wrap_joint('joint1', 1.0)
wrap_joint2 = fixed_tendon.wrap_joint('joint2', 1.0)
wrap_joint2 = fixed_tendon.wrap_joint('joint2', 2.0)
self.assertListEqual(
list(spatial_tendon.path),
[
wrap_site1,
wrap_site2,
wrap_pulley1,
wrap_site3_1,
wrap_sphere,
wrap_site4_1,
wrap_pulley2,
wrap_site3_2,
wrap_cylinder,
wrap_site4_2,
],
)
self.assertListEqual(
[w.target for w in spatial_tendon.path],
[
site1,
site2,
None, # Pulley wraps have no targets
site3,
sphere,
site4,
None, # Pulley wraps have no targets
site3,
cylinder,
site4,
],
)
self.assertEqual(spatial_tendon.path[8].sidesite, sidesite)
self.assertIsNone(spatial_tendon.path[7].sidesite)
self.assertListEqual(list(fixed_tendon.path), [wrap_joint1, wrap_joint2])
self.assertListEqual(
[w.target for w in fixed_tendon.path],
[joint1, joint2]
)
# Wrap type for geom is only set during compilation.
spec.compile()
@@ -1562,12 +1602,16 @@ class SpecsTest(absltest.TestCase):
self.assertEqual(wrap_site3_2.type, mujoco.mjtWrap.mjWRAP_SITE)
self.assertEqual(wrap_site4_2.type, mujoco.mjtWrap.mjWRAP_SITE)
self.assertEqual(wrap_pulley1.type, mujoco.mjtWrap.mjWRAP_PULLEY)
self.assertEqual(wrap_pulley1.divisor, 2.0)
self.assertEqual(wrap_sphere.type, mujoco.mjtWrap.mjWRAP_SPHERE)
self.assertEqual(wrap_cylinder.type, mujoco.mjtWrap.mjWRAP_CYLINDER)
self.assertEqual(wrap_pulley2.type, mujoco.mjtWrap.mjWRAP_PULLEY)
self.assertEqual(wrap_pulley2.divisor, 2.0)
self.assertEqual(wrap_joint1.type, mujoco.mjtWrap.mjWRAP_JOINT)
self.assertEqual(wrap_joint1.coef, 1.0)
self.assertEqual(wrap_joint2.type, mujoco.mjtWrap.mjWRAP_JOINT)
self.assertEqual(wrap_joint2.coef, 2.0)
if __name__ == '__main__':
absltest.main()