PS4コントローラ入力解釈アプリケーション作成(Raspberry Pi 3B + PyGame)

この記事では、「Raspberry Pi 3 MODEL B」とpythonライブラリ「PyGame」を使用して作成した、PS4コントローラ(以下、「DS4」とします)のボタン入力を解釈するアプリケーションを紹介します。

1. アプリケーション概要

本アプリケーションでは、ライセンス「LGPL」で公開されている「PyGame」を動的リンクしています。
本アプリケーションは、「LGPL」の原文(日本語訳)で明記されている『ライブラリ』を利用する著作物」に該当するため、ライセンス「LGPL」ではなく、「MIT License」で公開しています。(参考)GNU LESSER General Public License(日本語訳)
広告
「interpret_input_from_ds4_test.ipynb」の各ブロックの解説は次章以降で行います。

2. アプリケーション解説

2-1. Import Libraries


このブロックでは、pythonの標準ライブラリと「pygame Community」によって公開されているOSSのライブラリ「pygame」をアプリケーションで使用できるようにインポートします。

各ライブラリの用途は以下の通りです。

  • 「logging」: ログレベルの設定変更、実行・エラーログ出力に使用
  • 「sys」: 実行されたメソッド名の取得に使用
  • 「IntEnum」: ボタン種別、押下状態の定数定義時に使用
  • 「sleep」: DS4の入力信号を解釈する際のインターバルを実現するために使用
  • 「pygame」: DS4の入力信号を解釈するために使用

2-2. Define Constant Values


このブロックでは、ボタン種別、押下状態を分類できるように列挙型定数を定義します。

各列挙型定数の定義は以下の通りです。

  • 「Ds4BottonKey」:
    定義値 0 1 2 3 4 5 6 7
    ボタン X L1 R1 L2 R2
    定義値 8 9 10 11 12 13 14
    ボタン share options L3 R3 PSボタン touch_pad 未定義
  • 「BottonStatus」: 0/押す、1/離す
「DS4」以外の入力デバイスを使用する場合は、後述のpygame.joystick.Joystick関数の引数と復帰値(ボタン押下時)の対応関係を調べる必要があります。

2-3. Define Global Valiables


このブロックでは、ログ出力用のロガー、および取得したライブラリ「pygame」で取得したボタン種別、押下状態を格納するためのグローバル変数を定義します。

2-4. Define Classies

2-4-1. InterpretGamePad


このブロックでは、ライブラリ「pygame」を使用してDS4の入力信号を解釈するクラス「InterpretGamePad」を定義します。

クラス内メソッドの概要は以下の通りです。

メソッド名 __init__
メソッド名(和名) コンストラクタ
処理概要 1. メンバ変数定義、初期化
2. ライブラリ「pygame」の初期設定(メソッド「__init_pygame」の呼び出し)
入力 なし
出力 なし
特記事項 なし
メソッド名 get_current_botton_info
メソッド名(和名) ボタン情報(ボタン種別、押下状態)取得
処理概要 1. ボタン情報を出力する
入力(メンバ変数) 1. current_botton: (押された)ボタン種別(値域[0,14])
2. released_botton:(離された)ボタン種別(値域[0,14])
3. botton_status: 押下状態( 0/押された、1/離された)
出力(復帰値) 1. current_botton: (押された)ボタン種別(値域[0,14])
2. released_botton:(離された)ボタン種別(値域[0,14])
3. botton_status: 押下状態( 0/押された、1/離された)
特記事項 1. botton_statusが0の場合は、ユーザはcurrent_bottonをボタン種別として使用できる
2. botton_statusが1の場合は、ユーザはreleased_bottonをボタン種別として使用できる
メソッド名 interpret_current_event
メソッド名(和名) イベント解釈
処理概要 1. 入力デバイスからのイベントを解釈する
2. ボタンが押されたと解釈した場合、ボタン種別の解釈結果を(押された)ボタン種別に設定し、押下状態を0にする
3. ボタンが離されたと解釈した場合は、(押された)ボタン種別を(離された)ボタン種別に設定し、押下状態を1にする
さらに、(押された)ボタン種別を初期化する
入力 なし(ライブラリ「pygame」の参照メモリ)
出力(メンバ変数) 1. current_botton: (押された)ボタン種別(値域[0,14])
2. released_botton:(離された)ボタン種別(値域[0,14])
3. botton_status: 押下状態( 0/押された、1/離された)
特記事項 1. 入力デバイスは「DS4」を想定している
メソッド名 release_pygame
メソッド名(和名) ライブラリ「pygame」の解放
処理概要 1. ライブラリ「pygame」を解放する
入力 なし(ライブラリ「pygame」の参照メモリ)
出力(メンバ変数) なし(ライブラリ「pygame」参照メモリの解放)
特記事項 1. Pythonインタープリターがシャットダウンすると共にライブラリ「pygame」は解放されるため、必須ではない
メソッド名 __init_pygame
メソッド名(和名) ライブラリ「pygame」の初期化
処理概要 1. ライブラリ「pygame」を初期化する
入力 なし(ライブラリ「pygame」の参照メモリ)
出力 なし(ライブラリ「pygame」参照メモリの初期化)
特記事項 1. DS4以外の入力デバイスが接続されている場合は、pygame.joystick.Joystick関数の第一引数に与える数値を調整する必要がある
実行時のログ出力内容が「joystick name -> Sony Computer Entertainment Wireless Controller」となるように数値を調整する
2. 入力デバイスが接続されていない場合は、「joystick not found」とログ出力する

(ログ出力例)

interpret-game-pad-init-log

メソッド名 __interpret_current_botton
メソッド名(和名) (押された)ボタン種別解釈
処理概要 1. 入力デバイスからのイベントから、(押された)ボタン種別を解釈する
入力 なし(ライブラリ「pygame」の参照メモリ)
出力(復帰値) return_botton: (押された)ボタン種別(値域[0,14])
特記事項 1. 入力デバイスは「DS4」を想定している
2. joy_stick.get_button関数の復帰値が”True”となる引数の値が(押された)ボタン種別に該当する
ライブラリ「pygame」内のメソッドの詳細が知りたい方は、pygame documentationをご覧ください。

2-4-2. OperateBotton


(スーパークラス)

(サブクラス)

このブロックでは、クラス「InterpretGamePad」で取得したボタン種別ごとの機能を定義した「OperateBotton」を定義します。

スーパークラスでクラス構造を定義し、サブクラスでボタン種別ごとの機能を定義します。

クラス内メソッドの概要は以下の通りです。

メソッド名 __init__
メソッド名(和名) コンストラクタ
処理概要 なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる)
入力 なし
出力 なし(ログ出力のみ)
特記事項 1. 「Class({クラス名}) init」とログ出力する
2. 処理内容は任意に変更する

(ログ出力例)

operate-botton-class-init-log

メソッド名 press_botton
メソッド名(和名) ボタン押された際の振る舞い
処理概要 なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる)
入力 なし
出力 なし(ログ出力のみ)
特記事項 1. 「{クラス名}.{メソッド名} called」とログ出力する
2. 処理内容は任意に変更する
メソッド名 release_botton
メソッド名(和名) ボタン離された際の振る舞い
処理概要 なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる)
入力 なし
出力 なし(ログ出力のみ)
特記事項 1. 「{クラス名}.{メソッド名} called」とログ出力する
2. 処理内容は任意に変更する

(ログ出力例)

operate-botton-test-output-log

2-5. Create Instance

このブロックでは、前ブロックで定義したクラス「InterpretGamePad」「OperateBotton」のインスタンスを生成します。

クラス「OperateBotton」のインスタンスは配列に格納し、ボタン種別をインデックスとして、ボタン種別に対応したインスタンスを取得できるようにします。

クラス「InterpretGamePad」のインスタンス生成前には、「ds4drv」を使用して「DS4」と「Raspberry Pi」をBluetooth接続する必要があります。未接続の場合、コンストラクタから呼ばれる__init_pygame関数のログ出力が想定外(他のデバイス or 無効)なものになります。

2-6. InterpretGamePad and OperateBotton Functions Test


このブロックでは、以下のメソッドをテストします。

テスト用のループ処理は「PS4」ボタンが押された際に終了するように実装しています。

クラス名 メソッド名 テスト内容
InterpretGamePad interpret_current_event ボタンが押された/離された際に、妥当なログ出力が得られることをOperateBottonクラスの出力と共に確認する
get_current_botton_info 同上
OperateBotton press_botton 1. 押されたボタン種別に対応するメッセージ(※)がログ出力されることを確認する

(※)OperateBotton{ボタン名}.press_botton called

release_botton 押されたボタン種別に対応するメッセージ(※)がログ出力されることを確認する

(※)OperateBotton{ボタン名}.release_botton called

2-7. Post Process


このブロックでは、ライブラリ「pygame」の参照メモリを解放します。

広告

3. 記事内で使用している商品


4. 参考記事

4-1. Raspberry Piの環境整備


OSのインストール・初期セットアップ方法については、以下の記事をご覧ください。

関連記事

この記事では、Raspberry Piの購入後に実施する以下の2点について、書いています。 1. OS(Raspbian)インストール 2. 初期セットアップ この記事は以下のような方向けのものになります。 Raspberr[…]

raspberry-pi-initial-set-up

開発環境のセットアップ方法については、以下の記事をご覧ください。

関連記事

この記事では、Raspberry Pi 3 MODEL Bを対象に、ロボット製作に適した開発環境のセットアップ手順を紹介します。 このセットアップ手順を実行することで、以下の記事で紹介したようなロボット用のプログラミングが可能になりま[…]

make-jupyter-notebook
広告