VR徘徊(3) ゲームコントローラで亀を動かす

ROS2の環境に慣れる

前回に引き続いて、ROSを動かして行きます。

VR徘徊ではとりあえずの台車のステアリングにゲームコントローラを使います。将来はいろいろ考えるところはありますが、とりあえず手軽に試せるものとしてゲームコントローラで操舵します。

そのため、この辺をちゃんとしておきます。

背景

こういったものの操作にゲームコントローラは便利です。

以前作っていた「潜水艇」もステアリングはゲームコントローラです。進行方向の制御以外のことも1つのコントローラで出来るので便利です。とりあえず使うのには十分過ぎますし、何ならこれでずっとやっても良いくらいです。もっとも自分が「徘徊老人」になってしまった時、果してゲームコントローラを操作できるのかという心配はあります(伏線)。

その時に買ったゲームコントローラがいくつか手元にあるので、これを使うことにします。幸いにして、この世界で一番メジャーと言っても良い「DualShock3」が手元にあったので、これを使うことにします。

デバイスの準備

Orange Pi 5でUbuntuを起動して、ゲームコントローラをUSBに挿します。

特に何もしなくても、

# ls /dev/input/by-id/
usb-Sony_PLAYSTATION_R_3_Controller-event-if00	usb-Sony_PLAYSTATION_R_3_Controller-event-joystick

/dev/input/by-id/の下にデバイスが現れます。操作部分(ジョイスティック)のデバイスがusb-Sony_PLAYSTATION_R_3_Controller-event-joystickです。

基本的にこのことだけ把握してあれば十分です

いろんな情報を見ると、やれ/dev/input/js*というデバイスがどうこうとか、joistickユーティリティがどうこうとか書いてありますが、全部無視して下さい

どういうことかと言えば、上記のデバイスさえ存在していれば、ゲームコントローラは動きますし、/dev/input/js*というデバイスが作られなかったりするし、その関係でjoistickユーティリティとかは動きません。つまり何が起きるかと言えば、正しく動作する状態になっているはずなのに正しく動いてないと誤認することが起きます。

/dev/input/by-id/の下にデバイスが生えて来ていればそれで十分です。他のコントローラだと他の名前になっているかも知れませんが、それはそうだと言うだけなので気にしないで下さい。

ゲームコントローラnodeのインストール

ソース取得とbuild

ゲームコントローラが使えることを確認したら、ゲームコントローラnodeをインストールします。

これは、ゲームコントローラの情報を取得して、/joyというトピックにメッセージを流すためのnodeです。

ソースを取得します。その前に作業用のディレクトリを掘ります。ディレクトリは何でもいいのですが、今回はルンバを動かすこともあって、/create_wsというディレクトリにします。ルンバについて書かれた文書がそうなっていたというだけで、深い意味はありません。以後の作業で一貫していれば何でもいいです。

$ mkdir -p ~/create_ws/src
$ cd ~/create_ws/src
$ git clone -b ros2 https://github.com/ros-drivers/joystick_drivers.git
$ . ~/ros2_iron/local_setup.bash
$ cd joystick_drivers/
$ mv spaceenv .spaceenv
$ mv wiimote .wiimote
$  cd ..
$ colcon build --symlink-install

ゲームコントローラnodeのリポジトリは、https://github.com/ros-drivers/joystick_driversだということがわかります。

checkoutする時に、必ずros2ブランチを指定します。master(main)ブランチではありません

joystick_driversの下に入ってmvをしていますが、これは邪魔なドライバを除外するためです。

ちなみに、除外しているspacenavというのは、こんなの

wiimoteというのはこれ。

つまりWiiのゲームコントローラです。

これらを使いたければ除外する必要はありませんが、これらをbuildするためには別途ライブラリが必要となります。今回は必要ないしそもそも持ってもいないので、除外するだけです。

最後のcolconを入れるとbuildが始まりますが、残念ながらこのbuildは成功しないで止まります。diagnosticsというモジュールがないという意味のメッセージが出ます。

これはgiagnosticsというモジュールを入れてやれば良いわけですが、入れ方は2つあります。それは

  • ROS2の本体に追加する
  • ローカルワークスペース(この例では~/create_ws)に追加する

という方法です。どちらでも行けます。とりあえずは後者でやっておきます。前者でやるとROSの環境を再構築する必要があって時間がかかります。

とは言え、モジュールの性質を考えると前者の方が妥当(ローカルに入れると新しくワークスペース作るたびに持って来る必要がある)な気がするのですが、どうしてROS2の配布ソースの中に入っていないのかわかりません。私は前者で試した後に後者でも試しました。

そんなわけで、上記手順のcd ..の前に

$ git clone https://github.com/ros/diagnostics.git

というのを入れてやります。そうすれば、最後のbuildが無事成功します。

colconを使っていると「依存関係とかどうなるの?」とか「ディレクトリはどう扱っているの?」という疑問がわいて来るのですが、colconは

  • 依存関係はよしなにしてくれる
  • ディレクトリは深さ方向に探してよしなにしてくれる
  • buildした結果は起動したディレクトリの下に build, install, logの各ディレクトリを作り、それぞれ適当にやってくれる

ようになっています。ROS2本体がどこにあるかについては、colconを起動する前に$ . ~/ros2_iron/install/local_setup.bashとかやってますが、この中でいい感じに処理してくれています。

動作確認

buildが成功したら確認してみます。

$ . ./install/setup.bash
$ ros2 run joy joy_node

実はゲームコントローラのモジュールはいくつかあるのですが、ここで挙げた手順でやった場合はjoyを使うのが正しいようです。joy_linuxとか「らしい」感じのものがあるのですが、これは/dev/input/js*を使うものなので、動いてくれません。joyは内部でSDL2を使っていてSDL2はゲームコントローラのデバイスとして/dev/input/by-id/*を使います。この辺を間違えるとハマりますので注意しましょう。

これだけだと、

$ ros2 run joy joy_node
[INFO] [1702358906.872167151] [joy_node]: No haptic (rumble) available, skipping initialization
[INFO] [1702358906.872629143] [joy_node]: Opened joystick: Sony PLAYSTATION(R)3 Controller.  deadzone: 0.050000

と表示されるだけなので、トピックの内容を見てみます。

別コンソールを開いて、

$ . ~/ros2_iron/install/local_setup.bash
$ ros2 topic echo /joy

と入力してやると、

header:
  stamp:
    sec: 1702359078
    nanosec: 459662469
  frame_id: joy
axes:
- -0.0
- -0.0
- 1.0
- -0.0
- -0.0
- 1.0
buttons:
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
---

こんな感じのがずらーっと出て来ます。

ボタンを押したりジョイスティックを動かしたりすると、表示が変化します。これでめでたくゲームコントローラがROSで使えるようになりました。

joy → Twist変換を入れる

ゲームコントローラnodeが動くようになりましたが、このnodeから出て来るトピックはjoyという形式です。

sensor_msgs/Joy Message

これはゲームコントローラのnodeが扱うメッセージ形式なのですが、個々のボタンやジョイスティックの状態を通知します。

一方「亀」の方はTwistという形式のメッセージを使います。

geometry_msgs/Twist Message

Twistは「亀」だけではなく、ルンバ用のnodeでも使われています。Twistは台車のようなロボットの汎用制御メッセージ形式だと思えば、だいたい当ってます。メッセージを細かく読めば、linearは移動の方向、angularは姿勢のオイラー角のようです。

関係があることはわかりますが、そのまま使えるわけではないなということもわかると思います。

「亀」がjoyを解釈できるようにいじるのはどうかという話がありますが、それをやると

  • プログラムいじるのが面倒
    まぁ言うまでもなく
  • 「亀」の動作がjoyに依存してしまう
    そもそも今回のゴールは「亀」ではない
  • ゲームコントローラ以外のものはjoyを出すかどうかはわからない
    ゲームコントローラだけがモーション用UIではない

ということで、あまり素敵ではありません。

特に最初の方に「伏線」として「徘徊老人になってからゲームコントローラを使えるか」ということを書いていますが、この辺は人間工学的にいろいろなデバイスに交換する可能性があります。そうなると、joyを出すことが妥当かどうかということになります。それであるなら、「何だか知らないけどUIデバイスからのメッセージ」をTwistに変換してやるnodeを作ることにすれば、いろんな問題が解決してくれます。

まぁこの他にゲームコントローラからメッセージが出る頻度は結構高く、前述のros2 topicはずらーーっという感じでメッセージが流れます。頻度も高い上に量も多い。そして、リモコンだとするなら、これだけのメッセージを送信する必要があります。なるべく通信量を減らしたいところにこれはちょっと困りますね。そういった意味で、より低頻度で短いメッセージに変換するのは合理的です。

PlayStation-JoyInterface-ROS2を入れる

このためのモジュールとして今回は、

PlayStation-JoyInterface-ROS2

というのを使いました。そこで、

$ mkdir -p ~/create_ws/src
$ cd ~/create_ws/src
$ git clone https://github.com/HarvestX/PlayStation-JoyInterface-ROS2.git

という感じで取って来ます。

これで再度ワークスペースのbuildを行います。

$ cd ..
$ colcon build --symlink-install

多分、つつがなくbuildが成功すると思います。

buildするのはPlayStation-JoyInterface-ROS2だけなので、多分、

$ cd ..
$ colcon build --packages-select PlayStation-JoyInterface-ROS2 --symlink-install

という感じでモジュール単位の処理ができるはずだと思うのですが、エラーになったりならなかったりするので、モジュール単位のbuildはあまりいい感じじゃないです。

動かしてみる

さて、舞台装置が揃ったところで動かしてみましょう。

まず、「亀」を起動します。

$ . ~/ros2_iron/install/local_setup.bash
$ ros2 run turtlesim turtlesim_node

窓が開いて亀が表示されます。

次にゲームパッドを起動します。

$ . ~/create_ws/install/setup.bash
$ ros2 run joy joy_node

多分動いているでしょう。気になる人はros2 topicとかで確認してみて下さい。

teleopを起動します。

$ . ~/create_ws/install/setup.bash
$ ros2 launch p9n_bringup teleop.launch.py topic_name:=/turtle1/cmd_vel hw_type:="DualShock3"

コマンドラインの意味は置いておいて、ゲームコントローラの左レバーを動かすと、移動したり向きを変えたりします。

いろいろ動いてくれました。めでたし、めでたし

まとめ

今回はいろいろつまづきながらも、ちゃんと亀が動くところまで到達しました。

実は結構ハマってたのですが、これが最初のデバイスの認識あたりで、これ以外は実はすんなりと言うか公式ドキュメントやネットの情報からで解決できました。

次はこれを実機(ルンバ)で動かすわけですが、その前に

  • StereoPiにROSをインストールする
  • なんとなくハードウェアをちゃんとさせる
  • ネットワークをどうするか検討する

という作業が入ります。この辺もまたstep by stepでやって行きます。

最近のエントリー

404 WASP not found

第12回 「パーソナルサーバ」について考える

Jar Gardenに植物を植える

新しいお友達

Google翻訳、ChatGPT、Gemini...

Node.jsでGemini 1.5 FlashをAPI経由で使う

今日は「ぴろろんの日」

Node.jsでGPT-4oをAPI経由で使う

遠隔手話通訳実験

LLMと戯れてみる

新刊情報の収集

最近のできごと

Hieronymusのインボイス番号対応について

会計システム「Hieronymus」の現状

OrangePi5にZabbixをインストールする

オープンソースのノートアプリ「SiYuan」 - CasaOS AppStoreレビュー

お気に入りの色さがし1

創立記念日

SPDX License Listをデータ化した

Orange Pi5でC3TR-Adapterを試す