简体   繁体   English

Python-无线控制器和加法/值列表

[英]Python- Wireless Controller & List of Addends/Values

Hardware: RPi4 4GB, SteelSeries Stratus Duo WiFi/BTLE wireless controller硬件: RPi4 4GB, SteelSeries Stratus Duo WiFi/BTLE 无线控制器

Long Term Goal: Perform multiple tasks (ie, move/zero the toolhead, start/pause/stop the program, etc.) using the wireless controller which will interface with the RPi that is running a server that controls a CNC router.长期目标:使用无线控制器执行多项任务(即移动/调零工具头、启动/暂停/停止程序等),该控制器将与运行控制 CNC 路由器的服务器的 RPi 连接。

Short Term Goal: Determine which combination of buttons are being pressed without using an ungodly number of if/elif statements.短期目标:在不使用大量if/elif语句的情况下确定按下了哪些按钮组合。

Summary: I have already figured out how to read the output from the wireless controller using PyUSB.总结:我已经弄清楚如何使用 PyUSB 从无线控制器读取输出。 I've altered/added code to that which was included with PyUSB to produce some human-readable results.我已经对 PyUSB 中包含的代码进行了更改/添加,以产生一些人类可读的结果。 The output is formatted in a list, with each item's value being determined by some sort of button combination.输出格式为列表,每个项目的值由某种按钮组合确定。 (I know it says "array", but Python appears to treat it as a list.) (我知道它说的是“数组”,但 Python 似乎将它视为一个列表。)

This is the output when no buttons are pressed (Default):这是未按下任何按钮时的输出(默认):

array('B', [0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

The first two values ( ...[0, 20,...] ) seem to be some sort of identifiers, and those never change.前两个值 ( ...[0, 20,...] ) 似乎是某种标识符,并且永远不会改变。 Multiple buttons, however, utilize the same indexed location in the list.但是,多个按钮使用列表中的相同索引位置。 They all have different values, and are summed when pressed simultaneously.它们都有不同的值,并在同时按下时相加。 No combination of button values generate the same output for the indexed location.没有按钮值的组合为索引位置生成相同的输出。 Examples:例子:

Button A: array('B', [0, 20, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])按钮 A: array('B', [0, 20, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

Top Left: array('B', [0, 20, 0, 1, 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])

Top Left & A: array('B', [0, 20, 0, 17, 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])

Here is my current program, and as you can see the if/elif statements are starting to get a little out of hand.:这是我当前的程序,正如您所看到的,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)

Again, my desired result would be for the program to determine the combination of buttons being pressed- For instance, if the value for control[3] is 17 , is there a way to efficiently have the program determine that it is a combination of the assigned values of 16 and 1 (The 'A' button & the 'Top Left' button)?同样,我想要的结果是程序确定按下的按钮组合 - 例如,如果control[3]的值是17 ,有没有办法有效地让程序确定它是分配了161值(“A”按钮和“左上角”按钮)?

I've looked into possibly using a CSV file, itertools(permutations, combinations, etc.), embedded lists, and other such possible solutions.我已经研究过可能使用 CSV 文件、itertools(排列、组合等)、嵌入列表和其他此类可能的解决方案。 At first glance, all of these appear to be somewhere in the ballpark of what I want to do.乍一看,所有这些似乎都在我想要做的范围内。 Unfortunately, none of these (at least by themselves) appear to accomplish the goal.不幸的是,这些(至少就其本身而言)似乎都无法实现目标。 This is a completely uncharted area of programming for me, and any guidance would be greatly appreciated.这对我来说是一个完全未知的编程领域,任何指导将不胜感激。

Here's what I'd do.这就是我要做的。

I'd assign each button its own tuple of position and value, like this:我会为每个按钮分配自己的位置和值元组,如下所示:

buttons = [
    ('dir_up', 2, 1),
    ('dir_down', 2, 2),
    ('dir_left', 2, 4),
    ('dir_right', 2, 8),
    # ... etc, other buttons here
]

Then you can see which buttons are actually pressed with a generator:然后你可以看到生成器实际按下了哪些按钮:

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

PS For added clarity, you might find namedtuples or even enums useful. PS 为了更加清晰,您可能会发现命名元组甚至枚举很有用。

If the value for control[3] is 17, is there a way to efficiently have the program determine that it is a combination of the assigned values of 16 and 1如果 control[3] 的值为 17,是否有办法有效地让程序确定它是 16 和 1 的指定值的组合

This is the interesting bit of the question.这是这个问题的有趣之处。 And the answer is "yes".答案是“是”。 You may have noticed that the individual values (1, 2, 4, 8, 16, 32, 64...) are powers of 2 (2**1, 2**2, 2**3...) .您可能已经注意到单个值 (1, 2, 4, 8, 16, 32, 64...) 是 2 (2**1, 2**2, 2**3...)幂。 This means that the combined values can be thought of as binary digits.这意味着可以将组合值视为二进制数字。 So if I gave you 40, the only way to represent that using powers of 2 is 32 + 8. In binary, this is 101000. If you want to get this in Python then (at least in Python3) you can do bin(40) , which prints the string '0b10001'.因此,如果我给您 40,那么使用 2 的幂表示的唯一方法是 32 + 8。在二进制中,这是 101000。如果您想在 Python 中获得它,那么(至少在 Python3 中)您可以执行bin(40) ,打印字符串 '0b10001'。

In terms of how to make the most of this, I shall defer to art-solopov's answer.至于如何充分利用这一点,我将遵循艺术索洛波夫的回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM