hongtlee 님의 블로그

Mujoco 충돌 감지 파이프라인 본문

Study/Mujoco

Mujoco 충돌 감지 파이프라인

hongtlee 2025. 9. 30. 12:08

시뮬레이터를 사용하는 가장 큰 이유 중 하나는 충돌여부를 미리 판단하는 것이다.

기본적으로 Mujoco에서는 볼록한 물체에 대해 다룬다.
만약 오목한 물체를 다룬다면, 볼록하게 분해해서 적용하거나 sdf를 사용해야 한다.

기본적으로 충돌이란 서로 다른 두 물체의 가장 가까운 거리가 0이 될 때를 의미한다.

따라서 두 물체간의 거리를 구하는 것이 핵심이 되겠다.

 

Mujoco에서 충돌감지에 사용하는 간략한 Pipeline은 다음과 같다.

 

[Mujoco Contact Pipeline]

  1. n개의 geom을 한 쌍씩 묶어 n(n-1)/2개의 body 쌍을 생성한다.

  2. broad-phase : Modified Sweep-and-Prune으로 간략한 충돌 후보 쌍을 고름
    모든 geom 중심들의 공분산 행렬의 주성분(가장 큰 고유값의 고유벡터)을 정렬 축으로 잡고, 바운딩 구간을 투영해 구간이 겹치는 바디쌍을 추출한다.

  3. mid-phase : AABB BVH로 후보쌍을 추가적으로 필터링한다.
    각 body마다 AABB(정적 BVH)르 갖고 있고 broad-phase에서 나온 바디 쌍에 대해 두 트리를 재귀적으로 교차 탐색한다. AABB가 겹치지 않으면 그 하위 전체를 버린다.

  4. 추가적인 필터링
    • 각 geom의 타입 조합에 대해 Mujoco가 지원하는 타입 조합인지 확인. 예컨대, plane-plane 조합은 충돌로 지원하지 않음. 혹은 사용자가 충돌 감지를 끈 geom인 경우
    • sphere-sphere 조합은 계산비용이 저렴하므로, 각 geom의 contact margin을 고려해 구를 키워 계산. 
    • parent-child 관계의 geom 쌍은 충돌 감지에서 제외
    • contype / conaffinity 테스트. 각 기하구조는 contype & conaffinity 정수 쌍을 갖는데, 두 geom은 다음의 불린식을 통과 해야 함.
      (contype1 & conaffinity2) || (contype2 & conaffinity1)

  5. Narrow Phase : 정밀 충돌 확인 단계로 실행되는 함수는 mesh에 정의된 기하 구조에 따라 달라짐.
     
    • 기본 기하 구조 : 평면, 구, 캡슐, 원통, 타원체, 박스 등
      • Mujoco에서는 기본적으로 볼록 기하 구조에 대해 충돌을 다룸. 만약 오목하다면 렌더링은 오목할지언정 qhull 라이브러리로 계산된 볼록한 껍질(시뮬레이터에서 'H' 키로 확인 가능)로 대체되어 충돌검사됨.
        두 geom의 기본 기하 구조 쌍에 따라 실행되는 함수가 달라진다. 예를들어 capsule-capsule 쌍이라면 mjc_CapsuleCapsule이 실행된다.
    • Mesh type
      • 사용되는 함수는 mjc_Convex이다. 내부 알고리즘은 nativeccd, libccd  두 모드 중 하나가 사용되며 multiccd 플래그에 의해 제어된다. libccd은 레거시로 권장되지 않는다.
        • libccd(비권장) 
          MPR 기반. 두 기하 구조를 접선 축을 중심으로 ±1e-3 라디안만큼 회전하고 충돌 루틴을 다시 실행하여 여러 접촉점을 찾고, 새로운 접촉이 감지되면 추가되어 최대 4개의 추가 접촉점을 생성할 수 있다. 이 방법은 효과적이지만, 각 충돌 호출 비용이 5배 증가한다. 또한, MPR의 한계로 가까운 거리가 아니라면 잘못된 값을 반환할 수 있다.
        • nativeccd(권장)
          GJK + EPA 알고리즘 기반. GJK로 충돌점을 찾고, EPA로 충돌 깊이를 구한다. GJK와 EPA 알고리즘에 대한 설명은 다음 포스팅에서 다루겠다.
    • SDF plugins
      SDF는 signed distance field의 약자로, 물체의 표면이 0이고, 내부는 음수, 바깥은 양수로 표현된다.
      SDF와 ∇SDF으로 부터 두 SDF의 최대값을 최소화하는 방향으로 접점을 찾는 방식이다. 비용은 비싸지만 물체의 형상에 관계없이 충돌을 판단할 수 있다. 볼트와 너트를 결합한다면 기존 방식(mjc_Convex)  나사 흠이 매꿔져 convex한 mesh로 충돌 판정이 계산되므로 오목한 부분에 대해 계산할 수 없지만 SDF로 계산한다면 오목한 부분도 충돌 감지할 수 있다.
  6. 접촉들이 mjData.contact에 저장. 차후 제약 단계와 솔버 구성에 사용된다.
mjfCollision mjCOLLISIONFUNC[mjNGEOMTYPES][mjNGEOMTYPES] = {
  /*              PLANE  HFIELD  SPHERE            CAPSULE             ELLIPSOID         CYLINDER            BOX               MESH              SDF */
  /*PLANE     */ {0,     0,      mjc_PlaneSphere,  mjc_PlaneCapsule,   mjc_PlaneConvex,  mjc_PlaneCylinder,  mjc_PlaneBox,     mjc_PlaneConvex,  mjc_PlaneConvex},
  /*HFIELD    */ {0,     0,      mjc_ConvexHField, mjc_ConvexHField,   mjc_ConvexHField, mjc_ConvexHField,   mjc_ConvexHField, mjc_ConvexHField, mjc_HFieldSDF},
  /*SPHERE    */ {0,     0,      mjc_SphereSphere, mjc_SphereCapsule,  mjc_Convex,       mjc_SphereCylinder, mjc_SphereBox,    mjc_Convex,       mjc_SDF},
  /*CAPSULE   */ {0,     0,      0,                mjc_CapsuleCapsule, mjc_Convex,       mjc_Convex,         mjc_CapsuleBox,   mjc_Convex,       mjc_SDF},
  /*ELLIPSOID */ {0,     0,      0,                0,                  mjc_Convex,       mjc_Convex,         mjc_Convex,       mjc_Convex,       mjc_SDF},
  /*CYLINDER  */ {0,     0,      0,                0,                  0,                mjc_Convex,         mjc_Convex,       mjc_Convex,       mjc_SDF},
  /*BOX       */ {0,     0,      0,                0,                  0,                0,                  mjc_BoxBox,       mjc_Convex,       mjc_SDF},
  /*MESH      */ {0,     0,      0,                0,                  0,                0,                  0,                mjc_Convex,       mjc_MeshSDF},
  /*SDF       */ {0,     0,      0,                0,                  0,                0,                  0,                0,                mjc_SDF}
};

 

 

Mujoco에 model을 로드할 때, mjcf에서 각 body의 type을 지정한다. type에 따라 실행되는 충돌 함수가 다르고, 비용 또한 다르다.

따라서 mjcf을 작성할 때, object가 볼록하고 단순하다면 기본 기하 모델을 활용하고, 복잡하다면 mesh을 사용하는게 좋다.

만약 object에 오목한 부분이 존재하고 이 부분이 충돌 감지에 있어 중요하다면 SDF type을 사용하는게 좋다. mujoco 3.3.5부터는 sdf을 plugin으로 추가하지 않아도 된다.

 

결론은 다음과 같다.

  • 볼록한 object
    • 단순한 구조 → 기본 기하 구조 활용
    • 복잡한 구조 -> mesh type 사용
  • 오목한 object
    • 오목한 부분이 중요하지 않음 → mesh type 사용
    • 오목한 부분 바깥은 충돌 되지 않아야 함 → sdf type 사용

 

'Study > Mujoco' 카테고리의 다른 글

Mujoco 3.3.5 update  (1) 2025.09.02
Mujoco 장단점  (3) 2025.06.04
[Mujoco] 멀티 로봇 충돌 감지  (0) 2025.05.21