Genesis Visualization & Rendering

Cloud_ Ghost·2025년 1월 10일

Genesis

목록 보기
4/5
post-thumbnail

출처 : https://genesis-world.readthedocs.io/en/latest/user_guide/getting_started/visualization.html

Genesis에서 제공하는 User Guide를 읽으며 해석하며 어떻게 동작하는지 살펴보겠습니다.

Viewer

Genesis의 시각화 시스템

Genesis의 시각화 시스템은 생성한 장면(scene)의 시각화 도구(scene.visualizer)를 통해 관리됩니다. 시각화에는 두 가지 방법이 있습니다:
1. 인터랙티브 뷰어(Interactive Viewer): 별도의 쓰레드에서 실행되어 실시간으로 장면을 보여줍니다.
2. 카메라를 수동으로 추가: 장면에 카메라를 추가하고 이를 사용하여 이미지를 렌더링(rendering)합니다.


1. Interactive Viewer (인터랙티브 뷰어)

뷰어란?

뷰어(Viewer)는 Genesis가 제공하는 실시간 시각화 도구입니다.
이 도구를 사용하면 화면에 현재 장면을 실시간으로 렌더링하여 보여줍니다. 특히 개발자나 연구자는 장면의 구성 및 객체의 배치를 직관적으로 확인할 수 있습니다.

뷰어 설정

뷰어는 장면을 생성할 때 viewer_optionsvis_options 매개변수를 통해 설정할 수 있습니다.

샘플 코드와 주요 매개변수

scene = gs.Scene(
    show_viewer = True,  # 뷰어를 활성화할지 여부
    viewer_options = gs.options.ViewerOptions(
        res = (1280, 960),            # 뷰어 해상도 (픽셀 단위)
        camera_pos = (3.5, 0.0, 2.5), # 카메라 위치 (x, y, z 좌표, 단위: 미터)
        camera_lookat = (0.0, 0.0, 0.5), # 카메라가 바라볼 점 (x, y, z 좌표)
        camera_fov = 40,              # 카메라 시야각(Field of View), 단위: 도(degree)
        max_FPS = 60,                 # 최대 초당 프레임 (None으로 설정하면 최대 속도로 실행)
    ),
    vis_options = gs.options.VisOptions(
        show_world_frame = True,    # 월드 좌표축 시각화 여부
        world_frame_size = 1.0,     # 월드 좌표축 길이 (단위: 미터)
        show_link_frame = False,    # 개별 객체 링크의 좌표축 시각화 여부
        show_cameras = False,       # 추가한 카메라의 메쉬와 시야각 시각화 여부
        plane_reflection = True,    # 평면 반사 효과 활성화 여부
        ambient_light = (0.1, 0.1, 0.1), # 주변광(ambient light) 설정
    ),
    renderer = gs.renderers.Rasterizer(), # 카메라 렌더링 방식 (래스터라이저 사용)
)

뷰어 설정의 주요 기능 설명

1. viewer_options (뷰어 옵션)

  • res: 뷰어 창의 해상도를 지정합니다. (가로, 세로) 형태의 튜플로 입력하며, 단위를 픽셀로 나타냅니다. (일반적인 해상도를 생각하면 됩니다. 1920x1080, 1280x960 등)
    • None으로 설정하면, Genesis는 디스플레이 높이의 절반 크기로 4:3 비율의 창을 자동 생성합니다.
  • camera_pos: 카메라의 초기 위치를 (x, y, z) 형식으로 지정합니다.
  • camera_lookat: 카메라가 바라볼 지점의 좌표를 설정합니다.
  • camera_fov: 카메라의 시야각(Field of View)을 설정합니다. 값이 작을수록 줌(zoom)이 강해지고, 값이 클수록 넓은 시야를 보여줍니다.
    • 좁은 FOV: 더 적은 영역을 확대해서 보여줍니다 (줌인 효과).
    • 넓은 FOV: 더 많은 영역을 포괄하지만, 원근감이 강해지고 물체가 더 작아 보입니다 (줌아웃 효과).
  • max_FPS: 초당 최대 프레임을 설정합니다. None으로 설정하면 최대한 빠르게 실행됩니다.

2. vis_options (시각화 옵션)

  • show_world_frame: 월드 좌표축을 화면에 표시합니다. 디버깅이나 위치 파악에 유용합니다.
  • world_frame_size: 월드 좌표축의 길이를 설정합니다.
  • show_link_frame: 객체의 링크 좌표축 표시 여부입니다.
  • show_cameras: 추가된 카메라의 메쉬와 시야각을 시각화할지 여부입니다.
  • plane_reflection: 평면 반사 효과를 활성화합니다.
  • ambient_light: 주변광 설정으로, 장면의 기본적인 밝기를 제어합니다.

2. Renderer (렌더링 방식)

Genesis는 두 가지 렌더링 백엔드를 지원합니다:
1. Rasterizer: 빠른 렌더링 속도를 제공하며 뷰어와 기본 카메라에서 사용됩니다.

  • 사용 : gs.renderers.Rasterizer()
  • 빠른 렌더링 속도를 제공하므로, 실시간 시뮬레이션에 적합하며 또한 기본 defualt값이기도 합니다.
  1. RayTracer: 광선 추적 방식을 사용하여 사실적인 이미지를 생성하지만, 더 많은 계산이 필요합니다.
  • 사용 : gs.renderers.RayTracer()
  • RayTracer는 더 많은 계산이 필요하기 때문에 느리지만, 사실적 렌더링이 필요할 때 사용됩니다.

3. Viewer 객체의 활용

뷰어 객체는 생성된 장면에서 접근할 수 있습니다.

  • scene.visualizer.viewer 또는 scene.viewer로 뷰어에 접근 가능합니다.

카메라의 자세 제어

  • 카메라 자세 조회:
    cam_pose = scene.viewer.camera_pose
    cam_pose는 카메라의 현재 위치와 회전 정보를 제공합니다.

  • 카메라 자세 설정:
    scene.viewer.set_camera_pose(cam_pose)
    set_camera_pose() 메서드를 사용하여 카메라의 위치와 방향을 변경할 수 있습니다.

Camera & Headless Rendering

  • Genesis에서는 Viewer(뷰어)와는 별도로 카메라를 수동으로 추가할 수 있습니다.
  • Viewer는 실시간으로 장면을 확인할 수 있도록 화면에 출력되지만, 수동으로 추가한 카메라는 특정 작업이 필요할 때만 이미지를 렌더링합니다.

Headless mode

카메라는 뷰어나 디스플레이에 연결되지 않으며, 필요할 때만 렌더링된 이미지를 반환합니다. 따라서 카메라는 헤드리스 모드(headless mode)로 작동합니다.

  • 설명:
    • Headless Mode: 화면에 직접 출력하지 않고, 메모리에만 렌더링 결과를 저장하는 방식입니다.
    • 이렇게 하면 디스플레이가 필요 없는 서버 환경에서도 효율적으로 작업을 수행할 수 있습니다.

관련 코드

  • 코드 설명:
    cam = scene.add_camera(
        res    = (1280, 960),        # 렌더링 해상도 (가로 1280, 세로 960)
        pos    = (3.5, 0.0, 2.5),    # 카메라 위치 (x=3.5, y=0.0, z=2.5)
        lookat = (0, 0, 0.5),        # 카메라가 바라보는 지점
        fov    = 30,                 # 시야각(Field of View): 30도
        GUI    = False               # GUI 창을 생성하지 않음
    )
    • add_camera: 카메라를 추가하는 Genesis 메서드.
    • res: 렌더링된 이미지의 해상도. 더 높은 해상도는 세부 정보를 많이 보여주지만 처리 속도가 느려질 수 있습니다.
    • pos: 카메라의 위치를 나타내는 (x, y, z) 좌표입니다.
    • lookat: 카메라가 집중해서 바라보는 지점을 지정합니다.
    • fov: 카메라의 시야각으로, 장면을 얼마나 넓게 볼 수 있을지를 결정합니다.
    • GUI: True일 경우 OpenCV 창에 렌더링된 이미지를 실시간으로 보여줍니다.

      GUI=True로 설정하면 각 카메라가 OpenCV 창을 생성하여 렌더링된 이미지를 실시간으로 표시합니다.

      • GUI를 활성화하면 카메라 렌더링 결과를 실시간으로 확인할 수 있어 디버깅에 유용합니다.
      • Viewer GUI와 별도로 작동하므로 혼동하지 않도록 주의해야 합니다.

  • 설명:
    • scene.build(): 장면의 모든 객체와 카메라 설정을 확정하고 렌더링 준비를 마칩니다.
    • 카메라를 통해 RGB 이미지뿐만 아니라, 깊이 정보(depth), 세그멘테이션 마스크(segmentation mask), 표면 법선(surface normals)도 렌더링할 수 있습니다.

그래서 카메라는 뭐하는데?

카메라는 RGB 이미지, 깊이 정보(depth), 세그멘테이션 마스크, 표면 법선(surface normals) 렌더링을 지원합니다.

  • 설명:
    • RGB Image: 카메라가 실제로 볼 수 있는 컬러 이미지입니다.
    • Depth: 각 픽셀이 카메라로부터 얼마나 먼지에 대한 거리 정보를 제공합니다.
    • Segmentation Mask: 장면 내에서 객체별로 구분된 마스크 이미지를 생성합니다.
    • Surface Normals: 각 표면의 방향을 나타내는 법선 벡터 정보를 시각화합니다.
    • 기본적으로 RGB만 렌더링되며, 추가 정보를 얻으려면 아래처럼 설정해야 합니다.

기본적으로는 RGB만 렌더링되며, 추가 모드를 활성화하려면 camera.render() 호출 시 매개변수를 설정해야 합니다.

  • 코드 예제:
  scene.build()  # 장면 빌드

  # RGB, 깊이 정보, 세그멘테이션 마스크, 표면 법선 렌더링
  rgb, depth, segmentation, normal = cam.render(depth=True, segmentation=True, normal=True)
  • depth=True: 깊이 정보 렌더링 활성화.
  • segmentation=True: 세그멘테이션 마스크 활성화.
  • normal=True: 표면 법선 렌더링 활성화.

GUI=True로 설정하고 디스플레이가 연결되어 있다면, 4개의 창(RGB, Depth, Segmentation, Normal)이 표시됩니다.

  • 설명:
    • OpenCV 창을 통해 렌더링된 결과를 실시간으로 확인할 수 있습니다.
    • OpenCV 창이 까맣게 보인다면, cv2.waitKey(1)을 추가하거나 render()를 다시 호출하여 새로 고침하면 해결될 수 있습니다.

Genesis 카메라 요약

Genesis 카메라는 Viewer와 별도로 동작하며, 필요할 때만 이미지를 렌더링합니다.

  • 기본 설정: RGB 렌더링
  • 추가 정보: Depth, Segmentation Mask, Normal Map
  • GUI 옵션: OpenCV 창을 통해 결과를 실시간으로 확인 가능
  • 적용 사례: 디스플레이가 없는 환경에서도 이미지 데이터를 효율적으로 생성 가능

카메라 녹화

# 카메라 녹화를 시작합니다. 녹화가 시작되면 렌더링된 모든 RGB 이미지가 내부적으로 기록됩니다.
'''
이 기능은 카메라가 생성하는 RGB 이미지 데이터를 실시간으로 캡처하고 저장하는 역할을 합니다.
예를 들어, 시뮬레이션에서 특정 장면의 모든 프레임을 기록하거나 후속 분석을 위해 데이터를 저장하는 데 유용합니다.
내부적으로 기록된 데이터는 나중에 추출하거나 시각화, 분석 등에 활용할 수 있습니다.
'''
cam.start_recording()

import numpy as np
for i in range(120):
    scene.step()

    # change camera position
    cam.set_pose(
        pos    = (3.0 * np.sin(i / 60), 3.0 * np.cos(i / 60), 2.5),
        lookat = (0, 0, 0.5),
    )
    
    cam.render()

# 녹화를 중지하고 비디오를 저장합니다. filename이 지정되지 않으면 호출한 파일 이름을 사용하여 자동으로 이름이 생성됩니다.
cam.stop_recording(save_to_filename='video.mp4', fps=60)
'''
이 기능은 현재 진행 중인 녹화를 종료하고, 녹화된 내용을 하나의 비디오 파일로 저장합니다.
저장되는 파일 이름은 사용자가 직접 설정할 수 있습니다. 
'''

총 정리 코드

import genesis as gs

gs.init(backend=gs.gpu) # gpu로 변경, cpu는 너무 오래걸리기도 하고...

scene = gs.Scene(
    show_viewer = True,
    viewer_options = gs.options.ViewerOptions(
        res           = (1280, 960),
        camera_pos    = (3.5, 0.0, 2.5),
        camera_lookat = (0.0, 0.0, 0.5),
        camera_fov    = 40,
        max_FPS       = 60,
    ),
    vis_options = gs.options.VisOptions(
        show_world_frame = True,
        world_frame_size = 1.0,
        show_link_frame  = False,
        show_cameras     = False,
        plane_reflection = True,
        ambient_light    = (0.1, 0.1, 0.1),
    ),
    renderer=gs.renderers.Rasterizer(),
)

plane = scene.add_entity(
    gs.morphs.Plane(),
)
franka = scene.add_entity(
    gs.morphs.MJCF(file='xml/franka_emika_panda/panda.xml'), # 로봇팔을 불러옵니다.
)

cam = scene.add_camera(
    res    = (640, 480),
    pos    = (3.5, 0.0, 2.5),
    lookat = (0, 0, 0.5),
    fov    = 30,
    GUI    = False,
)

scene.build()

# render rgb, depth, segmentation, and normal
# rgb, depth, segmentation, normal = cam.render(rgb=True, depth=True, segmentation=True, normal=True)

cam.start_recording()
import numpy as np

for i in range(120):
    scene.step()
    cam.set_pose(
        pos    = (3.0 * np.sin(i / 60), 3.0 * np.cos(i / 60), 2.5),
        lookat = (0, 0, 0.5),
    )
    cam.render()
cam.stop_recording(save_to_filename='video_franka.mp4', fps=60)

비디오가 저장된 것을 확인할 수 있습니다.

이렇게 path를 지정해주면 지정된 path에 동영상이 생기는 것 또한 확인이 가능합니다.

(결과는 이렇게 저장이 됩니다.)

profile
행복합시다~

0개의 댓글