140 linhas
4.7 KiB
Python
140 linhas
4.7 KiB
Python
import sys; sys.path.append('..') # help python find open_bci_v3.py relative to scripts folder
|
|
import open_bci_v3 as bci
|
|
import streamer_tcp_server
|
|
import time, timeit
|
|
from threading import Thread
|
|
|
|
# Transmit data to openvibe acquisition server, intelpolating data (well, sort of) from 250Hz to 256Hz
|
|
# Listen to new connections every second using a separate thread.
|
|
|
|
# NB: Left here for resampling algorithm, prefer the use of user.py.
|
|
|
|
NB_CHANNELS = 8
|
|
|
|
# If > 0 will interpolate based on samples count, typically 1.024 to go from 250Hz to 256Hz
|
|
SAMPLING_FACTOR = -1.024
|
|
# If > 0 will interbolate based on elapsed time
|
|
SAMPLING_RATE = 256
|
|
|
|
SERVER_PORT=12345
|
|
SERVER_IP="localhost"
|
|
|
|
DEBUG=False
|
|
|
|
# check packet drop
|
|
last_id = -1
|
|
|
|
# counter for sampling rate
|
|
nb_samples_in = -1
|
|
nb_samples_out = -1
|
|
|
|
# last seen values for interpolation
|
|
last_values = [0] * NB_CHANNELS
|
|
|
|
# counter to trigger duplications...
|
|
leftover_duplications = 0
|
|
|
|
tick=timeit.default_timer()
|
|
|
|
# try to ease work for main loop
|
|
class Monitor(Thread):
|
|
def __init__(self):
|
|
Thread.__init__(self)
|
|
self.nb_samples_in = -1
|
|
self.nb_samples_out = -1
|
|
# Init time to compute sampling rate
|
|
self.tick = timeit.default_timer()
|
|
self.start_tick = self.tick
|
|
|
|
def run(self):
|
|
while True:
|
|
# check FPS + listen for new connections
|
|
new_tick = timeit.default_timer()
|
|
elapsed_time = new_tick - self.tick
|
|
current_samples_in = nb_samples_in
|
|
current_samples_out = nb_samples_out
|
|
print "--- at t: ", (new_tick - self.start_tick), " ---"
|
|
print "elapsed_time: ", elapsed_time
|
|
print "nb_samples_in: ", current_samples_in - self.nb_samples_in
|
|
print "nb_samples_out: ", current_samples_out - self.nb_samples_out
|
|
self.tick = new_tick
|
|
self.nb_samples_in = nb_samples_in
|
|
self.nb_samples_out = nb_samples_out
|
|
# time to watch for connection
|
|
# FIXME: not so great with threads
|
|
server.check_connections()
|
|
time.sleep(1)
|
|
|
|
def streamData(sample):
|
|
|
|
global last_values
|
|
|
|
global tick
|
|
|
|
# check packet skipped
|
|
global last_id
|
|
# TODO: duplicate packet if skipped to stay sync
|
|
if sample.id != last_id + 1:
|
|
print "time", tick, ": paquet skipped!"
|
|
if sample.id == 255:
|
|
last_id = -1
|
|
else:
|
|
last_id = sample.id
|
|
|
|
# update counters
|
|
global nb_samples_in, nb_samples_out
|
|
nb_samples_in = nb_samples_in + 1
|
|
|
|
# check for duplication, by default 1 (...which is *no* duplication of the one current sample)
|
|
global leftover_duplications
|
|
|
|
# first method with sampling rate and elapsed time (depends on system clock accuracy)
|
|
if (SAMPLING_RATE > 0):
|
|
# elapsed time since last call, update tick
|
|
now = timeit.default_timer()
|
|
elapsed_time = now - tick;
|
|
# now we have to compute how many times we should send data to keep up with sample rate (oversampling)
|
|
leftover_duplications = SAMPLING_RATE * elapsed_time + leftover_duplications - 1
|
|
tick = now
|
|
# second method with a samplin factor (depends on openbci accuracy)
|
|
elif SAMPLING_FACTOR > 0:
|
|
leftover_duplications = SAMPLING_FACTOR + leftover_duplications - 1
|
|
#print "needed_duplications: ", needed_duplications, "leftover_duplications: ", leftover_duplications
|
|
# If we need to insert values, will interpolate between current packet and last one
|
|
# FIXME: ok, at the moment because we do packet per packet treatment, only handles nb_duplications == 1 for more interpolation is bad and sends nothing
|
|
if (leftover_duplications > 1):
|
|
leftover_duplications = leftover_duplications - 1
|
|
interpol_values = list(last_values)
|
|
for i in range(0,len(interpol_values)):
|
|
# OK, it's a very rough interpolation
|
|
interpol_values[i] = (last_values[i] + sample.channel_data[i]) / 2
|
|
if DEBUG:
|
|
print " --"
|
|
print " last values: ", last_values
|
|
print " interpolation: ", interpol_values
|
|
print " current sample: ", sample.channel_data
|
|
# send to clients interpolated sample
|
|
#leftover_duplications = 0
|
|
server.broadcast_values(interpol_values)
|
|
nb_samples_out = nb_samples_out + 1
|
|
|
|
# send to clients current sample
|
|
server.broadcast_values(sample.channel_data)
|
|
nb_samples_out = nb_samples_out + 1
|
|
|
|
# save current values for possible interpolation
|
|
last_values = list(sample.channel_data)
|
|
|
|
if __name__ == '__main__':
|
|
# init server
|
|
server = streamer_tcp_server.StreamerTCPServer(ip=SERVER_IP, port=SERVER_PORT, nb_channels=NB_CHANNELS)
|
|
# init board
|
|
port = '/dev/ttyUSB1'
|
|
baud = 115200
|
|
monit = Monitor()
|
|
# daemonize theard to terminate it altogether with the main when time will come
|
|
monit.daemon = True
|
|
monit.start()
|
|
board = bci.OpenBCIBoard(port=port, baud=baud, filter_data=False)
|
|
board.startStreaming(streamData)
|