AEGLOSLAB 로봇공학 전서(全書)

제4부 기계 설계·구조·재료

4.15 CAD에서 로봇 모델로: URDF·MJCF 내보내기·관성 추정·충돌 메시 볼록 분해(V-HACD·CoACD)

4.15.1 이 장에서 배우는 것 / 선수 지식 / 특히 중요한 독자

이 장은 CAD 어셈블리를 URDF·MJCF 로봇 모델로 옮길 때 어떤 값이 어떻게 변하고 어디서 어긋나는지를 다룬다. 관성 텐서의 정의와 메시 적분(3.1), 모델 파일 형식 자체의 사양(27.9), CAD·FEA·PDM 도구의 구성(4.14)은 각 장이 맡고, 이 장은 그 사이의 변환 계층, 곧 링크 프레임 정리, 단위 환산, 관성 값의 표기 변환과 타당성 점검, 충돌 형상의 볼록 분해를 계산과 독립 라이브러리 대조로 확인한다.

배우는 것:

  • 링크 프레임과 관성 값의 표기 — URDF inertial의 질량 중심 프레임과 MJCF inertial의 주축 프레임, 전체 텐서와 주축 형식(rpy·쿼터니언)의 변환.
  • 단위와 규모 — 메시 좌표 단위가 틀렸을 때 질량과 관성이 얼마나 어긋나는가.
  • 고정 조인트 병합과 질량 추정의 원천 — 복합 관성, CAD 밀도 질량의 한계.
  • 관성 값의 타당성 점검 — 양의 정부호, 삼각형 부등식, 등가 상자, MuJoCo 컴파일 판정.
  • 충돌 형상과 볼록 분해 — 시각 메시와 충돌 메시의 구분, V-HACD와 CoACD의 동작 차이, 피복률·초과 부피·질량 과다 계상.

선수 지식: 0.14(개발 수명주기), 1.24(볼록 껍질·메시), 3.1(강체 동역학 기초: 관성 텐서), 4.14(설계 도구), 11.2(충돌 검사와 거리 계산).

특히 중요한 독자: CAD에서 시뮬레이터 모델을 만들어 동역학·학습 환경에 넘기는 로봇 엔지니어, 학습용 시뮬레이터에서 접촉이 비현실적으로 거동하는 원인을 찾는 연구자, 모델 파일의 관성 값을 검수하는 시스템 통합자.

출처 방침. 기준 시점은 2026-11-05이다. 직접 읽은 자료: ROS wiki "urdf/XML/link"(Wayback Machine 보존본, 원 주소는 접근 차단), REP 103(ros-infrastructure/rep 저장소의 원문), MuJoCo 문서 원문(google-deepmind/mujoco의 doc/XMLreference.rst·doc/modeling.rst·doc/computation/index.rst, 조회 시점의 main 브랜치), V-HACD v4.1.0의 include/VHACD.h 소스와 저장소 첫 화면, CoACD 저장소 첫 화면, 위키백과 "STL (file format)", SolidWorks URDF exporter·Fusion 360 URDF exporter(ROS 2)·onshape-to-robot 저장소 첫 화면. 직접 실행한 것: MuJoCo 3.17.0·Pinocchio 4.1.0·trimesh 5.2.0·SciPy 1.18.1·vhacdx 0.1.1(V-HACD 바인딩)·CoACD 1.0.14·V-HACD v4.1.0 C++(직접 빌드). 서지만 확인(Crossref): Mamou·Ghorbel(2009), Wei 외(2022), Mirtich(1996), Lien·Amato(2007). 읽지 못한 것: V-HACD·CoACD 논문 본문, ROS wiki의 SDF·Collada 사양, SolidWorks·Fusion·Onshape의 질량 특성 출력 규약(제품 문서), SDFormat 사양, Isaac Sim 임포터 문서. 이 장의 수치 계산은 4.15.5의 예제뿐이며 재료 밀도·치수는 모두 가정이다.

4.15.2 개념 — CAD 모델과 로봇 모델은 같은 물체의 서로 다른 모델이다

결론부터 적으면 다음과 같다. CAD는 수천 개의 면으로 이루어진 정밀 형상을 부품 좌표와 mm 단위로 담고, 로봇 모델은 링크 하나를 링크 프레임의 강체(질량, 질량 중심, 관성)와 가벼운 시각·충돌 형상으로 표현한다. 변환은 세 층으로 이루어진다. ① 관성: 질량·질량 중심·관성 텐서를 SI 단위와 링크 프레임으로 옮긴다. ② 형상: 시각용 상세 메시와 충돌용 단순 형상을 분리한다. ③ 구조: 조인트의 위치·축·한계와 고정 연결(병합)을 정한다. 이 가운데 오류가 가장 눈에 띄지 않는 것은 ①이다. 값이 틀려도 시뮬레이터는 대개 돌아가며, 단위가 $10^{3}$배 틀려도 관성이 양의 정부호이면 컴파일을 통과한다.

이 장의 계산 결과를 미리 적으면 다음과 같다. ① 기울여 장착한 U형 채널(0.1659 kg)의 질량 특성은 trimesh와 $5.4\times10^{-15}$ 안에서 같고, URDF·MJCF로 내보낸 관성을 Pinocchio와 MuJoCo가 읽은 값은 $10^{-14}$ 안에서 같다. ② ixy의 부호 하나가 뒤집히면 관성이 $5.2\,\%$ 어긋나는데 MuJoCo는 이를 컴파일 오류로 알리지 않는다. ③ mm 메시에 SI 밀도를 그대로 적용하면 질량이 $10^{9}$배, 관성이 $10^{15}$배가 된다. ④ 비볼록 메시를 단일 충돌 형상으로 적재하면 MuJoCo가 볼록 껍질로 대체해 공이 채널 위에 놓이고(중심 높이 $0.0516$ m, 이론 $0.052$), CoACD의 부품 3개는 채널 바닥에 놓이게(0.0176 m, 이론 $0.018$) 한다. ⑤ 같은 형상에서 V-HACD 상한 8과 64의 부품에서는 공이 채널 밖으로 굴러 나갔고 원인은 이 장이 분리하지 못했다.

CAD 어셈블리 질량 특성 단위·프레임 링크 프레임으로 정리 visual: 상세 메시 collision: 분해·기본 형상 inertial: 질량·중심·텐서 점검 — 관성: 양의 정부호·삼각형 부등식·단위 충돌 형상: 피복률·초과 부피 URDF·MJCF를 시뮬레이터에 적재해 질량·관성을 재확인
CAD에서 로봇 모델로의 변환 흐름. 어셈블리의 질량 특성을 단위·프레임 정리를 거쳐 visual(상세 메시)·collision(분해 또는 기본 형상)·inertial(질량·질량 중심·텐서)로 나누고, 관성과 충돌 형상을 점검한 뒤 시뮬레이터에 적재해 질량·관성을 다시 확인한다.

4.15.3 원리

4.15.3.1 링크 프레임과 질량 특성의 표기

URDF <inertial>은 origin(링크 프레임 $L$에서 본 질량 중심 프레임 $C$의 위치 xyz와 자세 rpy), mass, inertia($ixx,\dots,izz$)로 이루어진다. ROS wiki는 inertia가 질량 중심 $C_o$ 기준으로 $C$ 프레임에 고정된 단위 벡터에 대한 성분이며 $C$ 축이 주축과 일치할 필요는 없다고 적는다. inertial을 생략하면 질량과 관성이 0이 된다. MJCF inertial은 pos와 자세(quat 등)로 정한 관성 프레임을 사용하며 이 프레임의 원점이 질량 중심이고 축이 주축이므로 관성이 대각이다. 대각 값 diaginertia나 전체 텐서 fullinertia(순서 $M_{11},M_{22},M_{33},M_{12},M_{13},M_{23}$)를 받고, fullinertia는 컴파일러가 고유값 분해해 프레임 자세와 대각 값을 정한다. 고유값이 양수가 아니면 컴파일 오류이다(MuJoCo 문서). 두 형식은 $R_p\,\mathrm{diag}(d)\,R_p^{T}=I_c$로 서로 변환된다($R_p$는 주축을 열로 한 오른손 회전 행렬).

CAD가 내보내는 질량 특성이 어느 좌표계 기준인지(부품 원점, 질량 중심, 주축)는 제품마다 다르며 이 장은 각 CAD의 문서를 확인하지 못했다 (확인 필요). 확인할 수 있는 것은 변환 결과의 일관성이다. 링크 프레임을 조인트 위치에 두고 질량 중심 프레임을 origin으로 적는 것이 URDF의 구조이고, MuJoCo 문서는 로봇 모델의 메시 대부분이 조인트에 중심을 둔 좌표로 설계되어 있어 몸체 프레임을 조인트에 두고 메시를 그대로 참조하면 된다고 서술한다. 단위는 ROS의 REP 103이 SI 기본 단위(m·kg·s·rad)를 표준으로 삼으며 회전 표현은 쿼터니언, 회전 행렬, 고정축 롤-피치-요, 오일러각 순으로 권장한다.

URDF의 rpy는 고정축 롤-피치-요이며 회전 행렬은 $R=R_z(y)R_y(p)R_x(r)$이다. 이 장은 이를 SciPy from_euler("xyz")와 대조했다(풀이 예제 ⑥). 주관성 $d_1\le d_2\le d_3$는 삼각형 부등식 $d_1+d_2\ge d_3$을 만족해야 하며 등호는 얇은 평판의 경우에 성립한다(3.1). 주축이 아닌 축으로 표기한 텐서에서는 상호 관성 성분의 부호 규약이 중요하다. URDF의 ixy는 관성 텐서의 원소 $I_{xy}=-\int\rho xy\,dV$를 그대로 적는 값이며 3.1이 Pinocchio로 이를 확인했고 이 장은 같은 결과를 CAD 출력에서 생길 수 있는 오류 패턴으로 다시 시험했다.

4.15.3.2 단위와 규모

STL 파일은 규모 정보가 없고 단위가 임의이며 CAM 소프트웨어가 단위를 사용자에게 묻는다(위키백과). 따라서 CAD에서 mm로 내보낸 메시를 로봇 모델이 m로 읽으면 좌표가 $10^{3}$배 크다. 밀도가 고정이면 부피가 $s^{3}$, 질량이 $s^{3}$, 관성이 $s^{5}$로 변하므로 $s=10^{3}$에서 질량 $10^{9}$배, 관성 $10^{15}$배가 된다. URDF mesh의 scale은 메시의 축 정렬 경계 상자를 배율하며 MJCF mesh의 scale은 각 축 정점 배율이고 음수는 반전이다. 시각 메시의 배율만 맞추고 inertial을 CAD 값 그대로 두면 시각 형상은 일치해 보이는데 관성이 틀리므로, 변환 후에는 관성에서 계산한 등가 상자 크기를 형상 크기와 대조한다(4.15.5 ③).

4.15.3.3 질량 추정의 원천과 병합

링크의 질량은 부품별 재료 밀도와 부피에서 얻는 것이 기본이다. 이 값에는 케이블·체결구·윤활제·접착제·도장이 빠져 있고 내부 구조를 단순화한 모델이면 부피 자체가 틀린다. 따라서 조립 후 저울로 잰 질량과 대조하고, 틀린 값은 부품의 밀도를 조정하거나 3.7의 식별로 보정한다. 고정 조인트로 연결된 부품은 하나의 강체이므로 자식 링크의 관성은 평행축 정리로 부모 링크와 합산된다(Pinocchio와 MuJoCo의 URDF 적재가 이 합산 값을 모델 관성으로 사용함을 풀이 예제 ⑥에서 확인했다). 복합 질량 중심 $c=\sum m_i c_i/\sum m_i$이고 $I_c=\sum\bigl(I_i+m_i(\lVert d_i\rVert^{2}E-d_id_i^{T})\bigr)$, $d_i=c_i-c$이다. MuJoCo의 fusestatic 컴파일러 옵션은 URDF에서 기본 true이며 정적 몸체를 부모와 합쳐 모델을 줄인다. 같은 문서는 URDF 모델에 센서 부착용 질량 없는 더미 몸체가 많아 boundmass로 하한을 두는 방법을 소개하고 MuJoCo에서는 더미 몸체가 필요 없다고 서술한다.

4.15.3.4 시각 메시와 충돌 형상

ROS wiki는 <collision>이 시각 형상과 다를 수 있고 계산을 줄이려고 단순한 모델을 자주 사용한다고 적으며, 충돌 검사에는 링크당 면 수를 가능한 한 줄이고(이상적으로 1000개 미만) 가능하면 기본 형상으로 근사하기를 권한다. URDF는 충돌 형상 묶음을 따로 지원하지 않으며 한 링크에 <collision>을 여러 개 두면 그 합집합이 충돌 표현이다. MuJoCo는 메시를 렌더링에서는 비볼록 그대로 사용하지만 충돌 검출에서는 볼록 껍질로 대체한다(qhull로 계산). 비볼록 물체는 볼록 geom들로 분해해 같은 몸체에 붙여야 하며 문서는 CoACD와 mjfit 같은 외부 도구를 소개하고 충돌 메시를 기본 형상으로 대체하면 속도와 접촉 법선이 모두 개선된다고 서술한다. 메시에서 질량과 관성을 추정할 때의 inertia 속성은 legacy(기본, 비볼록에서 부피를 과대 계상), convex(볼록 껍질 사용, 권장), exact(비볼록도 정확, 수밀·방향 일관 메시 필요), shell(표면 질량)이다. MuJoCo의 메시 관성 알고리즘은 면과 메시 중심을 잇는 삼각뿔의 부호 있는 질량·관성을 합산하는 것으로 설명되며 O'Rourke, Computational Geometry in C 1.3.8절을 인용한다(문서). 다면체 질량 특성의 고전 문헌으로 Mirtich(1996)가 알려져 있다(서지만 확인). 같은 메시를 시각용·충돌용·관성용으로 사용할 때 어느 속성이 어느 계산에 적용되는지 분리해야 한다.

4.15.3.5 볼록 분해 — V-HACD와 CoACD

V-HACD(Voxelized Hierarchical Approximate Convex Decomposition)는 3차원 표면을 "거의 볼록한" 부분으로 분해하며 각 부분이 사용자 임계값보다 낮은 오목도를 갖게 하되 부분 수를 줄이려 한다고 저장소가 서술한다(BSD-3-Clause). v4.1.0 소스에서 확인한 동작은 다음과 같다. 메시를 복셀화하고(resolution) 부분의 경계 복셀 상자에서 가장 긴 변의 중앙을 분할 평면으로 재귀 분할하며(m_findBestPlane로 오목도가 큰 위치를 찾는 기능은 실험적이고 기본 꺼짐), 분할 결과의 부피 오차가 minimumVolumePercentErrorAllowed 미만이거나 깊이 한계 또는 변의 길이 한계에 이르면 멈추고, 부분 수가 maxConvexHulls를 넘으면 병합 비용에 따라 합친다. 출력은 복셀 위치를 원 메시 표면에 투영하는 shrinkWrap을 선택할 수 있다. 저장소에는 "V-HACD는 수명 종료에 이르렀고 새 개발과 버그 수정은 CoACD로 옮겨졌다"는 공지가 있으며 저장소는 보관(archived) 상태이다(조회 2026-11-05). 원 알고리즘의 서지는 Mamou·Ghorbel(ICIP 2009)이며 본문은 읽지 못했다. 근사 볼록 분해의 선행 연구로 Lien·Amato(2007)도 있다(서지만 확인).

CoACD는 입력 형상의 충돌 조건을 더 적은 성분으로 보존하는 근사 볼록 분해이며(MIT 라이선스, pip install coacd) 저장소는 오목도 종료 임계값(threshold, 0.01~1, 기본 0.05)과 탐색 설정(반복 수, 깊이 2~7 기본 3, 자식 노드 수 10~40 기본 20), 병합 상한 max_convex_hull(기본 −1, 상한 없음), 전처리 모드(auto는 입력의 다양체성을 자동 점검)를 문서화한다. 제목(Wei 외, ACM TOG 41(4), 2022)은 충돌 인지 오목도(collision-aware concavity)와 트리 탐색을 가리키며 이 장은 논문 본문을 읽지 못했고 저장소 설명의 범위에서 서술한다. 두 도구의 차이는 풀이 예제 ④에서 계산으로 확인한다.

볼록 분해의 평가 지표는 세 가지이다. 피복률은 원 입체 안의 점 중 부품 합집합에 들어가는 비율이고, 초과 부피는 입체 밖이지만 부품 안에 있는 부피를 원 부피로 나눈 값으로 충돌 판정이 거짓 접촉을 만드는 정도이며, 부품 부피 합 / 원 부피는 부품들이 겹치므로 1보다 크면 질량을 부품에서 추정할 때 과다 계상되는 정도이다. 질량과 관성은 충돌 부품이 아니라 원 입체(또는 CAD 질량 특성)에서 명시해야 한다.

4.15.3.6 변환 도구

도구입력 → 출력확인한 사실(출처: 저장소 첫 화면, 조회 2026-11-05)
SolidWorks to URDF ExporterSolidWorks 부가 기능 → URDF·메시MIT 라이선스, 최소 SolidWorks 2018 SP5(2017 이하는 동작할 수 있음), 최신 배포는 SolidWorks 2021(v1.6.1). 메시 변환 단계로 3DXML에서 DAE로 바꾸는 절차가 안내된다. 질량 특성을 어떻게 내보내는지는 이 장이 확인하지 못했다
fusion360-urdf-ros2Fusion 360 부가 기능 → ROS 2 패키지(URDF·STL·launch)MIT, 시험 환경 Fusion 360 2.0.20981·ROS 2 Humble·Jazzy. 생성 URDF에는 Gazebo 플러그인이나 ros2_control 설정이 없다고 README가 밝힌다
onshape-to-robotOnshape API → URDF·SDF·MuJoCoMIT. 관성 계산 방식과 충돌 형상 처리는 첫 화면에 없어 확인하지 못했다
MuJoCo URDF 적재URDF → MJCF 컴파일<mujoco> 확장 요소로 compiler 등을 지정, fusestatic·discardvisual 기본값이 URDF에서 다르고 URDF는 스키마 검사를 하지 않아 철자 오류가 경고 없이 무시된다고 문서가 서술
Pinocchio buildModelFromXMLURDF 문자열 → 모델이 장이 읽은 값을 수치로 확인(풀이 예제 ⑥)
V-HACD · vhacdx메시 → 볼록 부품V-HACD v4.1.0(BSD-3-Clause, 저장소 보관), vhacdx 0.1.1은 V-HACD 바인딩이며 faces를 VTK 형식([3,a,b,c,…])으로 받는다
CoACD메시 → 볼록 부품MIT, 1.0.14 판을 이 장이 실행

내보내기 도구의 관성 출력은 이 장이 검증하지 못했으므로 내보낸 모델은 이 장의 점검(4.15.4)을 거친 뒤 사용한다.

4.15.4 알고리즘

관성 내보내기 (링크 L, 부품 {P_i}):
  1. 각 부품의 수밀 메시 (V_i, F_i), 밀도 ρ_i 확인 (SI 단위로 환산: s = 단위 배율)
  2. (m_i, c_i, I_i) ← mesh_props(V_i, F_i, ρ_i) 를 링크 프레임 L에서 계산
  3. (m, c, I_c) ← compose({(m_i, c_i, I_i)})            # 고정 조인트 병합
  4. 형식 선택:  URDF: origin xyz = c, rpy = 0,  inertia = I_c의 6성분(텐서 원소)
                 URDF 주축형: d, R_p ← 고유분해(I_c);  rpy ← rpy_of(R_p)
                 MJCF: fullinertia = (I11 I22 I33 I12 I13 I23)  또는  diaginertia + quat_of(R_p)
  5. 점검: d_1 > 0, d_1 + d_2 ≥ d_3, 등가 상자 최대 변 ≤ 부품 경계 상자의 대각선

충돌 형상 선택 (링크마다):
  기본 형상(구·캡슐·상자·원기둥)으로 근사 가능한가 → 예: 기본 형상
  메시가 볼록한가 → 예: 볼록 껍질 하나
  아니면 분해 (V-HACD 또는 CoACD) → 피복률 ≥ 요구값, 초과 부피 ≤ 허용값, 부품 수 ≤ 상한
  이 부품들은 collision 전용: 질량·관성은 3~4단계의 값을 명시한다

4.15.5 풀이 예제 — U형 채널의 관성 내보내기와 충돌 분해

결론부터 적으면 다음과 같다. ① 메시 질량 특성에서 URDF·MJCF의 두 표기를 만들어 Pinocchio·MuJoCo가 읽은 값과 $10^{-14}$ 안에서 일치한다. ② 단위 오류와 부호 오류는 관성의 양의 정부호성을 해치지 않아 컴파일을 통과하며, 등가 상자 점검이 단위 오류를 드러낸다. ③ 비볼록 부품은 볼록 껍질로는 접촉이 어긋나고, CoACD는 부품 3개로 초과 부피 $0.1\,\%$를 얻으며, V-HACD는 부품 수 상한을 정해야 하고 상한이 커도 접촉이 안정하다는 보장은 없다. ④ 충돌 부품에서 추정한 질량은 부품이 겹치는 만큼 과다 계상된다.

구현. 수밀 메시 질량 특성·관성 이동·고유분해는 3.1의 mesh_props·steiner·jacobi_eig를 불러와 사용한다. 이 장에서 작성한 함수는 rot_rpy·rpy_of·quat_of·principal(주축 표기), check_inertia(타당성), urdf_inertial·mjcf_inertial(내보내기), compose(병합), hull_planes·hull_volume·in_part·eval_parts(볼록 분해 평가)이다. 메시 생성(ear_clip·extrude_xz·ring_mesh)과 입력 처리는 스크립트에 있으며, 볼록 분해 자체는 4.15-decomp.py가 V-HACD(vhacdx)·CoACD로 실행해 부품을 data/4.15-parts.json에 저장한다. 분해 평가는 저장된 부품을 입력으로 이 장의 순수 파이썬 코드가 수행한다.

항목값
입력 1 (형상)U형 채널: 폭 $60$ mm·높이 $40$ mm·길이 $80$ mm, 벽 $6$ mm, 바닥 $6$ mm, 알루미늄 유사 밀도 $2700$ kg/m³(가정). 단면을 귀 자르기로 삼각 분할해 압출한 수밀 메시(법선 바깥)
입력 2 (장착)링크 프레임에서 롤 $10^\circ$·피치 $-20^\circ$·요 $30^\circ$로 기울이고 $(20,-15,30)$ mm 이동
입력 3 (병합)같은 링크에 고정 조인트로 강 블록 $40\times40\times60$ mm(밀도 $7800$ kg/m³, 요 $15^\circ$, 위치 $(60,30,50)$ mm)를 연결
입력 4 (분해)U형 채널(원 메시)과 플랜지 링(안반지름 $20$ mm·바깥반지름 $40$ mm·높이 $10$ mm, 정 64각형). V-HACD(vhacdx) 부품 수 상한 1·3·8·16·64(링은 8·16·32·64, 기본 해상도 400000, 오차 $1\,\%$), CoACD 임계 $0.30\to0.02$(seed=0). 분해 계산 환경: Intel Core i5-13500(20 스레드)
입력 5 (평가)점 8000개 균일 표본(시드 90), 원 입체의 해석적 포함 판정
입력 6 (MuJoCo 시험)반지름 $12$ mm·질량 $0.05$ kg 공을 채널 중심 위 $0.09$ m에서 낙하(바닥 평면 $z=0$ 포함, $\Delta t=1$ ms, 3 s)
입력 7 (라이브러리 대조)trimesh 5.2.0, SciPy 1.18.1(Rotation·ConvexHull·Delaunay), Pinocchio 4.1.0, MuJoCo 3.17.0, V-HACD v4.1.0 C++ 직접 빌드
from math import sqrt, sin, cos, pi, atan2, asin

def rot_rpy(r, p, y):
    """URDF rpy(고정축 롤-피치-요): R = Rz(y) Ry(p) Rx(r)"""
    a, b = cos(r), sin(r)
    c, d = cos(p), sin(p)
    e, f = cos(y), sin(y)
    return [[e * c, e * d * b - f * a, e * d * a + f * b],
            [f * c, f * d * b + e * a, f * d * a - e * b],
            [-d, c * b, c * a]]

def rpy_of(R):
    """회전 행렬 -> (r, p, y), |p| < 90도"""
    p = -asin(max(-1.0, min(1.0, R[2][0])))
    return atan2(R[2][1], R[2][2]), p, atan2(R[1][0], R[0][0])

def quat_of(R):
    """회전 행렬 -> 쿼터니언 (w, x, y, z), w >= 0"""
    t = R[0][0] + R[1][1] + R[2][2]
    if t > 0:
        s = 2 * sqrt(t + 1)
        q = [s / 4, (R[2][1] - R[1][2]) / s,
             (R[0][2] - R[2][0]) / s, (R[1][0] - R[0][1]) / s]
    else:
        i = max(range(3), key=lambda k: R[k][k])
        j, k = (i + 1) % 3, (i + 2) % 3
        s = 2 * sqrt(R[i][i] - R[j][j] - R[k][k] + 1)
        q = [0.0] * 4
        q[1 + i] = s / 4
        q[0] = (R[k][j] - R[j][k]) / s
        q[1 + j] = (R[j][i] + R[i][j]) / s
        q[1 + k] = (R[k][i] + R[i][k]) / s
    return [x if q[0] >= 0 else -x for x in q]

def det3(R):
    a, b, c = R
    return (a[0] * (b[1] * c[2] - b[2] * c[1])
            - a[1] * (b[0] * c[2] - b[2] * c[0])
            + a[2] * (b[0] * c[1] - b[1] * c[0]))

def principal(I):
    """대칭 3x3 관성 -> (주관성 d, 오른손 주축 R: 열 = 축)"""
    d, Q = rb63.jacobi_eig(I)
    k = sorted(range(3), key=lambda i: d[i])
    R = [[Q[r][c] for c in k] for r in range(3)]
    if det3(R) < 0:
        for r in range(3):
            R[r][2] = -R[r][2]
    return [d[i] for i in k], R

def check_inertia(I, m):
    """양의 정부호, 삼각형 부등식, 등가 상자 변의 길이"""
    d, _ = principal(I)
    pd = d[0] > 0
    tri = d[0] + d[1] >= d[2]
    side = []
    for i in range(3):
        a, b = d[(i + 1) % 3], d[(i + 2) % 3]
        side.append(sqrt(max(0.0, 6 * (a + b - d[i]) / m)))
    return d, pd, tri, sorted(side)

def urdf_inertial(m, c, I, rpy=(0, 0, 0)):
    """URDF inertial: ixx..izz는 질량 중심 기준 텐서 성분"""
    f = lambda v: '%.17g' % v
    xyz = ' '.join(f(v) for v in c)
    ang = ' '.join(f(v) for v in rpy)
    key = ('ixx', 'ixy', 'ixz', 'iyy', 'iyz', 'izz')
    ij = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
    ten = ' '.join('%s="%s"' % (k, f(I[a][b]))
                   for k, (a, b) in zip(key, ij))
    return ('<inertial><origin xyz="%s" rpy="%s"/>'
            '<mass value="%s"/><inertia %s/></inertial>'
            % (xyz, ang, f(m), ten))

def mjcf_inertial(m, c, I):
    """MJCF inertial(fullinertia 순서: 11 22 33 12 13 23)"""
    f = lambda v: '%.17g' % v
    pos = ' '.join(f(v) for v in c)
    ij = ((0, 0), (1, 1), (2, 2), (0, 1), (0, 2), (1, 2))
    full = ' '.join(f(I[a][b]) for a, b in ij)
    return ('<inertial pos="%s" mass="%s" fullinertia="%s"/>'
            % (pos, f(m), full))

def compose(parts):
    """같은 프레임의 [(m, c, I_c)] -> 복합체 (m, c, I_c)"""
    m = sum(p[0] for p in parts)
    c = [sum(p[0] * p[1][k] for p in parts) / m
         for k in range(3)]
    I = [[0.0] * 3 for _ in range(3)]
    for pm, pc, pI in parts:
        d = [pc[k] - c[k] for k in range(3)]
        S = rb63.steiner(pI, pm, d)
        for i in range(3):
            for j in range(3):
                I[i][j] += S[i][j]
    return m, c, I

def hull_planes(V, F):
    """볼록 부품의 면 평면 (n, d): n.x <= d가 내부"""
    c = [sum(v[k] for v in V) / len(V) for k in range(3)]
    out = []
    for a, b, e in F:
        A, B, C = V[a], V[b], V[e]
        u = [B[k] - A[k] for k in range(3)]
        w = [C[k] - A[k] for k in range(3)]
        n = rb63.cross(u, w)
        ln = sqrt(rb63.dot(n, n))
        if ln < 1e-14:
            continue
        n = [x / ln for x in n]
        d = rb63.dot(n, A)
        if rb63.dot(n, c) > d:
            n, d = [-x for x in n], -d
        out.append((n, d))
    return out

def hull_volume(V, F):
    """볼록 부품의 부피(내부점-면 사면체 합)"""
    c = [sum(v[k] for v in V) / len(V) for k in range(3)]
    s = 0.0
    for a, b, e in F:
        u, v, w = [[V[i][k] - c[k] for k in range(3)]
                   for i in (a, b, e)]
        s += abs(rb63.dot(u, rb63.cross(v, w))) / 6
    return s

def in_part(bb, pl, p):
    """볼록 부품(상자 bb, 평면 pl)에 점 p가 속하는가"""
    for k in range(3):
        if not bb[k][0] <= p[k] <= bb[k][1]:
            return False
    return all(rb63.dot(n, p) <= d + 1e-12 for n, d in pl)

def eval_parts(parts, member, lo, hi, n, seed):
    """부품 합집합의 피복률(입체 점 중 포함 비율)과
    초과 부피비(입체 밖 포함 점 수 / 입체 안 점 수)"""
    rng = random.Random(seed)
    PL = []
    for V, F in parts:
        bb = [(min(v[k] for v in V), max(v[k] for v in V))
              for k in range(3)]
        PL.append((bb, hull_planes(V, F)))
    ins = cov = over = 0
    for _ in range(n):
        p = [rng.uniform(lo[k], hi[k]) for k in range(3)]
        inn = member(p)
        hit = any(in_part(bb, pl, p) for bb, pl in PL)
        ins += inn
        cov += inn and hit
        over += hit and not inn
    return cov / ins, over / ins

① 질량 특성과 표기 변환.

항목 (U형 채널, $\rho=2700$ kg/m³, 링크 프레임)값
부피 $V$ (m³) · 질량 $m$ (kg)6.144000e-05 · 0.165888
질량 중심 $c$ (m)(0.019869, 0.027679, 0.059396)
$I_{xx}, I_{yy}, I_{zz}$ (kg·m²)1.161596e-04, 1.196508e-04, 1.673061e-04
$I_{xy}, I_{xz}, I_{yz}$ (kg·m², 텐서 성분)4.372667e-06, -1.181039e-05, -1.855087e-05
주관성 $d_1,d_2,d_3$ (kg·m²)1.130846e-04, 1.137205e-04, 1.763113e-04
주축 rpy (도)(20.2836, 9.3913, -56.5488)
주축 쿼터니언 $(w,x,y,z)$(0.857190, 0.192727, -0.012161, -0.477423)
복원 오차: $R_p\,\mathrm{diag}(d)\,R_p^{T}$ 대 $I$ (최댓값 정규화) · rpy 행렬 대 $R_p$ · 쿼터니언 행렬 대 $R_p$2.4e-16 · 2.8e-16 · 1.1e-16

② 단위 환산.

메시 좌표 단위 (밀도는 SI)좌표 배율 $s$질량 비$I_{zz}$ 비
m (환산 후)11.000e+001.000e+00
cm 값을 환산 없이1001.000e+061.000e+10
mm 값을 환산 없이10001.000e+091.000e+15

③ 관성 값의 타당성 점검.

사례주관성 (kg·m²)양의 정부호삼각형 부등식등가 상자 변 (m)
정상: U형 채널(기울어진 장착)0.000113, 0.000114, 0.000176통과통과0.0427, 0.0797, 0.08
삼각형 부등식 위반: 주관성 1·1·31, 1, 3통과위반0, 4.24, 4.24
양의 정부호 위반: 주관성 1·1·1에 ixy=1.5-0.5, 1, 2.5위반위반0, 2.45, 4.9
상호 관성 부호 하나만 뒤집음(ixy)0.000106, 0.000122, 0.000175통과통과0.0436, 0.076, 0.0831
관성 단위 오류: mm²를 m²로 기입(×10⁶)113, 114, 176통과통과42.7, 79.7, 80

④ 볼록 분해: U형 채널.

분해 방법·설정부품 수정점 합피복률 (%)초과 부피 (원 부피 대비 %)부품 부피 합 / 원 부피계산 시간 (s)
V-HACD 상한 118100.0211.93.1251.53
V-HACD 상한 3326100.07.81.0741.54
V-HACD 상한 8866100.01.51.0141.99
V-HACD 상한 1616130100.01.41.0121.82
V-HACD 상한 6464501100.01.31.0111.78
CoACD 임계 0.30331100.00.11.0010.76
CoACD 임계 0.10331100.00.11.0010.81
CoACD 임계 0.05331100.00.11.0010.69
CoACD 임계 0.02331100.00.11.0010.80

⑤ 볼록 분해: 플랜지 링.

분해 방법·설정부품 수정점 합피복률 (%)초과 부피 (원 부피 대비 %)부품 부피 합 / 원 부피계산 시간 (s)
V-HACD 상한 8816098.96.41.0601.12
V-HACD 상한 161623098.92.01.0121.26
V-HACD 상한 323236898.60.40.9891.07
V-HACD 상한 646463298.70.40.9891.24
CoACD 임계 0.30416099.813.31.1402.10
CoACD 임계 0.10718499.84.71.0492.78
CoACD 임계 0.051020899.82.31.0233.71
CoACD 임계 0.021827699.80.81.0073.92
1 3 10 30 100 0.1 1 10 100 부품 수 초과 부피 [원 부피 대비 %] V-HACD, U형 채널 V-HACD, 링 CoACD, U형 채널 CoACD, 링
볼록 분해의 부품 수와 초과 부피(원 부피 대비 %). U형 채널의 V-HACD는 부품 1개(볼록 껍질)에서 $212\,\%$이고 상한이 커지면 $1.3\,\%$까지 줄며, CoACD는 부품 3개에서 $0.1\,\%$이다(점 하나). 링은 두 방법 모두 부품이 늘수록 줄어든다. 로그-로그 축이다.
볼록 껍질 위: 중심 52 mm 껍질 상면: 40 mm 채널 바닥 위: 중심 18 mm
U형 채널의 단면. 볼록 껍질을 충돌 형상으로 적재하면 공(반지름 12 mm)이 껍질 상면(40 mm, 점선) 위에 놓여 중심 높이가 52 mm가 되고, 분해 부품을 적재하면 채널 바닥 위에서 18 mm가 된다.

⑥ 라이브러리 대조(실행 2026-11-05). 같은 입력으로 trimesh 질량 특성, SciPy 회전, Pinocchio·MuJoCo의 URDF 적재(U형 채널과 강 블록을 고정 조인트로 연결한 모델), MJCF 컴파일, MuJoCo 컴파일 판정, MuJoCo 메시 inertia 모드, SciPy Delaunay·ConvexHull로 한 분해 평가, V-HACD v4.1.0 C++, MuJoCo 공 낙하를 시험했다.

비교결과
질량 특성: 이 장 대 trimesh mass_properties (질량·관성·질량 중심 최대 상대 차이)5.4e-15
rpy 행렬 $R_zR_yR_x$ 대 SciPy from_euler("xyz") · rpy_of 대 as_euler · 쿼터니언 quat_of 대 as_quat (최대 차이)3.3e-16 · 1.1e-16 · 1.1e-16
URDF inertial(전체 텐서, rpy=0)을 읽은 값 대 이 장: Pinocchio · MuJoCo (질량·질량 중심·관성 최대 상대 차이)0.0e+00 · 1.2e-14
URDF inertial(주관성 대각 + 주축 rpy)을 읽은 값 대 이 장: Pinocchio · MuJoCo1.6e-16 · 9.4e-15
MJCF fullinertia(순서 M11 M22 M33 M12 M13 M23) · diaginertia+quat을 컴파일한 값 대 이 장 (최대 상대 차이)1.2e-14 · 3.2e-16
URDF ixy의 부호만 뒤집으면 Pinocchio가 읽은 관성이 이 장과 벗어나는 크기 (최대 상대 차이)5.2e-02
상호 관성 세 성분 모두 곱 관성 정의($\int xy\,dm$)로 적은 경우(텐서 성분의 반대 부호): 같은 비교2.2e-01
고정 조인트 병합(U형 채널 0.1659 kg + 강 블록 0.7488 kg): 이 장 compose 대 Pinocchio · MuJoCo fusestatic (질량·질량 중심·관성 최대 상대 차이)1.3e-16 · 8.4e-15
병합 전 U형 채널 단독 값과 병합 값의 차이: 질량 비 · 질량 중심 이동 (mm)5.5139 · 33.79
MuJoCo 컴파일 판정: 정상컴파일 성공
MuJoCo 컴파일 판정: 삼각형 부등식 위반 1·1·3오류: Error: inertia must satisfy A + B >= C; use 'balanceinertia' to fix
MuJoCo 컴파일 판정: 양의 정부호 위반오류: Error: error 'inertia must have positive eigenvalues' in fullinertia
MuJoCo 컴파일 판정: ixy 부호 뒤집음컴파일 성공
MuJoCo 컴파일 판정: 단위 오류 ×10⁶컴파일 성공
MuJoCo 컴파일 판정: 삼각형 부등식 위반 1·1·3 + balanceinertia="true"컴파일 성공
MuJoCo 메시 inertia로 추정한 질량 / 참 질량(밀도 1000): exact · convex · legacy1.0000 · 3.1250 · 2.8597
볼록 껍질 부피 / 원 부피: SciPy ConvexHull (MuJoCo convex와 비교)3.1250
볼록 분해 평가 17건: 피복률 · 초과 부피 · 부품 부피 합 — 이 장(평면 시험·사면체 합) 대 SciPy(Delaunay 포함 시험·ConvexHull) 최대 차이0.0e+00 · 0.0e+00 · 1.5e-11
V-HACD: vhacdx 0.1.1 대 V-HACD v4.1.0 C++ 직접 빌드(U형 채널, 상한 3·8·16): 부품 수 차이 · 피복률·초과 부피 최대 차이0 · 0.0e+00
vhacdx에 faces를 (n,3) 배열로 넘긴 경우(볼록한 정육면체, 상한 8): 부품 수 · 부품 부피 합 / 원 부피 — VTK 형식으로 넘긴 경우8 · 0.029 — 1 · 1.000
MuJoCo 3.17.0 공 낙하(3 s): 원 메시 1개를 충돌 형상으로 적재 — 공 중심 $(y,z)$ (m) · 판정. 이론: 볼록 껍질 상면 위 $H+r=0.052$(0.040, 0.0516) · 상면 위에 놓임
같은 시험, V-HACD 상한 3(3개). 이론: 채널 바닥 위 $t_b+r=0.018$(0.040, 0.0178) · 채널 안에서 정지
같은 시험, V-HACD 상한 8(8개). 이론: 채널 바닥 위 $t_b+r=0.018$(-0.402, 0.0116) · 채널 밖으로 굴러나감
같은 시험, V-HACD 상한 64(64개). 이론: 채널 바닥 위 $t_b+r=0.018$(-0.254, 0.0116) · 채널 밖으로 굴러나감
같은 시험, CoACD 임계 0.05(3개). 이론: 채널 바닥 위 $t_b+r=0.018$(0.041, 0.0176) · 채널 안에서 정지
바닥 상면의 평균 높이 (mm, 중심선 20점, 참 값 6.0): V-HACD 상한 3 · 8 · 64 · CoACD 임계 0.056.250 · 6.000 · 6.000 · 5.990
부품 geom에서 MuJoCo가 추정한 질량 / 참 질량(V-HACD 상한 3, 밀도 1000): 부품 부피 합 / 원 부피와의 비교1.0738 대 1.0738

해석. 주축 rpy는 $(20.28^\circ,\,9.39^\circ,\,-56.55^\circ)$로 정해진다. 그러나 이 예에서 $d_1$과 $d_2$가 $0.56\,\%$밖에 차이 나지 않아 이 평면 안의 주축은 입력의 작은 변동에 민감하다(고유값이 겹치면 고유벡터는 유일하지 않다). 표기 변환이 정확하다는 것(복원 오차 $2\times10^{-16}$)과 주축 방향이 안정하다는 것은 다른 성질이며, 외부에 넘기는 값은 전체 텐서 형식(rpy=0)이 이 모호함을 피한다. 고정 조인트 병합으로 질량은 $5.51$배($0.1659\to0.9147$ kg), 질량 중심은 $33.8$ mm 이동하며 Pinocchio·MuJoCo와 $10^{-14}$ 안에서 같다. ixy의 부호 하나만 뒤집으면 관성이 $5.2\,\%$ 어긋나고, 세 상호 성분을 곱 관성 정의로 적으면 $22\,\%$ 어긋나는데 두 경우 모두 MuJoCo가 컴파일을 거부하지 않는다. MuJoCo가 거부하는 것은 삼각형 부등식 위반("inertia must satisfy A + B >= C")과 양이 아닌 고유값("inertia must have positive eigenvalues")이며, balanceinertia를 켜면 첫째가 통과한다. 단위 오류($10^{6}$배)는 통과하지만 등가 상자의 변이 $42.7\times79.7\times80$ m로 부품 경계 상자의 대각선 $0.108$ m를 크게 벗어나 이 장의 점검이 잡는다(정상 값은 $0.043\times0.080\times0.080$ m).

MuJoCo 메시 질량 추정은 exact 1.0000, convex 3.1250(볼록 껍질 부피비와 같음), legacy 2.8597로 비볼록 메시에서 legacy가 질량을 과대 계상한다. 볼록 분해에서 CoACD는 U형 채널에서 임계 $0.30$~$0.02$ 모두 부품 3개, 초과 부피 $0.1\,\%$로 해(세 상자)에 거의 일치하고 0.7~0.8 s 걸렸다. V-HACD는 상한 3에서 $7.8\,\%$, 8에서 $1.5\,\%$, 64에서 $1.3\,\%$이고 부품 수가 상한과 같았다. v4.1.0 소스의 분할 위치(가장 긴 변의 중앙)가 벽 경계와 맞지 않아 부품 수가 필요보다 많아진 뒤 상한으로 병합되는 구조와 일치하는 관찰이다. 플랜지 링에서는 V-HACD가 32개에서 초과 부피 $0.4\,\%$, CoACD가 18개에서 $0.8\,\%$이며 피복률은 V-HACD $98.6$~$98.9\,\%$, CoACD $99.8\,\%$이다. 어느 한 쪽이 일관되게 낫다는 결론은 이 두 형상에서 나오지 않는다. 부품 부피 합이 원 부피의 $1.074$배(V-HACD 상한 3)일 때 MuJoCo가 부품 geom에서 추정한 질량도 정확히 $1.0738$배여서, 충돌 부품에서 질량을 추정하면 겹침만큼 과다 계상됨이 확인된다.

공 낙하에서 원 메시 하나를 충돌 형상으로 사용하면 공 중심 높이가 $0.0516$ m로 볼록 껍질 상면 위에 놓인다(이론 $0.052$, 차이 $0.4$ mm는 연성 접촉의 침투로 추정된다). V-HACD 상한 3(0.0178 m)과 CoACD 3개(0.0176 m)는 채널 바닥(이론 $0.018$)에 놓이지만 V-HACD 상한 8과 64는 공이 채널 끝으로 굴러 나갔다(3 s 뒤 $y=-0.40$·$-0.25$ m에서 바닥 평면 위를 굴러 가는 중). 바닥 상면의 평균 높이는 V-HACD 상한 3이 $6.25$ mm(참 값 $6.0$)이고 상한 8·64는 $6.000$ mm여서 중심선 높이로는 원인이 설명되지 않는다. 부품 경계의 법선 불연속이나 부품 사이 단차가 후보로 추정되나 이 장은 분리하지 못했다. vhacdx에 faces를 $(n,3)$ 배열로 넘기면 오류 없이 잘못된 결과가 나온다(정육면체 상한 8에서 부품 8개, 부피 합이 원의 $2.9\,\%$). VTK 형식으로 넘기면 V-HACD v4.1.0 C++ 직접 빌드와 부품 수·피복률·초과 부피가 완전히 같다.

한계. 형상 두 개(U형 채널, 링)와 하나의 접촉 시험이다. 분해 평가는 점 8000개의 표본 추정이며 표본 오차는 이 장이 정량화하지 않았다(두 방법이 같은 점을 사용하므로 비교는 가능). 접촉 시험은 한 가지 공·낙하 조건과 MuJoCo 기본 접촉 매개변수이다. V-HACD·CoACD의 매개변수는 일부만 바꾸었고 시간은 한 환경의 1회 측정이다. CAD 제품이 내보내는 관성의 좌표계·부호 규약은 확인하지 못했다. 관성은 균일 밀도 가정이다.

견해: CAD에서 모델을 내보낼 때는 관성을 원 입체의 메시나 CAD 질량 특성에서 명시하고, 충돌 부품에서 추정한 값에 맡기지 않으며, 내보낸 값은 양의 정부호·삼각형 부등식에 등가 상자 점검을 더해 검수하는 것이 합리적이라고 본다. 근거는 이 장의 계산에서 단위 오류($10^{6}$배)와 부호 오류($5\,\%$~$22\,\%$)가 MuJoCo 컴파일을 통과했고 충돌 부품의 질량 추정이 부품 부피 합만큼 과다 계상되었다는 점이다. 충돌 형상은 기본 형상으로 근사하고, 그것이 안 되면 분해 뒤 접촉 시험(공 낙하 같은 단순 시험)으로 안착 결과를 확인한다. 근거는 같은 형상에서 분해 부품 수를 늘렸는데 접촉 결과가 오히려 나빠진 사례가 이 장에서 나왔다는 점이다.

4.15.6 설계 트레이드오프 — 충돌 형상의 표현

링크의 충돌 형상은 다음 중에서 정한다.

  • ① 기본 형상(구·캡슐·상자·원기둥). 쌍별 전용 충돌 함수가 있어 일반 볼록 충돌보다 계산이 가볍고 접촉 법선이 안정하다(MuJoCo 문서의 서술). 형상을 크게 단순화하므로 끼움·삽입 같은 접촉에는 부적합하다.
  • ② 볼록 껍질 하나(단일 메시). 설정이 가장 간단하다. 비볼록 형상에서는 오목부가 채워지므로 공이 U형 채널 위에 놓이는 것처럼 접촉이 어긋난다(이 장 계산).
  • ③ 볼록 분해 부품(V-HACD·CoACD). 비볼록 형상을 근사한다. 부품 수가 늘수록 충돌 검사 비용이 늘고 부품 경계에서 접촉이 불안정해질 수 있으며 부품의 합집합이 원 형상과 어긋난다.
방식장점비용주된 위험
① 기본 형상계산이 가볍고 법선이 안정형상 근사 작업접촉 정밀도 부족
② 볼록 껍질설정 최소계산 가벼움오목부가 채워져 거짓 접촉
③ 볼록 분해비볼록 접촉 근사분해 계산, 검사 비용 증가부품 경계 접촉 이상, 질량 과다 계상

견해: 로봇 링크는 ①을 기본으로 하고, 파지·삽입처럼 오목부가 접촉에 관여하는 부분만 ③으로 분해하며 ②는 외형이 거의 볼록한 부품에만 사용하는 것이 안전하다고 본다. 근거는 이 장의 U형 채널에서 ②가 접촉을 틀리게 만들었고 ③은 방법과 매개변수에 따라 결과가 갈렸다는 점이다. 도구 간의 정량 우열은 형상 두 개로는 판단할 수 없다.

4.15.7 응용 축 비교

응용 축CAD→모델 변환에 거는 요구이 장의 대응관련 장
산업·제조오프라인 프로그래밍·셀 충돌 검사에 사용하는 형상 충실도, 공구·부하 관성충돌 형상 분해, 부하 관성 명시11.2, 3.7
물류·이동차체·팔의 간단한 충돌 형상과 정확한 질량기본 형상 근사, 병합 관성11.2
도로 주행센서·차체 모델의 단위·좌표 일관성 (확인 필요)단위 환산 점검27.9
서비스외장 형상이 복잡한 접촉 안전시각 메시와 충돌 분리7.20
의료·헬스케어해석·시뮬레이션 모델의 검증 이력 (확인 필요)점검 기록41.21
휴머노이드·범용다수 링크의 질량·관성 정확도, 학습용 시뮬레이터의 접촉 안정성관성 점검, 충돌 단순화16.1, 16.4
필드지형 접촉용 거친 형상볼록 껍질·기본 형상4.13
국방·안보모델 파일의 관리·반출 통제 (확인 필요)설계 데이터 관리4.14

이 표는 이 책의 정리이며 응용별 요구 수치는 이 장이 확인하지 못했다.

4.15.8 관련 규격·프로토콜

문서발행무엇을 정하나상세 장
URDF XML 사양(link)ROS wikiinertial(질량 중심 프레임·질량·관성), visual·collision·메시 scale. 이 장은 Wayback 보존본을 읽었다27.9, 15.8
MJCF XML 참조MuJoCo 문서inertial·mesh inertia·compiler와 URDF 확장. 3.17.0 문서와 같은 main 원문을 읽었다27.9
REP 103ROSSI 기본 단위와 회전 표현의 권장 순서27.9
SDFormatOpen Robotics로봇·월드 모델 형식 — 이 장은 사양을 읽지 못했다 (확인 필요)27.9
STL사실상 표준표면 삼각형 메시. 규모 정보가 없고 단위가 임의(위키백과)4.17
STEP (ISO 10303)ISOCAD 중립 형식 — 요지는 4.144.14, A.3

4.15.9 관련 규제·인증 요구와의 연결

시뮬레이션 모델의 변환을 직접 규정하는 법령은 확인하지 못했다. 간접 연결은 시뮬레이션 결과를 안전·성능 근거로 사용할 때이다. 모델의 관성·충돌 형상이 틀리면 근거가 틀리므로 모델 점검 기록(이 장의 4.15.4 절차)을 기술 문서와 검증 이력에 남긴다(41.3). 시나리오 기반 시험(16.24)과 시뮬레이션 기반 안전 입증의 요구 수준은 적용 규격과 인증 경로에 따라 다르며 이 장은 확인하지 못했다 (확인 필요). 의료 로봇의 설계 검증 이력은 4.14.9와 41.21, 설계 데이터의 반출 통제는 40.15에서 다룬다.

4.15.10 한계·유의점·미해결

  • 자료의 한계. CAD 제품이 내보내는 질량 특성의 좌표계와 부호 규약, SDFormat·Isaac Sim 임포터의 동작, V-HACD·CoACD 논문 본문은 이 장이 읽지 못했다. 내보내기 도구 표는 저장소 첫 화면에 한정한다.
  • 모형 범위. 균일 밀도 단일 재료 메시, 형상 두 개의 분해 평가, MuJoCo 한 가지 접촉 시험이다. 중공·다재료 부품의 질량 중심, 가동 부품의 내부 질량(모터 로터 반사 관성), 케이블·유체의 질량은 포함하지 않았다.
  • 미해결. V-HACD 상한 8과 64에서 공이 채널을 벗어난 원인(부품 경계 접촉의 성질), 충돌 부품 수와 접촉 안정성의 관계, 학습용 시뮬레이터(16.4·16.5)에서의 같은 시험, CAD 질량 특성과 모델 관성의 자동 일관성 검사는 이 장이 다루지 못했다.

4.15.11 체크포인트·연구 질문·출처

체크포인트:

  1. 삼각형 메시에서 질량 중심·관성 텐서를 구하는 식을 작성하고, 원점이 물체 밖에 있어도 성립하는 이유를 설명하라(3.1).
  2. 고정 조인트 병합의 복합 관성이 평행축 정리로 합산됨을 유도하고, 질량 중심 이동량을 계산하라.
  3. 고유값이 거의 겹칠 때 주축 rpy가 불안정한 이유를 설명하고, 전체 텐서 형식이 이를 피하는 이유를 서술하라.
  4. 질량이 $s^{3}$, 관성이 $s^{5}$로 변하는 이유를 밀도 고정에서 유도하라.
  5. 삼각형 부등식 $d_1+d_2\ge d_3$이 평판에서 등호가 되는 이유와, 등가 상자 점검이 단위 오류를 잡는 이유를 설명하라.
  6. 초과 부피와 피복률의 의미를 충돌 검사의 거짓 양성·거짓 음성과 연결해 설명하라.

연구 질문:

  • 부품 경계에서의 접촉 불안정(볼록 부품이 맞닿는 가장자리)을 줄이는 분해 후처리는 무엇이며 이 장의 V-HACD 상한 8과 64 사례를 설명하는가?
  • CAD 질량 특성과 시뮬레이터 모델 관성의 불일치를 모델 적재 단계에서 자동으로 판정하는 점검(등가 상자, 질량 대비 부피)의 허용 한계는 얼마인가?
  • 충돌 부품의 수와 모양이 학습용 시뮬레이터(16.4)의 정책 학습 결과에 주는 영향은 어느 정도인가?

1차 출처(조회 2026-11-05).

  • ROS wiki, "urdf/XML/link"(Wayback Machine 보존본) — inertial·visual·collision·메시 해상도 권고를 읽었다. REP 103(ros-infrastructure/rep 저장소 rep-0103.rst) — 단위와 회전 표현을 읽었다.
  • MuJoCo 문서 원문(google-deepmind/mujoco, doc/XMLreference.rst·doc/modeling.rst·doc/computation/index.rst) — compiler(inertiafromgeom·balanceinertia·boundmass·fusestatic)·body/inertial·asset/mesh(inertia·scale·maxhullvert)·URDF 확장·충돌과 볼록 분해 절을 읽었다.
  • V-HACD(kmammou/v-hacd, v4.1.0, BSD-3-Clause) — VHACD.h 소스(ComputeSplitPlane·Parameters)와 첫 화면을 읽었다. CoACD(SarahWeiii/CoACD, MIT) 첫 화면. vhacdx 0.1.1(PyPI).
  • 위키백과 "STL (file format)". SolidWorks URDF exporter(ros/solidworks_urdf_exporter)·runtimerobotics/fusion360-urdf-ros2·Rhoban/onshape-to-robot 첫 화면.
  • 서지만 확인(Crossref): K. Mamou, F. Ghorbel, "A simple and efficient approach for 3D mesh approximate convex decomposition," 2009 16th IEEE ICIP, 3501–3504, doi:10.1109/icip.2009.5414068; X. Wei, M. Liu, Z. Ling, H. Su, "Approximate convex decomposition for 3D meshes with collision-aware concavity and tree search," ACM Trans. Graph. 41(4), 1–18, 2022, doi:10.1145/3528223.3530103; B. Mirtich, "Fast and accurate computation of polyhedral mass properties," J. Graphics Tools 1(2), 31–50, 1996, doi:10.1080/10867651.1996.10487458; J.-M. Lien, N. M. Amato, "Approximate convex decomposition of polyhedra," Proc. ACM Symp. Solid and Physical Modeling, 121–131, 2007, doi:10.1145/1236246.1236265.
  • MuJoCo 3.17.0, Pinocchio 4.1.0, trimesh 5.2.0, SciPy 1.18.1, numpy 2.5.4, vhacdx 0.1.1, CoACD 1.0.14 — 같은 입력의 독립 대조.

다음 장. 4.16은 제조·조립·원가 설계를 다룬다. 이 장이 CAD 모델을 시뮬레이션 모델로 옮겼다면 다음 장은 같은 CAD 모델을 실제 부품으로 만들 때의 제조 가능성(DFM)·조립 용이성(DFA)과 시작품에서 양산으로 가는 경로를 정리한다.