-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvirtual_controller.py
More file actions
106 lines (90 loc) · 2.86 KB
/
Copy pathvirtual_controller.py
File metadata and controls
106 lines (90 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import os
import time
import uinput
class VirtualController:
def __init__(self):
# make sure uinput module is running
os.system("modprobe uinput")
self.device = uinput.Device([
uinput.ABS_Y + (-255, 255, 0, 0),
uinput.ABS_X + (-255, 255, 0, 0),
uinput.ABS_RY + (-255, 255, 0, 0),
uinput.ABS_RX + (-255, 255, 0, 0),
uinput.ABS_Z + (0, 255, 0, 0),
uinput.ABS_RZ + (0, 255, 0, 0),
uinput.BTN_TL,
uinput.BTN_TR,
uinput.BTN_SOUTH,
uinput.BTN_NORTH,
uinput.BTN_WEST,
uinput.BTN_EAST,
uinput.BTN_THUMBL,
uinput.BTN_THUMBR,
uinput.BTN_SELECT,
uinput.BTN_START,
uinput.BTN_TRIGGER_HAPPY1,
uinput.BTN_TRIGGER_HAPPY2,
uinput.BTN_TRIGGER_HAPPY3,
uinput.BTN_TRIGGER_HAPPY4
])
def update(self, controls):
rt = controls[0]
rb = controls[1]
lt = controls[2]
lb = controls[3]
x = controls[4]
rt = map(rt, in_low=0, out_low=0)
rb = discretize(rb)
lt = map(lt, in_low=0, out_low=0)
lb = discretize(lb)
x = map(x)
self.device.emit(uinput.ABS_RZ, rt)
self.device.emit(uinput.BTN_TR, rb)
self.device.emit(uinput.ABS_Z, lt)
self.device.emit(uinput.BTN_TL, lb)
self.device.emit(uinput.ABS_X, x)
def press_a(self):
self.device.emit(uinput.BTN_SOUTH, 1)
time.sleep(0.25)
self.device.emit(uinput.BTN_SOUTH, 0)
def close(self):
self.device.destroy()
def map(val, in_low=-1, in_high=1, out_low=-255, out_high=255):
"""
Maps given value linearly from one range to another range. Constrains value to out_range
:param val: value to map
:param in_low: low end of input range
:param in_high: high end of input range
:param out_low: lowest value to output
:param out_high: highest value to output
:return: value mapped to new range (as int)
"""
val = max(val, in_low)
val = min(val, in_high)
val += in_low
val /= (in_high - in_low)
val *= (out_high - out_low)
val -= out_low
return int(val)
def discretize(val):
'''
Constrain val to either 0 or 1 (whichever is closest, 0.5 rounds up)
:param val: continuous number
:return: either 0 or 1
'''
if val < 0.5:
return 0
return 1
if __name__ == "__main__":
c = VirtualController()
print("controller initialized successfully")
try:
c.update([1, 0, 0, 1, 0.5])
print("events sent successfully")
secs = 15
print(f"keeping open for {secs} secs for profile configuration")
print("use ctrl-c to stop early")
time.sleep(secs)
finally:
c.close()
print("controller closed, test successful")