Implemented basic headpat firmware

This commit is contained in:
2026-06-04 01:22:27 +01:00
parent a1f8d05d52
commit e0482ee1a0
2 changed files with 73 additions and 0 deletions

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
python-osc
pyserial

71
src/Python/main.py Normal file
View File

@ -0,0 +1,71 @@
"""
Basic arse driver / software that just does the haptics.
"""
from threading import Thread
import argparse
import struct
import time
import os
from pythonosc.dispatcher import Dispatcher
from pythonosc import osc_server
import serial
class Device:
"""
Holds the serial port and opccasionally updates it
"""
def __init__(self, port: os.PathLike, refreshRate: int=30):
self._run = True
self._ser = serial.Serial(port, 9600)
self.areas = {'Fwd': 0, 'Mid': 0, 'Bck': 0}
self._updateThread = Thread(target=self._update)
self.refreshRate = refreshRate
self.intensity = 1
self._updateThread.start()
def updateAreasFromOSC(self, addr: str, value: float):
"""
Updates the areas variable based on an OSC message.
"""
area = addr.split('/')[-1]
self.areas[area] = round(value*255)
def _update(self):
while self._run:
values = self.areas.values()
values = [round(v * self.intensity) for v in values]
self._ser.write(struct.pack('<BBBB', 2, *values))
time.sleep(1 / self.refreshRate)
def close(self):
"""
Closes the serial port.
"""
self._run = False
self._updateThread.join()
self._ser.close()
parser = argparse.ArgumentParser(description='Basic headpat haptics')
parser.add_argument('serialPort', type=os.PathLike)
parser.add_argument('--oscRXPort', type=int, default=9001)
parser.add_argument('--intensity', type=float, default=1,
help='Intensity multiplier (0.0-1.0).')
args = parser.parse_args()
dev = Device(args.serialPort)
dev.intensity = args.intensity
dispatcher = Dispatcher()
dispatcher.map('/avatar/parameters/HeadpatHap/*', dev.updateAreasFromOSC)
serverIP = os.environ.get('VRCCO_OSCServerBind', '127.0.0.1')
serverPort = int(os.environ.get('VRCCO_OSCServerPort', args.oscRXPort))
server = osc_server.ThreadingOSCUDPServer((serverIP, serverPort), dispatcher, timeout=2.5)
server.serve_forever()