本文へスキップ

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時間のバッテリー寿命
  • 1つのバンドで最大8個のVerseGrip Stylusをドングルにペアリング可能

カスタマーサポート

お使いのデバイスやその操作についてご質問やご不明な点がございましたら、弊社サポートチームまでお問い合わせください。VerseGripスタイラスには、複雑な独自のワイヤレス技術が搭載されています。デバイスを開けると保証が無効になり、操作できなくなる場合があります。輸送時間の延長や高額な修理を避けるため、デバイスを開けないでください。

VerseGripスタイラスのセットアップとキャリブレーション

このセクションでは、ドングルの接続、VerseGrip Stylusの電源オン、キャリブレーションの手順について説明します。

セットアップ

  • ドングルをコンピューターのUSBポートに接続してください。
  • ハンドルを動かない平らな場所に置き、ボタンが上を向くようにし、ボールコネクタが画面の方を向くようにしてください。

電源オンとキャリブレーション

  • 電源ボタンを1回押してください。ステータスランプが赤色に点灯し、その後黄色に変わると、デバイスのIMUが自己校正を行っていることを示します。
  • 自動キャリブレーションが完了すると、スタイラスがコンピュータに接続されます。
  • スタイラスが無線接続に成功し、データを送信しているときは、ステータスランプが緑色に点滅します。
  • バッテリー残量が極端に少なくなると、VerseGrip Stylusは2分ごとに自動的に電源が切れます。すぐに充電してください。

再校正

キャリブレーション処理により、VerseGripの座標系がリセットされ、キャリブレーション中にデバイスが保持されていた方向が新しい基準軸となります。

  • 再キャリブレーションを行うには、スタイラスを再キャリブレーションしたい位置に保持し、キャリブレーションボタンを3秒間、またはシミュレーション上で向きが変わるまで押し続けてください。

以下は、キャリブレーション前とキャリブレーション後のデバイスの動作を比較したデモです。このデモを行う際は、キャリブレーションを実行する前に、図に示す配置でVerseGripを保持しておく必要があります。

スタンバイと電源オフ

  • 電源ボタンを1回押すと、スタンバイモードに戻ります。ステータスランプが白く点滅し始め、データ通信が停止します。
  • VerseGrip Stylusの電源を切るには、電源ボタンを5秒間押したまま放します。離すと、ステータスランプが消え、何も表示されなくなります。データの送信は停止します。

充電

  • VerseGripスタイラスをUSB-C充電ポートに接続してください。
  • 電源に接続すると充電状態を示すランプが青く点灯し、充電が完了すると消灯します。
  • 電源に接続した際、スタイラスの電源がオフになっている場合は、自動的に電源が入ります。

警告:2024年8月から12月の間に発送されたVerseGrip Stylusをお持ちの場合、バッテリーを完全に放電させないでください。一度放電してしまうと、充電できなくなる可能性があります。この状態になると、VerseGrip Stylusは電源に接続されている間のみ動作し続けますこの問題を解決するためのファームウェア更新ファイルを入手するには、Haply ご連絡ください。

ステートとライト・インジケータ

ライトの点灯パターン説明
イエロー速いフェードイン/フェードアウトセンサーの初期自動基準校正(VerseGripをテーブルの上に平らに置いてください)
素早い瞬きオリエンテーション校正ボタンが押され、校正プロセスが開始されました
ソリッドオリエンテーション校正ボタンを押しました。校正が完了しました。
レッド速いフェードイン/フェードアウトアダプタが切断されました。ホストからの信号がありません
素早い瞬き電源ボタンが押され、シャットダウン処理が開始されました
グリーンフェードイン/フェードアウトアダプターが接続されています。VerseGripはアクティブデータストリームモードです。
ソリッドアダプターが接続されています。VerseGripがアクティブデータストリームモードです。USB電源が接続されています。
ホワイトフェードイン/フェードアウトアダプターが接続されています。VerseGripはアイドル/スタンバイモードで、データストリーミングは行われていません。
ソリッドアダプター接続済み、VerseGripはアイドル/スタンバイモードでデータ転送なし、USB給電接続済み
オレンジFlash(インターレース方式)バッテリー残量低下の警告表示、通知は現在の状態で交互に表示される
ダブルフラッシュ(インターレース方式)バッテリー残量が危険なほど少ないという警告表示。現在の状態では、通知が交互に表示されます。
ティールフェードイン/フェードアウトデバイスのファームウェア更新モード
(より明るく)ソリッドユーザーがボタンを押すと、現在の表示色が点灯し、明るくなります
オフ明かりがないシャットダウン、電源オフ
充電インジケーターの色ライトの点灯パターン説明
ブルーソリッド充電
素早い瞬き充電がほぼ完了しました
オフ明かりがない充電完了

レガシー状態とライトインジケーター

以下のステータスライトは、VerseGrip Stylusの旧バージョン(ファームウェア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);

}
}