Python-无线控制器和加数/值列表
Posted
技术标签:
【中文标题】Python-无线控制器和加数/值列表【英文标题】:Python- Wireless Controller & List of Addends/Values 【发布时间】:2020-05-30 10:26:54 【问题描述】:硬件: RPi4 4GB,SteelSeries Stratus Duo WiFi/BTLE 无线控制器
长期目标:使用将与正在运行的 RPi 接口的无线控制器执行多项任务(即,移动/归零工具头,启动/暂停/停止程序等)控制 CNC 路由器的服务器。
短期目标:在不使用大量 if/elif
语句的情况下确定正在按下的按钮组合。
总结:我已经弄清楚了如何使用 PyUSB 读取无线控制器的输出。我已经更改/添加了 PyUSB 中包含的代码,以产生一些人类可读的结果。输出格式为列表,每个项目的值由某种按钮组合确定。 (我知道它说的是“数组”,但 Python 似乎将其视为一个列表。)
这是没有按下按钮时的输出(默认):
array('B', [0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
前两个值 (...[0, 20,...]
) 似乎是某种标识符,它们永远不会改变。然而,多个按钮在列表中使用相同的索引位置。它们都有不同的值,并在同时按下时相加。任何按钮值的组合都不会为索引位置生成相同的输出。例子:
按钮 A:array('B', [0, 20, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
左上角:array('B', [0, 20, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
左上角 & A:array('B', [0, 20, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
这是我当前的程序,你可以看到 if/elif 语句开始有点失控了。:
#!/usr/bin/python
from __future__ import division
import usb.core
import usb.util
import time
import os
import sys
#import csv
USB_IF = 0 # Interface
USB_TIMEOUT = 5 # Timeout in MS
USB_VENDOR = 0x1038 # SteelSeries
USB_PRODUCT = 0x1430 # Stratus Duo
dev = usb.core.find(idVendor=USB_VENDOR, idProduct=USB_PRODUCT)
endpoint = dev[0][(0,0)][0]
if dev.is_kernel_driver_active(USB_IF) is True:
dev.detach_kernel_driver(USB_IF)
usb.util.claim_interface(dev, USB_IF)
while True:
control = None
try:
control = dev.read(endpoint.bEndpointAddress, endpoint.wMaxPacketSize, USB_TIMEOUT)
CtrlA = control[2] #Directional Pad, Start/Select, L/R Stick Press
CtrlB = control[3] #Top Left/Top Right, Center, A, B, X, Y
CtrlC = control[4] #Left Trigger (0-255)
CtrlD = control[5] #Right Trigger (0-255)
CtrlEH = control[6:10] #Left Stick
CtrlIL = control[10:14] #Right Stick
print control
if CtrlA ==0:
print "No Input"
elif CtrlA == 1:
print "Directional Pad: Up"
elif CtrlA == 2:
print "Directional Pad: Down"
elif CtrlA == 4:
print "Directional Pad: Left"
elif CtrlA == 8:
print "Directional Pad: Right"
elif CtrlA == 16:
print "Right Center Button"
elif CtrlA == 32:
print "Left Center Button"
elif CtrlA == 64:
print "Left Stick Pressed"
elif CtrlA == 128:
print "Right Stick Pressed"
elif CtrlA == 192:
print "Right & Left Sticks Pressed"
else:
break
if CtrlC == 0:
print "Left Trigger: No Input"
elif 1 <= CtrlC <=254:
print "Left Trigger: " + ":.0%".format(CtrlC/255)
elif CtrlC == 255:
print "Left Trigger: Max"
else:
break
if CtrlD == 0:
print "Right Trigger: No Input"
elif 1 <= CtrlD <=254:
print "Right Trigger: " + ":.0%".format(CtrlD/255)
elif CtrlD == 255:
print "Right Trigger: Max"
else:
break
except:
pass
#Let Ctrl+C actually exit.
time.sleep(0.01)
同样,我想要的结果是让程序确定被按下的按钮的组合 - 例如,如果 control[3]
的值是 17
,有没有办法让程序有效地确定它是16
和 1
的指定值的组合(“A”按钮和“左上”按钮)?
我已经研究过可能使用 CSV 文件、itertools(排列、组合等)、嵌入式列表和其他此类可能的解决方案。乍一看,所有这些似乎都在我想做的事情的大致范围内。不幸的是,这些(至少它们本身)似乎都无法实现目标。对我来说,这是一个完全未知的编程领域,非常感谢任何指导。
【问题讨论】:
【参考方案1】:这就是我要做的。
我会为每个按钮分配自己的位置和值元组,如下所示:
buttons = [
('dir_up', 2, 1),
('dir_down', 2, 2),
('dir_left', 2, 4),
('dir_right', 2, 8),
# ... etc, other buttons here
]
然后你可以看到使用生成器实际按下了哪些按钮:
def pressed_buttons(control):
for button in buttons:
name, control_pos, value = button
# To check if the button was pressed, perform a binary masking
if control[control_pos] & value == value:
yield button
P。 S. 为了更清楚起见,您可能会发现 namedtuples 甚至 enums 很有用。
【讨论】:
【参考方案2】:如果 control[3] 的值为 17,有没有办法有效地让程序确定它是 16 和 1 的指定值的组合
这是这个问题的有趣之处。答案是“是”。您可能已经注意到各个值(1、2、4、8、16、32、64...)是 2 (2**1, 2**2, 2**3...)
的幂。这意味着可以将组合值视为二进制数字。因此,如果我给你 40,那么使用 2 的幂表示的唯一方法是 32 + 8。在二进制中,这是 101000。如果你想在 Python 中得到这个(至少在 Python3 中)你可以做bin(40)
,打印字符串 '0b10001'。
关于如何充分利用这一点,我将听从 art-solopov 的回答。
【讨论】:
以上是关于Python-无线控制器和加数/值列表的主要内容,如果未能解决你的问题,请参考以下文章
计算机网络实验(思科模拟器Cisco Packet Tracer)——无线路由和防火墙配置