6轴游戏手柄测试python程序

为了测试6轴无线游戏手柄,我写了一个python程序,利用网络上都有的3d茶壶虚拟手柄的姿态,同时输出按钮信息。手柄通过hid协议上传4元数和按键信息,代码解析这些信息并操作茶壶去动作,

手柄信息如下:

运行图像如下:

附上代码(注释掉的代码可以在坐标转换时候使用):

#program to parse the data read from the game controller and simulate the pose of the controller using a teapot

#author: shuaiwen

from __future__ import print_function

from OpenGL.GL import *

from OpenGL.GLU import *

from OpenGL.GLUT import *

import struct

import numpy

import hid

import time

import struct

import math

import tkinter as tk

import threading

global hidHandle

global pitch,yaw,roll

global base_rot

global button_info

global window

def toFloat(b0,b1,b2,b3):

    x=[b0,b1,b2,b3]

    return struct.unpack('<f',struct.pack('4B',*x))[0]

 

def q2Euler(w,x,y,z):

        t0 = +2.0 * (w * x + y * z)

        t1 = +1.0 - 2.0 * (x * x + y * y)

        X = math.degrees(math.atan2(t0, t1))

        t2 = +2.0 * (w * y - z * x)

        t2 = +1.0 if t2 > +1.0 else t2

        t2 = -1.0 if t2 < -1.0 else t2

        Y = math.degrees(math.asin(t2))

        t3 = +2.0 * (w * z + x * y)

        t4 = +1.0 - 2.0 * (y * y + z * z)

        Z = math.degrees(math.atan2(t3, t4))

        return X, Y, Z

 

def q_to_mat4(q):

    w, x, y, z = q

    return numpy.array(

        [[1 - 2*y*y - 2*z*z, 2*x*y - 2*z*w, 2*x*z + 2*y*w, 0],

        [2*x*y + 2*z*w, 1 - 2*x*x - 2*z*z, 2*y*z - 2*x*w, 0],

        [2*x*z - 2*y*w, 2*y*z + 2*x*w, 1 - 2*x*x - 2*y*y, 0],

        [0, 0, 0, 1] ],'f')

 

def drawFunc():

    glClear(GL_COLOR_BUFFER_BIT)

    global hidHandle

    global button_info

    global pitch,yaw,roll

    d=hidHandle.read(64)

    if d:

        q0=toFloat(d[0],d[1],d[2],d[3])

        q1=toFloat(d[4],d[5],d[6],d[7])

        q2=toFloat(d[8],d[9],d[10],d[11])

        q3=toFloat(d[12],d[13],d[14],d[15])

        key1=d[16]

        key2=d[18]

        key3=d[21]

        leftX=d[22]

        leftY=d[23]

        rightX=d[24]

        rightY=d[25]

        if key1&0x10:

            button_info.config(text='start key pressed')

            #print("start key pressed")

        if key1&0x20:

            button_info.config(text='back key pressed')

            #print("back key pressed")

        if key2==0xff:

            button_info.config(text='key 1 pressed')

            #print("key 1 pressed")

        if key3 ==0xff:

            button_info.config(text='key 2 pressed')

            #print("key 2 pressed")

        #print("lx:%d,ly=%d,rx=%d,ry=%d"%(leftX,leftY, rightX ,rightY))

        #qt=toFloat(0,0,0x90,0x40) #test data,equal to 4.5

        #theta=q2Euler(q0,q1*(-1.0),q2,q3)

        #print(theta)

       # delta0=theta[0]-pitch

       # pitch=theta[0]

       # delta1=theta[1]-yaw

       # yaw=theta[1]

       # delta2=theta[2]-roll

       # roll=theta[2]

       # if abs(delta0)>=1:

       #     glRotatef(delta0, 1, 0, 0)

       # if abs(delta1)>=1:

       #     glRotatef(delta1, 0, 1, 0)

       # if abs(delta2)>=1:

       #     glRotatef(delta2, 0, 0, 1)

        #tot_rot=q_to_mat4([q0,q1*(-1.0),q2,q3])

        #tot_rot=q_to_mat4([q0,q2,q3,q1*(-1.0)])

        #tot_rot=q_to_mat4([q0,q3,q2,q1*(-1.0)])

        tot_rot=q_to_mat4([q0,q1*(-1.0),q3,q2])   #according jinheyao Engineer, multiplier -1 shuold be act on the data.

        glLoadMatrixf(numpy.dot(tot_rot,base_rot))

    glutWireTeapot(0.5)

    glFlush()

 

def kbFunc(key, x, y):

    global window

    if key ==b'q' or key==b'Q':

        window.quit()

        sys.exit()

       

def initPos():

    global pitch,yaw,roll,base_rot

    pitch=9

    yaw=0

    roll=0

    base_rot=numpy.eye(4,dtype=int)

    base_rot[0]=[0,0,1,0]

    base_rot[2]=[-1,0,0,0]

   

def initHid():

    global hidHandle

    try:

        hidHandle=hid.device()

        hidHandle.open(0x2588, 0x2601)

        print("Manufacturer: %s" % hidHandle.get_manufacturer_string())

        print("Product: %s" % hidHandle.get_product_string())

        #print("Serial No: %s" % hidHandle.get_serial_number_string())

        hidHandle.set_nonblocking(1)

    except IOError as ex:

        print(ex)

 

def keyWin():

    global button_info

    global window

    window = tk.Tk()

    window.title('my window')

    window.geometry('300x100')

    button_info=tk.Label(window,bg='yellow',width=20,text='empty')

    button_info.pack()

    window.mainloop()

   

if __name__=="__main__":

    initHid()

    initPos()

    glutInit()

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA)

    glutInitWindowSize(400, 400)

    glutCreateWindow("Controller test")

    glutDisplayFunc(drawFunc)

    glutIdleFunc(drawFunc)

    glutKeyboardFunc(kbFunc)

    t =threading.Thread(target=keyWin,args=())

    t.start()

    glutMainLoop()

### 实现Python与北通手柄在Linux上的交互 为了实现在Linux系统上通过Python连接并控制北通手柄,需先确认手柄已成功被识别为输入设备。通常情况下,当插入兼容的USB游戏控制器时,现代Linux发行版会自动加载相应的驱动程序[^1]。 #### 安装必要的库文件和支持工具 确保安装`jstest-gtk`或命令行工具`joystick`来测试手柄是否正常工作: ```bash sudo apt-get install joystick jstest-gtk ``` 接着,对于编程接口的支持,推荐使用`inputs`库,它能够简化访问各种类型的输入硬件的过程。可以通过pip轻松安装此库: ```bash pip3 install inputs ``` #### 编写简单的Python脚本来读取手柄状态 下面是一个基本的例子,展示了怎样利用上述提到的`inputs`模块获取来自北通手柄的数据流: ```python from inputs import get_gamepad while True: events = get_gamepad() for event in events: print(event.ev_type, event.code, event.state) ``` 这段代码将持续监听由所连结的游戏垫产生的事件,并打印出每个接收到的信息条目,包括类型(按键按下/释放)、编码以及当前的状态值。这有助于理解具体哪些信号对应于特定的手柄操作。 #### 进一步处理和应用 一旦掌握了如何捕捉到这些原始数据之后,就可以基于实际需求开发更复杂的功能了——比如映射某些按钮组合至自定义动作,或是将摇杆位置转换成屏幕坐标用于导航目的等等。值得注意的是,在构建这类应用程序的过程中可能还需要考虑多线程机制以保持良好的响应性能;另外也要注意不同型号之间可能存在差异,因此建议针对目标设备做适当调整优化[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值