원문 캡처 · github.com
원문 캡처 · github.com

Relativty는 하드웨어·소프트웨어·펌웨어를 공개한 SteamVR용 DIY 가상현실(VR) 헤드셋 프로젝트다. 소비자용 완제품이 아니라 직접 부품을 준비하고 조립해야 하며, 기본 구성은 3자유도(3-DoF) 추적과 내장 컨트롤러 미지원이 특징이다.

프로젝트 소개에 따르면 헤드셋은 2K 해상도와 120FPS를 지원하고 Arduino와 호환된다. 실험적인 신체 추적 기능도 제공하지만, 추적 정밀도와 움직임의 자유도는 전용 센서에 미치지 못한다고 프로젝트 측은 설명한다. Relativty 웹사이트와 GitHub 저장소에서 정보를 확인할 수 있다.

최신 조립 안내

저장소에는 2023년 5월 기준 권장 빌드와 기존 빌드 안내가 함께 있다. 최신 안내는 최소 기능을 갖춘 헤드셋을 만드는 방법을 다루며, 전자공학과 Arduino 보드 프로그래밍에 대한 기본 지식이 필요하다. 조립 중 문제가 생기면 프로젝트의 Discord 커뮤니티에 문의할 수 있다.

전자 부품으로는 USB HID를 지원하는 ATmega32U4 마이크로컨트롤러(MCU)가 필요하다. 예시로 Arduino Pro Micro가 제시돼 있다. 관성측정장치(IMU)는 FastIMU 라이브러리가 지원하는 제품을 사용한다. PC용 소형 고해상도·고주사율 디스플레이와 드라이버 보드도 필요하다. 디스플레이와 보드는 호환성을 위해 가능하면 같은 묶음으로 구매하라고 안내한다. 가능한 디스플레이 선택지는 HadesVR 문서에 정리돼 있다.

디스플레이는 MCU가 아니라 VR 앱을 실행하는 컴퓨터에 연결한다. 원칙적으로 PC 모니터도 Relativty 디스플레이로 설정할 수 있으므로, 렌즈와 전용 디스플레이 등에 비용을 쓰기 전에 기존 모니터로 빌드를 시험해 볼 수 있다. 고성능 소형 디스플레이는 비싸고 섬세한 부품이므로 주의해서 다뤄야 한다.

Arduino Pro Micro를 쓸 때 IMU와 MCU는 전원 및 통신을 위해 다음과 같이 연결한다. MCU는 USB로 컴퓨터에 연결해 IMU 측정값을 SteamVR에 보낸다.

text
Pro Micro       IMU
VCC         ->  VCC
GND         ->  GND
SDA(pin 2)  ->  SDA
SCL(pin 3)  ->  SCL

다른 MCU를 사용하면 SDA와 SCL 핀 번호가 다를 수 있다. MCU의 VCC 전압이 IMU의 정격 작동 전압과 맞는지도 확인해야 한다. 잘못된 전압을 공급하면 부품이 손상될 수 있다. 디스플레이 드라이버 보드가 켜지지 않는다면 마이크로 USB 케이블이 너무 길어 전압이 떨어졌거나 컴퓨터 USB 포트의 전력 공급이 부족한 경우일 수 있다. 다른 포트나 전원 공급형 USB 허브를 시도할 수 있다.

기계 부품으로는 저장소의 Relativty_Mechanical_build 폴더에 있는 STL 파일로 출력하는 하우징, 지름 40mm·초점거리 50mm 렌즈, 스트랩과 얼굴 접촉부가 필요하다. 스트랩과 폼은 HTC Vive 교체 부품 등을 예로 들며, 부품은 Aliexpress 등에서 구할 수 있다고 안내한다. 3D 프린터를 이용할 수 없다면 Android VR 휴대전화 케이스를 개조해 디스플레이를 맞추고 IMU와 MCU를 붙이는 방법도 있다. 이 방식은 IPD 조절 기능을 포함한 부품을 한꺼번에 얻을 수 있다는 장점이 있다.

소프트웨어와 SteamVR 설정

Relativty는 Arduino 펌웨어와 SteamVR 드라이버를 사용한다. 컴퓨터에 Steam과 SteamVR을 설치해야 한다. Arduino IDE를 설치하고 MCU를 USB로 연결한 뒤, IDE 라이브러리 관리자에서 FastIMU를 내려받는다. IMU를 배선하고 IDE의 Examples/Fastimu/Calibrated_relativty 스케치를 MCU에 업로드한다. FastIMU에는 보정 데이터를 IMU의 EEPROM에 저장하는 보정 도구가 포함돼 있다. 보정은 사용 중 생길 수 있는 센서 드리프트를 줄이는 데 도움이 될 수 있다. 스케치를 업로드한 뒤 Arduino Serial Monitor에서 안내에 따라 보정을 시작하며, 이 작업은 한 번만 하면 된다.

SteamVR 드라이버는 저장소 ZIP 파일을 내려받아 Relativty-master 안의 Relativty_Driver\\Relativty 폴더를 SteamVR 설치 경로의 드라이버 디렉터리에 복사해 설치한다. drivers\\Relativty\\resources\\settings의 default.vrsettings 파일을 열어 장치와 디스플레이에 맞게 설정한다.

Arduino Pro Micro와 FastIMU를 사용하는 경우 Relativty_hmd 항목에서 다음 값을 설정한다.

text
       "hmdPid" : 32823,
       "hmdVid": 9025,
       "hmdIMUdmpPackets":  false,

다른 MCU라면 USB PID와 VID를 확인해야 한다. Arduino IDE에서 Tools/Get Board Info를 선택하면 장치 정보를 볼 수 있다. PID와 VID를 16진수에서 10진수로 바꿔 hmdPid와 hmdVid에 입력한다. 변환에는 16진수-10진수 변환기를 사용할 수 있다.

디스플레이 설정은 Relativty_extendedDisplay 항목에서 한다. windowX와 windowY는 VR 화면이 표시될 창의 시작 위치를, windowWidth와 windowHeight는 창 크기를 나타낸다. renderWidth와 renderHeight는 렌더링 해상도이며, 일반적으로 디스플레이의 실제 해상도와 같게 설정한다.

text
       "windowX" : 3440,
       "windowY" : 0,
text
       "windowWidth" : 1920,
       "windowHeight" : 1080,
text
       "renderWidth" : 1920,
       "renderHeight" : 1080,

그 밖의 설정 예시는 다음과 같다.

text
       "DistortionK1" : 0.4,
       "DistortionK2" : 0.5,
       "ZoomWidth" : 1,
       "ZoomHeight" : 1,
       "EyeGapOffsetPx" : 0,
       "IsDisplayRealDisplay" : true,
       "IsDisplayOnDesktop" : true

창 위치와 크기를 잘못 설정하면 드라이버가 충돌해 SteamVR에 화면이 나타나지 않을 수 있다. 안내는 Windows 디스플레이 설정에서 모든 화면의 위쪽 가장자리가 정렬된 상태를 전제로 한다. Windows는 연결된 화면 중 하나를 기본 디스플레이로 지정하며, 기본 화면의 왼쪽 위가 SteamVR 디스플레이 좌표계의 원점이다. 예를 들어 기본 화면이 3440×1440이고 VR 디스플레이가 오른쪽에 있으면 VR 화면의 시작 좌표는 (3440, 0)이다. 반대로 VR 디스플레이가 기본 화면 왼쪽에 놓인 예에서는 (−1920, 0)을 사용한다. 창과 렌더링의 너비·높이는 VR 디스플레이의 기본 해상도로 설정한다.

설정을 저장한 뒤 SteamVR을 시작한다. 문제가 있으면 SteamVR Web Console에서 전체 로그를 복사해 Discord 커뮤니티에 증상과 함께 올리도록 안내한다. VR 창을 클릭한 뒤 사라지는 경우 Windows PowerShell에서 다음 명령을 실행하면 VRCompositor가 해당 세션 동안 안정적으로 유지된다고 설명한다.

text
get-process vrcompositor | stop-process -Force;cd "C:\\Program Files (x86)\\Steam\\steamapps\\common\\SteamVR\\bin\\win64";.\\vrcompositor.exe

기존 빌드 방식

기존 하드웨어 설계는 Atmel SAM3X8E ARM Cortex-M3 프로세서와 MPU-6050 IMU를 사용하는 Relativty 메인보드를 기반으로 한다. ArduinoCore를 지원하고 MPU-6050 또는 MPU-9250에 연결할 수 있는 다른 프로세서도 사용할 수 있다. PCB는 Gerber 파일 폴더 Relativty_Electronics_build/GerberFiles.zip을 이용해 제작할 수 있으며, 저장소 안내는 jlcpcb 등에서 약 4달러에 제조·구매할 수 있다고 적고 있다. 부품은 다음 BOM 중 재고 상황에 맞는 파일을 참고하고, 배치 위치는 Eagle에서 열 수 있는 Relativty_Electronics_source/motherboard.brd에서 확인한다.

  • Relativty_Electronics_build/Assembly/jlcpcb.com_motherboard_BOM.csv
  • Relativty_Electronics_build/Assembly/motherboard_BOM.xlsx

대안으로 Arduino Due와 MPU-6050을 연결할 수 있다.

text
5V      -> VCC
GND     -> GND
SDA(20) -> SDA
SCL(21) -> SCL
PIN 2   -> INT

MPU-9250용 대체 펌웨어를 사용할 때는 다음과 같이 연결한다.

text
5V      -> VCC
GND     -> GND
SDA(20) -> SDA
SCL(21) -> SCL

Arduino Due의 ERASE와 RESET 버튼을 누른 뒤 Relativty 펌웨어를 설치한다. Arduino IDE에 Relativty 보드를 추가하려면 보드 인덱스 JSON을 복사해 IDE의 Preferences에서 Additional Boards Manager에 입력한다. Tools > Board > Board Manager에서 Relativty Board를 설치하고 IDE를 다시 시작한 다음 Tools > Boards에서 Relativty를 선택한다. Relativty_Firmware/firmware/firmware.ino를 열어 보드에 업로드한다.

다른 보드, 예를 들어 Arduino Due를 쓸 때는 Relativty_Firmware\\Relativty_board\\의 내용을 Arduino IDE에 설치한다. MPU-6050에는 Relativty_Firmware/firmware/firmware.ino, MPU-9250에는 Relativty_Firmware\\MP9250-HID\\MP9250-HID\\MP9250-HID.ino를 사용한다.

3D 출력 파일은 Relativty_Mechanical_build 폴더에 있으며, 조립용 나사는 screws_BOM.xlsx에 정리돼 있다. 프로젝트가 사용한 부품으로 스트랩, 폼, 렌즈가 제시돼 있다. 렌즈는 지름 40mm, 초점거리 50mm다.

헤드셋은 듀얼 디스플레이로 2K·120FPS를 지원한다고 소개하지만, 공개 설계이므로 다른 화면도 장착할 수 있다. 프로젝트가 사용한 화면은 이 제품이며, 판매자에 따라 비슷한 화면의 가격이 150~190달러일 수 있다고 안내한다.

기존 드라이버 설정에서는 Relativty PCB가 아닌 보드를 쓸 때 default.vrsettings의 PID와 VID를 바꾼다. Relativty PCB의 예시 값은 다음과 같다.

text
   "hmdPid" : 9,
   "hmdVid": 4617,

Arduino Due를 사용할 때는 다음 값이 제시돼 있다.

text
   "hmdPid" : 62,
   "hmdVid" : 9025,

다른 보드의 값은 Arduino IDE에서 보드를 선택하고 Tools/Get Board info를 눌러 확인한다. 예시 출력은 다음과 같다.

text
	BN: Arduino Due (Native USB Port) 	VID: 2341 	PID: 003e 	SN: HIDHB

VID와 PID는 16진수이므로 설정 파일에 넣기 전에 정수로 변환한다. 이어서 HMD 화면을 기본 디스플레이의 오른쪽 위에 맞춰 확장 화면으로 설정하고, Relativty_extendedDisplay에서 기본 화면 너비와 HMD의 기본 해상도를 입력한다.

text
       "windowX" : *whatever your primary screen resolution's width is*,
       "windowY" : 0,
       "windowWidth" : *HMD's native resolution width*,
       "windowHeight" : *HMD's native resolution height*,
       "renderWidth" : *HMD's native resolution width*,
       "renderHeight" : *HMD's native resolution height*,	  	  And at the bottom of this segment: 	        "IsDisplayRealDisplay" : true,
       "IsDisplayOnDesktop" : true

설정 파일의 쉼표를 삭제하면 구성이 깨질 수 있다. 마지막 항목만 쉼표를 붙이지 않는다. 확장 화면 설정이 작동하지 않으면 HMD를 기본 화면의 미러링 화면으로 설정하고 다음 값을 시험할 수 있다.

text
       "windowX" : 0,
       "windowY" : 0,
       "windowWidth" : *HMD's native resolution width*,
       "windowHeight" : *HMD's native resolution height*,
       "renderWidth" : *HMD's native resolution width*,
       "renderHeight" : *HMD's native resolution height*,	       "IsDisplayRealDisplay" : false,
       "IsDisplayOnDesktop" : true	

이 설정에서는 게임이 키보드나 마우스 입력을 필요로 할 때 VR 창이 입력을 받지 못해 게임을 플레이할 수 없게 될 수 있다. 동공 간 거리(IPD)는 Relativty_hmd의 IPDmeters에서 조절한다. 렌즈 왜곡 보정은 DistortionK1과 DistortionK2를 바꾼다.

text
       "IPDmeters" : 0.063,
text
       "DistortionK1" : 0.4,
       "DistortionK2" : 0.5,

드라이버를 등록하려면 보통 C:/Steam/steamapps/common/SteamVR/bin/win64/vrpathreg.exe에 있는 vrpathreg.exe를 찾는다. Windows 명령 프롬프트에서 SteamVR의 bin/win64 디렉터리로 이동해 실행한다. 드라이버 폴더가 C:/code/Relativty_Driver/Relativty에 있다면 다음 명령으로 등록하며, 같은 경로를 removedriver에 넣어 제거할 수 있다.

text
vrpathreg adddriver C:/code/Relativty_Driver/Relativty
text
vrpathreg removedriver C:/code/Relativty_Driver/Relativty

실험적 3D 신체 추적과 실행

실험적 추적 기능은 카메라 영상과 3D 신체 위치를 추정하도록 훈련한 인공신경망을 사용한다. CUDA를 사용하기 때문에 NVIDIA GPU에서만 실행할 수 있으며, 전용 센서에 비해 정밀도와 움직임의 자유도가 부족하다고 프로젝트는 설명한다. 프로젝트 측은 모델을 크게 개선할 수 있다고 보지만, 해당 추적은 실험 단계다.

웹캠을 연결하고 Python 3.8.4를 설치할 때 PATH 추가 옵션을 선택한다. 이어 PyTorch와 CUDA Toolkit 11.0을 설치한다.

text
python -m pip install torch===1.6.0 torchvision===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html

Relativty 릴리스 페이지에서 PYTHONPATH 폴더를 내려받아 그 위치를 Relativty_Driver/Relativty/resources/settings/default.vrsettings의 PyPath에 입력한다. 설정에서 tracking을 1로 바꾸면 추적이 켜지고, 0으로 바꾸면 끌 수 있다. 카메라에 맞춰 scalesCoordinateMeter와 offsetCoordinate를 조정해 보정할 수 있다. scalesCoordinateMeter는 AI가 정규화한 뒤 특정 축에서 1미터 이동했을 때 계산하는 좌표 변화량을 뜻한다. MPU-9250 펌웨어를 사용한다면 드라이버의 hmdIMUdmpPackets를 false로 바꾼다.

text
"hmdIMUdmpPackets":  false,

설정이 끝나면 헤드셋을 앞면이 바닥을 향하도록 평평한 곳에 놓고 연결한다. 몇 초 뒤 자동으로 보정되며, 이후 SteamVR 게임을 실행할 수 있다. 기본 구성은 컨트롤러를 내장 지원하지 않고 3-DoF 추적만 제공하므로, 손 추적 컨트롤러가 필요한 게임에서는 실제 사용이 제한될 수 있다. 더 많은 기능을 갖춘 DIY VR 프로젝트로는 HadesVR이 안내돼 있다.