Skip to content

Commit f6751d2

Browse files
committed
sdf cylinder
1 parent 156080a commit f6751d2

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

mujoco_warp/_src/collision_driver_test.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,24 @@ def test_box_box_face_penetration_depth(self):
11211121
</worldbody>
11221122
</mujoco>
11231123
""",
1124+
"sdf_cylinder": """
1125+
<mujoco>
1126+
<option sdf_iterations="10" sdf_initpoints="40"/>
1127+
<asset>
1128+
<mesh name="cube"
1129+
vertex="1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1"/>
1130+
</asset>
1131+
<worldbody>
1132+
<body pos="0 0 0">
1133+
<geom type="cylinder" size="0.3 0.6"/>
1134+
</body>
1135+
<body pos="0 0 1.5" euler="30 0 0">
1136+
<freejoint/>
1137+
<geom type="sdf" mesh="cube"/>
1138+
</body>
1139+
</worldbody>
1140+
</mujoco>
1141+
""",
11241142
}
11251143

11261144
@parameterized.parameters(_SDF_VOLUME.keys())

mujoco_warp/_src/collision_sdf.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ def capsule(p: wp.vec3, size: wp.vec3) -> float:
193193
return wp.length(diff) - r
194194

195195

196+
@wp.func
197+
def cylinder(p: wp.vec3, size: wp.vec3) -> float:
198+
r = size[0]
199+
h = size[1]
200+
dx = wp.length(wp.vec2(p[0], p[1])) - r
201+
dy = wp.abs(p[2]) - h
202+
return wp.min(wp.max(dx, dy), 0.0) + wp.length(wp.vec2(wp.max(dx, 0.0), wp.max(dy, 0.0)))
203+
204+
196205
@wp.func
197206
def grad_sphere(p: wp.vec3) -> wp.vec3:
198207
c = wp.length(p)
@@ -252,6 +261,40 @@ def grad_capsule(p: wp.vec3, size: wp.vec3) -> wp.vec3:
252261
return wp.vec3(0.0)
253262

254263

264+
@wp.func
265+
def grad_cylinder(p: wp.vec3, size: wp.vec3) -> wp.vec3:
266+
r = size[0]
267+
h = size[1]
268+
269+
radial_dist = wp.length(wp.vec2(p[0], p[1]))
270+
if radial_dist > MJ_MINVAL:
271+
u = wp.vec3(p[0] / radial_dist, p[1] / radial_dist, 0.0)
272+
else:
273+
u = wp.vec3(0.0)
274+
275+
w = wp.vec3(0.0, 0.0, wp.sign(p[2]))
276+
277+
dx = radial_dist - r
278+
dy = wp.abs(p[2]) - h
279+
280+
if dx > 0.0 and dy > 0.0:
281+
v = wp.vec2(dx, dy)
282+
len_v = wp.length(v)
283+
if len_v > MJ_MINVAL:
284+
return u * (dx / len_v) + w * (dy / len_v)
285+
else:
286+
return wp.vec3(0.0)
287+
elif dx > 0.0:
288+
return u
289+
elif dy > 0.0:
290+
return w
291+
else:
292+
if dx > dy:
293+
return u
294+
else:
295+
return w
296+
297+
255298
@wp.func
256299
def user_sdf(p: wp.vec3, attr: vec_pluginattr, sdf_type: int) -> float:
257300
"""User-defined SDF function.
@@ -418,6 +461,8 @@ def sdf(type: int, p: wp.vec3, attr: vec_pluginattr, sdf_type: int, volume_data:
418461
return sphere(p, attr_vec3)
419462
elif type == GeomType.CAPSULE:
420463
return capsule(p, attr_vec3)
464+
elif type == GeomType.CYLINDER:
465+
return cylinder(p, attr_vec3)
421466
elif type == GeomType.BOX:
422467
return box(p, attr_vec3)
423468
elif type == GeomType.ELLIPSOID:
@@ -478,6 +523,8 @@ def sdf_grad(
478523
return grad_sphere(p)
479524
elif type == GeomType.CAPSULE:
480525
return grad_capsule(p, attr_vec3)
526+
elif type == GeomType.CYLINDER:
527+
return grad_cylinder(p, attr_vec3)
481528
elif type == GeomType.BOX:
482529
return grad_box(p, attr_vec3)
483530
elif type == GeomType.ELLIPSOID:

0 commit comments

Comments
 (0)