AEGLOSLAB 엔비디아 기술 스택

제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 2 브리지 코드 검증·SIL ② Replicator 합성데이터 학습 데이터 Isaac Sim (9.11) PhysX 물리 · USD 씬 · RTX 센서 Isaac ROS(9.7~9.10) cuVSLAM·nvblox· cuMotion·Nav2 = 실로봇 배포 전 같은 코드 검증 '코드를 시험' 완벽 라벨 데이터셋(분할· 박스·깊이) → 인지 모델 학습 (9.7~9.9) TensorRT(5.2)로 배포 '그 코드가 먹을 데이터를 생성'
  • 다리 ①: 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)
LiDARPointCloud2 / 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 루프(시뮬이 실센서·실로봇을 대신):

센서 카메라· LiDAR·TF· clock 명령 JointCommand· cmd_vel Isaac Sim Isaac ROS 인지· 플래닝 cuVSLAM(자세 9.9) nvblox(지도 9.9) cuMotion(궤적 9.10)·Nav2

시뮬 로봇이 명령대로 움직임 → 센서 갱신 → 닫힌 루프. 실로봇 배포 전: 같은 코드를 시뮬에서 안전하게(부서질 걱정 없이, 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 합성데이터 파이프라인(개념):

① 씬 구성 로봇/물체/환경 배치(USD, 9.11.5) ② annotator 무엇을 GT로 추출하나: RGB· depth·semantic/instance seg·2D/3D bbox·normals ③ randomizer 무엇을 흔드나: 물체 위치·색· 재질·조명·카메라(도메인 랜덤화 9.12.6) ④ trigger 언제: on_frame(매 프레임)· 간격 — 매번 랜덤화→렌더→GT 캡처 ⑤ writer 어디로/어떤 포맷: BasicWriter / KITTI·COCO 등 → 디스크 데이터셋

결과: 이미지 + 완벽한 라벨(분할·박스·깊이) 수천~수만 장, 자동·무비용.

  • 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의 구조를 본다. 시뮬이 학습 엔진으로.