この記事では、「Raspberry Pi 3 MODEL B」とpythonライブラリ「PyGame」を使用して作成した、PS4コントローラ(以下、「DS4」とします)のボタン入力を解釈するアプリケーションを紹介します。
1. アプリケーション概要
- [アプリケーション]
https://github.com/hotsmmr/RwRP/blob/master/notebooks/interpret_input_from_ds4_test.ipynb
本アプリケーションは、DS4の入力信号を解釈し、ボタンの種別と押下状態を識別するものです。
ボタンの種別は全13種、押下状態は押す/離すの2種類に対応しています。
本アプリケーションは、「LGPL」の原文(日本語訳)で明記されている『ライブラリ』を利用する著作物」に該当するため、ライセンス「LGPL」ではなく、「MIT License」で公開しています。(参考)GNU LESSER General Public License(日本語訳)
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/離す
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_current_botton |
メソッド名(和名) | (押された)ボタン種別解釈 |
処理概要 | 1. 入力デバイスからのイベントから、(押された)ボタン種別を解釈する |
入力 | なし(ライブラリ「pygame」の参照メモリ) |
出力(復帰値) | return_botton: (押された)ボタン種別(値域[0,14]) |
特記事項 | 1. 入力デバイスは「DS4」を想定している |
2. joy_stick.get_button関数の復帰値が”True”となる引数の値が(押された)ボタン種別に該当する |
2-4-2. OperateBotton
(スーパークラス)
(サブクラス)
このブロックでは、クラス「InterpretGamePad」で取得したボタン種別ごとの機能を定義した「OperateBotton」を定義します。
スーパークラスでクラス構造を定義し、サブクラスでボタン種別ごとの機能を定義します。
クラス内メソッドの概要は以下の通りです。
メソッド名 | __init__ |
メソッド名(和名) | コンストラクタ |
処理概要 | なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる) |
入力 | なし |
出力 | なし(ログ出力のみ) |
特記事項 | 1. 「Class({クラス名}) init」とログ出力する |
2. 処理内容は任意に変更する |
(ログ出力例)
メソッド名 | press_botton |
メソッド名(和名) | ボタン押された際の振る舞い |
処理概要 | なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる) |
入力 | なし |
出力 | なし(ログ出力のみ) |
特記事項 | 1. 「{クラス名}.{メソッド名} called」とログ出力する |
2. 処理内容は任意に変更する |
メソッド名 | release_botton |
メソッド名(和名) | ボタン離された際の振る舞い |
処理概要 | なし(サブクラスでは、スーパークラスの同メソッドが呼ばれる) |
入力 | なし |
出力 | なし(ログ出力のみ) |
特記事項 | 1. 「{クラス名}.{メソッド名} called」とログ出力する |
2. 処理内容は任意に変更する |
(ログ出力例)
2-5. Create Instance
このブロックでは、前ブロックで定義したクラス「InterpretGamePad」「OperateBotton」のインスタンスを生成します。
クラス「OperateBotton」のインスタンスは配列に格納し、ボタン種別をインデックスとして、ボタン種別に対応したインスタンスを取得できるようにします。
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 3 MODEL Bを対象に、ロボット製作に適した開発環境のセットアップ手順を紹介します。 このセットアップ手順を実行することで、以下の記事で紹介したようなロボット用のプログラミングが可能になりま[…]