Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added compatibility with OpenGloves NamedPipe v2 #6

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 112 additions & 91 deletions serial_utils/ipc.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,112 @@
# win32Pipe
'''
https://stackoverflow.com/questions/48542644/python-and-windows-named-pipes
'''
import struct, time
import win32pipe, win32file, win32con, pywintypes

class NamedPipe:
def __init__(self, right_hand=True):
if right_hand:
# OpenGloves /named-pipe-communication-manager/src/DeviceProvider.cpp#L77
self.pipename = r'\\.\\pipe\\vrapplication\\input\\right'
else:
self.pipename = r'\\.\\pipe\\vrapplication\\input\\left'
self.fingers = [False]*5
self.joys = [0.0, 0.0]
self.buttons = [False]*8

def encode(self, flexion, joys=None, bools=None):
''' Struct format is from: https://github.com/LucidVR/opengloves-driver/.../EncodingManager.h#L17
const std::array<float, 5> flexion; // Between 0 and 1
const float joyX; // Between -1 and 1
const float joyY;
const bool joyButton; // 0
const bool trgButton; // 1
const bool aButton; // 2
const bool bButton; // 3
const bool grab; // 4
const bool pinch; // 5
const bool menu; // 6
const bool calibrate; // 7
'''
if joys is not None:
print(joys)
joyX = joys[0]
joyY = joys[1]
else:
joyX = 0.0
joyY = 0.0

if bools is None:
bools = [False, False, False, False, False, False, False, False]

# https://tuttlem.github.io/2016/04/06/packing-data-with-python.html
pack_obj = struct.pack('@5f', flexion[0], flexion[1], flexion[2], flexion[3], flexion[4])
joys = struct.pack('@2f', joyX, joyY)
pack_bools = struct.pack('@8?', *bools)
pack_obj = pack_obj + joys + pack_bools
return pack_obj

def send(self, fingers, joys=None, bools=None):
encoded = self.encode(fingers, joys, bools)
try:
# https://github.com/LucidVR/opengloves-driver/blob/develop/overlay/main.cpp#L128
open_mode = win32con.GENERIC_READ | win32con.GENERIC_WRITE

pipe = win32file.CreateFile(self.pipename,
open_mode,
0, # no sharing
None, # default security
win32con.OPEN_EXISTING,
0, # win32con.FILE_FLAG_OVERLAPPED,
None)
win32file.WriteFile(pipe, encoded)
win32file.CloseHandle(pipe)
except pywintypes.error:
print("Pipe busy")


if __name__ == "__main__":
ipc_right = NamedPipe(right_hand=True)
ipc_left = NamedPipe(right_hand=False)

try:
for i1 in range(0,10):
for i2 in range(0,10):
for i3 in range(0,10):
for i4 in range(0,10):
for i5 in range(0,10):
fingers = [i1/10, i2/10, i3/10, i4/10, i5/10]
bools = [True]*8
bools[6] = True
ipc_left.send(fingers, bools=bools)
ipc_right.send(fingers, bools=bools)

time.sleep(0.01)
print(f"Wrote {fingers} to IPC")
except KeyboardInterrupt:
print("Quitting")

quit()
# win32Pipe
# https://stackoverflow.com/questions/48542644/python-and-windows-named-pipes

import pywintypes
import struct
import time
import win32con
import win32file
import win32pipe


def encode(flexions, splay, joys, bools):
""" Struct format is from: https://github.com/LucidVR/opengloves-driver/wiki/Driver-Input#opengloves-input-methods
const std::array<std::array<float, 4>, 5> flexion; // Between 0 and 1
const std::array<float, 5> splay; // Between 0 and 1
const float joyX; // Between -1 and 1
const float joyY; // Between -1 and 1
const bool joyButton; // 0
const bool trgButton; // 1
const bool aButton; // 2
const bool bButton; // 3
const bool grab; // 4
const bool pinch; // 5
const bool menu; // 6
const bool calibrate; // 7

const float trgValue; // between 0 - 1
"""

if splay is None:
splay = [0.0] * 5

if joys is None:
joys = [0.0] * 2

if bools is None:
bools = [False] * 8

# https://tuttlem.github.io/2016/04/06/packing-data-with-python.html
packed_flexions = struct.pack('@20f', *flexions)
packed_splays = struct.pack('@5f', *splay)
packed_joys = struct.pack('@2f', *joys)
packed_bools = struct.pack('@8?', *bools)
packed_trg = struct.pack('@f', (flexions[4] + flexions[5] + flexions[6] + flexions[7]) / 4)

return packed_flexions + packed_splays + packed_joys + packed_bools + packed_trg


class NamedPipe:
def __init__(self, right_hand=True):
if right_hand:
# OpenGloves /named-pipe-communication-manager/src/DeviceProvider.cpp#L77
self.pipe_name = r'\\.\pipe\vrapplication\input\glove\v2\right'

else:
self.pipe_name = r'\\.\pipe\vrapplication\input\glove\v2\left'

try:
# https://github.com/LucidVR/opengloves-driver/blob/develop/overlay/main.cpp#L128
open_mode = win32con.GENERIC_READ | win32con.GENERIC_WRITE

self.pipe = win32file.CreateFile(self.pipe_name,
open_mode,
0, # no sharing
None, # default security
win32con.OPEN_EXISTING,
0, # win32con.FILE_FLAG_OVERLAPPED,
None)

win32pipe.SetNamedPipeHandleState(self.pipe,
win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_READMODE_BYTE | win32pipe.PIPE_WAIT,
None,
None)


except pywintypes.error:
print("Pipe busy")
time.sleep(0.1)
self.__init__()

def send(self, flexions, splay=None, joys=None, bools=None):
encoded = encode(flexions, splay, joys, bools)
win32file.WriteFile(self.pipe, encoded)


if __name__ == "__main__":
ipc_right = NamedPipe(right_hand=True)
ipc_left = NamedPipe(right_hand=False)

try:
for i1 in range(0, 10):

for i2 in range(0, 10):

for i3 in range(0, 10):

for i4 in range(0, 10):

for i5 in range(0, 10):

flexions = [i1/10, i1/10, i1/10, i1/10, i2/10, i2/10, i2/10, i2/10, i3/10, i3/10, i3/10, i3/10, i4/10, i4/10, i4/10, i4/10, i5/10, i5/10, i5/10, i5/10]

ipc_left.send(flexions)
ipc_right.send(flexions)

time.sleep(0.01)

print(f"Wrote {flexions} to IPC")

except KeyboardInterrupt:
print("Quitting")
quit()