본문으로 이동

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

VerseGrip 스타일러스 첫 사용 가이드

VerseGrip은 Inverse3, Inverse3X 및 MinVerse 에 방향 추적 기능을 추가합니다. 이 글에서는 VerseGrip 스타일러스의 설정 방법과 주요 기능을 소개합니다.

VerseGrip 스타일러스 소개​

VerseGrip Stylus 장치는 독자적인 고속 무선 통신 기술을 사용하여 방향 추적은 물론, 손으로 수행하는 입출력(I/O) 작업을 지원합니다. 이 장치는 다양한 응용 분야에서 폭넓은 활용성을 제공하도록 설계되었습니다.

주요 특징은 다음과 같습니다:

  • 사용자 입력 버튼 2개,
  • 교정 버튼 1개,
  • 1개의 전원/대기 버튼
  • 2개의 LED 상태 표시등
  • USB-C 충전 포트
  • 최대 1 KHz의 무선 통신 속도
  • 배터리 사용 시간 10~12시간
  • 단일 대역에서 하나의 동글에 최대 8개의 VerseGrip 스타일러스를 페어링할 수 있습니다.

고객 서비스​

기기나 작동 방식에 대해 궁금한 점이나 우려 사항이 있으시면, 저희 지원팀에 문의하여 도움을 받으시기 바랍니다. VerseGrip Stylus 기기에는 정교한 독자적인 무선 기술이 적용되어 있습니다. 기기를 개봉하면 보증이 무효화되며, 기기를 더 이상 사용할 수 없게 될 수도 있습니다. 배송 지연 및 고액의 수리 비용을 방지하기 위해, 기기를 절대 개봉하지 마십시오.

VerseGrip 스타일러스의 설정 및 보정​

이 섹션에서는 동글을 연결하고, VerseGrip Stylus 기기를 켜며, 보정을 수행하는 단계를 설명합니다.

설치​

  • 동글을 컴퓨터의 USB 포트에 연결하십시오.
  • 손잡이를 움직이지 않을 평평한 표면에 올려놓고, 버튼이 위를 향하게 하며 볼형 커넥터가 화면 쪽을 향하도록 하십시오.

전원 연결 및 보정​

  • 전원/절전 버튼을 한 번 누르십시오. 상태 표시등이 빨간색으로 켜졌다가 노란색으로 바뀌면, 기기의 관성 측정 장치(IMU)가 자동 보정 작업을 수행 중임을 나타냅니다.
  • 자동 보정이 완료되면 스타일러스가 컴퓨터에 연결됩니다.
  • 스타일러트가 성공적으로 연결되어 무선으로 데이터를 전송하면 상태 표시등이 녹색으로 깜빡입니다.
  • 배터리 잔량이 매우 부족할 경우, VerseGrip Stylus 기기는 2분마다 자동으로 전원이 꺼집니다. 즉시 충전해 주십시오.

재보정​

보정 과정은 VerseGrip의 좌표계를 재설정하여, 보정 중에 장치를 잡고 있는 방향이 새로운 기준축이 되도록 합니다.

  • 재보정하려면 스타일러스를 재보정하고자 하는 위치에 놓은 다음, 보정 버튼을 3초 동안 누르고 있거나 시뮬레이션 화면에서 방향이 바뀔 때까지 계속 누르고 계십시오.

아래는 기기가 보정되지 않은 상태와 보정된 상태에서의 작동 방식을 비교한 시연 영상입니다. 시연을 진행하려면 보정 전에 그림과 같이 VerseGrip 기기를 잡아야 합니다.

대기 모드 및 전원 끄기​

  • 전원/대기 버튼을 한 번 눌러 대기 모드로 돌아가십시오. 상태 표시등이 흰색으로 깜빡이기 시작하고 데이터 전송이 중단됩니다.
  • VerseGrip Stylus 기기를 끄려면 전원/대기 버튼을 5초 동안 길게 누른 다음 손을 떼십시오. 버튼을 떼면 상태 표시등이 꺼지고 더 이상 빛이 나지 않습니다. 데이터 전송도 중단됩니다.

충전​

  • VerseGrip Stylus 기기를 USB-C 충전 포트에 연결하십시오.
  • 기기가 전원 콘센트에 연결되면 충전 표시등이 파란색으로 계속 켜져 있으며, 배터리가 완전히 충전되면 꺼집니다.
  • 스타일러트를 전원 콘센트에 연결할 때 전원이 꺼져 있다면, 자동으로 켜집니다.

주의: 2024년 8월부터 12월 사이에 출하된 VerseGrip Stylus 기기를 사용 중이신 경우, 배터리가 완전히 방전되지 않도록 주의하십시오. 배터리가 완전히 방전되면 더 이상 충전을 유지하지 못할 수 있습니다. 이 경우, VerseGrip Stylus 기기는 전원에 연결되어 있는 동안에만 작동합니다. 이 문제를 해결할 수 있는 펌웨어 업데이트 파일을 받으시려면 Haply 고객 지원팀에 문의하십시오.

상태 및 표시등​

색상빛의 시퀀스설명
쟈운빠른 삽입/제거 퐁듀센서의 초기 기준 자동 보정 (VerseGrip 장치를 테이블 위에 움직이지 않게 놓으십시오)
빠른 깜빡임방향 보정 버튼을 눌렀으며, 보정 과정이 시작되었습니다.
Fixe방향 보정 버튼을 눌렀으며, 보정이 완료되었습니다.
루즈빠른 삽입/제거 퐁듀어댑터가 분리되었으며, 호스트로부터 신호가 없습니다.
빠른 깜빡임전원/절전 버튼이 눌린 상태이며, 종료 절차가 시작되었습니다.
Vert입력/출력 퐁듀연결된 어댑터, 데이터 전송 모드가 활성화된 VerseGrip
Fixe어댑터 연결됨, VerseGrip 데이터 전송 모드 활성화됨, USB 전원 연결됨
블랑입력/출력 퐁듀어댑터 연결됨, VerseGrip 대기/휴면 모드, 데이터 전송 없음
Fixe어댑터 연결됨, VerseGrip 대기/절전 모드, 데이터 전송 없음, USB 전원 연결됨
오렌지플래시 (교대)배터리 부족 경고, 현재 상태에서 알림이 번갈아 표시됩니다.
이중 깜빡임 (교대로)배터리 잔량이 매우 낮다는 경고, 현재 상태에서 알림이 번갈아 표시됩니다.
사르셀입력/출력 퐁듀기기 펌웨어 업데이트 방법
(더 활발하게)Fixe사용자 버튼이 눌린 상태에서 현재 표시 색상이 고정되어 있으며 더 선명해집니다.
꺼짐빛이 전혀 없다정지, 전원 차단
충전 표시등 색상빛의 시퀀스설명
블뢰Fixe담당
빠른 깜빡임충전이 거의 끝났습니다
꺼짐빛이 전혀 없다충전이 완료되었습니다

이전 상태 및 표시등​

아래의 상태 표시등은 VerseGrip Stylus의 이전 버전(펌웨어 1.10 및 그 이전 버전)에서 사용되던 상태와 색상을 나타냅니다.

색상빛의 시퀀스설명
루즈Fixe대기 중인 구성 요소 초기화
깜빡임대기 모드. 데이터 전송 없음
블뢰Fixe센서의 초기 기준 자동 보정 (VerseGrip 장치를 테이블 위에 움직이지 않게 놓으십시오)
Vert깜빡임연결된 어댑터, 데이터 전송 모드가 활성화된 VerseGrip
꺼짐빛이 전혀 없다정지, 전원 차단
충전 표시등 색상빛의 시퀀스설명
블뢰Fixe담당
빠른 깜빡임충전이 거의 끝났습니다
꺼짐빛이 전혀 없다충전이 완료되었습니다

코드 예시​

다음은 C++에서 VerseGrip 스타일러스를 사용하는 간단한 예시입니다.

#include <external/libhv.h>

#include <nlohmann/json.hpp>

#include <chrono>
#include <cstdio>
#include <string>

using namespace hv;
using json = nlohmann::json;

// Procedure to get the first detected and available Wired VerseGrip Stylus device id
std::string get_first_verse_grip_device_id(const json &data) {
const auto& vgs = data["wireless_verse_grip"];

if (vgs.empty()) {
return "";
}

return vgs.items().begin().key();
}

int main() {
const auto print_delay = std::chrono::milliseconds(100);
auto current = std::chrono::high_resolution_clock::now();
bool first_message = true;
std::string device_id;

WebSocketClient ws;

ws.onmessage = [&](const std::string &msg) {
json data = json::parse(msg);

if (first_message) {
first_message = false;
const std::string first_id = get_first_verse_grip_device_id(data);

if (first_id.empty()) {
printf("no Wireless VerseGrip found.\n");
ws.close();
return;
}

device_id = first_id;
}

if (device_id.empty() || !data["wireless_verse_grip"].contains(device_id)) {
return;
}

const auto now = std::chrono::high_resolution_clock::now();

if (std::chrono::high_resolution_clock::now() > current + print_delay) {
current = now;
const json state = data["wireless_verse_grip"][device_id];

printf("Rotation : { x:%f, y:%f, z:%f, w:%f }, Hall:%i, Button : [%d, %d, %d], Battery: {%f}\n",
state["orientation"]["x"].get<float>(),
state["orientation"]["y"].get<float>(),
state["orientation"]["z"].get<float>(),
state["orientation"]["w"].get<float>(),
state["hall"].get<int8_t>(),
state["buttons"]["a"].get<bool>(),
state["buttons"]["b"].get<bool>(),
state["buttons"]["c"].get<bool>(),
state["battery_level"].get<float>());
}
};

ws.open("ws://localhost:10000");

printf("Press ENTER to stop...\n\n");
while (std::cin.get() != '\n') {
}

if (ws.isConnected()) {
ws.close();
}

return 0;
}
#include <string.h>

#include <chrono>
#include <iostream>
#include <iterator>
#include <string>
#include <thread>

#include "HardwareAPI.h"

int main(int argc, char* argv[])
{
char* portName;

if (argc < 2)
{
std::printf("Usage: %s <port>\n", argv[0]);
}
else
{
#if defined(_WIN32) || defined(_WIN64)
portName = _strdup(argv[1]); // argv1;
#endif
#if defined(__linux__)
portName = strdup(argv[1]); // argv1;
#endif
}

Haply::HardwareAPI::IO::SerialStream serial_stream(portName);

Haply::HardwareAPI::Devices::Handle handle(&serial_stream);

while (true)
{
Haply::HardwareAPI::Devices::Handle::VersegripStatusResponse data;
data = handle.GetVersegripStatus();
std::printf(
"device_id: %d battery_level: %f quaternion: %f %f %f %f buttons: "
"%d error_flags: %d\n",
data.device_id, data.battery_level, data.quaternion[0],
data.quaternion[1], data.quaternion[2], data.quaternion[3],
data.buttons, data.error_flag);

}
}