I found a raycasting parity mismatch on current main (722a4ac314315ba00f085ed226e293b1fe629885). Rays exactly tangent to sphere, capsule, ellipsoid, cylinder, and box geoms return the expected hit in MuJoCo 3.14.0 but return no intersection in MuJoCo Warp.
I reproduced this on CPU through the public ray API:
sphere: MuJoCo=2.00000000/geom 0, MJWarp=-1.00000000/geom -1
capsule: MuJoCo=2.00000000/geom 0, MJWarp=-1.00000000/geom -1
ellipsoid: MuJoCo=2.00000000/geom 0, MJWarp=-1.00000000/geom -1
cylinder: MuJoCo=2.00000000/geom 0, MJWarp=-1.00000000/geom -1
box: MuJoCo=2.00000000/geom 0, MJWarp=-1.00000000/geom -1
The same behavior reaches rangefinder sensors: tangent sphere, capsule, ellipsoid, and cylinder hits return 2.0 in MuJoCo and -1.0 in MuJoCo Warp.
The apparent cause is _ray_quad, which currently rejects det < MJ_MINVAL. A tangent intersection has det == 0, so it is discarded. Native MuJoCo instead rejects det < 0 || a < mjMINVAL:
https://github.com/google-deepmind/mujoco/blob/393c1e421755e90c5dd2243e5ba81f6324f6d7aa/src/engine/engine_ray.c#L103-L115
The complete native guard matters here. Changing only the determinant comparison would allow tangencies, but it would mishandle degenerate axis-parallel capsule and cylinder subproblems where a == 0.
A focused fix could mirror MuJoCo’s guard and add parity coverage for all bounded primitive types, including the public ray, BVH-backed ray, and rangefinder paths. I would be happy to submit the fix and regression tests if this matches the intended tangent-hit behavior.
I found a raycasting parity mismatch on current main (
722a4ac314315ba00f085ed226e293b1fe629885). Rays exactly tangent to sphere, capsule, ellipsoid, cylinder, and box geoms return the expected hit in MuJoCo 3.14.0 but return no intersection in MuJoCo Warp.I reproduced this on CPU through the public ray API:
The same behavior reaches rangefinder sensors: tangent sphere, capsule, ellipsoid, and cylinder hits return
2.0in MuJoCo and-1.0in MuJoCo Warp.The apparent cause is
_ray_quad, which currently rejectsdet < MJ_MINVAL. A tangent intersection hasdet == 0, so it is discarded. Native MuJoCo instead rejectsdet < 0 || a < mjMINVAL:https://github.com/google-deepmind/mujoco/blob/393c1e421755e90c5dd2243e5ba81f6324f6d7aa/src/engine/engine_ray.c#L103-L115
The complete native guard matters here. Changing only the determinant comparison would allow tangencies, but it would mishandle degenerate axis-parallel capsule and cylinder subproblems where
a == 0.A focused fix could mirror MuJoCo’s guard and add parity coverage for all bounded primitive types, including the public ray, BVH-backed ray, and rangefinder paths. I would be happy to submit the fix and regression tests if this matches the intended tangent-hit behavior.