주요 콘텐츠로 건너뛰기

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

VerseGrip 스타일러스 시작하기

VerseGrips는 Inverse3, Inverse3X 및 MinVerse 방향 추적 기능을 추가합니다. 이 글에서는 VerseGrip 스타일러스의 설정 절차와 주요 기능을 설명합니다.

버즈그립 스타일러스

VerseGrip 스타일러스는 독자적인 고속 무선 통신 기술을 활용하여 방향 추적 및 손 안에서의 입출력(I/O) 기능을 제공합니다. 이 제품은 다양한 용도에 걸쳐 폭넓게 활용될 수 있도록 설계되었습니다.

주요 기능은 다음과 같습니다:

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

고객 지원

장치 또는 장치 작동에 대한 질문이나 우려 사항이 있는 경우 지원팀에 문의하여 도움을 받으세요. VerseGrip 스타일러스에는 복잡한 독점 무선 기술이 포함되어 있습니다. 장치를 개봉하면 보증이 무효화되고 작동이 불가능해질 수 있습니다. 배송 시간이 길어지고 수리 비용이 많이 드는 것을 방지하려면 장치를 열지 마세요.

VerseGrip 스타일러스 설정 및 보정

이 섹션에서는 동글 연결, VerseGrip 스타일러스 켜기 및 보정 단계를 간략하게 설명합니다.

설정

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

전원 켜기 및 보정

  • 전원 버튼을 한 번 누르세요. 상태 표시등이 빨간색으로 켜졌다가 노란색으로 바뀌며, 이는 기기 내 IMU가 자체 보정 중임을 나타냅니다.
  • 자동 보정 후, 스타일러스가 컴퓨터에 연결됩니다.
  • 스타일러스가 무선으로 성공적으로 연결되어 데이터를 전송 중일 때, 상태 표시등이 녹색으로 깜빡입니다.
  • 배터리 잔량이 매우 부족하면 VerseGrip 스타일러스가 2분마다 자동으로 꺼집니다. 즉시 충전해 주십시오.

재보정

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

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

다음은 보정 전과 보정 후 기기의 작동 방식을 비교한 시연 영상입니다. 시연을 진행하려면 보정을 시작하기 전에 그림과 같이 VerseGrip을 잡아야 합니다.

대기 및 전원 끄기

  • 전원 버튼을 한 번 눌러 대기 모드로 돌아가십시오. 상태 표시등이 흰색으로 깜빡이기 시작하며, 데이터 전송이 중단됩니다.
  • 버즈그립 스타일러스를 끄려면 전원 버튼을 5초간 누르고 있다가 놓습니다. 손을 놓으면 상태 표시등이 꺼지고 아무 표시도 나타나지 않습니다. 데이터 전송이 중지됩니다.

충전

  • VerseGrip 스타일러스를 USB-C 충전 포트에 연결하세요.
  • 전원에 연결하면 충전 상태 표시등이 파란색으로 계속 켜져 있으며, 충전이 완료되면 꺼집니다.
  • 전원에 연결할 때 스타일러스가 꺼져 있으면 자동으로 켜집니다.

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

상태 및 표시등 표시기

색상조명 시퀀스설명
노란색빠른 페이드 인/아웃초기 자동 센서 기준 보정 (VerseGrip을 테이블 위에 평평하게 놓으십시오)
빠른 깜빡임보정 시작 버튼을 눌렀으며, 보정 과정이 시작되었습니다
단단한보정 시작 버튼을 눌렀습니다. 보정이 완료되었습니다.
빨간색빠른 페이드 인/아웃어댑터가 분리되었습니다. 호스트에서 신호가 수신되지 않습니다.
빠른 깜빡임전원 버튼을 눌렀습니다. 종료 절차가 시작되었습니다.
녹색점진적 시작/종료어댑터 연결됨, VerseGrip 데이터 스트림 모드 활성화됨
단단한어댑터 연결됨, VerseGrip 데이터 스트림 모드 활성화됨, USB 전원 연결됨
흰색점진적 시작/종료어댑터 연결됨, VerseGrip 대기 모드에서 데이터 스트리밍 없음
단단한어댑터 연결됨, VerseGrip 유휴/대기 모드(데이터 전송 없음), USB 전원 연결됨
오렌지플래시 (인터레이스 방식)배터리 부족 경고 표시, 현재 상태에서 알림이 교대로 표시됩니다
더블 플래시 (인터레이스 방식)배터리 잔량이 매우 낮을 때의 경고 표시가 현재 상태에서 간헐적으로 나타납니다
청록색점진적 시작/종료기기 펌웨어 업데이트 모드
(더 밝게)단단한사용자가 버튼을 누르면, 현재 표시 색상이 단색으로 변하고 더 밝아집니다
꺼짐빛이 없다종료, 전원 끄기
충전 표시등 색상조명 시퀀스설명
파란색단단한충전
빠른 깜빡임충전이 거의 완료되었습니다
꺼짐불이 안 들어옴충전이 완료되었습니다

레거시 상태 및 표시등

아래의 상태 표시등은 이전 버전의 VerseGrip 스타일러스(펌웨어 1.10 이하)에서 사용되던 상태 및 색상입니다.

색상조명 시퀀스설명
빨간색단단한구성 요소 초기화 보류 중
깜빡대기 모드. 데이터 전송 없음
파란색단단한초기 자동 센서 기준 보정 (VerseGrip을 테이블 위에 평평하게 놓으십시오)
녹색깜빡어댑터 연결됨, VerseGrip 활성 데이터 스트림 모드
꺼짐빛이 없다종료, 전원 끄기
충전 표시등 색상조명 시퀀스설명
파란색단단한충전
빠른 깜빡임충전이 거의 완료되었습니다
꺼짐불이 안 들어옴충전이 완료되었습니다

샘플 코드

다음은 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);

}
}