From: pin Date: Fri, 2 Apr 2010 13:24:44 +0000 (+0000) Subject: Ajout pywiiuse, version transmise par mail par Gary Bishop. X-Git-Url: https://scm.cri.ensmp.fr/git/minwii.git/commitdiff_plain/b1d5972142e87c4cc58e08e44cbd025cf5f6b26c?hp=fef42cdf1a3436f9053238c2de13a67fd126f344 Ajout pywiiuse, version transmise par mail par Gary Bishop. git-svn-id: https://svn.cri.ensmp.fr/svn/minwii/trunk@121 fe552daf-6dbe-4428-90eb-1537e0879342 --- diff --git a/src/pywiiuse/PyWiiUse.py b/src/pywiiuse/PyWiiUse.py new file mode 100755 index 0000000..55a1c98 --- /dev/null +++ b/src/pywiiuse/PyWiiUse.py @@ -0,0 +1,361 @@ +'''Python interface to the wiiuse library for the wii remote + +Just a simple wrapper, no attempt to make the api pythonic. I tried to hide ctypes where +necessary. + +This software is free for any use. If you or your lawyer are stupid enough to believe I have any +liability for it, then don't use it; otherwise, be my guest. + +Gary Bishop, January 2008 +hacked for new API and data June 2009 +''' + +import os +import ctypes +from ctypes import c_char_p, c_int, c_byte, c_uint, c_uint16, c_float, c_short, c_void_p, c_char +from ctypes import CFUNCTYPE, Structure, POINTER, Union, byref, cdll +import sys + +# duplicate the wiiuse data structures + +class _Structure(Structure): + def __repr__(self): + '''Print the fields''' + res = [] + for field in self._fields_: + res.append('%s=%s' % (field[0], repr(getattr(self, field[0])))) + return self.__class__.__name__ + '(' + ','.join(res) + ')' + +class vec2b(_Structure): + _fields_ = [('x', c_byte), + ('y', c_byte), + ] + +class vec3b(_Structure): + _fields_ = [('x', c_byte), + ('y', c_byte), + ('z', c_byte), + ] + +class vec3f(_Structure): + _fields_ = [('x', c_float), + ('y', c_float), + ('z', c_float), + ] + +class orient(_Structure): + _fields_ = [('roll', c_float), + ('pitch', c_float), + ('yaw', c_float), + ('a_roll', c_float), + ('a_pitch', c_float), + ] + + def __repr__(self): + return 'orient(roll=%f pitch=%f yaw=%f a_roll=%f a_pitch=%f)' % ( + self.roll, self.pitch, self.yaw, self.a_roll, self.a_pitch) + +class accel(_Structure): + _fields_ = [('cal_zero', vec3b), + ('cal_g', vec3b), + ('st_roll', c_float), + ('st_pitch', c_float), + ('st_alpha', c_float), + ] + +class ir_dot(_Structure): + _fields_ = [('visible', c_byte), + ('x', c_uint), + ('y', c_uint), + ('rx', c_short), + ('ry', c_short), + ('order', c_byte), + ('size', c_byte), + ] + +class ir(_Structure): + _fields_ = [('dot', ir_dot*4), + ('num_dots', c_byte), + ('aspect', c_int), + ('pos', c_int), + ('vres', c_uint*2), + ('offset', c_int*2), + ('state', c_int), + ('ax', c_int), + ('ay', c_int), + ('x', c_int), + ('y', c_int), + ('distance', c_float), + ('z', c_float), + ] + +class joystick(_Structure): + _fields_ = [('max', vec2b), + ('min', vec2b), + ('center', vec2b), + ('ang', c_float), + ('mag', c_float), + ] + +class nunchuk(_Structure): + _fields_ = [('accel_calib', accel), + ('js', joystick), + ('flags', POINTER(c_int)), + ('btns', c_byte), + ('btns_held', c_byte), + ('btns_released', c_byte), + ('orient_threshold', c_float), + ('accel_threshold', c_int), + ('accel', vec3b), + ('orient', orient), + ('gforce', vec3f), + ] + +class classic_ctrl(_Structure): + _fields_ = [('btns', c_short), + ('btns_held', c_short), + ('btns_released', c_short), + ('r_shoulder', c_float), + ('l_shoulder', c_float), + ('ljs', joystick), + ('rjs', joystick), + ] + +class guitar_hero_3(_Structure): + _fields_ = [('btns', c_short), + ('btns_held', c_short), + ('btns_released', c_short), + ('whammy_bar', c_float), + ('js', joystick), + ] + +class expansion_union(Union): + _fields_ = [('nunchuk', nunchuk), + ('classic', classic_ctrl), + ('gh3', guitar_hero_3), + ] + +class expansion(_Structure): + _fields_ = [('type', c_int), + ('u', expansion_union), + ] + +class wiimote_state(_Structure): + _fields_ = [('exp_ljs_ang', c_float), + ('exp_rjs_ang', c_float), + ('exp_ljs_mag', c_float), + ('exp_rjs_mag', c_float), + ('exp_btns', c_uint16), + ('exp_orient', orient), + ('exp_accel', vec3b), + ('exp_r_shoulder', c_float), + ('exp_l_shoulder', c_float), + ('ir_ax', c_int), + ('ir_ay', c_int), + ('ir_distance', c_float), + ('orient', orient), + ('btns', c_uint16), + ('accel', vec3b), + ] + +if os.name == 'nt': + JunkSkip = [('dev_handle', c_void_p), + ('hid_overlap', c_void_p*5), # skipping over this data structure + ('stack', c_int), + ('timeout', c_int), + ('normal_timeout', c_byte), + ('exp_timeout', c_byte), + ] +else: + JunkSkip = [('bdaddr', c_void_p), + ('bdaddr_str', c_char*18), + ('out_sock', c_int), + ('in_sock', c_int), + ] + +EVENT = 1 +STATUS = 2 +CONNECT = 3 +DISCONNECT = 4 +UNEXPECTED_DISCONNECT = 5 +READ_DATA = 6 +NUNCHUK_INSERTED = 7 +NUNCHUK_REMOVED = 8 +CLASSIC_CTRL_INSERTED = 9 +CLASSIC_CTRL_REMOVED = 10 +GUITAR_HERO_3_CTRL_INSERTED = 11 +GUITAR_HERO_3_CTRL_REMOVED = 12 + +class wiimote(_Structure): + _fields_ = [('unid', c_int), + ] + JunkSkip + [ + ('state', c_int), + ('leds', c_byte), + ('battery_level', c_float), + ('flags', c_int), + ('handshake_state', c_byte), + ('read_req', c_void_p), + ('accel_calib', accel), + ('exp', expansion), + ('accel', vec3b), + ('orient', orient), + ('gforce', vec3f), + ('ir', ir), + ('btns', c_uint16), + ('btns_held', c_uint16), + ('btns_released', c_uint16), + ('orient_threshold', c_float), + ('accel_threshold', c_int), + ('lstate', wiimote_state), + ('event', c_int), + ('event_buf', c_byte*32), + ] + +wiimote_p = POINTER(wiimote) +wiimote_pp = POINTER(wiimote_p) + +# make function prototypes a bit easier to declare +def cfunc(name, dll, result, *args): + '''build and apply a ctypes prototype complete with parameter flags + e.g. +cvMinMaxLoc = cfunc('cvMinMaxLoc', _cxDLL, None, + ('image', POINTER(IplImage), 1), + ('min_val', POINTER(double), 2), + ('max_val', POINTER(double), 2), + ('min_loc', POINTER(CvPoint), 2), + ('max_loc', POINTER(CvPoint), 2), + ('mask', POINTER(IplImage), 1, None)) +means locate cvMinMaxLoc in dll _cxDLL, it returns nothing. +The first argument is an input image. The next 4 arguments are output, and the last argument is +input with an optional value. A typical call might look like: + +min_val,max_val,min_loc,max_loc = cvMinMaxLoc(img) + ''' + atypes = [] + aflags = [] + for arg in args: + atypes.append(arg[1]) + aflags.append((arg[2], arg[0]) + arg[3:]) + return CFUNCTYPE(result, *atypes)((name, dll), tuple(aflags)) + +# get the shared library +if os.name == 'nt': + dll = cdll.LoadLibrary('wiiuse.dll') +else: + dll = cdll.LoadLibrary('libwiiuse.so') + +# access the functions +init = cfunc('wiiuse_init', dll, wiimote_pp, + ('wiimotes', c_int, 1)) +# find = cfunc('wiiuse_find', dll, c_int, +# ('wm', wiimote_pp, 1), +# ('max_wiimotes', c_int, 1), +# ('timeout', c_int, 1)) +# connect = cfunc('wiiuse_connect', dll, c_int, +# ('wm', wiimote_pp, 1), +# ('wiimotes', c_int, 1)) +# poll = cfunc('wiiuse_poll', dll, c_int, +# ('wm', wiimote_pp, 1), +# ('wiimotes', c_int, 1)) +find = dll.wiiuse_find +connect = dll.wiiuse_connect +poll = dll.wiiuse_poll +set_leds = dll.wiiuse_set_leds +motion_sensing = dll.wiiuse_motion_sensing +set_accel_threshold = dll.wiiuse_set_accel_threshold +set_orient_threshold = dll.wiiuse_set_orient_threshold +set_orient_threshold.argtypes = [wiimote_p, c_float] +set_timeout = dll.wiiuse_set_timeout + +def is_pressed(dev, button): + return dev.btns & button + +def is_held(dev, button): + return dev.btns_held & button + +def is_released(dev, button): + return dev.btns_released & button + +def is_just_pressed(dev, button): + return is_pressed(dev, button) and not is_held(dev, button) + +def using_acc(wm): + return wm.state & 0x10 + +def using_exp(wm): + return wm.state & 0x20 + +def using_ir(wm): + return wm.state & 0x40 + +LED_NONE = 0 +LED_1 = 0x10 +LED_2 = 0x20 +LED_3 = 0x40 +LED_4 = 0x80 + +LED = [LED_1, LED_2, LED_3, LED_4] + +EXP_NONE = 0 +EXP_NUNCHUK = 1 +EXP_CLASSIC = 2 + +SMOOTHING = 0x01 +CONTINUOUS = 0x02 +ORIENT_THRESH = 0x04 +INIT_FLAGS = SMOOTHING | ORIENT_THRESH + +IR_ABOVE = 0 +IR_BELOW = 1 + +ASPECT_4_3 = 0 +ASPECT_16_9 = 1 + +button = { '2':0x0001, + '1':0x0002, + 'B':0x0004, + 'A':0x0008, + '-':0x0010, + 'Home':0x0080, + 'Left':0x0100, + 'Right':0x0200, + 'Down':0x0400, + 'Up':0x0800, + '+':0x1000, + } + +nunchuk_button = { 'Z':0x01, + 'C':0x02, + } + + +if __name__ == '__main__': + def handle_event(wm): + print 'EVENT', wm.unid, wm.btns + print wm.gforce.x, wm.gforce.y, wm.gforce.z + + nmotes = 1 + wiimotes = init(nmotes) + print 'press 1&2' + found = find(wiimotes, nmotes, 2) + if not found: + print 'no wiimotes found' + sys.exit(1) + + connected = connect(wiimotes, nmotes) + if connected: + print 'connected to %d wiimotes (of %d found)' % (connected, found) + else: + print 'failed to connect to any wiimote.' + sys.exit(1) + + set_leds(wiimotes[0], 0x50) + motion_sensing(wiimotes[0], 1) + + while True: + if poll(wiimotes, nmotes): + for i in range(nmotes): + m = wiimotes[i][0] + if wiimotes[i][0].event == EVENT: + handle_event(wiimotes[i][0]) + diff --git a/src/pywiiuse/example.py b/src/pywiiuse/example.py new file mode 100755 index 0000000..27721b4 --- /dev/null +++ b/src/pywiiuse/example.py @@ -0,0 +1,114 @@ +#! /usr/bin/python + +'''Try to implement the example in python''' + +import PyWiiUse as wiiuse + +import sys +import time +import os + +nmotes = 2 + +def handle_event(wm): + print '--- EVENT [wiimote id %i] ---' % wm.unid, wm.btns, wm.btns_held, wm.btns_released + if wm.btns: + for name,b in wiiuse.button.items(): + if wiiuse.is_pressed(wm, b): + print name,'pressed' + + if wiiuse.is_just_pressed(wm, wiiuse.button['-']): + wiiuse.motion_sensing(wmp, 0) + if wiiuse.is_just_pressed(wm, wiiuse.button['+']): + wiiuse.motion_sensing(wmp, 1) + if wiiuse.is_just_pressed(wm, wiiuse.button['B']): + wiiuse.toggle_rumble(wmp) + if wiiuse.is_just_pressed(wm, wiiuse.button['Up']): + wiiuse.set_ir(wmp, 1) + if wiiuse.is_just_pressed(wm, wiiuse.button['Down']): + wiiuse.set_ir(wmp, 0) + + if wiiuse.using_acc(wm): + print 'roll = %f' % wm.orient.roll + print 'pitch = %f' % wm.orient.pitch + print 'yaw = %f' % wm.orient.yaw + + if wiiuse.using_ir(wm): + for i in range(4): + if wm.ir.dot[i].visible: + print 'IR source %i: (%u, %u)' % (i, wm.ir.dot[i].x, wm.ir.dot[i].y) + print 'IR cursor: (%u, %u)' % (wm.ir.x, wm.ir.y) + print 'IR z distance: %f' % wm.ir.z + + if wm.exp.type == wiiuse.EXP_NUNCHUK: + nc = wm.exp.u.nunchuk + + for name,b in wiiuse.nunchuk_button.items(): + if wiiuse.is_pressed(nc, b): + print 'Nunchuk: %s is pressed' % name + + print 'nunchuk roll = %f' % nc.orient.roll + print 'nunchuk pitch = %f' % nc.orient.pitch + print 'nunchuk yaw = %f' % nc.orient.yaw + print 'nunchuk joystick angle: %f' % nc.js.ang + print 'nunchuk joystick magnitude: %f' % nc.js.mag + + +def handle_ctrl_status(wmp, attachment, speaker, ir, led, battery_level): + wm = wmp[0] + print '--- Controller Status [wiimote id %i] ---' % wm.unid + print 'attachment', attachment + print 'speaker', speaker + print 'ir', ir + print 'leds', led[0], led[1], led[2], led[3] + print 'battery', battery_level + +def handle_disconnect(wmp): + print 'disconnect' + +if os.name != 'nt': print 'Press 1&2' + +wiimotes = wiiuse.init(nmotes) + +found = wiiuse.find(wiimotes, nmotes, 5) +if not found: + print 'not found' + sys.exit(1) + +connected = wiiuse.connect(wiimotes, nmotes) +if connected: + print 'Connected to %i wiimotes (of %i found).' % (connected, found) +else: + print 'failed to connect to any wiimote.' + sys.exit(1) + +for i in range(nmotes): + wiiuse.set_leds(wiimotes[i], wiiuse.LED[i]) + #wiiuse.rumble(wiimotes[i], 1) + +# for i in range(nmotes): +# wiiuse.rumble(wiimotes[i], 0) + +#wiiuse.status(wiimotes[0]) + +wiiuse.motion_sensing(wiimotes[0], 1) + +fp = file('mydata.txt', 'w') +t0 = time.time() +try: + while True: + if wiiuse.poll(wiimotes, nmotes): + for i in range(nmotes): + m = wiimotes[i][0] + if wiimotes[i][0].event == wiiuse.EVENT: + #handle_event(wiimotes[i][0]) + wm = wiimotes[i][0] + t = time.time() - t0 + print >>fp, i, t, wm.gforce.x, wm.gforce.y, wm.gforce.z +except KeyboardInterrupt: + for i in range(nmotes): + wiiuse.set_leds(wiimotes[i], 0) + #wiiuse.disconnect(wiimotes[i]) + +fp.close() +print 'done' diff --git a/src/pywiiuse/setup.py b/src/pywiiuse/setup.py new file mode 100755 index 0000000..d96beb6 --- /dev/null +++ b/src/pywiiuse/setup.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +from distutils.core import setup +import os + +setup(name='PyWiiUse', + version='2.00', + description='Python wrapper for the wiiuse interface to the Wiimote', + author='Gary Bishop', + author_email='gb@cs.unc.edu', + url='http://www.cs.unc.edu/~gb/', + py_modules=['PyWiiUse' ], + ) + diff --git a/src/pywiiuse/wiiuse.dll b/src/pywiiuse/wiiuse.dll new file mode 100755 index 0000000..a7e228c Binary files /dev/null and b/src/pywiiuse/wiiuse.dll differ