はじめに
以前 Linux Input Subsystem を使ってキーボードの入力イベントを取得して,カムロボの操作を試みた.
確かにキーボードイベントは取得できたが,キーボードでは ON/OFF の操作しかできず,カムロボの移動速度の調整が難しく,変速ボタンを実装して無理やり対応していた.
今回は移動速度を調整できるようゲームパッドの入力イベント取得方法を模索する.
pygame 導入
ゲームパッド
今回使うゲームパッドはこれ.
https://amzn.to/3V6fCCa
Xbox のパッドとして認識されてる様子.
$ cat /proc/bus/input/devices
I: Bus=0003 Vendor=045e Product=028e Version=0114
N: Name="Microsoft X-Box 360 pad"
P: Phys=usb-0000:00:14.0-8/input0
S: Sysfs=/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/input/input122
U: Uniq=
H: Handlers=event23 js0
B: PROP=0
B: EV=20000b
B: KEY=7cdb000000000000 0 0 0 0
B: ABS=3003f
B: FF=107030000 0
キーボードの時と同様,インプットデバイスの出力を解析すれば何を入力しているのか判別できるようになるが,今回は pygame という便利なライブラリを使って楽をする.
$ hexdump -C /dev/input/js0
00000000 28 de da 2d 00 00 81 00 28 de da 2d 00 00 81 01 |(..-....(..-....|
00000010 28 de da 2d 00 00 81 02 28 de da 2d 00 00 81 03 |(..-....(..-....|
00000020 28 de da 2d 00 00 81 04 28 de da 2d 00 00 81 05 |(..-....(..-....|
00000030 28 de da 2d 00 00 81 06 28 de da 2d 00 00 81 07 |(..-....(..-....|
...
pygame
pygame は高水準言語でありながらゲーム開発ができる便利なライブラリの集まり.
pygame news
pygame をインストールする.
$ pip install pygame
適当に入力イベントを拾うだけのコードを書いて,どんなイベントが発生してるか観察する.C では 50 行くらい書いた内容が,Python では 10 行程度で終わってしまった.pygame すごい.
import pygame
import time
pygame.init()
pygame.joystick.init()
joys = pygame.joystick.Joystick(0)
joys.init()
while True:
eventlist = pygame.event.get()
print(eventlist)
time.sleep(0.5)
キャプチャできた Event は eventlist に格納される.あとはを適当に処理すればいい.
>>> type(eventlist)
<class 'list'>
>>> eventlist
[<Event(1540-JoyButtonUp {'joy': 0, 'instance_id': 0, 'button': 1})>]
>>> type(eventlist[0])
<class 'Event'>
>>> eventlist[0].joy
0
KEY | TYPE | INDEX |
---|---|---|
B | button | 0 |
A | button | 1 |
Y | button | 2 |
X | button | 3 |
L1 | button | 4 |
R1 | button | 5 |
Select | button | 6 |
Start | button | 7 |
Hart | button | 8 |
Stick Left (Press) | button | 9 |
Stick Right (Press) | button | 10 |
Hat Up | hat | 0 |
Hat Down | hat | 0 |
Hat Right | hat | 0 |
Hat Left | hat | 0 |
Stick Left (Horizontal) | axis | 0 |
Stick Left (Vertical) | axis | 1 |
L2 | axis | 2 |
Stick Right (Horizontal) | axis | 3 |
Stick Right (Vertical) | axis | 4 |
R2 | axis | 5 |
ここで得られたデータをもとに,もう少しこのゲームパッドに合わせたコードに修正する.
import pygame
from pygame.locals import *
import time
PAD_BUTTON_B = 0
PAD_BUTTON_A = 1
PAD_BUTTON_Y = 2
PAD_BUTTON_X = 3
PAD_BUTTON_L1 = 4
PAD_BUTTON_R1 = 5
PAD_BUTTON_SELECT = 6
PAD_BUTTON_START = 7
PAD_BUTTON_HART = 8
PAD_BUTTON_JOY_LEFT = 9
PAD_BUTTON_JOY_RIGHT = 10
PAD_HAT = 0
PAD_AXIS_LEFT_HORIZONTAL = 0
PAD_AXIS_LEFT_VERTICAL = 1
PAD_AXIS_L2 = 2
PAD_AXIS_RIGHT_HORIZONTAL = 3
PAD_AXIS_RIGHT_VERTICAL = 4
PAD_AXIS_R2 = 5
pygame.init()
pygame.joystick.init()
joys = pygame.joystick.Joystick(0)
joys.init()
while True:
eventlist = pygame.event.get()
for e in eventlist:
#print(e)
if e.type == pygame.locals.JOYBUTTONDOWN:
if e.button == PAD_BUTTON_B:
print("B down")
elif e.button == PAD_BUTTON_A:
print("A down")
elif e.button == PAD_BUTTON_Y:
print("Y down")
elif e.button == PAD_BUTTON_X:
print("X down")
elif e.button == PAD_BUTTON_L1:
print("L1 down")
elif e.button == PAD_BUTTON_R1:
print("R1 down")
elif e.button == PAD_BUTTON_SELECT:
print("SELECT down")
elif e.button == PAD_BUTTON_START:
print("START down")
elif e.button == PAD_BUTTON_HART:
print("HART down")
elif e.button == PAD_BUTTON_JOY_RIGHT:
print("JOY R down")
elif e.button == PAD_BUTTON_JOY_LEFT:
print("JOY L down")
elif e.type == pygame.locals.JOYBUTTONUP:
if e.button == PAD_BUTTON_B:
print("B up")
elif e.button == PAD_BUTTON_A:
print("A up")
elif e.button == PAD_BUTTON_Y:
print("Y up")
elif e.button == PAD_BUTTON_X:
print("X up")
elif e.button == PAD_BUTTON_L1:
print("L1 up")
elif e.button == PAD_BUTTON_R1:
print("R1 up")
elif e.button == PAD_BUTTON_SELECT:
print("SELECT up")
elif e.button == PAD_BUTTON_START:
print("START up")
elif e.button == PAD_BUTTON_HART:
print("HART up")
elif e.button == PAD_BUTTON_JOY_RIGHT:
print("JOY R up")
elif e.button == PAD_BUTTON_JOY_LEFT:
print("JOY L up")
elif e.type == pygame.locals.JOYAXISMOTION:
if e.axis == PAD_AXIS_LEFT_HORIZONTAL:
print("axis L H", e.value)
elif e.axis == PAD_AXIS_LEFT_VERTICAL:
print("axis L V", e.value)
elif e.axis == PAD_AXIS_R2:
print("axis R2", e.value)
elif e.axis == PAD_AXIS_RIGHT_HORIZONTAL:
print("axis R H", e.value)
elif e.axis == PAD_AXIS_RIGHT_VERTICAL:
print("axis R V", e.value)
elif e.axis == PAD_AXIS_L2:
print("axis L2", e.value)
elif e.type == pygame.locals.JOYHATMOTION:
if e.value[0] > 0:
print("hat Right", e.value[0])
if e.value[0] < 0:
print("hat Left", e.value[0])
if e.value[1] > 0:
print("hat Up", e.value[1])
if e.value[1] < 0:
print("hat Down", e.value[1])
time.sleep(0.1)
ソケットと組み合わせて tcp で操作してみた感じはこんな.
おわりに
今回は 8bitdo SN30 Pro の入力イベント取得方法を模索した.思いの外簡単に実装できた.
今回使ったのはほぼジョイスティック周りのライブラリのみなので,他にも使えそうなものがあったら紹介する.たぶん.
コメント