Skip to content

Sdf collisions general case #555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 46 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e9ec58e
first version
jvonmuralt Jul 28, 2025
6280fe5
tmp
jvonmuralt Jul 28, 2025
099a4ab
fix
jvonmuralt Jul 28, 2025
0cf2d87
fix
jvonmuralt Jul 28, 2025
45dfa8b
fix torus
jvonmuralt Jul 28, 2025
0a4cd28
fix
jvonmuralt Jul 29, 2025
09d420c
add plane implementation
jvonmuralt Jul 29, 2025
af003dc
fix sdf plugin registration
jvonmuralt Jul 29, 2025
d796e61
cleanup
jvonmuralt Jul 29, 2025
ff35b6b
fix direction
jvonmuralt Jul 29, 2025
80ec0ec
pass oct aabb
jvonmuralt Aug 8, 2025
f1c8a73
revert pass oct aabb
jvonmuralt Aug 8, 2025
0333ff5
tmp
jvonmuralt Aug 8, 2025
0a37b09
Revert "tmp"
jvonmuralt Aug 13, 2025
1672f27
Revert "revert pass oct aabb"
jvonmuralt Aug 13, 2025
b29a8db
add projection
jvonmuralt Aug 13, 2025
2e7addc
add test
jvonmuralt Aug 19, 2025
a5a5888
Merge remote-tracking branch 'upstream/main' into sdf_collisions
jvonmuralt Aug 19, 2025
5beaedf
format
jvonmuralt Aug 19, 2025
ab5d742
cleanup
jvonmuralt Aug 19, 2025
39a5caa
cleanup
jvonmuralt Aug 19, 2025
ef47385
kernel cleanup
jvonmuralt Aug 19, 2025
cd8250b
use warp world to index conversion
jvonmuralt Aug 19, 2025
b828d9c
kernel param fix
jvonmuralt Aug 19, 2025
f6422af
kernel write
jvonmuralt Aug 19, 2025
002e8be
fix
jvonmuralt Aug 19, 2025
671b134
minor
jvonmuralt Aug 19, 2025
83632c2
minor
jvonmuralt Aug 19, 2025
201e51f
fix some tests
jvonmuralt Aug 19, 2025
6cc6b4f
return fd grad
jvonmuralt Aug 20, 2025
121c203
remove file
jvonmuralt Aug 20, 2025
c8dfc6d
move cow, rename, fix description
jvonmuralt Aug 20, 2025
e032943
sensor
jvonmuralt Aug 20, 2025
36473f4
minor refactor
jvonmuralt Aug 20, 2025
bc682d5
add test
jvonmuralt Aug 20, 2025
d8d1c38
sensor
jvonmuralt Aug 20, 2025
0799ec0
sensor
jvonmuralt Aug 20, 2025
61cbb5f
Revert "sensor"
jvonmuralt Aug 20, 2025
3a38c86
refactor
jvonmuralt Aug 20, 2025
624c2bd
Revert "move cow, rename, fix description"
jvonmuralt Aug 20, 2025
1a74c97
fix
jvonmuralt Aug 20, 2025
13ad081
kernel analyzer
jvonmuralt Aug 20, 2025
a3df407
kernel analyzer 2
jvonmuralt Aug 20, 2025
48e0b41
minor
jvonmuralt Aug 21, 2025
a529100
reorder
jvonmuralt Aug 21, 2025
13254ec
call mujoco_octree_to_warp_volume earlier
jvonmuralt Aug 21, 2025
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
107 changes: 107 additions & 0 deletions mujoco_warp/_src/collision_driver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import mujoco
import numpy as np
import pytest
import warp as wp
from absl.testing import absltest
from absl.testing import parameterized
Expand All @@ -25,6 +26,25 @@

from . import test_util
from . import types
from .collision_sdf import VolumeData
from .collision_sdf import sample_volume_sdf
from .io import sample_octree_sdf


@wp.kernel
def sample_sdf_kernel(
# In:
points: wp.array(dtype=wp.vec3),
volume_data: VolumeData,
# Out:
results_out: wp.array(dtype=float),
):
"""Kernel to sample SDF values at given points using Warp volume."""
tid = wp.tid()
point = points[tid]
sdf_value = sample_volume_sdf(point, volume_data)
results_out[tid] = sdf_value


_TOLERANCE = 5e-5

Expand Down Expand Up @@ -507,6 +527,93 @@ def test_sdf_collision(self, fixture):
result = check_dist
np.testing.assert_equal(result, True, f"Contact {i} not found in Gjk results")

@pytest.mark.skipif(not wp.get_device().is_cuda, reason="SDF volumes require CUDA device")
def test_sdf_volumes(self):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice!

"""Tests SDF volumes."""
mjm, mjd, m, d = test_util.fixture(fname="collision_sdf/cow.xml", qpos0=True)

octadr = mjm.mesh_octadr[0]
oct_child = mjm.oct_child[8 * octadr :].reshape(-1, 8)
oct_aabb = mjm.oct_aabb[6 * octadr :].reshape(-1, 6)
oct_coeff = mjm.oct_coeff[8 * octadr :].reshape(-1, 8)

cow_geom_id = 2
root_aabb = oct_aabb[0]
vmin = root_aabb[:3] - root_aabb[3:]
vmax = root_aabb[:3] + root_aabb[3:]

test_points_local = []
margin = 0.02
vmin_safe = vmin + margin * (vmax - vmin)
vmax_safe = vmax - margin * (vmax - vmin)

center = (vmin + vmax) / 2.0
test_points_local.append(center)

corners = [
np.array([vmin[0], vmin[1], vmin[2]]),
np.array([vmax[0], vmin[1], vmin[2]]),
np.array([vmin[0], vmax[1], vmin[2]]),
np.array([vmin[0], vmin[1], vmax[2]]),
np.array([vmax[0], vmax[1], vmin[2]]),
np.array([vmax[0], vmin[1], vmax[2]]),
np.array([vmin[0], vmax[1], vmax[2]]),
np.array([vmax[0], vmax[1], vmax[2]]),
]
test_points_local.extend(corners)

face_centers = [
np.array([vmin[0], center[1], center[2]]),
np.array([vmax[0], center[1], center[2]]),
np.array([center[0], vmin[1], center[2]]),
np.array([center[0], vmax[1], center[2]]),
np.array([center[0], center[1], vmin[2]]),
np.array([center[0], center[1], vmax[2]]),
]
test_points_local.extend(face_centers)

for i in range(6):
t = i / 5.0
point_local = vmin_safe + t * (vmax_safe - vmin_safe)
for dim in range(3):
variation = 0.1 * (i % 3 - 1) / 6.0 * (vmax_safe[dim] - vmin_safe[dim])
point_local[dim] += variation
point_local = np.clip(point_local, vmin_safe, vmax_safe)
test_points_local.append(point_local)

num_test_points = len(test_points_local)
points_array = wp.array([wp.vec3(p[0], p[1], p[2]) for p in test_points_local], dtype=wp.vec3)
results_array = wp.zeros(num_test_points, dtype=float)

volume_data = VolumeData()
cow_mesh_id = mjm.geom_dataid[cow_geom_id]
volume_ids_np = m.volume_ids.numpy()
volume_id = volume_ids_np[cow_mesh_id]

center = oct_aabb[0][:3]
half_size = oct_aabb[0][3:]

volume_data.volume_id = volume_id
volume_data.center = wp.vec3(center[0], center[1], center[2])
volume_data.half_size = wp.vec3(half_size[0], half_size[1], half_size[2])

wp.launch(sample_sdf_kernel, dim=num_test_points, inputs=[points_array, volume_data, results_array])
wp.synchronize()

warp_results = results_array.numpy()
tolerance = 1e-2
matches = 0

for j, point_local in enumerate(test_points_local):
mj_sdf = sample_octree_sdf(np.array(point_local), oct_child, oct_aabb, oct_coeff)
warp_sdf = warp_results[j]
diff = abs(mj_sdf - warp_sdf)
if diff < tolerance:
matches += 1

success_rate = matches / num_test_points
assert success_rate >= 0.9, f"SDF matching rate too low: {success_rate:.1%} (expected >= 90%)"

@parameterized.parameters(_FIXTURES.keys())
def test_collision(self, fixture):
"""Tests collisions with different geometries."""
Expand Down
Loading
Loading