APIリファレンス
ContactGlove Python SDKは、ContactGloveを扱うためのPythonライブラリです。
必要環境
対応言語はPython 3.10以上です。
SDK本体はpure Pythonで、OS固有のビルドは不要です。 Windows 11、macOS、Ubuntuで動作確認済みです。 viewerのセットアップとDivingStationの利用環境は、それぞれ確認してください。
あらかじめDivingStationをインストールし、起動しておく必要があります。
このライブラリは次のパッケージに依存しています。
| パッケージ名 | バージョン |
|---|---|
| python-osc | >=1.7.5 |
| matplotlib | >=3.7.5(examples/viewerでのみ使用) |
インストール
配布パッケージをコンピューターに保存して展開し、展開したフォルダで同梱のwheelファイルをインストールします。
python -m pip install ./contactglovesdk-X.Y.Z-py3-none-any.whl依存パッケージ(python-osc、matplotlibなど)はpipが自動的にインストールします。
使い方
DivingStationへの接続と切断
DivingStationに接続するには、ContactGloveClient.connect_to_hostメソッドを使います。
connect_to_hostに渡すHostは、ホスト名、IPアドレス、DivingStation側の受信ポートの3つの情報を持ちます。ホスト名は、ホストを区別するためにユーザーが自由に決める名前です。IPアドレスは、DivingStationを実行しているコンピューターに割り当てられたIPアドレスです。DivingStationの受信ポートは、DivingStationがSDKからのOSCリクエストを受信するポートです。通常は25791ですが、DivingStation側で変更できます。変更した場合は、同じ値を設定してください。
SDK(ローカル)側の受信ポートは、ContactGloveClientのコンストラクタ引数local_portで指定します。0(既定)を渡すとOSが空いているポートを自動で割り当てます。割り当てられたポートは、接続後にclient.local_portプロパティで確認できます。
DSへOSCコマンドを送るときの送信元ポートは、コンストラクタ引数send_portで指定します。0(既定)を渡すとOSが空いているポートを割り当てます。最初の送信(接続など)の後は、client.send_portプロパティで実際のポート番号を確認できます。
LAN承認待ちやデータ途絶からの復帰のためにリトライするには、disconnectやcloseを呼ばずに、同じクライアントでconnect_to_host(host)を再度呼び出してください。同じ送信ソケットからConnectを再送し、受信ポートも維持します(send_port=0の場合も同じです)。SDKは30秒ごとにConnectを自動で再送することも続けます。呼び出しが成功しても、LAN承認が完了したとは限りません。DivingStationの再起動後は、リトライでセッションを復帰できます。必要ならDivingStationで再度承認してください。明示的なDisconnectはセッションを終了し、承認待ちや承認済みの状態を取り消すことがあります。
DivingStationとの接続を閉じるには、disconnectメソッドを使います。SDK全体の終了処理としては、close()(またはwith文によるコンテキストマネージャー形式)でローカルサーバーと送信ソケットを停止します。
from contactglovesdk import ContactGloveClient, Host
host = Host("localhost", "127.0.0.1", 25791)
with ContactGloveClient() as client:
# Connect to DivingStation
client.connect_to_host(host)
# Do various things
# Disconnect from DivingStation
client.disconnect(host)値を読み取る
グローブに関するさまざまな情報を読み取るメソッドがあります。返される値は、呼び出した時点で最後に受信したデータです。取得できる値とメソッドは次のとおりです。
| 取得できる値 | メソッド名 |
|---|---|
| グローブ自体の情報 | get_data_for_glove |
| グローブが振動に対応しているか | does_glove_support_haptics |
| 各指関節の開き角・曲げ角 | get_ergonomics_data_for_glove |
| 各指関節の位置・回転 | get_skeleton_data_for_glove |
| 生センサーの位置・回転 | get_rawsensor_data_for_glove |
| グローブに取り付けたコントローラーからの入力 | get_controller_data_for_glove |
| 接続中のすべてのグローブのID | get_ids_of_available_gloves |
| 接続中のグローブの総数 | get_number_of_available_gloves |
グローブのデータは非同期に届きます。接続する前にコールバックを登録して実際のグローブIDを取得し、データが届いてから読み取ってください。接続の呼び出しはローカルセッションを開始しますが、DivingStationの接続承認やデータ送信を確認するものではありません。
from threading import Event
from contactglovesdk import ContactGloveClient, DeviceConnectedState, Host, InvalidIDError
host = Host("localhost", "127.0.0.1", 25791)
received = Event()
glove_ids = []
def on_glove(glove):
if glove.connected_state == DeviceConnectedState.Connected and not received.is_set():
glove_ids.append(glove.id)
received.set()
with ContactGloveClient() as client:
client.register_callback_for_glove_data_stream(on_glove)
client.connect_to_host(host)
try:
if received.wait(timeout=5):
try:
glove = client.get_data_for_glove(glove_ids[0])
print(f"id={glove.id}")
except InvalidIDError:
print("The glove is no longer available")
else:
print("No glove data received within 5 seconds")
finally:
client.disconnect(host)データが届かない場合は、グローブがDivingStationに接続され有効になっていることと、必要な接続承認が完了していることを確認してください。グローブが複数ある場合は、最初のIDが目的のグローブとは限らないため、対象のIDを選んでください。
値の変化を自動で受け取る
グローブに関するさまざまな値が更新されるたびに自動で呼び出されるコールバックを登録できます。コールバックはOSCの受信スレッドから呼び出されるため、コールバック内の処理は複数のスレッドからアクセスされることを前提に実装してください。コールバックが例外を送出した場合、SDKはトレースバック付きでcontactglovesdkロガーに記録し(loggingを設定していない場合はstderrに表示されます)、他のコールバックの呼び出しを続けます。
| 呼び出しのきっかけになる値 | メソッド名 |
|---|---|
| グローブ自体の情報 | register_callback_for_glove_data_stream |
| 各指関節の開き角・曲げ角 | register_callback_for_ergonomics_stream |
| 各指関節の位置・回転 | register_callback_for_skeleton_stream |
| 生センサーの位置・回転 | register_callback_for_rawsensor_stream |
| グローブに取り付けたコントローラーからの入力 | register_callback_for_controller_data_stream |
次のように使います。
import time
from contactglovesdk import ContactGloveClient, GloveData, Host
host = Host("localhost", "127.0.0.1", 25791)
def on_glove(g: GloveData) -> None:
print(f"[callback] id={g.id} battery={g.battery_percentage}%"
f" left={g.is_left} state={g.connected_state.name}")
with ContactGloveClient() as client:
# Registering callbacks before connecting avoids missing updates
client.register_callback_for_glove_data_stream(on_glove)
client.connect_to_host(host)
# Wait for 5 seconds
time.sleep(5)
client.disconnect(host)振動
vibrate_gloveメソッドは、振動機能を持つグローブに振動コマンドを送ります。コマンドは、現在接続中のすべてのDSホストに送られます。 YOUR_GLOVE_ID はDivingStationから受信した実際のIDに置き換えてください。
client.vibrate_glove("YOUR_GLOVE_ID", frequency=200.0, amplitude=0.8, duration=0.2)定義されている型と関数
このSDKが定義し、利用できるようにしている型と関数は次のとおりです。
クラス
| 名前 | 説明 |
|---|---|
ContactGloveClient | ContactGlove SDK v2のメインクラス |
Host | DivingStationのホスト情報を保持するデータクラス |
GloveData | グローブデバイスの情報を保持するデータクラス |
ControllerData | コントローラーの入力状態を保持するデータクラス |
ErgonomicsData | 指の開き角と曲げ角のデータを保持するデータクラス |
SkeletonData | 手のスケルトンデータ(関節の位置と回転)を保持するデータクラス |
RawSkeletonData | リターゲット前の手のスケルトンデータを保持するデータクラス。 |
RawSensorData | 片手分の生センサーのTransformデータを保持するデータクラス |
RetargetProfileInfo | リターゲットプロファイルの情報を運ぶ応答を保持するデータクラス。 |
Transform | 位置と回転を組み合わせたTransform |
Vec3 | 3次元ベクトル |
Quaternion | 回転を表すクォータニオン |
列挙型
| 名前 | 説明 |
|---|---|
DeviceFamilyType | デバイスの種類を表す列挙型 |
DeviceColor | デバイスの表示色設定を表す列挙型 |
DeviceConnectedState | デバイスの接続状態を表す列挙型 |
ButtonStatus | ボタンの押下状態を表す列挙型 |
TrackingState | IK由来のデータのトラッキング状態を表す列挙型。 |
ErgonomicsIndex | ErgonomicsData.valuesの各要素が表す関節を示す列挙型 |
SkeletonNode | SkeletonData.positionsの各要素が表す関節を示す列挙型 |
SkeletonRotationNode | SkeletonData.rotationsの各要素が表す関節を示す列挙型 |
RawSensorIndex | RawSensorData.transformsの各要素が表すセンサーを示す列挙型 |
例外
| 名前 | 説明 |
|---|---|
ContactGloveSDKError | SDKが発生させる例外の基底クラス |
SDKNotAvailableError | ローカルのUDPソケットを開けなかったとき(ポートが使用中の場合など)に発生します |
NotConnectedError | 接続が必要な操作を、その接続が存在しない状態で行おうとしたときに発生します |
InvalidIDError | 指定したグローブIDのデータが現在のデータストアに存在しないときに発生します |
定数
| 名前 | 値 | 説明 |
|---|---|---|
ERGONOMICS_COUNT | 20 | 片手あたりのエルゴノミクスデータの要素数(5本の指 × 4関節) |
SKELETON_NODE_COUNT | 25 | 片手あたりのスケルトンの位置の要素数 |
SKELETON_ROTATION_COUNT | 19 | 片手あたりのスケルトンの回転の要素数(手首と5つの指先のノードを除きます) |
RAW_SENSOR_COUNT | 5 | 片手あたりの生センサーのTransformの数(指1本につき1つ) |
DeviceFamilyType
class DeviceFamilyType(IntEnum)デバイスの種類を表す列挙型
/DS2/HC/Deviceのdevice_typeフィールドに対応します。
主な対象はContactGlove3です。
| 値 | 説明 |
|---|---|
ContactGlove | ContactGlove |
ContactSheet | ContactSheet |
ContactGlove2 | ContactGlove2 |
ContactGlove3 | ContactGlove3 |
DeviceColor
class DeviceColor(IntEnum)デバイスの表示色設定を表す列挙型
/DS2/HC/Deviceのcolorフィールドに対応します。
表示色の型名の移行
表示色設定の公開型名はDeviceColorです。旧版でLedColorを使っているコードは、
from contactglovesdk import DeviceColorへ変更し、LedColor.Greenなどの参照を
DeviceColor.Greenへ置き換えてください。GloveData.colorのフィールド名、色の数値、
OSCの通信形式は同じです。
LedColorはDeviceColorの互換エイリアスとして公開されているため、旧import名も引き続き動作します。
新しいコードではDeviceColorを使ってください。
シリアライズされた列挙値は、旧版とのデータ受け渡しに対応するため、LedColorの型名を保持します。
| 値 | 説明 |
|---|---|
Magenta | マゼンタ |
Red | 赤 |
Orange | オレンジ |
Yellow | 黄 |
Green | 緑 |
Cyan | シアン |
Blue | 青 |
Achromatic | 無彩色 |
DeviceConnectedState
class DeviceConnectedState(IntEnum)デバイスの接続状態を表す列挙型
/DS2/HC/Deviceのconnected_stateフィールドに対応します。
| 値 | 説明 |
|---|---|
Unknown | 状態不明 |
Connected | 接続済み |
Unconnected | 未接続 |
Pairing | 接続を試行中 |
ButtonStatus
class ButtonStatus(IntEnum)ボタンの押下状態を表す列挙型
/DS2/HC/Controllerの各ボタンのフィールドに対応します。
| 値 | 説明 |
|---|---|
Unpressed | 押されていない |
Touching | 触れている(タッチセンサーで検出) |
Pressed | 押されている |
TrackingState
class TrackingState(IntEnum)IK由来のデータのトラッキング状態を表す列挙型。
/DS2/HC/Ergonomics、/DS2/HC/HandSkeleton、/DS2/HC/HandSkeletonRawのtracking_stateフィールドに対応します。
IkFailedまたはNotAttemptedの値は表示や診断には使えますが、制御、速度の推定、補間には使わないでください。これらの用途で有効なのは Tracked の値だけです。
NotAttempted は必要なIK処理が実行されなかったことを表します。前段の処理失敗や入力不足のほか、更新間隔の制御で既存の姿勢を再利用するなど、姿勢計算が不要と判断された場合も含みます。この状態自体はIKの失敗を意味しません。
SkeletonData はリターゲットIK、RawSkeletonData と ErgonomicsData はソーススケルトンIKの状態を表し、同じ時刻でも状態が異なる場合があります。
| 値 | 説明 |
|---|---|
Tracked | 今回のIKパスで得られた有効な値 |
IkFailed | IKパスを試みたものの失敗した値 |
NotAttempted | 前段の失敗・入力不足や更新間隔による意図的な省略などで、IK処理を実行しなかった値 |
ErgonomicsIndex
class ErgonomicsIndex(IntEnum)ErgonomicsData.valuesの各要素が表す関節を示す列挙型
インデックスは片手分(ERGONOMICS_COUNT = 20要素)で、values[i]はErgonomicsIndex(i)に対応します。値の単位は度で、曲げ角は指を伸ばしたときに0度です。
| 値 | 説明 |
|---|---|
ThumbCMC | 親指のCMC関節の曲げ角 |
ThumbMCP | 親指のMCP関節の曲げ角 |
ThumbIP | 親指のIP関節の曲げ角 |
ThumbTilt | 親指のMCP関節の傾き角 |
IndexMCP | 人差し指のMCP関節の曲げ角 |
IndexPIP | 人差し指のPIP関節の曲げ角 |
IndexDIP | 人差し指のDIP関節の曲げ角 |
IndexTilt | 人差し指のMCP関節の傾き角 |
MiddleMCP | 中指のMCP関節の曲げ角 |
MiddlePIP | 中指のPIP関節の曲げ角 |
MiddleDIP | 中指のDIP関節の曲げ角 |
MiddleTilt | 中指のMCP関節の傾き角 |
RingMCP | 薬指のMCP関節の曲げ角 |
RingPIP | 薬指のPIP関節の曲げ角 |
RingDIP | 薬指のDIP関節の曲げ角 |
RingTilt | 薬指のMCP関節の傾き角 |
LittleMCP | 小指のMCP関節の曲げ角 |
LittlePIP | 小指のPIP関節の曲げ角 |
LittleDIP | 小指のDIP関節の曲げ角 |
LittleTilt | 小指のMCP関節の傾き角 |
SkeletonNode
class SkeletonNode(IntEnum)SkeletonData.positionsの各要素が表す関節を示す列挙型
インデックスは片手分(SKELETON_NODE_COUNT = 25要素)で、positions[i]はSkeletonNode(i)に対応します。
| 値 | 説明 |
|---|---|
Wrist | 手首 |
ThumbCMC | 親指のCMC関節 |
ThumbMCP | 親指のMCP関節 |
ThumbIP | 親指のIP関節 |
ThumbTip | 親指の指先 |
IndexCMC | 人差し指のCMC関節 |
IndexMCP | 人差し指のMCP関節 |
IndexPIP | 人差し指のPIP関節 |
IndexDIP | 人差し指のDIP関節 |
IndexTip | 人差し指の指先 |
MiddleCMC | 中指のCMC関節 |
MiddleMCP | 中指のMCP関節 |
MiddlePIP | 中指のPIP関節 |
MiddleDIP | 中指のDIP関節 |
MiddleTip | 中指の指先 |
RingCMC | 薬指のCMC関節 |
RingMCP | 薬指のMCP関節 |
RingPIP | 薬指のPIP関節 |
RingDIP | 薬指のDIP関節 |
RingTip | 薬指の指先 |
LittleCMC | 小指のCMC関節 |
LittleMCP | 小指のMCP関節 |
LittlePIP | 小指のPIP関節 |
LittleDIP | 小指のDIP関節 |
LittleTip | 小指の指先 |
SkeletonRotationNode
class SkeletonRotationNode(IntEnum)SkeletonData.rotationsの各要素が表す関節を示す列挙型
インデックスは片手分(SKELETON_ROTATION_COUNT = 19要素)で、rotations[i]はSkeletonRotationNode(i)に対応します。
SkeletonNodeと異なり、手首と5つの指先のノードは回転の値を持たないため除かれています。
| 値 | 説明 |
|---|---|
ThumbCMC | 親指のCMC関節 |
ThumbMCP | 親指のMCP関節 |
ThumbIP | 親指のIP関節 |
IndexCMC | 人差し指のCMC関節 |
IndexMCP | 人差し指のMCP関節 |
IndexPIP | 人差し指のPIP関節 |
IndexDIP | 人差し指のDIP関節 |
MiddleCMC | 中指のCMC関節 |
MiddleMCP | 中指のMCP関節 |
MiddlePIP | 中指のPIP関節 |
MiddleDIP | 中指のDIP関節 |
RingCMC | 薬指のCMC関節 |
RingMCP | 薬指のMCP関節 |
RingPIP | 薬指のPIP関節 |
RingDIP | 薬指のDIP関節 |
LittleCMC | 小指のCMC関節 |
LittleMCP | 小指のMCP関節 |
LittlePIP | 小指のPIP関節 |
LittleDIP | 小指のDIP関節 |
RawSensorIndex
class RawSensorIndex(IntEnum)RawSensorData.transformsの各要素が表すセンサーを示す列挙型
インデックスは片手分(RAW_SENSOR_COUNT = 5要素)で、transforms[i]はRawSensorIndex(i)に対応します。
| 値 | 説明 |
|---|---|
Thumb | 親指 |
Index | 人差し指 |
Middle | 中指 |
Ring | 薬指 |
Little | 小指 |
ERGONOMICS_COUNT
ERGONOMICS_COUNT: int = 20片手あたりのエルゴノミクスデータの要素数(5本の指 × 4関節)
SKELETON_NODE_COUNT
SKELETON_NODE_COUNT: int = 25片手あたりのスケルトンの位置の要素数
SKELETON_ROTATION_COUNT
SKELETON_ROTATION_COUNT: int = 19片手あたりのスケルトンの回転の要素数(手首と5つの指先のノードを除きます)
RAW_SENSOR_COUNT
RAW_SENSOR_COUNT: int = 5片手あたりの生センサーのTransformの数(指1本につき1つ)
ContactGloveClient
from contactglovesdk import ContactGloveClientContactGlove SDK v2のメインクラス
ポーリングの戻り値と各ストリームのコールバックには、互いに独立したスナップショットを渡します。ネストしたリストや座標・回転の値も独立しており、変更してもSDKのキャッシュやほかのコールバックへ渡す値には影響しません。
使い方:
import time
from contactglovesdk import ContactGloveClient, Host, InvalidIDError
host = Host("localhost", "127.0.0.1", 25791)
with ContactGloveClient() as client:
# Register before connecting so the first update is not missed.
client.register_callback_for_glove_data_stream(
lambda g: print(g.id, g.battery_percentage)
)
client.connect_to_host(host)
try:
# Poll until an ID arrives or the five-second deadline expires.
deadline = time.monotonic() + 5.0
glove_ids = client.get_ids_of_available_gloves()
while not glove_ids and time.monotonic() < deadline:
time.sleep(0.1)
glove_ids = client.get_ids_of_available_gloves()
if glove_ids:
try:
glove = client.get_data_for_glove(glove_ids[0])
print(glove.id)
except InvalidIDError:
print("The glove is no longer available")
else:
print("No glove data received within 5 seconds")
finally:
client.disconnect(host)パブリックメソッド
| 戻り値 | 名前 | 説明 |
|---|---|---|
__init__ | ContactGlove SDK v2のメインクラス | |
int | start_server | どのホストにも接続せずに、ローカルのOSCサーバーを起動します。 |
int | None | local_port | ローカルのOSCサーバーが使っているポート番号。動作していない間はNoneです。 |
int | None | send_port | OSCの送信ソケットが使っているポート番号。最初の送信の前はNoneです。 |
None | close | ローカルのOSCサーバーと送信ソケットを停止します。 |
None | connect_to_host | DivingStationに接続し、データストリームを開始します。 |
None | disconnect | DSから切断します。 |
bool | does_glove_support_haptics | グローブが振動に対応しているかを確認します。 |
GloveData | get_data_for_glove | グローブIDに対応するグローブの情報を読み取ります。 |
ControllerData | get_controller_data_for_glove | グローブIDに対応するコントローラーの入力データを読み取ります。 |
ErgonomicsData | get_ergonomics_data_for_glove | グローブIDに対応する指の開き角と曲げ角のデータを読み取ります。 |
SkeletonData | get_skeleton_data_for_glove | グローブIDに対応する関節の位置と回転のデータを読み取ります。 |
RawSkeletonData | get_raw_skeleton_data_for_glove | グローブIDに対応するリターゲット前の手のスケルトンを読み取ります。 |
RawSensorData | get_rawsensor_data_for_glove | グローブIDに対応する生センサーのTransformデータを読み取ります。 |
list[str] | get_ids_of_available_gloves | 現在把握しているすべてのグローブのIDを読み取ります。 |
int | get_number_of_available_gloves | 現在把握しているグローブの総数を読み取ります。 |
None | vibrate_glove | グローブを振動させます。 |
None | request_retarget_profile_info | リターゲットプロファイルの表示名と説明をDivingStationに要求します。 |
None | register_callback_for_glove_data_stream | グローブの情報が更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_controller_data_stream | コントローラーのデータが更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_ergonomics_stream | エルゴノミクスデータが更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_skeleton_stream | スケルトンデータが更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_raw_skeleton_stream | リターゲット前のスケルトンが更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_rawsensor_stream | 生センサーのTransformデータが更新されたときに呼び出されるコールバックを登録します。 |
None | register_callback_for_retarget_profile_info_stream | リターゲットプロファイル情報の応答を受け取るコールバックを登録します。 |
クラス属性
| 戻り値 | 名前 | 説明 |
|---|---|---|
int | DEFAULT_DS_PORT | DivingStation側のOSC受信ポート番号の既定値 |
__init__
ContactGloveClient(local_host: str = "0.0.0.0", local_port: int = 0, send_port: int = 0)引数
-
local_hostローカルのOSCサーバーがbindするネットワークインターフェース("0.0.0.0"ですべてのインターフェース)。 -
local_portローカルのOSCサーバーがbindするポート番号(0ならOSが空いているポートを自動で選びます)。 -
send_portDSへOSCを送るためのローカルのUDPポート番号(0ならOSが空いているポートを自動で選びます)。
start_server
def start_server(self) -> intどのホストにも接続せずに、ローカルのOSCサーバーを起動します。
connect_to_hostを呼ぶ前にローカルのポート番号が必要な場合に使います。
戻り値
サーバーが実際にbindしたポート番号。
例外
SDKNotAvailableErrorポートのbindに失敗した場合。
local_port
@property
def local_port(self) -> int | NoneローカルのOSCサーバーが使っているポート番号。動作していない間はNoneです。
send_port
@property
def send_port(self) -> int | NoneOSCの送信ソケットが使っているポート番号。最初の送信の前はNoneです。
close
def close(self)ローカルのOSCサーバーと送信ソケットを停止します。
実行中のストリームコールバックがある場合は、それが終わるのを待ってから戻ります。
connect_to_host
def connect_to_host(self, host: Host)DivingStationに接続し、データストリームを開始します。
ローカルのOSCサーバーがまだ動作していなければ起動し、hostに/DS2/HC/Connect <local_port>を送ります。接続を維持している間は、同じ送信ソケットから30秒ごとにConnectを再送します。
同じIPアドレスとDSポートに対してもう一度呼び出すと、Disconnectを送ったり、送信ソケット・受信ポート・keepaliveワーカーを置き換えたりせずに、Connectを再送します。LAN承認待ちやデータ消失からの復帰のためのリトライに使ってください。send_portが0の場合も、OSが選んだ送信元ポートは維持されます。呼び出しから戻っても、LAN承認が完了したとは限りません。DSの再起動後は、Connectのリトライでセッションを復帰できます。必要ならDSで再度承認してください。明示的なdisconnectはセッションを終了し、承認待ちや承認済みの状態を取り消すことがあります。
引数
host接続先のDSのホスト情報。
例外
SDKNotAvailableErrorローカルの受信ポートまたは送信ポートのbindに失敗した場合。
disconnect
def disconnect(self, host: Host)DSから切断します。
hostに/DS2/HC/Disconnect <local_port>を送ります。最後の接続を閉じるときは、実行中のストリームコールバックが終わるまで待ちます。
引数
hostconnect_to_hostに渡したものと同じホスト情報。
例外
NotConnectedError指定したホストへの接続が存在しない場合。
does_glove_support_haptics
def does_glove_support_haptics(self, glove_id: str) -> boolグローブが振動に対応しているかを確認します。
引数
glove_id確認するグローブのID。
戻り値
振動機能があるかどうか。
例外
InvalidIDError指定したIDのグローブが存在しない場合。
get_data_for_glove
def get_data_for_glove(self, glove_id: str) -> GloveDataグローブIDに対応するグローブの情報を読み取ります。
引数
glove_id読み取るグローブのID。
戻り値
グローブの情報のスナップショット。
例外
InvalidIDError指定したIDのグローブが存在しない場合。
get_controller_data_for_glove
def get_controller_data_for_glove(self, glove_id: str) -> ControllerDataグローブIDに対応するコントローラーの入力データを読み取ります。
引数
glove_id読み取るグローブのID。
戻り値
コントローラーの入力データのスナップショット。
例外
InvalidIDError指定したIDのデータをまだ受信していない場合。
get_ergonomics_data_for_glove
def get_ergonomics_data_for_glove(self, glove_id: str) -> ErgonomicsDataグローブIDに対応する指の開き角と曲げ角のデータを読み取ります。
引数
glove_id読み取るグローブのID。
戻り値
エルゴノミクスデータのスナップショット。
例外
InvalidIDError指定したIDのデータをまだ受信していない場合。
get_skeleton_data_for_glove
def get_skeleton_data_for_glove(self, glove_id: str) -> SkeletonDataグローブIDに対応する関節の位置と回転のデータを読み取ります。
引数
glove_id読み取るグローブのID。
戻り値
スケルトンデータのスナップショット。
例外
InvalidIDError指定したIDのデータをまだ受信していない場合。
get_raw_skeleton_data_for_glove
def get_raw_skeleton_data_for_glove(self, glove_id: str) -> RawSkeletonDataグローブIDに対応するリターゲット前の手のスケルトンを読み取ります。
戻り値
位置と回転を含む、独立したスナップショット。
例外
InvalidIDError指定したIDのデータをまだ受信していない場合。
get_rawsensor_data_for_glove
def get_rawsensor_data_for_glove(self, glove_id: str) -> RawSensorDataグローブIDに対応する生センサーのTransformデータを読み取ります。
引数
glove_id読み取るグローブのID。
戻り値
生センサーのTransformデータのスナップショット。
例外
InvalidIDError指定したIDのデータをまだ受信していない場合。
get_ids_of_available_gloves
def get_ids_of_available_gloves(self) -> list[str]現在把握しているすべてのグローブのIDを読み取ります。
戻り値
グローブIDのリスト。
get_number_of_available_gloves
def get_number_of_available_gloves(self) -> int現在把握しているグローブの総数を読み取ります。
戻り値
グローブの総数。
vibrate_glove
def vibrate_glove(self, glove_id: str, frequency: float, amplitude: float, duration: float)グローブを振動させます。
コマンドは、現在接続中のすべてのDSホストに送られます。
引数
-
glove_id振動させるグローブのID。 -
frequency振動の周波数(Hz、100.0〜500.0)。 -
amplitude振動の振幅(0.0〜1.0)。 -
duration振動の持続時間(秒、0.001〜1.0)。
例外
-
InvalidIDError指定したIDのグローブが存在しない場合。 -
ValueErrorfrequency、amplitude、durationのいずれかが仕様の範囲外であるか、有限の値でない場合。
request_retarget_profile_info
def request_retarget_profile_info(self, profile_uuid: str, request_id: int)リターゲットプロファイルの表示名と説明をDivingStationに要求します。
応答は、register_callback_for_retarget_profile_info_streamで登録したコールバックに届きます。
引数
-
profile_uuid問い合わせる36文字のUUID。 -
request_idリクエストとその応答を対応付ける符号付き32ビット整数。
例外
ValueErrorUUIDまたはリクエストIDがプロトコルの形式に合わない場合。
register_callback_for_glove_data_stream
def register_callback_for_glove_data_stream(self, callback: Callable[[GloveData], None])グローブの情報が更新されたときに呼び出されるコールバックを登録します。
/DS2/HC/Deviceを受信するたびに、更新後のGloveDataを引数としてコールバックが呼び出されます。コールバックはOSCの受信スレッドから呼び出されます。connected_stateがUnconnectedのレコードも渡されますが、その時点でそのIDのデータはもう読み取れません。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
引数
callback登録するコールバック関数。
register_callback_for_controller_data_stream
def register_callback_for_controller_data_stream(self, callback: Callable[[ControllerData], None])コントローラーのデータが更新されたときに呼び出されるコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
引数
callback登録するコールバック関数。
register_callback_for_ergonomics_stream
def register_callback_for_ergonomics_stream(self, callback: Callable[[ErgonomicsData], None])エルゴノミクスデータが更新されたときに呼び出されるコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
引数
callback登録するコールバック関数。
register_callback_for_skeleton_stream
def register_callback_for_skeleton_stream(self, callback: Callable[[SkeletonData], None])スケルトンデータが更新されたときに呼び出されるコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
引数
callback登録するコールバック関数。
register_callback_for_raw_skeleton_stream
def register_callback_for_raw_skeleton_stream(self, callback: Callable[[RawSkeletonData], None])リターゲット前のスケルトンが更新されたときに呼び出されるコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
register_callback_for_rawsensor_stream
def register_callback_for_rawsensor_stream(self, callback: Callable[[RawSensorData], None])生センサーのTransformデータが更新されたときに呼び出されるコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
引数
callback登録するコールバック関数。
register_callback_for_retarget_profile_info_stream
def register_callback_for_retarget_profile_info_stream(self, callback: Callable[[RetargetProfileInfo], None])リターゲットプロファイル情報の応答を受け取るコールバックを登録します。
コールバックが送出した例外はcontactglovesdkロガーに記録され、他のコールバックの呼び出しは妨げられません。
DEFAULT_DS_PORT
DEFAULT_DS_PORT: int = 25791DivingStation側のOSC受信ポート番号の既定値
Host
from contactglovesdk import HostDivingStationのホスト情報を保持するデータクラス
connect_to_host() / disconnect()に渡します。SDK(ローカル)側の受信ポートはContactGloveClientが管理するため、このクラスには含まれません。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | host_name | ホスト名(例:"localhost") |
str | ip_address | IPアドレス(例:"127.0.0.1") |
int | port | DivingStation側のOSC受信ポート番号 |
Host.host_name
host_name: strホスト名(例:"localhost")
Host.ip_address
ip_address: strIPアドレス(例:"127.0.0.1")
Host.port
port: int = 25791DivingStation側のOSC受信ポート番号
GloveData
from contactglovesdk import GloveDataグローブデバイスの情報を保持するデータクラス
OSCアドレス/DS2/HC/Deviceから受信したデータに対応します。
レコードの構成(デバイスごとに10フィールド):
string id, string pair_id,
int battery_percentage, int is_haptics, int is_left,
int device_type, int color, int connected_state,
string name, int is_external_power_presentパブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | デバイスID |
str | pair_id | ペアになっているグローブのID(ない場合は空文字列) |
int | battery_percentage | バッテリー残量 [0 - 100]。-1は無効な値を表します |
bool | is_haptics | 振動機能があるかどうか |
bool | is_left | 左手用のグローブかどうか |
DeviceFamilyType | device_type | デバイスの種類 |
DeviceColor | color | デバイスの表示色設定 |
DeviceConnectedState | connected_state | 接続状態 |
str | name | デバイス名 |
bool | is_external_power_present | 外部給電を検出しているかどうか |
GloveData.id
id: str = ""デバイスID
GloveData.pair_id
pair_id: str = ""ペアになっているグローブのID(ない場合は空文字列)
GloveData.battery_percentage
battery_percentage: int = -1バッテリー残量 [0 - 100]。-1は無効な値を表します
GloveData.is_haptics
is_haptics: bool = False振動機能があるかどうか
GloveData.is_left
is_left: bool = False左手用のグローブかどうか
GloveData.device_type
device_type: DeviceFamilyType = DeviceFamilyType.ContactGloveデバイスの種類
GloveData.color
color: DeviceColor = DeviceColor.Achromaticデバイスの表示色設定
GloveData.connected_state
connected_state: DeviceConnectedState = DeviceConnectedState.Unknown接続状態
GloveData.name
name: str = ""デバイス名
GloveData.is_external_power_present
is_external_power_present: bool = False外部給電を検出しているかどうか
ControllerData
from contactglovesdk import ControllerDataコントローラーの入力状態を保持するデータクラス
OSCアドレス/DS2/HC/Controllerから受信したデータに対応します。
レコードの構成(コントローラーごとに15フィールド):
string id, int is_left,
int a, int b, int sys,
int trigger_button, int joystick_button, int trackpad_button,
float trigger, float grip_value, float grip_force,
float joystick_x, float joystick_y,
float trackpad_x, float trackpad_yパブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | グローブID |
bool | is_left | 左手かどうか |
ButtonStatus | a_button | Aボタンの押下状態 |
ButtonStatus | b_button | Bボタンの押下状態 |
ButtonStatus | sys_button | システムボタンの押下状態 |
ButtonStatus | trigger_button | トリガーボタンの押下状態 |
ButtonStatus | joystick_button | ジョイスティックボタンの押下状態 |
ButtonStatus | trackpad_button | トラックパッドのタッチの押下状態 |
float | trigger | トリガーの値(0.0〜1.0) |
float | grip_value | グリップの値(0.0〜1.0) |
float | grip_force | グリップの力(0.0〜1.0) |
float | joystick_x | ジョイスティックのX軸の値(-1.0〜1.0) |
float | joystick_y | ジョイスティックのY軸の値(-1.0〜1.0) |
float | trackpad_x | トラックパッドのX軸の値(-1.0〜1.0) |
float | trackpad_y | トラックパッドのY軸の値(-1.0〜1.0) |
ControllerData.id
id: str = ""グローブID
ControllerData.is_left
is_left: bool = False左手かどうか
ControllerData.a_button
a_button: ButtonStatus = ButtonStatus.UnpressedAボタンの押下状態
ControllerData.b_button
b_button: ButtonStatus = ButtonStatus.UnpressedBボタンの押下状態
ControllerData.sys_button
sys_button: ButtonStatus = ButtonStatus.Unpressedシステムボタンの押下状態
ControllerData.trigger_button
trigger_button: ButtonStatus = ButtonStatus.Unpressedトリガーボタンの押下状態
ControllerData.joystick_button
joystick_button: ButtonStatus = ButtonStatus.Unpressedジョイスティックボタンの押下状態
ControllerData.trackpad_button
trackpad_button: ButtonStatus = ButtonStatus.Unpressedトラックパッドのタッチの押下状態
ControllerData.trigger
trigger: float = 0.0トリガーの値(0.0〜1.0)
ControllerData.grip_value
grip_value: float = 0.0グリップの値(0.0〜1.0)
ControllerData.grip_force
grip_force: float = 0.0グリップの力(0.0〜1.0)
ControllerData.joystick_x
joystick_x: float = 0.0ジョイスティックのX軸の値(-1.0〜1.0)
ControllerData.joystick_y
joystick_y: float = 0.0ジョイスティックのY軸の値(-1.0〜1.0)
ControllerData.trackpad_x
trackpad_x: float = 0.0トラックパッドのX軸の値(-1.0〜1.0)
ControllerData.trackpad_y
trackpad_y: float = 0.0トラックパッドのY軸の値(-1.0〜1.0)
ErgonomicsData
from contactglovesdk import ErgonomicsData指の開き角と曲げ角のデータを保持するデータクラス
OSCアドレス/DS2/HC/Ergonomicsから受信したデータに対応します。
レコードの構成(片手ごとに25フィールド):
string id, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo, int tracking_state,
float[20] valuesvalues[i]はErgonomicsIndex(i)に対応します。
角度の単位は度で、曲げ角は指を伸ばしたときに0度です。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | グローブID |
bool | is_left | 左手かどうか |
int | timestamp_ms | フレームが生成された時刻(Unix時間、ミリ秒) |
TrackingState | tracking_state | IK由来のトラッキング状態 |
list[float] | values | 関節ごとの開き角・曲げ角の値(片手20要素、度) |
ErgonomicsData.id
id: str = ""グローブID
ErgonomicsData.is_left
is_left: bool = False左手かどうか
ErgonomicsData.timestamp_ms
timestamp_ms: int = 0フレームが生成された時刻(Unix時間、ミリ秒)
ErgonomicsData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedIK由来のトラッキング状態
ErgonomicsData.values
values: list[float] = [0.0, ...] # 20 elements関節ごとの開き角・曲げ角の値(片手20要素、度)
SkeletonData
from contactglovesdk import SkeletonData手のスケルトンデータ(関節の位置と回転)を保持するデータクラス
OSCアドレス/DS2/HC/HandSkeletonから受信したデータに対応します。
レコードの構成(メッセージごとに1レコード、157フィールド):
string id, string profile_uuid, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo, int tracking_state,
float[75] # 25 nodes × (p_x, p_y, p_z)
float[76] # 19 nodes × (q_w, q_x, q_y, q_z)positions[i]はSkeletonNode(i)に対応します(25要素)。
rotations[i]はSkeletonRotationNode(i)に対応します(19要素。手首と5つの指先のノードは除かれます)。
位置の単位はメートルで、model-rooted空間(手首を原点とする座標系)で表されます。回転は親ノードに対するローカルのクォータニオンです。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | グローブID |
str | profile_uuid | リターゲットプロファイルの固定UUID |
bool | is_left | 左手かどうか |
int | timestamp_ms | フレームが生成された時刻(Unix時間、ミリ秒) |
TrackingState | tracking_state | リターゲットのIKに由来するトラッキング状態 |
list[Vec3] | positions | ノードごとの位置(25要素)。インデックスはSkeletonNodeを参照してください |
list[Quaternion] | rotations | ノードごとの回転(19要素)。インデックスはSkeletonRotationNodeを参照してください |
SkeletonData.id
id: str = ""グローブID
SkeletonData.profile_uuid
profile_uuid: str = ""リターゲットプロファイルの固定UUID
SkeletonData.is_left
is_left: bool = False左手かどうか
SkeletonData.timestamp_ms
timestamp_ms: int = 0フレームが生成された時刻(Unix時間、ミリ秒)
SkeletonData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedリターゲットのIKに由来するトラッキング状態
SkeletonData.positions
positions: list[Vec3] = [Vec3(x=0.0, y=0.0, z=0.0), ...] # 25 elementsノードごとの位置(25要素)。インデックスはSkeletonNodeを参照してください
SkeletonData.rotations
rotations: list[Quaternion] = [Quaternion(w=1.0, x=0.0, y=0.0, z=0.0), ...] # 19 elementsノードごとの回転(19要素)。インデックスはSkeletonRotationNodeを参照してください
RawSkeletonData
from contactglovesdk import RawSkeletonDataリターゲット前の手のスケルトンデータを保持するデータクラス。
OSCアドレス/DS2/HC/HandSkeletonRawから受信したデータに対応します。メッセージごとに1レコードで、profile_uuidを除き、位置と回転の構成はSkeletonDataと同じです。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | グローブID |
bool | is_left | 左手かどうか |
int | timestamp_ms | フレームが生成された時刻(Unix時間、ミリ秒) |
TrackingState | tracking_state | ソーススケルトンのIKに由来するトラッキング状態 |
list[Vec3] | positions | ノードごとの位置(25要素)。インデックスはSkeletonNodeを参照してください |
list[Quaternion] | rotations | ノードごとの回転(19要素)。インデックスはSkeletonRotationNodeを参照してください |
RawSkeletonData.id
id: str = ""グローブID
RawSkeletonData.is_left
is_left: bool = False左手かどうか
RawSkeletonData.timestamp_ms
timestamp_ms: int = 0フレームが生成された時刻(Unix時間、ミリ秒)
RawSkeletonData.tracking_state
tracking_state: TrackingState = TrackingState.TrackedソーススケルトンのIKに由来するトラッキング状態
RawSkeletonData.positions
positions: list[Vec3] = [Vec3(x=0.0, y=0.0, z=0.0), ...] # 25 elementsノードごとの位置(25要素)。インデックスはSkeletonNodeを参照してください
RawSkeletonData.rotations
rotations: list[Quaternion] = [Quaternion(w=1.0, x=0.0, y=0.0, z=0.0), ...] # 19 elementsノードごとの回転(19要素)。インデックスはSkeletonRotationNodeを参照してください
RawSensorData
from contactglovesdk import RawSensorData片手分の生センサーのTransformデータを保持するデータクラス
OSCアドレス/DS2/HC/RawSensorTransformsから受信したデータに対応します。各Transformは、/DS2/HC/HandSkeletonと同じ右手系のmodel-rooted空間で表されます。位置はwristを原点とするセンサーの中心位置で、回転はセンサーのローカル座標系からmodel-rooted空間への向きです。
レコードの構成(片手ごとに39フィールド):
string id, int is_left,
int generated_at_ms_hi, int generated_at_ms_lo,
float[35] # 5 sensors × (p_x, p_y, p_z, q_w, q_x, q_y, q_z)transforms[i]はRawSensorIndex(i)に対応します(5要素。親指、人差し指、中指、薬指、小指の順)。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
str | id | グローブID |
bool | is_left | 左手かどうか |
int | timestamp_ms | フレームが生成された時刻(Unix時間、ミリ秒) |
list[Transform] | transforms | センサーごとの位置と回転(片手5要素)。インデックスはRawSensorIndexを参照してください |
RawSensorData.id
id: str = ""グローブID
RawSensorData.is_left
is_left: bool = False左手かどうか
RawSensorData.timestamp_ms
timestamp_ms: int = 0フレームが生成された時刻(Unix時間、ミリ秒)
RawSensorData.transforms
transforms: list[Transform] = [Transform(position=Vec3(x=0.0, y=0.0, z=0.0), rotation=Quaternion(w=1.0, x=0.0, y=0.0, z=0.0)), ...] # 5 elementsセンサーごとの位置と回転(片手5要素)。インデックスはRawSensorIndexを参照してください
RetargetProfileInfo
from contactglovesdk import RetargetProfileInfoリターゲットプロファイルの情報を運ぶ応答を保持するデータクラス。
OSCアドレス/DS2/HC/HandSkeleton/Profileから受信したデータに対応します。
statusは0(存在する)、1(UUIDは有効だが該当するプロファイルが存在しない)、2(不正な問い合わせ)のいずれかです。
パブリック属性
| 型 | 名前 | 説明 |
|---|---|---|
int | request_id | リクエストとその応答を対応付ける、クライアントが指定した値 |
str | profile_uuid | リターゲットプロファイルのUUID(statusによります) |
int | status | プロファイル情報の取得結果(0、1、2) |
str | name | ユーザーに表示するプロファイル名 |
str | description | プロファイルの説明 |
RetargetProfileInfo.request_id
request_id: int = 0リクエストとその応答を対応付ける、クライアントが指定した値
RetargetProfileInfo.profile_uuid
profile_uuid: str = ""リターゲットプロファイルのUUID(statusによります)
RetargetProfileInfo.status
status: int = 0プロファイル情報の取得結果(0、1、2)
RetargetProfileInfo.name
name: str = ""ユーザーに表示するプロファイル名
RetargetProfileInfo.description
description: str = ""プロファイルの説明
Transform
from contactglovesdk import Transform位置と回転を組み合わせたTransform
RawSensorData.transformsの各要素として使われます。
パブリック属性
Transform.position
position: Vec3 = Vec3(x=0.0, y=0.0, z=0.0)位置
Transform.rotation
rotation: Quaternion = Quaternion(w=1.0, x=0.0, y=0.0, z=0.0)回転
Vec3
from contactglovesdk import Vec33次元ベクトル
パブリック属性
Vec3.x
x: float = 0.0X成分
Vec3.y
y: float = 0.0Y成分
Vec3.z
z: float = 0.0Z成分
Quaternion
from contactglovesdk import Quaternion回転を表すクォータニオン
パブリック属性
Quaternion.w
w: float = 1.0スカラー成分
Quaternion.x
x: float = 0.0X成分
Quaternion.y
y: float = 0.0Y成分
Quaternion.z
z: float = 0.0Z成分
ContactGloveSDKError
from contactglovesdk import ContactGloveSDKErrorclass ContactGloveSDKError(Exception)SDKが発生させる例外の基底クラス
SDKNotAvailableError
from contactglovesdk import SDKNotAvailableErrorclass SDKNotAvailableError(ContactGloveSDKError)ローカルのUDPソケットを開けなかったとき(ポートが使用中の場合など)に発生します
NotConnectedError
from contactglovesdk import NotConnectedErrorclass NotConnectedError(ContactGloveSDKError)接続が必要な操作を、その接続が存在しない状態で行おうとしたときに発生します
InvalidIDError
from contactglovesdk import InvalidIDErrorclass InvalidIDError(ContactGloveSDKError)指定したグローブIDのデータが現在のデータストアに存在しないときに発生します