python - Python-无线控制器和加数/值列表
问题描述
硬件: RPi4 4GB,SteelSeries Stratus Duo WiFi/BTLE 无线控制器
长期目标:使用无线控制器执行多项任务(即,移动/归零工具头,启动/暂停/停止程序等),无线控制器将与运行控制 CNC 路由器的服务器的 RPi 接口。
短期目标:确定按下了哪些按钮组合,而不使用过多的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(排列、组合等)、嵌入式列表和其他此类可能的解决方案。乍一看,所有这些似乎都在我想做的事情的大致范围内。不幸的是,这些(至少它们本身)似乎都无法实现目标。对我来说,这是一个完全未知的编程领域,任何指导将不胜感激。
解决方案
如果 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 - 在 Python 中绘制之前向下采样一个 numpy 向量
- spring-boot - JAXBSring 和普通字符串
- java - 找不到 Gradle DSL 方法:'destination()'
- azure - Azure SFTP 文件传输到 Blob 存储
- perl - pp - PAR 打包程序,找不到 strict.pm
- java - 如何在 Java Struts2 中进行下一个和上一个链接
- javascript - 将文件上传到远程文件服务器 (PHP)
- azure - 启用托管标识后 Azure 应用服务停止工作
- docker - 启动 minikube 时设置 kubeconfig 失败
- c# - MOQ 创建抽象类的 Mock 返回 null