はじめに
プログラミングの勉強を始めた頃は、プログラム書いたは良いけどターミナルから値を入力するのダサすぎ…って思ってたものです。
電気回路の知識がちょっと増えるにつれて、押しボタンスイッチとかジョイスティックを押したのを検知してプログラムを起動できるようになりましたが、今回はUbuntuやラズパイ上で動いているプログラムにPS4のコントローラから数値入力を渡す方法を模索したいと思います。
「PS4 Linux」で検索するとPCゲームのコントローラにPS4コントローラを使う方法が出てきますが、今回は自分で作ったプログラムにコントローラの値を受け渡す方法です。
意外と情報が少ない
ROSを使っていれば、PS4コントローラでコントロールする方法は簡単に見つかります。pythonの「ds4drv」でコントローラとPCを接続して、ROSのjoy_nodeで値を読み込んでjoyトピックで出してくれるのでそれを使うだけです。
しかし、ROSを使ってないシステムでコントローラの値を使いたいときはどうすれば良いんじゃ…ってことで探してみました。
やり方
環境:
Ubuntu 16.04、ラズパイ(Jessie)
コントローラをPCと接続するところまでは「ds4drv」を使います。次のコマンドをターミナルに入力してインストール、起動します。
sudo pip install ds4drv sudo ds4drv
起動したらPS4コントローラの「PSボタン」と「SHAREボタン」を青のランプがカチカチッと早い点滅をするまで同時に押します。成功すると「connected」的なのがターミナルに出ると思います。
続いて値の表示ですが、こちらのページにサンプルプログラムと解説がありましたがヘッダ等がありませんでしたので、色々調べた結果コンパイルできるようになったものを載せます。
#include <linux/joystick.h> #include <linux/input.h> #include <unistd.h> #include <fcntl.h> #include <iostream> #define BUTTON_DATA_MAX 100 #define STICK_DATA_MAX 100 int fd= open( "/dev/input/js0", O_RDONLY ); unsigned char ButtonData[BUTTON_DATA_MAX]; signed int StickData[STICK_DATA_MAX]; int main(int argc, char** argv){ for(;;){ struct js_event event; if( read( fd, &event, sizeof(struct js_event) ) >= sizeof(struct js_event) ){ switch( event.type & 0x7f ){ case JS_EVENT_BUTTON: if( event.number < BUTTON_DATA_MAX ){ ButtonData[ event.number ]= event.value != 0; std::cout << event.value << std::endl; } break; case JS_EVENT_AXIS: if( event.number < STICK_DATA_MAX ){ StickData[ event.number ]= event.value; } break; } } } close( fd ); }
これをds4.cppに保存してg++でコンパイル
g++ ds4.cpp
すればいけるはずです。
ちなみにjoystick.hの場所は僕の環境では/usr/include/linux/joystick.hでした。
出力ファイルa.outができていると思うので実行すると、ボタンを押したタイミングで1が出力されるはずです。
ppdr@raspberrypi:~ $ ./a.out 0 0 0 0 1 0
あとは値を表示するなり他のプログラムにパイプで渡したり自由にどうぞ。
./a.out | ./my_program.exe
プログラムの内容は全然追えていませんが、event.numberがボタンの種類、event.valueがボタンの値を示すみたいです。この辺はどうなってるかまだ把握していないので、std::coutしてみてご確認ください。
この辺の情報をご存知の方は教えていただけると幸いですm(_ _)m