ユーザーマニュアル

このマニュアルは、ContactGlove ROS2 SDK V2の配布パッケージを使うための手順書です。 グローブのデータを配信するブリッジと、別PC・コンテナで購読するためのメッセージ単独パッケージのインストール方法を説明します。 DivingStationへの接続、データ取得・可視化・振動・ロボット連携の手順も記載しています。

パラメータ一覧、全トピック一覧、メッセージフィールド、QoS、座標軸やTF命名の完全な仕様はAPIリファレンスを参照してください。

できること

ブリッジはDivingStationに接続し、次の機能を提供します。

  • 左右のグローブ情報、指関節角度、25関節スケルトン、raw sensor transform、 コントローラー入力をROS2トピックとして取得
  • グローブIDを指定して振動コマンドを送信
  • RViz2でリターゲット後のSkeletonを表示
  • JointStateと同梱URDFを使ってRobotModelを表示
  • リターゲット後のSkeletonとURDFを同じRViz2画面で比較
  • namespaceと受信ポートを分けて複数ノードを運用

接続はノード起動時に自動で行われ、ノード終了時に切断されます。無通信時の再接続は try_reconnect で制御できます。

インストール

対応環境

  • ContactGlove3 Pro(ContactGlove3 ではブリッジにデータが届きません)
  • Ubuntu 22.04 LTS (Jammy) + ROS2 Humble + amd64(x86-64)
  • Ubuntu 24.04 LTS (Noble) + ROS2 Jazzy + amd64(x86-64)

OSとROS2の組み合わせに合う配布ZIPを使用してください。ARM64や上記以外のOS・ROS2は、この配布物の対象外です。 ROS2とそのAPTリポジトリを設定済みの環境で、ZIPを展開したディレクトリからインストールします。 配信側と購読側では、同じROS2ディストリビューションと互換性のあるメッセージ定義を使用してください。

用途に合うパッケージを選ぶ

ZIPには、同じROS2ディストリビューション向けの3つのDEBが入っています。ルートにbridgeとmsgs、lib/にC++ランタイムがあります。

  • 配信側では contactglove-ros2-bridge、contactglove-ros2-msgs、contactglove-sdk-v2 の3つをインストールします。bridgeはドライバーと可視化機能、msgsは contact_glove_msgs を提供します。配信側にはDivingStationも必要です。
  • 別PC・コンテナの購読側では contactglove-ros2-msgs だけをインストールします。DivingStationとC++ランタイムは不要です。ZIPの install/ はsourceしません。

bridgeとmsgsのファイル所有権は分離されており、配信側では両方をインストールします。 aptは隣にあるDEBや lib/ 内のランタイムを自動探索しません。「ブリッジ: 配布ZIPに同梱されたDEBを使用する(推奨)」のコマンドで必要なファイルを明示してください。

購読専用: メッセージ単独DEBをインストールする

contactglove-ros2-msgs は、contact_glove_msgs の9種類のメッセージと GetRetargetProfile サービス定義、 生成済みのC/C++・Pythonインターフェース、型サポート、ament/CMake情報を含みます。 このパッケージだけでグローブに接続したり、デバイスのデータを配信したりすることはできません。 データの配信側では、DivingStationとブリッジを起動しておく必要があります。

sudo apt update
sudo apt install ./contactglove-ros2-msgs_*.deb

# Ubuntu 24.04 / Jazzy
source /opt/ros/jazzy/setup.bash
# Ubuntu 22.04 / Humbleでは、上の代わりに次を実行する
# source /opt/ros/humble/setup.bash

ros2 pkg prefix contact_glove_msgs
ros2 interface show contact_glove_msgs/msg/GloveData
ros2 interface show contact_glove_msgs/srv/GetRetargetProfile
python3 -c 'from contact_glove_msgs.msg import GloveData; print(GloveData())'

新しいターミナルでは、使用するROS2のsetupファイルをsourceしてください。 購読側では、C++ランタイムのインストール補助スクリプトを実行せず、ZIP内の install/setup.bash もsourceしません。 同じメッセージを含む別のワークスペースを重ねてsourceすることも避けてください。

Pythonの購読プログラムには ros-<distro>-rclpy、C++の購読プログラムのビルドには ros-<distro>-rclcpp とCMakeなどの開発ツールを別途導入してください。 <distro> は humble または jazzy です。CMakeでは find_package(contact_glove_msgs REQUIRED) を使用します。 トピック名と型はAPIリファレンスを参照してください。

別PC・コンテナから購読する場合は、配信側と同じ ROS_DOMAIN_ID を指定し、DDSの探索ができるネットワークを使用します。 コンテナのネットワーク設定とファイアウォールも確認してください。 「配信を確認する」のコマンドで受信を確認できます。QoSは配信側に合わせます。

以降のブリッジのインストールと起動の手順は、配信側のPC・コンテナで行います。

ブリッジ: 配布ZIPに同梱されたDEBを使用する(推奨)

ブリッジにはContactGlove C++/C/Rust SDK V2ランタイム0.4.4とDivingStation v2以降が必要です。 DivingStationとの通信にはProtocol v2を使用します。

配布ZIPを展開したディレクトリで実行します。ZIPルートの contactglove-ros2-bridge_*.deb を使うと、現在のROS2環境へ直接インストールできます。

sudo apt update
sudo apt install ./lib/contactglove-sdk-v2_*.deb \
  ./contactglove-ros2-msgs_*.deb ./contactglove-ros2-bridge_*.deb

# インストール後にsourceする。Humbleの場合は /opt/ros/humble/setup.bash を使用する
source /opt/ros/jazzy/setup.bash

ContactGlove ROS2 SDK V2のdebをaptでインストールすると、RViz2、xacro、robot_state_publisherなどの 実行時依存も自動的にインストールされます。異なるROS2ディストリビューション向けの debを混在させないでください。新しいターミナルでは、使用するROS2のsetupファイルをsourceします。

旧一体型ブリッジ(0.2.2以前)からの更新

起動中のContactGloveノードを停止し、旧ZIPをsourceしたターミナルを閉じます。使用するROS2とOSに対応する新しいZIPを別ディレクトリに展開し、展開したZIPのルートから以下を実行してください。bridgeが更新され、版を限定したDebianの Breaks / Replaces によりメッセージのファイル所有権がmsgsへ移ります。force-overwriteや /opt/ros/ 内のファイルの手動削除は不要です。

sudo apt update
sudo apt install ./lib/contactglove-sdk-v2_*.deb \
  ./contactglove-ros2-msgs_*.deb ./contactglove-ros2-bridge_*.deb

旧配信側を購読専用へ変更する場合は、先にbridgeを削除してからmsgsだけをインストールします。

sudo apt remove contactglove-ros2-bridge
sudo apt install ./contactglove-ros2-msgs_*.deb

ブリッジ: DEBの代わりに配布ZIPのinstallディレクトリを使用する

ContactGlove ROS2 SDK V2をシステムへインストールせず、配布ZIP内の install/ をsourceして使う方法です。

# Humbleの場合は /opt/ros/humble/setup.bash を使用する
source /opt/ros/jazzy/setup.bash

# 可視化機能を使う場合のみインストールする
sudo apt install ros-${ROS_DISTRO}-rviz2 ros-${ROS_DISTRO}-xacro ros-${ROS_DISTRO}-robot-state-publisher

# 同梱のContactGlove C++/C/Rust SDK V2ランタイムをインストールする
bash scripts/install_contactglove_sdk_deb.sh

# 配布ZIP内のROS2パッケージを有効化する
source install/setup.bash

新しいターミナルを開くたびに、ROS2のsetupと install/setup.bash を この順番でsourceしてください。トピック配信だけを使う場合、RViz2・xacro・ robot_state_publisherは不要です。

ブリッジのインストールを確認する

ros2 pkg prefix contact_glove
ros2 pkg prefix contact_glove_msgs
ros2 pkg executables contact_glove

2つのパッケージと contact_glove_node / contact_glove_rviz_node が表示されれば準備完了です。

インストールされる文書

メッセージ単独DEBは、最小導入手順のREADME日英とライセンス文書を /opt/ros/<distro>/share/contact_glove_msgs/ に配置します。 ブリッジDEBでは /opt/ros/<distro>/share/contact_glove/ にも配置します。 詳しいガイドとこのユーザーマニュアルは、このサイトで管理します。

基本的な使い方

DivingStationを同じPCで起動している場合

DivingStationでグローブを接続してから、次を実行します。

ros2 launch contact_glove contact_glove.launch.xml

既定ではDivingStationの 127.0.0.1:25791 へ接続し、 ROS2ノードはUDPポート 25788 でデータを受信します。

DivingStationを別PCで起動している場合

信頼できるLANを使用してください。DivingStationのSDK / Protocolで待受範囲をLAN に公開にします。 待受範囲を変更した場合は、DivingStationを再起動してください。既定のこのコンピューターのみでは、別のPCから接続できません。LANに公開した場合、既定の接続承認設定では別のPCからの接続に承認が必要です。同じPCからの接続は自動で許可されます。

ds_ip にDivingStationを起動しているPCの数値IPアドレスを指定します。

ros2 launch contact_glove contact_glove.launch.xml ds_ip:=192.168.1.100

接続承認が必要な設定では、DivingStationに表示される接続要求を許可してください。

DivingStationの待受ポート(既定25791)を ds_port に指定します。

ros2 launch contact_glove contact_glove.launch.xml \
  ds_ip:=192.168.1.100 \
  ds_port:=25791

ds_port はDivingStation側の受信ポート、 receive_port はROS2ノード側のコールバック受信ポートです。 両方のPCの実際の受信ポートで、必要なUDP通信を許可してください。同じPCで複数のSDKノードを使う場合は、 ノードごとに重複しない receive_port を指定します。

SDKからDivingStationへ送るOSCパケットの送信元ポートは send_port で指定できます。 既定の send_port=0 ではOSが空きポートを選びます。送信元ポートを指定する必要が ある場合は指定してください。自動タイムアウト時はDisconnectせず、同じsocketからConnectを再送するため、 OSが選んだ送信元ポートと承認待ちを維持します。

DivingStationは、接続中のセッションを送信元UDP endpoint と receive_port の組で識別します。 明示的なDisconnectまたは最終Connectから90秒経過でセッションは失効するため、ポートを固定しても 次回接続時の承認は引き継がれません。

# 送信元ポートとコールバック受信ポートを固定したい場合
ros2 launch contact_glove contact_glove.launch.xml \
  receive_port:=25788 \
  send_port:=25789

複数のSDKノードを同じPCで使う場合は、ノードごとに重複しない receive_port を割り当ててください。 正確な意味と既定値はAPIリファレンスの「ノードパラメータ」を参照してください。

配信を確認する

まずトピック一覧を確認します。

ros2 topic list

代表的なデータは次のように確認できます。

ros2 topic echo --qos-durability transient_local /contact_glove/left/glove_data
ros2 topic echo --qos-profile sensor_data /contact_glove/left/ergonomics
ros2 topic echo --qos-profile sensor_data /contact_glove/left/skeleton
ros2 topic echo --qos-profile sensor_data /contact_glove/left/raw_skeleton
ros2 topic echo --qos-profile sensor_data /contact_glove/left/controller
ros2 topic echo /contact_glove/left/joint_states

右手は left を right に読み替えます。 namespaceを変更した場合は contact_glove も使用中のnamespaceへ変更します。

glove_dataは起動前の最新状態を受け取るためtransient localを指定します。 ergonomics、skeleton、raw skeleton、raw sensor transform、controllerはsensor data QoSを使用します。 完全なトピック一覧とQoSはAPIリファレンスの「トピック一覧」を参照してください。

Retarget profileを照会する

Skeleton.profile_uuid の表示名・説明が必要な場合は、UUIDを指定してサービスを呼びます。 非同期のrequest IDはノードが内部で管理するため、利用者が相関処理を行う必要はありません。

ros2 service call /contact_glove/get_retarget_profile \
  contact_glove_msgs/srv/GetRetargetProfile \
  "{profile_uuid: '00000000-0000-4000-8000-000000000001'}"

存在するprofileは status: 0(STATUS_FOUND)と name / description を返します。 有効形式だが存在しないUUIDは status: 1、UUID形式が不正でC++ SDKが送信を拒否した場合は status: 4 です。DivingStationからプロトコル上の無効な問い合わせを示す応答(status 2)を受信した場合、 ブリッジはprofile情報を空にして status: 2 を返します。現行C++ SDKは送信前にUUIDを検証するため、 このサービスへ不正なUUIDを渡した場合は通常 status: 4 となります。 DivingStationから応答がなければ既定1秒で status: 3 になります。 待機時間はlaunch時に変更できます。

ros2 launch contact_glove contact_glove.launch.xml \
  retarget_profile_timeout_ms:=3000

可視化

リターゲット後のSkeletonをRViz2で表示する

ros2 launch contact_glove contact_glove_with_rviz.launch.xml

リターゲット後のSkeletonは、左手を青、右手を赤のMarkerArrayとして表示します。RViz2を起動せず、 変換ノードだけを使う場合は次のようにします。

ros2 launch contact_glove contact_glove_with_rviz.launch.xml enable_rviz2:=false

既定表示の左右の手首位置は動作確認用のプレースホルダであり、 実際の手首6DoFではありません。

URDFハンドモデルを表示する

JointStateと同梱URDFをrobot_state_publisherへ入力し、RViz2のRobotModelで表示します。

ros2 launch contact_glove contact_glove_with_urdf.launch.xml hand:=both

hand:=left または hand:=right で片手だけを表示できます。

リターゲット後のSkeletonとURDFを同時に表示する

ros2 launch contact_glove contact_glove_with_urdf_and_rviz.launch.xml hand:=both

同時表示ではこのcombined launchを使用してください。 contact_glove_with_rviz.launch.xml と contact_glove_with_urdf.launch.xml を既定設定のまま別々に起動すると、 両方がドライバーを起動して同じreceive_portへのbindが衝突します。

既に別のlaunchからドライバーを起動している場合は、追加する可視化launchへ start_driver:=false を指定できます。

実際の手首位置へ追従させる

リターゲット後のSkeleton表示ではプレースホルダ手首TFを無効にします。

ros2 launch contact_glove contact_glove_with_rviz.launch.xml \
  publish_placeholder_wrist_tf:=false

外部トラッカー側から、parent_frame_id で指定したフレームから 対象グローブのwristフレームへのTFを配信してください。

URDF表示では publish_wrist_placement:=false を指定し、 外部ノードから左右URDFのwristフレームへのTFを配信します。

フレーム名、namespace prefix、座標系、回転規約はAPIリファレンスの 「メッセージの座標系」「TF frame名の命名規則」「JointState + URDF」を参照してください。

複数構成で使う

複数のDivingStationまたは複数ノードを使う

ROS2トピックはnamespaceで分離し、同じPC上の各ノードには異なる receive_port を割り当てます。

ros2 launch contact_glove contact_glove.launch.xml \
  namespace:=station_a \
  ds_ip:=192.168.1.100 \
  receive_port:=25788

ros2 launch contact_glove contact_glove.launch.xml \
  namespace:=station_b \
  ds_ip:=192.168.1.101 \
  receive_port:=25789

この例ではトピックが /station_a/... と /station_b/... に分かれます。namespaceはUDPソケットを分離しないため、 同じPCでreceive_portを重複させることはできません。別々のPCでノードを動かす場合は、 各PCで同じポート番号を使用できます。

同じ側に複数グローブがある

glove_data、ergonomics、skeletonなどの通常トピックでは、同じ側の複数グローブが 同じトピック上に配信されます。メッセージの id で識別してください。

一方、left/joint_states / right/joint_states は 1台分のURDFモデル用です。対象IDを指定しない場合、その側で最初に受信したグローブを選択します。 固定する場合は次のように起動します。

ros2 launch contact_glove contact_glove_with_urdf.launch.xml \
  hand:=left \
  left_joint_state_glove_id:=YOUR_LEFT_GLOVE_ID

同じ側の複数グローブを別々のURDFで表示する場合は、グローブごとにノードを起動し、 異なるnamespace・receive_port・対象IDを指定します。

ros2 launch contact_glove contact_glove_with_urdf.launch.xml \
  namespace:=glove_a \
  receive_port:=25788 \
  hand:=left \
  left_joint_state_glove_id:=GLOVE_ID_A

ros2 launch contact_glove contact_glove_with_urdf.launch.xml \
  namespace:=glove_b \
  receive_port:=25789 \
  hand:=left \
  left_joint_state_glove_id:=GLOVE_ID_B

対象IDはglove_dataの id で確認できます。 選択規則と各パラメータの仕様はAPIリファレンスの 「同じサイドに複数グローブがある場合」を参照してください。

振動させる

まずglove_dataで、対象のID、接続状態、振動対応の有無を確認します。

ros2 topic echo --qos-durability transient_local /contact_glove/left/glove_data

確認した実際のIDを指定して振動コマンドを送ります。

ros2 topic pub --once \
  /contact_glove/left/haptics_body \
  contact_glove_msgs/msg/HapticsBody \
  "{id: 'YOUR_GLOVE_ID', frequency: 200.0, amplitude: 0.8, duration: 0.5}"

右手はトピックの left を right に変更します。 周波数・振幅・時間の有効範囲はAPIリファレンスまたは次のコマンドで確認できます。

ros2 interface show contact_glove_msgs/msg/HapticsBody

ロボットシステムへ統合する

一般的なROS2ロボットスタックへは、次のインターフェースを使用します。

  • left/joint_states / right/joint_states
  • 同梱の左右URDF
  • robot_state_publisher

JointStateはErgonomicsの度単位の値をラジアンへ変換したものです。 joint名、並び順、左右の扱い、QoS、URDFのjoint軸はAPIリファレンスの 「JointState + URDF」を参照してください。

25関節TFはリターゲット後のSkeletonの位置・回転を確認するデバッグ機能です。 URDFの関節階層による統合にはJointStateとURDFを使用してください。

トラブルシューティング

メッセージ単独DEBをインストールできない

OS・ROS2・CPUアーキテクチャが配布物の対応環境と一致しているか確認してください。 旧一体型bridge(0.2.2以前)がある場合は、上記の更新手順を使用してください。新bridgeには同じ版のmsgsが必要です。bridgeのインストールでは3つのローカルDEBをaptへ渡します。aptは隣のファイルを自動探索しません。

別PC・コンテナのトピックが見つからない

配信側でブリッジが起動し、ローカルでトピックが見えることを確認してください。 購読側ではROS2のsetupをsourceし、配信側と ROS_DOMAIN_ID を合わせます。 DDSの探索・通信を妨げるコンテナのネットワーク設定やファイアウォールがないかも確認してください。 メッセージ単独パッケージには、DivingStationへ接続するドライバーは含まれません。

ブリッジから何もpublishされない

次を確認してください。

  • DivingStation v2以降が起動している
  • DivingStation上でグローブが接続済み
  • 配信側でROS2と、DEBを使わずZIP内のブリッジを利用する場合のinstall/setup.bashをsource済み
  • ds_ip と ds_port がDivingStationの設定と一致
  • ROS2ノード側の receive_port が他プロセスと重複していない
  • ファイアウォールでUDP通信がブロックされていない

別PCへ接続する場合、DivingStation側では既定の 25791/udp、 ROS2ノード側では既定の 25788/udp を許可します。

sudo ufw allow 25791/udp
sudo ufw allow 25788/udp

ポートを変更している場合は実際の値を許可してください。 DivingStationをWindowsで動かしている場合は、WindowsファイアウォールでDivingStationの受信を許可してください。

2つ目のノードが接続できない

同じPC上の2ノードへ同じreceive_portを指定すると、2つ目のUDP bindが失敗します。 25788、25789 のように異なる値を指定してください。 namespaceを変えるだけでは解決しません。

トピックはあるがデータを確認できない

購読側のQoSを確認してください。

  • glove_data: transient localを指定
  • ergonomics、skeleton、raw sensor transform、controller: sensor data QoSを指定
  • joint_states、haptics、skeleton markers: reliable互換のQoSを使用

正確なQoSはAPIリファレンスの「トピック一覧」を参照してください。

RViz2にスケルトンが表示されない

次を確認してください。

  • 使用中namespaceのskeletonとskeleton_markersがpublishされている
  • RViz2のFixed Frameがworld、または指定したparent_frame_idになっている
  • プレースホルダ表示を使う場合はpublish_placeholder_wrist_tfがtrue
  • MarkerのTopicが使用中namespaceのskeleton_markersになっている

左右の手の位置が実際の位置と違う

既定表示は左右を並べて確認するためのプレースホルダです。 実際の手首位置を使う場合は「実際の手首位置へ追従させる」の手順で プレースホルダを無効にし、外部トラッカーからTFを配信してください。

振動しない

次を確認してください。

  • HapticsBody.idがglove_data.idと一致
  • is_hapticsがtrue
  • connected_stateが接続済み
  • frequency、amplitude、durationが有効範囲内
  • 対象デバイスがDivingStation上で接続済み