← BlogIsaac Sim 작동 원리· 4/10

물리 200Hz, 렌더 60Hz를 분리하는 이유 — substeps

물리를 한 루프에 여러 번(substep) 밟고 렌더는 가끔만 하는 이유 — 안정성과 성능을 동시에 잡는 timestep 분리. 다리 로봇이 60Hz에서 불안정한 이유도 여기 있다.

약 2분
Isaac-SimPhysXtimestepsubstepssimulation-basics

물리 200Hz, 렌더 60Hz를 분리하는 이유

시뮬레이션 루프를 짜다 보면 자연스러운 질문이 생깁니다. "한 프레임에 물리 한 번, 렌더 한 번 하면 되지 않나?" 실제로는 그렇게 하면 물리는 불안정하고 렌더는 낭비입니다. 그래서 물리와 렌더의 빈도를 분리합니다.

물리는 촘촘히, 렌더는 띄엄띄엄

핵심 아이디어: 한 메인 루프(loop) 안에서 물리는 여러 번(substep) 밟고, 렌더는 한 번만(또는 가끔) 합니다.

도식 렌더링 중…

타임라인으로 보면 이렇습니다.

물리 tick:  | | | | | | | | | | | | | | | | | | | |   (촘촘, 200Hz)
렌더 frame: |          |          |          |        (띄엄, 60Hz)
            └─ 한 loop 안에 물리 substep 여러 개 ─┘

physics_substeps = round(rendering_dt / physics_dt) — 즉 렌더 한 번 사이에 물리를 몇 번 밟을지가 정해집니다. 물리 dt가 작을수록(빈도 높을수록) 적분이 안정적이고, 렌더는 무거우니 필요한 만큼만 합니다.

루프 구조를 코드로 보면 한눈에 들어옵니다.

# 한 루프: 물리는 여러 번, 렌더는 한 번
substeps = round(rendering_dt / physics_dt)   # 예: 200Hz / 60Hz
while running:
    for _ in range(substeps):
        physics.step(physics_dt)              # 촘촘히 (안정성)
    render()                                  # 가끔 (성능)

왜 물리는 촘촘해야 하나 — 안정성

물리 적분은 timestep이 크면 발산하거나 관통(tunneling)이 일어납니다. 빠른 충돌·강한 접촉일수록 작은 dt가 필요합니다.

💡 다리 로봇은 60Hz로 부족하다 — 발이 땅에 닿는 순간의 강한 접촉力 때문에, 사족·이족 로봇은 60Hz에서 체고가 무너지거나 기우뚱(tilt)합니다. 200Hz 이상으로 물리를 밟아야 안정적으로 섭니다. 반대로 천천히 굴러가는 AMR은 더 낮은 빈도로도 충분합니다.

왜 렌더는 띄엄띄엄 해도 되나 — 성능

렌더(특히 RTX)는 비쌉니다. 그런데 물리 검증·궤적 수집에는 매 물리 틱마다 화면을 그릴 필요가 없습니다. 그래서 "물리는 200Hz, 렌더는 10~60Hz" 식으로 디커플링해 GPU를 아낍니다.

⚠️ 단, 헤드리스라도 렌더가 필요한 경우가 있습니다 — HLS 스트리밍·영상 녹화·RTX 센서·합성 데이터는 렌더 결과를 쓰니까요. "headless = no-render"가 아니라는 점은 별도 글에서 다룹니다.

이렇게 물리와 렌더의 시간 축을 분리해 두면, 안정성(물리 고빈도)과 성능(렌더 저빈도)을 동시에 챙길 수 있습니다.

한 줄 정리

📌 한 루프 안에서 물리는 여러 번(substep, 예 200Hz) 밟고 렌더는 가끔(예 60Hz) 한다. 물리 고빈도는 안정성(특히 다리 로봇의 접촉), 렌더 저빈도는 성능을 위한 것 — substeps = round(rendering_dt / physics_dt)로 둘을 잇는다.