openyou / emokit

Open source driver for accessing raw data from the Emotiv EPOC EEG headset
http://www.openyou.org
Other
521 stars 235 forks source link

Convert get_level() to return floating point value. #252

Open ghost opened 7 years ago

ghost commented 7 years ago

All headsets should return floating point sensor levels.

minifiredragon commented 7 years ago

hmmm, I just did that the hard way, I am going to upload a little more in a moment.

warrenarea commented 7 years ago

don't quote me on that, i may have done that wrong.. remembered having a heck of a time with big endian last time.

warrenarea commented 7 years ago

yeah, from the looks of it.... when it stores the Epoc CSV, it is storing it in the plain integer format.

but when it stores the Epoc+ data.... i'm pretty sure it stores it in the BIg-Endian format. When I created a version of Cykit to work with OpenVibe, to stream it to its TCP writer... i had to send it in a continuous stream in big-endian format.

i think its probably more data efficient, and thats probably their standard.

medical grade eeg probably has more sensitivity, so they probably uses floats as well.

warrenarea commented 7 years ago

its a pain in the butt understanding how python works with big endian, lol i think it took me like a week to grasp it, plus i was learning python 3 at the time.

in theory, my cykit should have a big endian setup.. at least for the conversion -to- big-endian.

warrenarea commented 7 years ago

https://github.com/CymatiCorp/CyKit/blob/master/Openvibe-Readme.md

perhaps that will help.... as you can see... openvibe lets you select settings on what type of format the raw data is in.

in my case.... i used Big-Endian 16-bit SIGNED integer.
so it was in big-endian format, but was an integer.

so i'm thinking for Epoc+ it will probably be... a Big-Endian 16-bit SIGNED float

ghost commented 7 years ago

The struct module has it builtin

minifiredragon commented 7 years ago

Ok, I just made a file running the epoc+ along with the emokit running. I moved the headset around. Where do you want the data? The CSV is to big to post here.

ghost commented 7 years ago

pastebin?

warrenarea commented 7 years ago
             cy = ""
             values = [packet.sensors[name]['value'] for name in 'AF3 F7 F3 FC5 T7 P7 O1 O2 P8 T8 FC6 F4 F8 AF4'.split(' ')]
cy = struct.pack('>' + str(len(values)) + 'h',*values)

https://docs.python.org/2/library/struct.html

So > indicates the endianness, in this case, that would be for big.

It shows here though that... a float is 4 bytes long.... which might complicate things. we either have to convert the two groups, together..... or separately.

minifiredragon commented 7 years ago

Well isnt this nice, the CSV seperates the motion from the EEG.

motionCap.zip

minifiredragon commented 7 years ago

Ok, lets think about the data you have. Given the fact that the data is in 2 separate files, you would have 2 feeds. 1 feed at 256samples, and 1 feed at 128 samples. So 2 counters.

ghost commented 7 years ago

Makes sense.

minifiredragon commented 7 years ago

Well at least I understand this output a little better. Now I am trying to figure out what the 2 of you are talking about.

minifiredragon commented 7 years ago

These values in the emokit decrypted CSV, what's there base?

warrenarea commented 7 years ago

its base 10, but i believe in its big-endian format. you might have to do some reading up on that. its kind of a confusing format. lol basically binary in reverse.

Bill, i tried running it through OpenVibe, as it is capable of reading several different formats, didn't have much luck.

will have to try again later though...

minifiredragon commented 7 years ago

<---- Started off learning Assembly. I am trying to dig into 20 year old memories of endian and conversions.

warrenarea commented 7 years ago

big endian can contain multiple bytes, it strings together, reversed binary data. think thats how it works. basically its all reversed binary and concatenated.

like bill said, python contains some methods for it built into struct. though it was confusing for me, with all the changes in unicode they did, for python 3.

got to use google on this one.

warrenarea commented 7 years ago

plus i think it will require a lot of python experimentation... i recommend using python from the command line on this one, and just typing in instructions... but we'll need some kind of guide... like we need to know what the values are supposed to be.

minifiredragon commented 7 years ago

I am working on a script to take the results in the zip i posted and look for the hex equivalent of a number. Just to see if it is in there. No matter how the number is created, it will always have the same hex bytes.

ghost commented 7 years ago

The gyro is 2048 at 0 I believe.

minifiredragon commented 7 years ago

All the available data is being collected right?

ghost commented 7 years ago

?

ghost commented 7 years ago

I believe so you can try increase the read size to see if there's more.

ghost commented 7 years ago

I think I just had a light blub moment though.

minifiredragon commented 7 years ago

I am not looking at the data ... and i am not looking at it at this moment... but a float is 4 hex values. When you divide the column count by 4 you do not get 14 channels.

minifiredragon commented 7 years ago

Also, there seems to be an internal clock that transmits with the data.

minifiredragon commented 7 years ago

Maybe even 2 timers that start when the head set is powered on.

ghost commented 7 years ago

one of those characters is a byte, 8bits in a byte, two bytes per sensor=16bits, 32 bytes in the data stream.

ghost commented 7 years ago

But we may have to do the same shifting thing because of the counter.

ghost commented 7 years ago

The gyro data doesn't move very much either 2048-52 quickly glancing over the data.

ghost commented 7 years ago

The values we observe also only move one 104-110 when moving the gyro.

ghost commented 7 years ago

My point is we need to find the conversion for chr(104) -> 2048.00

ghost commented 7 years ago

and then artificially increment 104 and the conversion counts up 2049 and so on..

ghost commented 7 years ago

er 106 and 105 rather it should be noted that they are one byte position apart and the 0 value or 2048 is the same.

ghost commented 7 years ago

They are also at indexes 29(106) and 30(105).

ghost commented 7 years ago

maybe we need to use bit masks 8 * the byte index? 232,233,234,235,236,237,238,239

240,241,242,243,244,245,246,247

minifiredragon commented 7 years ago

I was reading the half precision float standard.

minifiredragon commented 7 years ago

The answer maybe in the wiki article.

minifiredragon commented 7 years ago

Is this of use? http://forums.devshed.com/python-programming-11/converting-half-precision-floating-hexidecimal-decimal-576842.html

ghost commented 7 years ago

I figured it out I'm pretty sure.

minifiredragon commented 7 years ago

Where do I modify the python to check if there is more data

ghost commented 7 years ago

This version will attempt to read more automatically, I'm pretty sure it'll still return 32 bytes though.

ghost commented 7 years ago

Also, has all my scratch code I was using trying to find the values.

I'm pretty sure it turns out they store 4 sets of shorts, then you have to do math. Like @warrenarea said big endian.

They share the most significant bits which subtract to 256 * 8 to shift the byte and subtract the least significant bits then add them together.

ghost commented 7 years ago

Hmm maybe not.

minifiredragon commented 7 years ago

ok

ghost commented 7 years ago

Looking at the bits in the sensor values is interesting though: ['0', '1', '1', '1', '1', '1', '1', '0', '0', '0', '0', '1', '1', '1'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '0', '0', '0', '0', '1'] ['0', '1', '1', '1', '1', '1', '1', '0', '1', '1', '1', '0', '1', '0'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '1', '1', '1', '0', '1'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '1', '1', '1', '0', '0'] ['0', '1', '1', '1', '1', '1', '0', '0', '0', '1', '1', '0', '0', '0'] ['0', '1', '1', '1', '1', '1', '0', '0', '1', '0', '0', '1', '1', '1'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1', '1'] ['0', '1', '1', '1', '1', '1', '0', '1', '1', '0', '0', '0', '0', '0'] ['0', '1', '1', '1', '1', '1', '1', '0', '0', '0', '0', '0', '0', '0'] ['1', '0', '0', '1', '0', '0', '1', '1', '1', '0', '0', '0', '0', '1'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '0'] ['0', '1', '1', '1', '1', '1', '1', '1', '0', '0', '1', '1', '1', '0'] ['0', '1', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0'] ['0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '0', '0']

minifiredragon commented 7 years ago

And here I am trying to unplug from the matrix...

ghost commented 7 years ago

8192 4096 2048 1024 512 256 128 64 32 16 8 4 2 1 '0', '1', '1', '1', '1', '1', '0', '1', '0', '1', '0', '1', '1', '0'

8022 * 0.51

4091.22

minifiredragon commented 7 years ago

and .13 for epoc+?

ghost commented 7 years ago

yeah with two bits added, the math works better if multiplied by .13