Skip to content

Segfault during Mesh-Primitive collision when Primitive is dynamic #1104

@gianni0907

Description

@gianni0907

Summary

I am experiencing a segmentation fault when using the warp backend in MJX. The crash occurs specifically during a collision between a static Mesh geom and a dynamic Primitive geom (Sphere) attached to a joint.

The issue does not occur if:

  1. I use the jax backend (simulation runs perfectly).
  2. The primitive geom is not attached to a joint (i.e., if it is static).

I have attempted to increase nconmax and njmax to rule out buffer overflows related to constraint limits, but the segfault persists.

Reproduction Steps

I have created a minimal reproduction case consisting of a simple XML scene and a Python runner.

1. test_mesh_prim_collision.xml

  • A static dodecahedron mesh (from google-deepmind/mujoco_warp/mujoco_warp/test_data/meshes/dodecahedron.stl).
  • A dynamic sphere (attached to a free joint).
  • Collision masks (contype/conaffinity) are set to ensure interaction.
<mujoco model="test_mesh_prim_collision">
  <compiler meshdir="generated"/>

  <asset>
      <mesh name="dodecahedron" file="./assets/dodecahedron.stl" scale="0.04 0.04 0.04" />
  </asset>
  <worldbody>
    <light cutoff="100" diffuse="1 1 1" dir="-0 0 -1.3" directional="true" exponent="1" pos="0 0 1.3" specular=".1 .1 .1"/>
    
    <geom name="mesh" contype="0" conaffinity="1" pos="2 1 1" type="mesh" mesh="dodecahedron" rgba="1 0 1 1"/>
    
    <body name="ball" pos="-1 -1 1">
      <inertial mass="0.1" pos="0 0 0" diaginertia="1e-5 1e-5 1e-5"/>
      <joint name="ball_free"/>
      <geom name="ball" size="0.03" type="sphere" contype="1" conaffinity="0"/>
    </body>
  </worldbody>
</mujoco>

2. test_mesh_prim_collision.py, to run with impl=warp (by default) to trigger the crash.

import argparse
import contextlib
import os
from typing import Any, Dict
import jax.numpy as jp
import mujoco
import mujoco.mjx as mjx
import mujoco.viewer
import numpy as np
from mujoco_playground._src import mjx_env

def get_assets() -> Dict[str, bytes]:
  assets = {}
  # Adjust path as necessary for repro
  path = mjx_env.ROOT_PATH / "models" / "generated" / "assets" 
  mjx_env.update_assets(assets, path, "*.xml")
  return assets

XML_PATH = os.path.join(os.path.dirname(__file__), "models/test_mesh_prim_collision.xml")

def _load_models(impl: str):
    model_assets = get_assets()
    mj_model = mujoco.MjModel.from_xml_path(XML_PATH, model_assets)
    mj_model.opt.timestep = 0.004
    mjx_model = mjx.put_model(mj_model, impl=impl)
    return mj_model, mjx_model

def _sync_viewer_state(mj_model: mujoco.MjModel, mj_data: mujoco.MjData, mjx_data: Any) -> None:
    """Copy MJX state into an MjData buffer before rendering."""
    mj_data.qpos[:] = np.asarray(mjx_data.qpos)
    mj_data.qvel[:] = np.asarray(mjx_data.qvel)
    if mj_model.na > 0 and getattr(mjx_data, "act", None) is not None:
        mj_data.act[:] = np.asarray(mjx_data.act)
    mujoco.mj_forward(mj_model, mj_data)

def run_simulation(steps: int, visualize: bool, impl: str, nconmax: int, njmax: int) -> None:
    mj_model, mjx_model = _load_models(impl)
    data = mjx_env.make_data(mj_model, impl=mjx_model.impl.value, nconmax=nconmax, njmax=njmax)
    data = mjx.forward(mjx_model, data)
    action = jp.zeros(mjx_model.nu)

    mj_data = mujoco.MjData(mj_model) if visualize else None
    viewer_cm = (
            mujoco.viewer.launch_passive(mj_model, mj_data)
            if visualize
            else contextlib.nullcontext(None)
    )

    with viewer_cm as viewer:
        for step_idx in range(steps):
            data = mjx_env.step(mjx_model, data, action)

            if viewer is not None:
                if not viewer.is_running():
                    print("Viewer closed; stopping simulation early.")
                    break
                _sync_viewer_state(mj_model, mj_data, data)
                viewer.sync()

if __name__ == "__main__":
    args = _parse_args() # Assumed arg parser from repro script
    run_simulation(steps=args.steps, visualize=not args.headless, impl=args.impl, nconmax=args.nconmax, njmax=args.njmax)

System info

  • OS: Ubuntu 22.04
  • MuJoCo Version: 3.4.0
  • MuJoCo-Warp Version: 0.0.2
  • GPU: NVIDIA GeForce RTX 4060 Laptop GPU

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions