import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
VerseGrip スタイラスの使い始め
VerseGripは、Inverse3 、Inverse3X、MinVerse に姿勢追跡機能を追加します。この記事では、VerseGrip Stylusの設定手順とその機能について解説します。
VerseGrip スタイラスのご紹介
VerseGrip Stylusは、独自の高速無線通信技術を採用し、向きや手元での入出力(I/O)を正確に追跡します。幅広い用途に対応できるよう設計されており、高い汎用性を備えています。
主な特徴は以下の通りです:
- ユーザー入力用ボタンが2つ、
- 1つのキャリブレーションボタン、
- 電源/スタンバイボタン 1つ
- 2つのLEDステータスランプ
- USB-C充電ポート
- 最大1 kHzの無線通信速度
- バッテリー駆動時間は10~12時間
- 1つのバンド上の1つのドングルには、最大8本のVerseGripスタイラスをペアリングできます

カスタマーサービス
お使いのデバイスやその動作に関してご質問やご不明な点がございましたら、サポートチームまでご連絡ください。VerseGrip Stylus には、複雑な独自開発のワイヤレス技術が搭載されています。 本製品を開封すると、保証が無効となり、製品が使用できなくなる可能性があります。配送の遅延や高額な修理費用を避けるため、本製品を開封しないでください。
VerseGrip スタイラスの設定とキャリブレーション
このセクションでは、ドングルの接続、VerseGrip Stylus 本体の電源投入、およびキャリブレーションの手順について説明します。
インストール
- ドングルをコンピュータのUSBポートに接続してください。
- ハンドルを、動かない平らな面に置き、ボタンが上を向くようにし、ボールコネクタが画面の方を向くようにしてください。
電源投入と校正
- 電源/スリープボタンを1回押してください。ステータスランプが赤く点灯し、その後黄色に変わります。これは、本機の慣性計測ユニット(IMU)が自動校正を行っていることを示しています。
- 自動キャリブレーションが完了すると、スタイラスがコンピュータに接続されます。
- スタイラスが正常に接続され、ワイヤレスでデータを送信しているときは、ステータスランプが緑色に点滅します。
- バッテリー残量が危険なレベルになると、VerseGrip Stylusは2分ごとに自動的に電源が切れます。その場合は、直ちに充電してください。
再校正
キャリブレーションプロセスでは、VerseGripの座標系がリセットされ、キャリブレーション中にデバイスが保持されていた方向が新しい基準軸となります。
- 再キャリブレーションを行うには、スタイラスを再キャリブレーションしたい位置に持ち、キャリブレーションボタンを3秒間、またはシミュレーション上で向きが変わるまで押し続けてください。
以下に、校正前と校正後の本機の動作を比較したデモを掲載します。このデモを行う際は、校正前にVerseGripを図に示す配置で保持してください。

待機状態と電源オフ
- 電源/スリープボタンを1回押すと、スリープモードに戻ります。ステータスランプが白く点滅し始め、データ転送が停止します。
- 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 Stylusを使用する簡単な例です。
#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);
}
}