20Isaac Sim · MuJoCo 시뮬레이션
Isaac Sim USD 모델과 MuJoCo 디지털 트윈으로 가상 텔레오퍼레이션·데이터 수집·Sim-to-Real 을 체험합니다.
왜 진짜 물리 시뮬레이터가 필요한가#
이 강좌의 시뮬레이터는 지금까지 아주 쓸모 있었습니다. 관절을 돌리고, IK 를 풀고, 궤적을 녹화했지요. 하지만 이 시뮬레이터는 기구학만 계산합니다. 중력도, 마찰도, 부딪힘의 반발도 없습니다. 큐브는 "그리퍼가 충분히 닫히고 TCP 가 가까우면 붙는다"는 단순 규칙으로 집힙니다.
실제 세상에서는 이런 일이 생깁니다.
- 팔을 쭉 뻗으면 모터가 무게를 못 이겨 처집니다 (19장의 중력 토크).
- 그리퍼가 블록을 너무 세게 쥐면 미끄러지거나 튕겨 나갑니다.
- 빠르게 휘두르면 관절이 목표를 지나쳤다가 되돌아옵니다.
물리 시뮬레이터는 이런 현상을 계산해 줍니다. 실물을 망가뜨릴 걱정 없이 수천 번 실험하고, 정책 학습용 데이터를 쏟아낼 수 있습니다. reBot 생태계에서는 두 가지가 공식으로 준비되어 있습니다.
| MuJoCo | NVIDIA Isaac Sim | |
|---|---|---|
| 모델 형식 | MJCF (.xml) | USD (.usda) |
| 강점 | 가볍고 빠른 접촉 물리, 브라우저 데모로도 체험 가능 | 사실적 렌더링, 카메라 합성 데이터, GPU 대량 병렬 |
| 필요 장비 | 일반 PC (온라인 데모는 브라우저만) | NVIDIA RTX GPU (권장 RTX 3070 이상, VRAM 8GB+) |
| reBot 자료 | 온라인 데모, MuJoCo Menagerie 모델 | Isaac Sim 위키, reBot-Isaacsim |
설치 없이 — 온라인 MuJoCo 디지털 트윈#
공식 저장소 README 는 B601-RS MuJoCo 디지털 트윈을 브라우저에서 바로 체험할 수 있는 온라인 데모를 소개합니다. 처음 모델을 받는 데 시간이 조금 걸리며 Chrome 이나 Edge 를 권장합니다.
| 기능 | 화면에서 찾을 것 |
|---|---|
| 구성 전환 | "Arm only" ↔ "AGV chassis"(이동 차체). AGV 는 WASD·화살표로 운전, Space 는 즉시 정지 |
| TCP 조작 | "Enable TCP drag" 후 TCP 표식을 끌어 손끝 이동, Open/Close 로 그리퍼 |
| 카메라 | 전역 오버헤드 카메라 + D405 손목 카메라, 나란히/위아래 보기 |
| 자동 데모 | 빨강 큐브·파랑 블록·노랑 원기둥 중 골라 "Put away"(제자리 정리), "Stack"(쌓기) |
| 접촉·힘 | 접촉 개수, 그립 힘(Grip force), 관절 토크·오차 곡선 |
| 분해도 | "Disassemble" 로 부품을 펼치고, 부품을 눌러 조립·관절·재질 정보 보기 |
MuJoCo 모델 들여다보기 — mujoco_collision 의 의미#
17장에서 메시 폴더 중 mujoco_collision/ 이 따로 있던 것을 기억하나요? 물리 시뮬레이터에서 집기는 접촉 형상이 전부입니다. 손가락을 볼록 껍질 하나로 단순화하면, 손가락 안쪽 오목한 부분까지 "꽉 찬 덩어리"로 계산되어 블록이 실제보다 일찍 닿거나 손가락끼리 관통합니다. 그래서 공식 패키지는 손가락을 앞·중간·뒤 세 조각으로 나누고 캐리지·스토퍼까지 따로 둔 10조각을 MuJoCo 접촉용으로 제공합니다. README 의 경고 그대로 "완전한 손가락의 단일 convex hull 로 바꾸면 닫을 때 관통, 과도하게 큰 접촉면, 불안정한 파지가 다시 생길 수 있습니다."
reBot-Isaacsim 저장소의 mjcf/rebot_devarm/ 에는 MuJoCo Menagerie(DeepMind 가 관리하는 고품질 로봇 모델 모음)의 [seeed_rebot_devarm](https://github.com/google-deepmind/mujoco_menagerie/tree/da76818e269b82289eba39808e2fb91d679d6994/seeed_rebot_devarm) 모델이 복사되어 있고, README 가 그 설계를 자세히 설명합니다.
| 설계 | 내용 (README 기준) |
|---|---|
| 충돌 형상 | 링크마다 8~12조각 볼록 분해(convex decomposition), 총 92개. 링크당 볼록 껍질 하나면 부피가 실제의 3.24배, 분해하면 1.89배 |
| 자기 충돌 | 켜져 있음. 인접 링크 등 11쌍만 제외 |
| 구동기 | 위치 구동기. 토크 한계 RS-06 36 N·m(관절 1~3), RS-00 14 N·m(관절 4~6) — 실물 펌웨어에서 읽은 값 |
| 그리퍼 | 1:1 랙-피니언이라 두 손가락을 <equality joint> 로 묶음 (독립 자유도 아님) |
| 중력 검증 | MuJoCo 의 중력 항과 Pinocchio g(q) 를 5개 자세에서 비교, 최대 차이 5.9e-6 N·m |
<joint name="joint2" type="hinge" range="-3.14 0" axis="0 0 -1" class="rs06"/>
...
<equality>
<joint joint1="joint_left" joint2="joint_right" polycoef="0 1 0 0 0" .../>
</equality>위 발췌를 보면 RS 모델인데 joint2 범위가 -3.14 ~ 0 이고 손가락 이름이 joint_left/joint_right 입니다. 이 자산은 저장소의 이전 RS URDF(urdf/00-arm-rs_asm-v3)에서 만들어졌기 때문입니다. 현재 Rebot_Arm_description/RS 의 URDF(joint2 0 ~ 3.14, gripper_joint1/2)와 부호·이름이 다릅니다. 저장소 문서도 "응용 프로그램의 관절 부호 매핑을 적용하라"고 당부합니다. 시뮬레이터 사이에서 자세 값을 옮길 때는 반드시 각 모델 파일의 range·axis·이름을 대조하세요.
ROS 2 를 쓴다면 공식 작업공간의 rebotarm_mujoco_rs 패키지가 RS MuJoCo 모델을 ROS 에 붙여 줍니다. kinematic 모드는 ROS 관절 상태를 그대로 MuJoCo 에 복사하고, physics 모드는 PD 제어 + 중력 항으로 목표를 따라갑니다. 이 래퍼는 SocketCAN 을 열지 않으므로 실물 팔은 여전히 reBotArmController 하나만 제어합니다(18장).
ros2 launch rebotarm_mujoco_rs mujoco_rs.launch.py \
arm_namespace:=rebotarm_rs simulation_mode:=physics use_viewer:=trueIsaac Sim — USD 모델과 가상 텔레오퍼레이션#
준비물#
Isaac Sim 위키 기준 요구 사양입니다.
| 항목 | 요구 |
|---|---|
| Isaac Sim | 6.0.0 독립 실행 패키지 |
| OS | Ubuntu 22.04 / 24.04 LTS (권장), 또는 Windows 11 + WSL2 |
| GPU | NVIDIA RTX, 권장 RTX 3070 이상, VRAM 8GB 이상, 드라이버 535 이상 |
| RAM / 저장공간 | 32GB 이상 / SSD 여유 100GB 이상 |
URDF 에서 USD 로#
Isaac Sim 은 USD(Universal Scene Description) 라는 장면 형식을 씁니다. reBot-Isaacsim 의 RS 자산(usd/RS-rebot-dev-arm/RS-rebot-dev-arm.usda)은 urdf-usd-converter 로 URDF 를 변환한 뒤, scripts/prep_asset.py 로 후처리한 결과입니다. 변환기만으로는 부족한 것을 스크립트가 채웁니다.
- 관절 8개에 구동기(drive) 와 검증된 게인·토크 한계를 붙입니다 (변환 직후 관절은 "기구학 전용"이라 힘이 없습니다).
- 충돌 형상을 혼합으로: 팔은 볼록 껍질, 그리퍼(
gripper_end·좌우 손가락)는 볼록 분해. - Isaac 로봇 스키마를 붙여 Gain Tuner 같은 도구가 로봇을 인식하게 합니다.
DM 자산은 usd/reBot_B601_DM/reBot_B601_DM.usda 에 있습니다. 변환 과정과 검증 결과(관절별 한계 유지 테스트, 중력 처짐 분석)는 저장소 docs/VALIDATION.md 에 기록되어 있어, 시뮬레이션 모델도 검증 대상이라는 좋은 예를 보여 줍니다.
송신부와 수신부 — 두 터미널 구조#
reBot-Isaacsim 은 수신부(Isaac Sim 안에서 관절을 움직임)와 송신부(관절각을 보냄)를 UDP 로 잇습니다.
터미널 2 (송신부) 터미널 1 (수신부)
reBotArm_control_py uv 환경 ── UDP JSON ──▶ Isaac Sim 의 python
gravity_joint_sender 등 127.0.0.1:5005 isaacsim_joint_receiver{"sequence": 123, "timestamp": 1718000000.123,
"joint_positions": [0.0, 0.1, 0.2, -0.1, 0.0, -0.02],
"gripper_position": 0.05}| 송신부 | 하는 일 | 실물 필요 |
|---|---|---|
isaacsim_joint_test_sender | 미리 정한 자세 사이를 천천히 오가며 통신 확인 | 아니요 |
isaacsim_ik_sender | x y z [r p y] 를 입력하면 IK 로 풀어 전송 | 아니요 (IK 계산만) |
isaacsim_traj_sender | IK + 관절 공간 MIN_JERK 궤적으로 부드럽게 | 아니요 |
gravity_joint_sender | 중력 보상 손잡이 모드: 실물 팔을 손으로 움직이면 Isaac Sim 의 팔이 60 Hz 로 따라옴 | 예 |
joint_reader_sender | Real-to-Sim: 다른 프로그램이 돌리는 실물 팔을 읽기만 해서 비춤 | 예 |
gravity_joint_sender 가 바로 가상 텔레오퍼레이션입니다. 19장의 중력 보상(MIT + g(q))으로 실물 팔을 가볍게 만들어 리더 암처럼 쓰고, 그 관절각으로 가상 팔을 조종합니다. 저장소는 그리퍼를 떼고 손잡이를 단 개조 팔을 예로 듭니다.
# 터미널 1 — 수신부를 먼저
cd reBotArm_Isaacsim
./run_isaacsim_receiver.sh
# 터미널 2 — 실물 없이 통신 확인
cd reBotArm_Isaacsim
uv run python isaacsim_joint_test_sender.py위키 본문은 저장소 주소를 hopcan/reBot-Isaacsim 으로, 터미널 1 명령을 ${ISAACSIM_PYTHON_EXE} gravity_joint_sender.py 로 적고 있지만, 저장소 README 는 Seeed-Projects/reBot-Isaacsim 이고 수신부는 isaacsim_joint_receiver.py(run_isaacsim_receiver.sh)입니다. 또 실물 송신부를 쓰기 전에 python set_hw_rs.py 로 하드웨어 설정을 RS 로 맞추라고 안내합니다. 실행 전 저장소 README 의 최신 순서를 확인하세요.
gravity_joint_sender 와 joint_reader_sender 는 실제 CAN 버스(can0, 1 Mbps)에 붙습니다. SDK 의 example/9 중력 보상을 동시에 돌리지 마세요 — 버스를 서로 빼앗습니다. RS 는 48V 전원이고, 중력 보상 중인 팔도 토크가 켜져 있으니 비상 시 전원을 바로 끊을 수 있게 하세요.
Sim-to-Real 갭과 도메인 랜덤화#
시뮬레이션에서 완벽히 되던 동작이 실물에서는 어긋나는 현상을 Sim-to-Real 갭이라고 합니다. 원인은 "모델이 현실을 100% 담지 못한다"는 것입니다.
| 갭의 원천 | reBot 에서의 예 |
|---|---|
| 질량·관성 | URDF 질량 합 RS 6.01 kg vs 사양 약 6.7 kg (17장) — 케이블·나사 누락 |
| 마찰·백래시 | reBot-Isaacsim 측정: 실물 그리퍼 정지 마찰은 손가락 기준 13.6 N, 백래시 ±0.37 mm |
| 구동기 | 실물은 MIT 게인·전류 한계·통신 지연, 시뮬은 이상적 구동기 |
| 접촉 | 접촉 형상 단순화, 마찰 계수 추정 |
| 센서 | 카메라 노이즈·조명·색감, 엔코더 잡음 |
reBot-Isaacsim 의 docs/GRIPPER_RESIDUAL_MOTION.md 는 좋은 사례입니다. 팔을 휘두를 때 실물 그리퍼 손가락은 사실상 움직이지 않는데, 시뮬레이션에서는 8 Hz 로 휘두를 때 약 0.25 mm 흔들렸습니다. 구동기 강성을 16배 올려도 거의 그대로였고, 문서는 이것이 강성 문제가 아니라는 점을 측정으로 하나씩 확인해 나갑니다. 시뮬레이션의 차이는 추측이 아니라 측정으로 좁힌다는 태도를 배울 수 있습니다.
갭을 줄이는 두 가지 큰 전략은 다음과 같습니다 (일반론).
- 시스템 식별(system identification) — 실물을 측정해 모델 값을 맞춥니다. 19장의
tau_scale조정, reBot-Isaacsim 의 마찰·강성 측정이 여기에 속합니다. - 도메인 랜덤화(domain randomization) — 시뮬레이션의 질량·마찰·게인·조명·카메라 위치·물체 색을 에피소드마다 조금씩 무작위로 바꿔 학습시킵니다. 정책이 "정확히 이 세계"가 아니라 "이 근처의 여러 세계"에서 통하도록 배우면, 실물도 그 범위 안의 한 세계로 받아들여질 가능성이 커집니다.
Seeed 는 NVIDIA Isaac 과 함께 Learning Physical AI — A Sim-to-Real VLA Pipeline with Seeed reBot Arm and NVIDIA Isaac 코스를 안내합니다. 시뮬레이션에서 데이터를 만들고 VLA(시각-언어-행동) 정책을 학습해 실물 reBot 에 옮기는 흐름입니다. 커리큘럼·가격 등 세부는 페이지에서 최신 정보를 확인하세요. 정책 학습 자체는 16장을 참고하세요.
세 시뮬레이터 비교#
| 항목 | 강좌 브라우저 시뮬레이터 | MuJoCo | Isaac Sim |
|---|---|---|---|
| 계산 | 기구학만 (FK·IK) | 강체 동역학 + 접촉 | 강체 동역학 + 접촉 (PhysX / Newton) |
| 중력·마찰·토크 | 없음 | 있음 | 있음 |
| 집기 | 단순 규칙(닫힘 + 근접 → 붙음) | 접촉 메시와 마찰로 계산 | 접촉 메시와 마찰로 계산 |
| 카메라 | 손목·스탠드 가상 카메라 | 오버헤드·D405 손목 (데모) | 사실적 렌더링, 합성 데이터 |
| 모델 | 공식 URDF (RS/DM 전환) | MJCF (Menagerie 기반 RS) | USD (RS·DM) |
| 설치 | 없음 | pip 또는 브라우저 데모 | RTX GPU + Isaac Sim 6.0 |
| 잘하는 일 | 개념 학습, 관절·IK·궤적 연습, LeRobot 형식 녹화 | 빠른 물리 실험, 파지 검증 | 대규모 데이터 생성, 시각 정책, Sim-to-Real |
| 못하는 일 | 처짐·미끄러짐·충돌 반력 | 사진 같은 렌더링 | 가벼운 실행 |
- 시뮬레이터 Python 탭에서 아래를 실행해 팔을 최대한 앞으로 뻗었다가 접습니다.
arm.home()
for x in [0.30, 0.45, 0.60]:
ok = arm.move_to(x, 0.0, 0.20, t=1.5) # 위치만 맞추기
print(x, "도달" if ok else "실패", [round(a, 1) for a in arm.get_joints()])
arm.home()- 각 자세에서 실물이라면 어느 관절이 가장 힘들지(중력 토크가 클지) 예상해 적어 보세요. 19장의 결과와 비교합니다.
- 큐브를 켜고
arm.cube()위치로 가서arm.close()한 뒤 들어 올려 보세요. 실물이나 MuJoCo 라면 어떤 이유로 실패할 수 있을지(미끄러짐, 손가락 관통, 블록 회전 등) 세 가지를 적습니다. 녹화탭으로 이 동작을 LeRobot 형식으로 내보내 보세요. 이 데이터를 실물 정책 학습에 그대로 쓰면 어떤 갭이 생길까요?
정리#
- 이 강좌 시뮬레이터는 기구학 전용이고, MuJoCo·Isaac Sim 은 중력·마찰·접촉을 계산하는 물리 시뮬레이터입니다.
- 온라인 MuJoCo 디지털 트윈은 설치 없이 TCP 드래그, D405 손목 카메라, 정리·쌓기 데모, 접촉·힘 모니터를 제공합니다.
mujoco_collision메시는 손가락을 여러 조각으로 나눈 세밀 접촉 형상으로, 하나의 볼록 껍질로 바꾸면 집기가 불안정해집니다.- Isaac Sim 자산은 URDF →
urdf-usd-converter→ 후처리(구동기·충돌·스키마)로 만든 USD 이고, reBot-Isaacsim 은 UDP 송신부/수신부 구조로 IK·궤적·중력 보상 텔레오퍼·Real-to-Sim 을 지원합니다. - 변환된 자산(MJCF·USD)은 관절 부호·이름이 현재 URDF 와 다를 수 있으니 항상 대조하세요.
- Sim-to-Real 갭은 시스템 식별(측정으로 모델 맞추기)과 도메인 랜덤화(무작위로 흔들어 학습)로 줄입니다.
확인 문제#
- 강좌 브라우저 시뮬레이터로는 확인할 수 없고 MuJoCo 로는 확인할 수 있는 현상 두 가지를 쓰세요.
- 그리퍼 손가락의 MuJoCo 접촉 형상을 하나의 볼록 껍질로 단순화하면 어떤 문제가 생길 수 있나요?
- reBot-Isaacsim 에서 실물 없이 통신부터 확인하려면 어떤 송신부를 쓰나요? 수신부와 송신부 중 무엇을 먼저 켜나요?
- reBot-Isaacsim 의 RS MJCF 에서
joint2범위가-3.14 ~ 0인 것을 보고 무엇을 조심해야 하나요? - 도메인 랜덤화가 Sim-to-Real 갭을 줄이는 원리를 한 문장으로 설명하세요.
- 예: 팔이 중력으로 처지는 것, 그리퍼가 블록을 쥘 때의 접촉 힘과 미끄러짐, 관절 토크, 충돌 반력.
- 손가락 안쪽까지 꽉 찬 덩어리로 계산되어 닫을 때 관통하거나 접촉면이 너무 커져 파지가 불안정해집니다.
isaacsim_joint_test_sender.py를 씁니다. **수신부(run_isaacsim_receiver.sh)를 먼저** 켜고 송신부를 켭니다.- 현재
Rebot_Arm_description의 RS URDF(joint20 ~ 3.14)와 부호 약속이 반대이므로, 자세 값을 옮길 때 부호 매핑을 적용하고 관절 이름(joint_left/rightvsgripper_joint1/2)도 대조해야 합니다. - 시뮬레이션 조건을 무작위로 바꿔 가며 학습하면 정책이 여러 세계에서 통하도록 배우므로, 실물도 그중 하나처럼 다룰 수 있게 됩니다.