メインコンテンツへスキップ

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

VerseGrip スタイラスの使い始め

VerseGripsは、Inverse3 、Inverse3X、およびMinVerse に姿勢検出機能を追加します。この記事では、VerseGripスタイラスのセットアップ手順とその機能について説明します。

VerseGrip スタイラス​

VerseGrip Stylusは、独自の高速無線技術を採用し、向き検知およびハンドヘルド入出力(I/O)機能を実現しています。汎用性が高く、幅広い用途に対応するように設計されています。

主な機能には以下のものがあります:

  • 2つのユーザー入力ボタン、
  • 1 キャリブレーションボタン、
  • 1 電源/スタンバイボタン
  • 2つのステータスLED
  • USB-C充電ポート
  • 最大1 kHzの無線通信
  • 10~12時間のバッテリー駆動時間
  • 1本のバンドに、最大8本のVerseGripスタイラスをドングルとペアリングできます

カスタマーサポート​

お使いのデバイスやその操作に関してご質問やご不明な点がございましたら、弊社サポートチームまでお問い合わせください。VerseGrip Stylusには、複雑な独自開発の無線技術が採用されています。デバイスを分解すると保証が無効となり、動作しなくなる可能性があります。配送期間の長期化や高額な修理費用を避けるため、デバイスを分解しないでください。

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

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

設備​

  • ドングルをコンピュータのUSBポートに差し込んでください。
  • ハンドルを、滑らない平らな面に置き、ボタンが上を向くようにし、ボールジョイントが画面の方を向くようにしてください。

電源投入と校正​

  • 電源ボタンを1回押してください。ステータスランプはまず赤く点灯し、その後黄色に変わります。これは、本体のIMUが自己校正を行っていることを示しています。
  • 自動キャリブレーションが完了すると、スタイラスがコンピュータに接続されます。
  • スタイラスが正常に接続され、ワイヤレスでデータ転送が行われていると、ステータスランプが緑色に点滅します。
  • バッテリー残量が危険なほど少なくなると、VerseGrip Stylusは2分ごとに自動的に電源が切れます。その場合は、直ちに充電してください。

再校正​

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

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

以下では、校正前と校正後の本デバイスの動作を比較するデモンストレーションをご紹介します。このデモンストレーションを行うには、校正前にVerseGripを図に示す構成で保持しておく必要があります。

待機モードと電源オフ​

  • 電源ボタンを1回押すと、スタンバイモードに戻ります。ステータスランプが白く点滅し始め、データ転送が終了します。
  • VerseGripスタイラスの電源を切るには、電源ボタンを5秒間長押ししてから指を離してください。指を離すと、ステータスランプが消え、表示もなくなります。これにより、データ転送が終了します。

積載​

  • VerseGrip StylusをUSB-C充電ポートを介して電源に接続してください。
  • 電源が接続されている間、充電状態インジケーターは青色で点灯し続け、バッテリーが完全に充電されると消灯します。
  • スタイラスの電源がオフの状態のときに電源に接続すると、自動的に電源が入ります。

警告:2024年8月から12月の間に出荷されたVerseGrip Stylusデバイスについては、バッテリーを完全に放電させないでください。バッテリーが完全に放電すると、状況によっては充電できなくなる可能性があります。この状態になっても、VerseGrip Stylusは電源に接続されている限り動作し続けます。この問題を解決するためのファームウェア更新ファイルを入手するには、Haply のサポートまでお問い合わせください。

状態と表示ランプ​

色ライトシーケンス説明
ゲルブ素早い表示/非表示の切り替えセンサー基準値の自動初期校正(VerseGripを机の上に静止させた状態で置く)
速い点滅位置合わせ・校正ボタンを押して、校正処理を開始しました
Dauerhaft位置合わせ・校正ボタンを押しました。校正が完了しました。
腐敗素早い表示/非表示の切り替えアダプタが外れている、ホストからの信号がない
速い点滅電源ボタンを押して、電源オフ処理を開始しました
Grün表示/非表示アダプターが接続されており、VerseGripはアクティブなデータストリームモードになっています
Dauerhaftアダプターが接続されています。VerseGripはアクティブなデータ転送モードです。USB給電が接続されています。
ヴァイス表示/非表示アダプターが接続されています。VerseGripはアイドル/スタンバイモードで、データ転送は行われていません。
Dauerhaftアダプターが接続されています。VerseGripはアイドル/スタンバイモードで、データ転送は行われていません。USB給電が接続されています。
オレンジブリッツ(入れ子)バッテリー残量低下の警告表示、現在の状態での通知がネストされている
ドッペルブリッツ(入れ子式)バッテリー残量が危険なほど低くなった際の警告表示、現在の状態に関する通知がネストされている
ターキス表示/非表示本機器のファームウェア更新モード
(ヘラー)Dauerhaftユーザーボタンを押すと、現在の表示色が固定され、明るくなります
Aus照明なしシャットダウン、電源を切る
充電インジケーターの色ライトシーケンス説明
ブラウDauerhaft積載
速い点滅充電がほぼ完了しました
Aus照明なし充電が完了しました

以前の状態と表示ランプ​

以下のステータスランプは、VerseGrip Stylusの旧バージョン(ファームウェア1.10以前)で見られた、以前の状態および色です。

色ライトシーケンス説明
腐敗Dauerhaftコンポーネントの初期化が未完了です
ブリンケンスタンバイモード。データ転送なし
ブラウDauerhaftセンサー基準値の自動初期校正(VerseGripを机の上に静止させた状態で置く)
Grünブリンケンアダプターが接続されており、VerseGripはアクティブなデータストリームモードになっています
Aus照明なしシャットダウン、電源を切る
充電インジケーターの色ライトシーケンス説明
ブラウDauerhaft積載
速い点滅充電がほぼ完了しました
Aus照明なし充電が完了しました

サンプルコード​

ここでは、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);

}
}