제9부 로보틱스
9.12 Isaac Sim II — ROS 브리지·합성데이터
9.12.1 이 장에서 배우는 것 / 선수 지식
9.11에서 Isaac Sim의 토대(PhysX·씬·RTX 센서)를 세웠다. 그런데 시뮬은 그 자체로 실행하려고 만드는 것이 아니다 — 개발·학습·검증 워크플로우의 일부가 되어야 쓸모가 있다. 이 장은 시뮬을 실제 워크플로우에 잇는 두 다리 — ① ROS 2 브리지로 시뮬 센서·로봇을 Isaac ROS(9.7~9.10)에 연결해 실로봇과 같은 코드를 시뮬에서 실행하는 SIL(Software-in-the-Loop), ② 합성 데이터 생성(Replicator) 으로 완벽한 라벨의 학습 데이터를 만드는 법 — 을 실습 관점으로 판다.
핵심 통찰: 시뮬의 두 출구는 "코드 검증(SIL)"과 "데이터 생성(SDG)"이다. 9.11의 RTX 센서·물리는 두 방향으로 흘러나간다 — 한쪽은 ROS 브리지를 타고 Isaac ROS 인지·플래닝(9.7~9.10)으로 가서 실로봇 배포 전에 같은 스택을 안전하게 검증(SIL)하고, 다른 쪽은 Replicator를 타고 완벽한 라벨 데이터셋이 되어 그 인지 모델을 학습시킨다. 두 출구가 합쳐지면 시뮬은 "코드를 시험하고 그 코드가 먹을 데이터를 만드는" 개발·데이터 엔진이 된다. 그리고 둘 다의 성패는 시간 동기(/clock)와 Sim2Real 갭(노이즈·랜덤화) 에 달렸다.
배우는 것:
- 두 다리 — 시뮬을 워크플로우에 잇는 ROS 브리지(코드 검증)·합성데이터(학습 데이터).
- ROS 2 브리지 — OmniGraph(Action Graph)로 시뮬 센서·TF·조인트를 ROS 2 토픽으로, 명령을 구독.
- SIL(Software-in-the-Loop) — 시뮬 센서로 cuVSLAM·nvblox·cuMotion(9.7~9.10) 을 실로봇 배포 전 검증. /clock·use_sim_time의 결정적 역할.
- 합성 데이터(Replicator) — annotator(분할·박스·깊이)·writer·randomizer로 완벽 라벨 데이터셋(10.5 예고).
- 도메인 랜덤화 개요 — 무엇을·왜 흔들어 Sim2Real을 좁히나(9.14·10.6 예고).
선수 지식: 9.11(Isaac Sim 토대·RTX 센서·Sim2Real)·9.7~9.10(Isaac ROS 인지·플래닝 — SIL 대상)·9.8(ROS 그래프·검증)·8.7/9.9(시간 동기·타임스탬프)·7.7/8.14(데이터 플라이휠·데이터 엔진). ROS 2 토픽·TF·use_sim_time 기초는 가정. 대규모 병렬 RL은 9.13, 도메인 랜덤화·합성데이터 심화는 9.14·10.5·10.6, Sim2Real은 10.7.
정직: Isaac Sim의 ROS 브리지·OmniGraph·Replicator의 노드·API·확장명·출력 포맷은 릴리스 의존이 크다. 이 장은 "시뮬을 코드 검증·데이터 생성에 어떻게 잇는가의 절차·원리"(브리지 구조·SIL·합성데이터 워크플로우·시간 동기·랜덤화의 이유)를 가르치고, 구체 노드·API·메뉴는 "그 릴리스 문서로 확인". 코드는 개념 골격. ROS 브리지를 통한 센서 전송은 충실도·해상도에 따라 실시간이 아닐 수 있음(시뮬 시간으로 디커플)을 정직하게 둔다. 합성데이터 심화(Replicator 전모·랜덤화 전략)는 10.5·10.6.
9.12.2 시뮬을 워크플로우에 연결한다 — 두 다리
9.11의 시뮬(물리·센서)은 두 방향으로 흘러나가 워크플로우의 일부가 된다.
- 다리 ①: ROS 브리지 → SIL(코드 검증): 시뮬 센서를 ROS 2 토픽으로 내보내면, 실로봇과 똑같은 Isaac ROS 코드(인지 9.7~9.9·플래닝 9.10)가 시뮬 입력으로 실행된다. 실로봇에 배포하기 전에 위험·비용 없이 인지·내비·매니퓰레이션을 검증·디버깅(9.10 충돌 회피를 시뮬에서 먼저).
- 다리 ②: Replicator → SDG(데이터 생성): 시뮬의 완벽한 GT 라벨(9.11.6)을 데이터셋으로 추출해, 그 인지 모델(9.7~9.9)을 학습시킨다. 실라벨링(비용이 크고 노이즈) 대신 시뮬이 라벨을 추가 비용 없이.
- 둘이 합쳐지면: 시뮬은 데이터 엔진(8.14)의 일부 — 데이터를 만들고(②), 그 데이터로 학습한 코드를 시뮬에서 검증하고(①), 실패 케이스를 시뮬로 재현·보강(7.7 플라이휠). 인지(9.7~9.9)→행동(9.10)→학습(9.13)이 시뮬을 통해 순환.
- 공통 관문: 두 다리 모두 시간 동기(/clock) 와 Sim2Real 갭(센서 노이즈·도메인 랜덤화)에 성패가 달렸다 — 이 장의 두 경고.
핵심: 시뮬의 두 출구는 ROS 브리지(코드 검증·SIL) 와 Replicator(데이터 생성·SDG) 다. 하나는 실로봇 배포 전 같은 스택(9.7~9.10)을 안전하게 검증하고, 하나는 그 스택이 먹을 완벽 라벨 데이터를 만든다. 둘이 합쳐 시뮬을 개발·데이터 엔진으로 만들며, 공통 관문은 시간 동기·Sim2Real.
9.12.3 ROS 2 브리지 — 시뮬 센서를 ROS로
ROS 2 브리지는 Isaac Sim과 ROS 2를 잇는 확장(extension)이다. 시뮬의 센서·상태를 ROS 토픽으로 발행하고, ROS 명령을 구독해 시뮬 로봇을 움직인다.
ROS 2 브리지가 잇는 것(개념 — 노드·토픽은 릴리스 의존):
| 방향 | 종류 | 내용 |
|---|---|---|
| Isaac Sim → ROS 2 (발행) | 카메라 | RGB / depth / 분할(image_raw, camera_info) |
| LiDAR | PointCloud2 / LaserScan | |
| TF | 로봇 링크 좌표 변환(map→odom→base_link 정신, 9.9) | |
| JointState | 관절 위치·속도 | |
| IMU, 접촉 센서 … | ||
| /clock | 시뮬 시간(★ 시간 동기의 핵심, 9.12.4) | |
| ROS 2 → Isaac Sim (구독) | JointCommand / ros2_control | 관절 목표(cuMotion 궤적 9.10 실행) |
| cmd_vel | 이동 명령(모바일 로봇) |
- OmniGraph(Action Graph)로 배선: Isaac Sim은 노드 그래프(OmniGraph) 로 시뮬↔ROS를 잇는다 — "On Playback Tick → ROS2 Context → ROS2 Publish Camera/TF/JointState", "ROS2 Subscribe JointState → Articulation 구동" 같은 노드를 연결. ROS 2 launch가 노드를 잇듯(9.8), OmniGraph가 시뮬 안에서 배선한다(노드명은 릴리스 확인).
- 메시지 타입 정합: 시뮬이 내는 토픽은 표준 ROS 메시지(
sensor_msgs/Image·PointCloud2·tf2_msgs/TFMessage·sensor_msgs/JointState)라, ROS 쪽(Isaac ROS·Nav2·MoveIt)은 실센서와 구분 없이 받는다 — 그래서 같은 코드가 실행된다(SIL). - QoS·camera_info: 센서 토픽은 QoS(보통 sensor data, 9.8.7)·
camera_info(intrinsic, 캘리브레이션 8.13)를 함께 내야 하류(스테레오·nvblox)가 동작. - 전송 오버헤드(정직): 고해상도·고프레임 영상을 브리지로 내보내면 직렬화·전송 비용이 있어 실시간보다 느릴 수 있다 — 그래서 시뮬 시간으로 디커플(다음 절). NITROS zero-copy(9.7)는 ROS 노드 사이 이야기이고, 시뮬↔ROS 경계는 표준 전송이다.
핵심: ROS 2 브리지는 OmniGraph로 시뮬 센서·TF·조인트를 표준 ROS 메시지로 발행하고 명령을 구독한다 — 표준 메시지라 ROS 쪽(Isaac ROS·Nav2)이 실센서와 구분 없이 받아 같은 코드가 실행된다.
camera_info·QoS·/clock을 함께 내는 것이 하류 동작의 전제. 고해상도 전송은 실시간이 아닐 수 있어 시뮬 시간으로 디커플.
9.12.4 Software-in-the-Loop — 시뮬에서 같은 인지 스택을
브리지의 실질적 가치는 SIL(Software-in-the-Loop) — 실로봇에 탑재할 바로 그 소프트웨어(Isaac ROS 9.7~9.10)를 시뮬 센서로 검증하는 것이다.
SIL 루프(시뮬이 실센서·실로봇을 대신):
시뮬 로봇이 명령대로 움직임 → 센서 갱신 → 닫힌 루프. 실로봇 배포 전: 같은 코드를 시뮬에서 안전하게(부서질 걱정 없이, 9.11).
- 무엇을 검증하나: cuVSLAM이 시뮬 카메라·IMU로 자세를 잘 추정하나, nvblox가 시뮬 깊이로 지도를 만드나, cuMotion이 시뮬 장애물을 피해 팔을 움직이나(9.10), Nav2가 시뮬 코스트맵으로 길을 찾나 — 실로봇 없이 알고리즘·통합·파라미터를 시험·디버깅.
- /clock과 use_sim_time(SIL의 핵심): 시뮬 시간은 벽시계와 다를 수 있다(느린 렌더로 시뮬 1초가 벽시계 3초, 또는 가속). 그래서 브리지가
/clock(시뮬 시간) 을 발행하고, 모든 ROS 노드는use_sim_time:=true로 설정해 벽시계 대신 시뮬 시간을 따른다. 이를 안 하면:- TF·센서 타임스탬프가 노드마다 다른 시계(시뮬 vs 벽시계)를 써 시간 불일치 → nvblox가 깊이를 틀린 자세에 융합(9.9 함정)·TF 외삽 실패·동기 깨짐.
- 즉 SIL의 90% 문제가 /clock·use_sim_time 누락이다(9.9.7의 "시간 동기 1순위"가 시뮬에선 이것).
- SIL vs HIL: SIL은 소프트웨어를(브리지로) 시험. HIL(Hardware-in-the-Loop) 은 실제 컴퓨트(Jetson)·일부 하드웨어를 루프에 넣어 더 현실적으로(타이밍·자원). Isaac Sim은 SIL이 주, HIL도 구성 가능(릴리스·구성 의존).
- 결정적 회귀: 시뮬은 결정적(9.11, GPU 비결정 유의)이라 같은 시나리오로 회귀 — 알고리즘 변경이 인지·플래닝을 깨뜨리는지 시뮬에서 자동 검증(8.14 재시뮬·9.8 rosbag 정신).
견해: SIL은 실로봇에 탑재할 바로 그 Isaac ROS 코드(9.7~9.10)를 시뮬 센서로 닫힌 루프 검증하는 것 — 위험·비용 없이 인지·내비·매니퓰레이션을 시험·회귀. 그 성패의 핵심 요인은
/clock발행 + 모든 노드use_sim_time:=true다(시뮬 시간으로 통일). 이것을 빠뜨리면 "시뮬은 실행되는데 인지가 이상한" 시간 불일치에 빠진다 — SIL 디버깅 1순위.
9.12.5 합성 데이터 생성(Replicator) — 완벽한 라벨을 무한히
두 번째 다리는 합성 데이터 생성(SDG) — 시뮬의 완벽한 GT(9.11.6)를 학습 데이터셋으로 추출하는 Replicator다(전모는 10.5, 여기선 실습 골격).
Replicator 합성데이터 파이프라인(개념):
결과: 이미지 + 완벽한 라벨(분할·박스·깊이) 수천~수만 장, 자동·무비용.
- annotator = GT 채널: 무엇을 정답으로 지정할지. 의미 분할(픽셀 클래스)·인스턴스 분할(객체 ID)·2D/3D 박스·깊이·법선 — 시뮬이 픽셀마다 정확히 안다(실라벨링 불가능한 정밀도). 인지 모델(검출·분할·깊이, 9.7~9.9)의 학습 타깃.
- writer = 출력 포맷: 데이터셋을 디스크에 표준 포맷(KITTI·COCO 등)으로 → 학습 파이프라인(PyTorch·TAO·NeMo)이 바로 소비. 커스텀 writer로 원하는 구조도.
- 왜 합성인가(9.11 재확인): ① 완벽·자동 라벨(실라벨링 비용·노이즈 제거) ② 무한·롱테일(희귀·위험 장면도 안전하게 생성) ③ 균형(클래스·조건을 의도대로) ④ 결함 없는 GT(깊이·3D 박스는 실세계서 정확히 못 잼). 데이터가 병목인 인지(8.14 데이터 엔진)에 결정적.
- 헤드리스·배치(9.11.7): 데이터 생성은 보통 headless로 서버·클라우드에서 대량 배치 — GUI 없이 수만 장.
- 한계(정직, 10.7): 합성만으로 학습하면 Sim2Real 갭 — 그래서 도메인 랜덤화(다음 절) 와 실데이터 혼합이 필요. 합성만으로는 충분하지 않고 실데이터를 보강·대체(부분) 한다.
핵심: Replicator는 씬→annotator(GT 채널)→randomizer(변형)→trigger→writer(데이터셋) 로 완벽 라벨 데이터를 자동·대량 생성한다 — 실라벨링의 비용·노이즈·불가능(정밀 깊이·3D)을 푼다. 인지 모델(9.7~9.9)의 학습 연료. 단 합성만으론 갭이 있어 도메인 랜덤화·실데이터 혼합 필수(10.7). 전모는 10.5.
9.12.6 도메인 랜덤화 개요 — 무엇을·왜 흔드나
합성 데이터·시뮬 학습의 Sim2Real을 좁히는 핵심 기법이 도메인 랜덤화(domain randomization) 다(심화는 9.14·10.6, 여기선 개념 수준).
도메인 랜덤화: 시뮬을 매번 다르게 → 모델이 '본질'을 배우게.
| 구분 | 항목 |
|---|---|
| 흔드는 것(시각·물리) | 조명(방향·세기·색) · 텍스처·재질·색 · 물체 위치·자세·개수 · 카메라(자세·FOV·노이즈) · 배경·방해물(distractor) · 마찰·질량(물리) |
| 안 흔드는 것(과제 불변) | 학습 대상의 본질(예: '컵'의 형태 클래스) · 물리 법칙 |
효과: 모델이 '이 조명·이 배경'이 아니라 '컵이라는 것'을 배움 → 실세계(또 다른 분포)서도 일반화.
- 왜 좁히나: 시뮬과 실세계는 분포가 다르다(갭). 시뮬을 한 모습으로 고정해 학습하면 모델이 그 특정 외형(조명·텍스처)에 과적합해 실세계서 취약. 무작위로 크게 흔들면, 모델은 변하는 표면적 요소를 무시하고 불변(과제 본질) 을 배운다 — 실세계도 "또 하나의 무작위 변형"처럼 보여 일반화(10.7).
- 시각 vs 물리 랜덤화: 시각(조명·텍스처·색)은 비전 인지(9.7~9.9)의 갭을, 물리(마찰·질량·게인·지연)는 제어·RL(9.13·9.14)의 동역학 갭을 좁힌다. 용도가 무엇을 흔들지 정한다.
- 무엇을 안 흔드나: 과제의 불변(본질) — 분류 대상의 형태 클래스, 물리 법칙 — 은 그대로 둔다. 흔들 것과 둘 것의 구분이 설계의 핵심.
- Replicator·Isaac Lab과의 연결: 합성데이터(9.12.5)의 randomizer가 시각 랜덤화, Isaac Lab(9.13·9.14)의 환경 랜덤화가 물리 랜덤화 — 같은 정신. 심화·전략은 9.14·10.6.
견해: 도메인 랜덤화는 "시뮬을 매번 다르게 만들어 모델이 표면이 아닌 본질을 배우게"다 — 시각(비전 갭)·물리(동역학 갭)를 크게 흔들되 과제 불변은 둔다. 이것이 합성데이터·시뮬 학습이 실세계로 넘어가는 다리(Sim2Real, 10.7). 개요일 뿐 전략(얼마나·무엇을·자동 튜닝)은 9.14·10.6.
9.12.7 워크스루 — SIL 루프 + 데이터셋 한 배치
두 다리를 각각 골격 코드로. ① ROS 브리지 SIL, ② Replicator 데이터 생성.
① ROS 브리지 + SIL (시뮬 센서로 cuVSLAM·nvblox 검증, 9.9)
# (Isaac Sim 측) ROS 2 브리지 확장 활성 + OmniGraph로 카메라·TF·clock 발행 구성
# - On Playback Tick → ROS2 Publish Camera(RGB/depth/camera_info) → /camera/*
# - ROS2 Publish TF, ROS2 Publish Clock(/clock) ← 시간 동기 필수
# - (이동 로봇이면) ROS2 Subscribe Twist(/cmd_vel) → 로봇 구동
# Play(▶) 누르면 시뮬이 ROS 토픽 발행 시작
# (ROS 2 측) 실로봇과 같은 Isaac ROS 그래프(9.8)를 use_sim_time으로 실행
ros2 launch my_perception slam_mapping.launch.py use_sim_time:=true # ★ /clock 따름
ros2 topic hz /camera/rgb ; ros2 topic echo /clock # 시뮬 센서·시간 확인
ros2 run tf2_ros tf2_echo map base_link # cuVSLAM 자세(9.9)
# RViz로 nvblox 메시·cuVSLAM 궤적 시각화 — 실로봇 없이 인지 검증
SIL 체크포인트:
· /clock 발행 + 모든 노드 use_sim_time:=true → 타임스탬프 일관(9.12.4)
· ros2 topic hz가 시뮬 센서율과 맞나(실시간 아닐 수 있음 — 시뮬 시간 기준)
· cuVSLAM 자세·nvblox 지도가 시뮬 환경과 일치 → 실로봇 전 검증 완료
이상: 인지가 이상·TF 외삽 실패 → use_sim_time 누락(벽시계 혼용) 1순위
② Replicator 합성 데이터 한 배치
# Replicator로 라벨된 데이터셋 생성(개념 골격 — API·모듈은 릴리스 의존, 반드시 확인)
import omni.replicator.core as rep
camera = rep.create.camera(position=(0, 0, 2), look_at=(0, 0, 0))
render_product = rep.create.render_product(camera, resolution=(640, 480))
cube = rep.create.cube(semantics=[("class", "cube")]) # 의미 라벨 부여
# 도메인 랜덤화: 매 프레임 위치·색·조명 흔들기(9.12.6)
with rep.trigger.on_frame(num_frames=1000):
with cube:
rep.modify.pose(position=rep.distribution.uniform((-1, -1, 0), (1, 1, 0)))
rep.randomizer.color(colors=rep.distribution.uniform((0, 0, 0), (1, 1, 1)))
rep.randomizer.light(intensity=rep.distribution.uniform(300, 1500))
# annotator + writer: RGB + 분할 + 2D 박스를 KITTI/COCO 등으로
writer = rep.WriterRegistry.get("BasicWriter")
writer.initialize(output_dir="/data/synth", rgb=True,
semantic_segmentation=True, bounding_box_2d_tight=True)
writer.attach([render_product])
rep.orchestrator.run() # 1000장: 매번 랜덤화→렌더→GT 캡처→디스크
데이터 생성 체크포인트:
· 출력에 이미지 + 라벨(분할 마스크·박스·깊이)이 정확히 정렬되나
· 랜덤화가 충분히 다양한가(조명·위치·색) → 일반화(9.12.6)
· 포맷이 학습 파이프라인(PyTorch/TAO/NeMo)과 맞나
→ 이 데이터로 인지 모델 학습 → TensorRT(5.2) → 엣지 배포(9.2) → SIL(①)로 검증
- 두 다리가 닫는 루프: ②로 만든 데이터로 학습한 모델을 ①의 SIL로 검증하고, 실패 장면을 다시 ②로 생성·보강 → 데이터 플라이휠(7.7·8.14)이 시뮬 안에서.
견해: SIL 실습의 1순위는
/clock+use_sim_time:=true(시간 일관), 합성데이터 실습의 1순위는 randomizer(다양성)와 annotator-이미지 정렬이다. 둘을 이으면 시뮬이 "데이터 생성(②)→학습→SIL 검증(①)→실패 보강(②)" 의 플라이휠을 순환한다(8.14). 실로봇 없이 인지·플래닝(9.7~9.10)을 만들고 검증하는 완결 워크플로우.
9.12.8 중간 점검 (체크포인트)
- [ ] 시뮬의 두 출구가 ROS 브리지(SIL·코드 검증) 와 Replicator(SDG·데이터 생성) 이고, 합쳐 데이터 엔진이 됨을 안다.
- [ ] ROS 브리지가 OmniGraph로 시뮬 센서·TF·조인트·/clock을 표준 ROS 메시지로 발행·구독함을 안다.
- [ ] SIL이 실로봇 배포 전 같은 Isaac ROS 코드(9.7~9.10) 를 시뮬로 검증하는 것이고, /clock·use_sim_time이 시간 일관의 핵심임을 안다.
- [ ] Replicator가 annotator(GT)·randomizer·writer로 완벽 라벨 데이터를 자동 생성함과 합성데이터의 가치·한계를 안다.
- [ ] 도메인 랜덤화가 시각·물리를 흔들어 본질을 배우게 해 Sim2Real을 좁힘(10.7)을 안다.
- [ ] 두 다리가 데이터 생성→학습→SIL 검증→보강의 플라이휠(7.7·8.14)을 닫음을 안다.
증상→의심: SIL서 인지 이상·TF 외삽 실패 → use_sim_time:=true 누락·/clock 미발행(벽시계 혼용) → 1순위. 시뮬 토픽이 ROS에 안 옴 → 브리지 확장 비활성·OmniGraph 미구성·QoS·토픽명 → 브리지 그래프·ros2 topic list. 하류(nvblox)가 동작 안 함 → camera_info·깊이·TF 누락 → 발행 채널 확인. 합성 라벨이 이미지와 어긋남 → annotator 정렬·좌표·writer 설정. 학습한 모델이 실세계서 취약 → 랜덤화 부족·합성만 사용 → 도메인 랜덤화↑·실데이터 혼합(10.7). 브리지가 느림 → 고해상도 전송 오버헤드 → 시뮬 시간 기준(실시간 기대 말 것). 데이터 다양성 부족 → randomizer 범위↑.
9.12.9 트레이드오프·대안
| 결정 | 트레이드오프 |
|---|---|
| SIL(브리지) vs HIL | 빠름·안전·확장 vs 실컴퓨트/타이밍 현실성 |
| 합성 데이터 vs 실데이터 | 완벽·무한·무비용 라벨·롱테일 vs 실제 분포(갭 없음) |
| 합성만 vs 합성+실 혼합 | 규모·라벨 vs Sim2Real 강건(혼합이 보통 최선) |
| 랜덤화 크게 vs 작게 | 일반화·갭 축소 vs 학습 난이도·비현실 데이터 |
| 포토리얼 렌더 vs 빠른 렌더(SDG) | 갭 작은 데이터 vs 대량 생성 속도 |
| ROS 브리지 vs 네이티브 시뮬 API | 실코드 재사용·SIL vs 시뮬 직접 제어·속도 |
견해: 실로봇 배포 스택(9.7~9.10)을 검증하려면 ROS 브리지 SIL이 거의 필수 — 같은 코드를 안전·반복으로 시험. 데이터가 병목인 인지는 합성+실 혼합이 보통 최선이다: 합성으로 규모·완벽 라벨·롱테일을, 실데이터로 실제 분포·갭 보정을. 합성만으로는 Sim2Real 갭이 남고(10.7), 실만으로는 라벨 비용·롱테일·정밀 GT(깊이·3D) 확보가 어렵다. 도메인 랜덤화는 크게 흔들되 과제 불변은 유지 — 너무 크면 학습이 어렵고 너무 작으면 갭이 안 닫힌다(9.14·10.6).
비엔비디아 정직: 시뮬↔ROS 연동·합성데이터는 NVIDIA만의 것이 아니다 — Gazebo도 ROS 2와 긴밀하고(ros_gz_bridge), 합성데이터는 Unity Perception·BlenderProc·다양한 도구가 있다. Replicator/Isaac Sim의 강점은 RTX 포토리얼리즘(갭 작은 데이터)·OpenUSD 에셋·대규모 GPU·Isaac ROS/Lab 통합·완벽한 멀티 GT(분할·3D 박스·깊이 동시) 다. 경량 ROS 시뮬·기본 데이터는 Gazebo·다른 도구로 충분할 수 있다 — 포토리얼·대규모·정밀 멀티 GT·스택 통합이 필요하면 Isaac Sim. 합성데이터의 효과(갭 축소)는 과제·랜덤화·혼합 비율 의존이라 자기 과제에서 검증(시뮬 성공≠실세계).
9.12.10 흔한 함정
- use_sim_time·/clock 누락. 노드가 벽시계를 써 타임스탬프 불일치 → 인지·TF 외삽 실패 → /clock 발행 + 모든 노드
use_sim_time:=true(SIL 1순위, 9.12.4). - camera_info·TF 누락. 하류(스테레오·nvblox 9.9)가 intrinsic·자세 없어 동작 안 함 → 브리지가 함께 발행.
- 브리지에 실시간 기대. 고해상도 영상 전송은 직렬화·렌더로 느릴 수 있음 → 시뮬 시간 기준(벽시계 아님).
- 합성 라벨·이미지 어긋남. annotator 정렬·좌표계·writer 설정 오류 → 마스크/박스가 이미지와 안 맞음 → 시각 검증.
- 합성만으로 학습. Sim2Real 갭으로 실세계 취약 → 도메인 랜덤화 + 실데이터 혼합(10.7).
- 랜덤화 부족/과다. 부족하면 과적합(갭), 과다하면 비현실·학습 난이도 → 적정·점진(9.14·10.6).
- 지나치게 이상적인 센서로 SDG. 노이즈 없는 데이터로 학습 → 실세계 노이즈에 취약 → 센서 노이즈 모델(9.11.6).
- QoS·메시지 타입 불일치. 시뮬 토픽 QoS가 구독자와 안 맞아 연결 안 됨 → SensorDataQoS 정합(9.8.7).
- SIL 성공을 실로봇으로 단정. SIL은 소프트웨어 검증, 실타이밍·하드웨어 차이 → HIL·실로봇 병행.
- 포맷 불일치. writer 포맷이 학습 파이프라인과 안 맞음 → KITTI/COCO/커스텀 정합.
9.12.11 연습문제
연습 1 (브리지·시간 동기). ROS 2 브리지가 무엇을 발행·구독하는지 들고, SIL에서 /clock과 use_sim_time이 왜 필수인지 — 누락 시 어떤 증상이 나는지 9.9과 연결해 설명하라.
정답
발행: 시뮬 센서·상태를 표준 ROS 메시지로 — 카메라(RGB/depth/분할 sensor_msgs/Image+camera_info), LiDAR(PointCloud2/LaserScan), TF(tf2_msgs/TFMessage, 로봇 링크 좌표), JointState(관절 위치·속도), IMU, 그리고 /clock(시뮬 시간). 구독: 명령 — JointCommand/ros2_control(관절 목표, cuMotion 궤적 9.10 실행), cmd_vel(이동). OmniGraph(Action Graph)로 배선. 표준 메시지라 ROS 쪽(Isaac ROS·Nav2·MoveIt)이 실센서와 구분 없이 받아 같은 코드가 실행된다(SIL). /clock·use_sim_time 필수성: 시뮬 시간은 벽시계와 다를 수 있다 — 느린 렌더로 시뮬 1초가 벽시계 3초, 또는 가속. 브리지가 /clock(시뮬 시간)을 발행하고 모든 ROS 노드가 use_sim_time:=true 로 설정하면 노드들이 벽시계 대신 시뮬 시간을 공통으로 따른다. 누락 시 증상(9.9 연결): 노드마다 시계가 달라(시뮬 vs 벽시계) ① 센서·TF 타임스탬프 불일치 → nvblox가 깊이를 틀린 자세에 융합(9.9.7 "시간 동기 1순위") → 지도 흐릿·이중 ② TF 외삽 실패(요청 시각에 변환 없음) → cuVSLAM 자세 조회 에러 ③ 동기 기반 융합(스테레오·VIO) 깨짐. 즉 "시뮬은 실행되는데 인지가 이상하다"의 90%가 use_sim_time 누락. 9.9에서 실로봇의 시간 동기가 1순위였듯, 시뮬에선 /clock·use_sim_time이 그 1순위. 진단: ros2 topic echo /clock(발행 확인), 각 노드 use_sim_time 파라미터 확인.
연습 2 (SIL의 가치). SIL(Software-in-the-Loop)이 무엇이고, cuVSLAM·nvblox·cuMotion(9.7~9.10)을 실로봇 배포 전 시뮬에서 검증하는 절차와 그 이점을 설명하라. HIL과의 차이도.
정답
SIL: 실로봇에 탑재할 바로 그 소프트웨어(Isaac ROS 인지·플래닝 9.7~9.10)를 ROS 브리지로 시뮬 센서·시뮬 로봇과 닫힌 루프로 실행해 검증하는 것. 시뮬이 실센서·실로봇을 대신. 검증 절차: ① Isaac Sim에서 씬(로봇·환경·물체, 9.11) 구성, ROS 브리지로 카메라·LiDAR·TF·/clock·JointState 발행, JointCommand/cmd_vel 구독 구성(OmniGraph). ② 실로봇과 같은 Isaac ROS launch(9.8)를 use_sim_time:=true 로 실행 — cuVSLAM(자세 9.9)·nvblox(지도 9.9)·cuMotion(궤적 9.10)·Nav2. ③ 닫힌 루프: 시뮬 센서→인지·플래닝→명령→시뮬 로봇 구동→센서 갱신. ④ 검증: RViz로 cuVSLAM 궤적·nvblox 지도가 시뮬 환경과 일치하나, cuMotion이 시뮬 장애물을 피하나(9.10), Nav2가 길을 찾나. ⑤ 결정적 회귀: 같은 시나리오로 알고리즘 변경의 회귀(8.14). 이점: ① 안전(실로봇 안 부숨, 9.10 충돌을 시뮬서 먼저) ② 비용·속도(하드웨어 없이, 빠른 리셋) ③ 재현(결정적 회귀) ④ 롱테일(위험 시나리오 안전 시험) ⑤ 조기 통합 디버깅(파라미터·연동 오류를 실로봇 전에). HIL과 차이: SIL은 소프트웨어만 시뮬 센서로(컴퓨트는 개발 PC). HIL(Hardware-in-the-Loop) 은 실제 컴퓨트(Jetson)·일부 하드웨어를 루프에 넣어 실타이밍·자원·하드웨어 특성까지 검증 — 더 현실적이나 복잡. Isaac Sim은 SIL이 주, HIL도 구성 가능. 정직: SIL 성공은 소프트웨어 로직 검증이지 실타이밍·센서 노이즈·하드웨어 차이를 다 못 잡음 → HIL·실로봇 병행, Sim2Real(10.7).
연습 3 (합성데이터 워크플로우). Replicator로 객체 검출용 라벨 데이터셋을 만드는 워크플로우를 annotator·randomizer·writer로 설계하고, 합성 데이터가 실데이터 라벨링 대비 주는 네 가지 이점과 한계를 답하라.
정답
워크플로우: ① 씬 구성 — 검출 대상 객체(USD)·환경·카메라 배치(9.11.5). 객체에 의미 라벨(semantics) 부여. ② annotator(GT 채널) — 검출이면 RGB + 2D/3D bounding box + 인스턴스 분할(필요시 의미 분할·깊이). 시뮬이 픽셀·객체마다 정확히 안다. ③ randomizer(도메인 랜덤화 9.12.6) — 매 프레임 객체 위치·자세·개수, 색·재질·텍스처, 조명(방향·세기·색), 카메라(자세·FOV·노이즈), 배경·distractor를 무작위. 과제 불변(객체 형태 클래스)은 유지. ④ trigger — on_frame(num_frames=N)으로 N장, 매번 랜덤화→렌더→GT 캡처. ⑤ writer — BasicWriter 또는 KITTI/COCO로 이미지+박스+마스크를 디스크에 → 학습 파이프라인(PyTorch/TAO) 소비. 헤드리스 배치로 수만 장. 네 이점: ① 완벽·자동 라벨 — 실라벨링의 비용·시간·인간 노이즈 제거(픽셀·박스 정확). ② 무한·롱테일 — 희귀·위험·드문 장면도 안전하게 대량(실수집 어려운 케이스). ③ 균형·제어 — 클래스·조건·시점을 의도대로(불균형 해소). ④ 불가능한 GT — 3D 박스·정확한 깊이·법선은 실세계서 정밀 측정 곤란한데 시뮬은 정확. 한계: ① Sim2Real 갭(10.7) — 합성만으론 실분포와 달라 실세계 취약 → 도메인 랜덤화·실데이터 혼합 필수. ② 충실도 의존 — 비현실 렌더·노이즈 없으면 갭↑. ③ 씬·에셋 제작 비용 — 다양한 현실적 에셋·씬을 만드는 노력. ④ 검증 필요 — 합성 효과는 과제·랜덤화 의존이라 실데이터로 검증. 보통 합성(규모·롱테일·완벽 라벨) + 실(실제 분포) 혼합이 최선. 전모는 10.5·10.6.
연습 4 (도메인 랜덤화). 도메인 랜덤화가 Sim2Real을 좁히는 원리를 설명하고, 비전 인지와 제어/RL에서 각각 무엇을 흔들어야 하는지, 무엇을 흔들면 안 되는지 답하라.
정답
원리: 시뮬과 실세계는 분포가 다르다(갭). 시뮬을 한 모습으로 고정해 학습하면 모델이 그 특정 외형(이 조명·이 텍스처·이 마찰)에 과적합해 실세계(다른 분포)서 취약. 시뮬을 매번 크게 무작위로 바꾸면, 모델은 변하는 표면적 요소(조명·텍스처·배경)를 무시하고 불변(과제 본질) 을 배운다 — 결과적으로 실세계도 "또 하나의 무작위 변형"처럼 보여 일반화. 즉 "특정 도메인에 맞추기" 대신 "도메인 변화에 불변인 특징 배우기". 비전 인지(9.7~9.9)서 흔들 것: 시각 요소 — 조명(방향·세기·색·그림자), 텍스처·재질·색, 배경, distractor(방해 물체), 카메라(자세·FOV·노출·노이즈·왜곡), 물체 위치·자세. 비전 갭은 외형 분포 차이라 시각 랜덤화가 핵심. 제어/RL(9.13·9.14)서 흔들 것: 물리·동역학 — 마찰계수, 질량·관성, 드라이브 게인(stiffness/damping 9.11), 액추에이터 지연·노이즈, 지면·외란(밀기). 제어 갭은 동역학 차이라 물리 랜덤화가 핵심(로봇이 다양한 물리에 강건한 정책 학습). 흔들면 안 되는 것: 과제의 불변(본질) — 분류·검출 대상의 형태 클래스(컵은 컵 모양), 물리 법칙(중력·운동 방정식), 목표·보상 구조. 이를 흔들면 모델이 배울 일관된 신호가 없어진다. 균형(9.14·10.6): 너무 작게 흔들면 갭이 안 닫히고(과적합), 너무 크게 흔들면 비현실·학습 난이도↑(수렴 안 됨). 적정 범위·점진·자동 튜닝(심화 9.14·10.6)이 설계의 핵심. 정직: 랜덤화는 갭을 좁히되 없애진 못함 → 실데이터·실로봇 검증 병행(10.7).
연습 5 (진단·플라이휠). "SIL을 띄웠는데 시뮬은 실행되는데 cuVSLAM 자세가 이상하거나 nvblox 지도가 안 생긴다." 원인 후보를 우선순위로. 그리고 합성데이터+SIL이 어떻게 데이터 플라이휠(7.7·8.14)을 닫는지 설명하라.
정답
진단(우선순위): ① use_sim_time/clock 누락(최우선) — 노드가 벽시계를 써 타임스탬프 불일치 → cuVSLAM TF 외삽 실패·nvblox가 깊이를 틀린 자세에 융합. 진단: ros2 topic echo /clock, 각 노드 use_sim_time. 해결: /clock 발행 + 모든 노드 use_sim_time:=true. ② camera_info·TF·깊이 미발행 — nvblox·스테레오가 intrinsic·자세·깊이 없어 동작 안 함. 진단: ros2 topic list·hz, tf2_echo. 해결: 브리지 OmniGraph에 해당 채널 추가. ③ 토픽명·QoS 불일치 — 브리지 토픽과 노드 구독명/QoS 안 맞음. 진단: rqt_graph·QoS 경고. 해결: remap·SensorDataQoS(9.8). ④ 브리지 확장 비활성/그래프 미구성 — 토픽 자체가 안 옴. 해결: 확장·OmniGraph 확인. ⑤ 센서 충실도·시뮬 환경 — 무텍스처 시뮬 환경서 cuVSLAM 특징 부족(9.9 한계 시뮬판). 해결: 텍스처·조명. ⑥ 시간 진행/Play — 시뮬이 Play 안 됐거나 멈춤. 공통: use_sim_time이 1순위, 그다음 채널 누락. 데이터 플라이휠(7.7·8.14): ① 합성데이터(②) 로 인지 모델(9.7~9.9) 학습 → ② TensorRT(5.2) 최적화·엣지 배포 → ③ SIL(①) 로 시뮬에서 그 모델·스택 검증 → ④ 실패 케이스 발견(cuVSLAM이 특정 장면서 흔들림·검출 놓침) → ⑤ 그 실패 장면을 Replicator로 재현·대량 생성(②로 복귀, 롱테일 보강) → ⑥ 재학습 → ③ 재검증. 즉 생성→학습→검증→실패발견→보강이 시뮬 안에서 순환 — 실로봇 없이(혹은 병행) 데이터·코드를 함께 개선. 실데이터(실패 수집)도 이 루프에 합류(8.14 데이터 엔진). 핵심: 시뮬이 데이터 생성기(②)이자 검증기(①) 라 플라이휠의 두 축을 모두 담당 → 빠른 반복. 정직: 시뮬 플라이휠도 Sim2Real 갭(10.7)이 있어 실데이터·실로봇 검증으로 닫아야 완성.
9.12.12 요약 · 다음 장
- 두 다리: 시뮬의 출구는 ROS 브리지(SIL·코드 검증) 와 Replicator(SDG·데이터 생성) — 합쳐 데이터 엔진(8.14).
- ROS 2 브리지: OmniGraph로 시뮬 센서·TF·조인트·/clock을 표준 ROS 메시지로 발행·구독 → ROS 쪽이 실센서와 구분 없이 받아 같은 코드(SIL).
- SIL: 실로봇 배포 전 같은 Isaac ROS 코드(9.7~9.10) 를 시뮬 센서로 닫힌 루프 검증. /clock + use_sim_time:=true 가 시간 일관의 핵심(누락 = 인지 이상 1순위). SIL vs HIL.
- Replicator: annotator(GT)·randomizer·writer 로 완벽 라벨 데이터 자동·대량 생성 — 실라벨링의 비용·노이즈·불가능(깊이·3D) 해결. 합성만으론 갭 → 혼합(10.7).
- 도메인 랜덤화: 시각(비전)·물리(제어)를 흔들어 본질을 배우게 → Sim2Real 좁힘. 과제 불변은 유지. 심화 9.14·10.6.
- 플라이휠: 생성(②)→학습→SIL 검증(①)→실패 보강(②). 정직: API·포맷 릴리스 의존, 브리지 비실시간 가능, 시뮬 성공≠실세계(실로봇 병행).
다음 장: 9.13 Isaac Lab I — GPU 병렬 RL 구조. 시뮬을 코드 검증(SIL)·데이터 생성(SDG)에 이었으니, 이제 시뮬의 가장 강력한 쓰임 — 대규모 병렬 강화학습 — 으로 간다. PhysX GPU 물리(9.11)로 수천 개 로봇 환경을 한 GPU에서 동시에 실행해 정책을 학습하는 Isaac Lab의 구조를 본다. 시뮬이 학습 엔진으로.