nh2 / hemokit

Haskell library for the Emotiv EEG, inspired by the Emokit code
31 stars 13 forks source link

Formatting for Openvibe #4

Open warrenarea opened 9 years ago

warrenarea commented 9 years ago
if I have the following data, how it will transfer?

EmotivState {counter = 34, battery = 70, gyroX = 115, gyroY = -39, sensors = fromList [8769,7945,8113,8658,8455,8767,8857,8351,7744,9585,8141,8019,8177,9101], qualities = fromList [24,24,0,0,8,24,16,0,0,8,16,8,16,24]}

You should use the --format spaced option, then the data will look like this:

$ ./hemokit-dump --format spaced 48 0 646 -1636 14260 5451 6184 15047 13613 6573 15294 9075 5637 9415 8906 4214 16064 4322 0 0 0 0 0 0 0 0 0 0 0 0 0 0 128 0 288 -1082 16339 731 9041 5104 3837 6126 1916 14906 9550 2759 10431 5920 6503 14713 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 -1340 -1270 3461 9534 11386 15808 9507 5725 3030 12763 6679 8898 3755 13544 2893 10611 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ...

I am working on a python script to convert the sensor values to a format openvibe can read.

i've looked over your code, and i see that these are 16-bit ints, big endian bytes. but i am having trouble deciphering the values you have listed here.

i see here the format is: 'counter' 'battery' 'gyroX' 'gyroY' 'sensors' 'counter' 'battery' 'gyroX' 'gyroY' 'quality?' 'counter' 'battery' 'gyroX' 'gyroY' 'sensors' etc.

Could you please step through how you would convert one of these values back to its original value? for example: 'counter' 48 = 0000000110000000 ? = 34

i've tried studying your code, but i am not very fluent with haskell.

thank you for your time.

nh2 commented 9 years ago

Hey, Hemokit can already output its data so that Openvibe can read it: --format sensorbytes. This is a binary format, exactly how Openvibe likes it.

Check out this mini-tutorial I wrote, it describes how you connect the two.

The --format spaced output you are using currently is not a format that Openvibe can read. It is more useful when you want to communicate with other programs, e.g. Matlab.

Let me know whether this solves your question, and don't hesitate to ask more :)

nh2 commented 9 years ago

(I also just updated the README to mention the wiki: https://github.com/nh2/hemokit#connecting-with-other-programs)

warrenarea commented 9 years ago

well yes, i realize hemokit can already communicate with openvibe by using --format sensorbytes

i was using the spaced example above for a reference.

https://github.com/CymatiCorp/CyKit My project is located here, TCP server that can connect to openvibe, however i'm having issues setting up the format.

do you just send a line of 14 sensors as bytes in a sequence, and should they be delimited? because an array seems to put 0x00 in between them.

i see now that you have to pad the empty spaces with 0's, though i think i seen from a packet capture of the oscillator it was padding with 0x20 which is 32 (ie a space key).

warrenarea commented 9 years ago

I think what i'm having trouble understanding is the length of the byte strings you are sending to openvibe. When I connected to hemokit via telnet and piped it to a file, and converted the hex data. i found the individual packets delimited by 0d 0a (crlf)

20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 23 0d 0a

20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 1f 2e 21 6b 1e be 22 62 24 26 1e 9a 20 90 1f e9 1f 7d 20 37 20 e1 23 66 21 20 20 20 20 20 23 1f 2c 21 64 1e c0 22 60 24 2a 1e 9a 20 8d 1f e5 1f 7b 20 3b 20 df 23 od oa

20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 1f 23 21 5f 1e bc 22 6b 24 26 1e 97 20 93 1f e2 1f 78 20 40 20 da 23 6a 23

they are padded with x20 but the byte strings lengths seem to have varying length some 54 bytes, some 78 bytes, 108 bytes. etc.

the way i understood it, was that each sensor value should be converted to a 2 byte (16-bits) unsigned integer in big-endian format, and then padded to match something like 32 bytes?

nh2 commented 9 years ago

do you just send a line of 14 sensors as bytes in a sequence, and should they be delimited? because an array seems to put 0x00 in between them.

When sending the data via TCP, e.g. with the --format sensorbytes --serve 127.0.0.1 option, I don't send any delimiters, I just put the data in and flush the socket.

When printing to stdout (--format sensorbytes without --serve), then I print a newline after the 14 sensor values, so one newline after each complete reading.

https://github.com/nh2/hemokit/blob/master/apps/Dump.hs#L131 https://github.com/nh2/hemokit/blob/master/apps/Dump.hs#L171 https://github.com/nh2/hemokit/blob/master/apps/Dump.hs#L196

an array seems to put 0x00 in between them

What do you mean by this?

the way i understood it, was that each sensor value should be converted to a 2 byte (16-bits) unsigned integer in big-endian format, and then padded to match something like 32 bytes?

No, there is no padding involved, it should just be 14 16-bit-unsigned-big-endian integers after each other.

individual packets delimited by 0d 0a (crlf)

That's odd, shouldn't be a case with the TCP server.

Could you make a recording using sudo hemokit-dump --mode raw > yourfile.bin and send me yourfile.bin so that I can have a look at it?

warrenarea commented 9 years ago

http://blueskynet.org/edu/openvibe/hemokit.txt

TCP Writer output (from sinus generator) http://blueskynet.org/edu/openvibe/sinusOut1.txt http://blueskynet.org/edu/openvibe/sinusOut2.txt

nh2 commented 9 years ago

Could you make a recording using sudo hemokit-dump --mode raw > yourfile.bin and send me yourfile.bin so that I can have a look at it?

Ah sorry, this will actually give the decrypted data which Hemokit cannot currently read in.

Could you send me the output of sudo cat /dev/hidraw1 > yourfile.encrypted.bin instead (assuming /dev/hidraw1 is your EPOC device file), and also the serial number of your EPOC?

http://blueskynet.org/edu/openvibe/sinusOut1.txt http://blueskynet.org/edu/openvibe/sinusOut2.txt

These two give me HTTP 404 not found.

warrenarea commented 9 years ago

apologies http://blueskynet.org/edu/openvibe/sinusOut.txt http://blueskynet.org/edu/openvibe/sinusOut2.txt EmotivDeviceInfo {hidapiDeviceInfo = DeviceInfo {path = "\?\hid#vid_21a1&pid _0001&mi_01#9&33e8a85f&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}", vendorId = 8609, productId = 1, serialNumber = Just "SN201404226268GM", releaseNumber = 3 , manufacturerString = Just "Emotiv Systems Inc.", productString = Just "0000000 0000", usagePage = 65535, usage = 2, interfaceNumber = 1}} hemokit-dump.exe: Device open (by path) failed: hid_open returned NULL

nh2 commented 9 years ago

Ah, are you on Windows? (Sorry, I have to go to bed for some hours, it's 4am here :))

warrenarea commented 9 years ago

yes, windows. i alos might add my values are in the signed integer ranges as well.

Packets Received: 1932 Packets Processed: 1904 Y Reading: 3 Quality: 0 F3 Reading: 891 Quality: 0 F4 Reading: 219 Quality: 0 P7 Reading: -318 Quality: 0 FC6 Reading: 56 Quality: 0 F7 Reading: -214 Quality: 0 F8 Reading: 14 Quality: 0 T7 Reading: 364 Quality: 0 P8 Reading: -350 Quality: 0 FC5 Reading: 267 Quality: 0 AF4 Reading: -126 Quality: 0 Unknown Reading: 46 Quality: 0 T8 Reading: 146 Quality: 0 X Reading: 8 Quality: 0 O2 Reading: 1075 Quality: 0 O1 Reading: 614 Quality: 0 AF3 Reading: 779 Quality: 0 Battery: 62

warrenarea commented 9 years ago

this output from the latest version of emokit

warrenarea commented 9 years ago

raw hemokit-dump http://blueskynet.org/edu/openvibe/yourfile.bin

warrenarea commented 9 years ago

taken just now hemokit

warrenarea commented 9 years ago

whats curious is that the values appear in the correct ranges in hemokit. however.... hemokit doesnt display signal data if the Drift is Disabled. Also, the signal display starts to increase in delay until it takes over a minute to update. so the drift correction could possibly be slowing it down further.

warrenarea commented 9 years ago

i believe i've solved some of my issues if not all. i'm not above thanking the lord on this one. lol

The reason why we see in the outputs i provided an 0D 0A (CRLF) every 80 bytes, is i believe an (ibm/ms) telnet issue as it truncates every 80 bytes. The padding I believe can be contributed to the same issue, what we see as 0x20 is a space, which is telnet padding the 80 byte chunks.

I scripted something to read the connection manually, and the padding was nowhere to be found.

also. what i was referring to earlier of the 0x00 being delimited in arrays. this is how Python separates array indexes, and i was trying to drop the entire array as raw data.

also, i was sending \r\n which is a typical CRLF for windows, where-as openvibe being primarily programmed from a unix based machines, uses primarily the \n formatting. I think this created an extra character that offset the data as well.

warrenarea commented 9 years ago

I'm still uncertain why emokit data provides lower values, while yours provides the ideal range of 8700 - 8900. it shouldn't change the results either way, as the device is designed to work in the range of -8900 to 8900.

At first i thought it was because my device seems to give two product names, both Epoc BCI as well as the 0000000000 which is what yours connects to.

i thought perhaps emokit was connecting to one and yours the other, but i disabled Epoc BCI and this was not the case. however, i did notice my console update became a little more fluid... I think what was happening is that being emokit is multi-threaded(simulated threading anyways) with gevent, and it was creating multiple threads for each 'device' id found, so its doing double the work. why when disabling Epoc BCI, it started working a little smoother.

my other epoc usb would only report one device as "Emotiv RAW DATA"

not sure how your hemokit is set up, what would happen if it detected two 'valid' epoc id's?

warrenarea commented 9 years ago

I have gotten my python tcp server to work with openvibe, and it seemed to have to do with the CRLF ( both \r\n AND \n ) characters. it now uses no terminating characters and works quite well.

it is now one continuous stream without even an \n at the end. i think the \n seemed to be offsetting my data.

i also switched openvibe to read 1 sample per block.
i read this was unadvised as it could slow things down, but i seemed to have more jittery slow downs from larger blocks. (even on hemokit)

with hemokit i seem to get huge delays that increase quickly. also... i am not able to Disable the drift checking with hemokit. as well 'Signal Display' will not display unless the EEG property is set to true.

I tried to figure out what the difference was in hemokit / cykit streams, and the only thing i can ascertain is that you may also be using a terminating character in your data, or your socket protocol is appending one on that may be read by openvibe.

your setup does appear to be producing what seems to be the correct data, so who am i to say it doesn't work. however the delay, may indicate that the 'drift correction' is working overtime to correct for something.

i'm certain Cykit is working successfully now, and produces the results instantly with no delay and no drift correction.

nh2 commented 9 years ago

OK, I think I can reproduce your problem. Turning drift correction off in the Openvibe Acquisitor, I get after running it for 6000 seconds:

[  INF  ] Stopping the acquisition.
[WARNING] After 6013.4 seconds, theorical samples per second does not match real samples per second
[WARNING]   Received : 768928 samples
[WARNING]   Should have received : 769671 samples
[WARNING]   Drift was : -743 samples (-0.09%)
[WARNING]   The driver did not try to correct this difference

Now I am not entirely sure if this is indeed a problem, or if it is simply that the EPOC device does have drift (its timer may not be 100% accurate), and that whatever you use as alternative driver in Cykit does some drift correction itself. @warrenarea do you happen to know that?

Also @warrenarea, does it work if in the Openvibe settings you set the drift correction to 10ms as opposed to the default 2ms?

warrenarea commented 9 years ago

I'll give it a try changing the drift correction in just a minute.

my initial observations indicate the problem is with the sending of the data. i tried connecting directly to both Cykit and hemokit to see the differences, and your data appeared to be setting each 14 channel string, on a new line. also there were lines of data that had 28 channels on them.

where cykit was just one continuous stream of data.

my thinking is that the acquisition server is working harder to compensate for the offset data, and thus slows down the receiving on the openvibe end.

I will get back to you in an hour with screenshots and such.

warrenarea commented 9 years ago

i might add, in my site screenshots of it working in openvibe, you will see my values are negative numbers.. this is partly due to me modifying it. my CMS (reference sensors) are relatively close to my other contacts now. so its probably measuring the ground/impedance differently, regardless it still works well and is within the normal ranges. a typical device will give the values of 8700-8900. as long as its in the -8900 to 8900 range though, its fine.

warrenarea commented 9 years ago

also, take a look at the samples per block, when I use the 32 blocks as recommended from your website, i get big gaps in between the data. like its only reading 1 or 2 samples, and then the rest are blank.

which reminds me, when I was receiving packets directly from it, i remembered getting a bunch of blank lines, which probably coincides with these gaps.

where-as if i use the 1 sample per block, the data displays correctly, however it gets the delay. cykit also uses 1 sample per block, and i think yours can and should too.

warrenarea commented 9 years ago

hemo1

hemokit-dump.exe - with 32 samples per block.

hemo2

hemokit-dump.exe - with 1 samples per block.

warrenarea commented 9 years ago

hemo3

I performed a 'static test' immediately after the device connects to receive the incoming data, as you can see in the image, it takes 5 seconds for the data to be displayed from the time of the test.

static test is just tapping the sensors to create data.

warrenarea commented 9 years ago

there is no drift connection in cykit, its taking the data from emokit's module.

warrenarea commented 9 years ago

drift correction from 2ms to 10ms made no difference.

by the way, this is done from hemokit-dump.exe provided, and not a build of my own.

nh2 commented 9 years ago

which reminds me, when I was receiving packets directly from it, i remembered getting a bunch of blank lines, which probably coincides with these gaps.

I think what you see in this regard (with the gaps) is a problem that only appears on Windows. I remember somebody sending me an email telling me about the same problem. I think this problem is independent from the drift that you observe, and I don't know yet if it's Hemokit or OpenVibe that works different on Windows than on Linux in this case.

hemokit-dump.exe - with 1 samples per block.

How do you manage to set Sample count per sent block to 1? In my UI, 4 is the lowest value. Which OpenVibe version do you have?

I'm also collecting some info about the data arriving too slowly (drift over time) in issue #6.

Thanks for your help so far by the way - I hope we will get this sorted out! :)

warrenarea commented 9 years ago
Open C:\Program files\OpenViBE\share\openvibe\applications\acquisition-server\interface.ui

Navigate to line 53 and edit the '4' digit, to a '1' like so: <col id="0" translatable="yes">1</col>

warrenarea commented 9 years ago

my first instinct was to look to haskell's socket protocol, to see if its appending any terminating characters on its own. this might even be a windows socket issue. however i got slowed down with haskell's 'interesting' syntax and documenting.

it appears a lot of people are using linux for applications such as this.

i don't plan to use this very frequently with openvibe for myself, someone else inspired me to get it to work for openvibe.

warrenarea commented 9 years ago

http://blueskynet.org/edu/openvibe/cykit.pcap

http://blueskynet.org/edu/openvibe/hemokit.pcap

I took the liberty of using RawCap (Raw packet capturing program) to record the two different streams.

not sure if this will be useful, perhaps you will be able to see a difference? trouble is, if there was a \n being added in, there could have also been a 0x10 in the data as well.

warrenarea commented 9 years ago

http://stackoverflow.com/questions/22430686/why-does-windows-need-withsocketsdo

perhaps this has something to do with it. i believe this is the equivalant to what i suggested https://github.com/openyou/emokit/pull/121 here.

apparently before handling sockets, winsock has to be initialized.

warrenarea commented 9 years ago

i forgot those were pcap capture files, that include tcp header information. here is the raw data i converted http://blueskynet.org/edu/openvibe/hemokit-raw.txt http://blueskynet.org/edu/openvibe/cykit-raw.txt

i have to say, i didnt find what i was really looking for, there doesnt appear to be any terminating characters, but an unusual amount of 0x00 in cykit.

then again, cykit is using a signed integer, so that could be a difference.