LSL4Unity icon indicating copy to clipboard operation
LSL4Unity copied to clipboard

How do I define my own custom sampling rate?

Open rajshekarreddy97 opened this issue 2 years ago • 8 comments

I would like to define my own custom sampling rate that is independent of the frame rate (I would not like to use the update, fixed update etc). How do I go about doing so?

rajshekarreddy97 avatar May 26 '23 17:05 rajshekarreddy97

Is it at a regular interval? Or is this some irregularly-occuring event?

cboulay avatar May 26 '23 17:05 cboulay

In either case, don't use a class that derives from ABaseOutlet. Instead just use the LSL.cs directly to create your stream. e.g., https://github.com/labstreaminglayer/LSL4Unity/blob/master/Samples~/SimplePhysicsEventOutlet/SimpleOutletTriggerEvent.cs#L26-L35

Note that if you specify a regular rate that is not an even multiple/factor of the framerate (or physics rate for FixedUpdate), then you're going to have a tough time sending data at this regular rate. The end effect will be a lot of jitter in your timestamps. LSL and the XDF importers can dejitter, but you should thoroughly test this before you collect expensive data.

cboulay avatar May 26 '23 17:05 cboulay

It would be at a regular interval. I would like to sample the data at 120Hz but I cannot get the framerate to reach 120Hz in my specific project. This is because I have an eye tracker in my VR headset that samples at 120Hz. Have you ever come across such an issue?

rajshekarreddy97 avatar May 26 '23 17:05 rajshekarreddy97

Let's assume your game is running at 90 fps.

If you're asking the Eye Tracker for the data inside your game loop, you're retrieving data 90 times per second. How do you receive the data? Just one sample (hopefully the latest sample)? Or do you receive sometimes 1, sometimes 2 samples, then you have to decide what to do with it?

If it's the latter, then you can create a stream with 120 Hz and use push_chunk to push a length-1 or length-2 array of samples. LSL timestamps the newest sample in a chunk then works backward to automatically timestamp all the older samples in a chunk at the defined interval. e.g., when you push 2 samples when local_clock() = 3.14159, LS will give sample-2 a timestamp of 3.14159 seconds and it'll give sample-1 a timestamp of 3.14159-(1/120) = 3.13325.

But, if you only receive 1 sample on each frame, never more than that, I'd create an outlet with a sample rate of whatever your frame rate is. In that case you can use a class that inherits from ABaseOutlet.

cboulay avatar May 26 '23 19:05 cboulay

FYI, in case you haven't seen it, you may be interested in this: https://github.com/labstreaminglayer/PicoNeo2Eye

cboulay avatar May 26 '23 20:05 cboulay

Thank you for the detailed response!! For context, I'm using the HP Reverb G2 Omnicept which has the Tobii eye tracker sampling at 120Hz. I'm getting the latest sample by subscribing to the events generated by HP's Omnicept SDK. The effective sampling rate of these events is 115Hz (not 120 exactly).

I currently do not have a technique that can sample at 120Hz, and not rely on the events. Would you happen to know how to go about this in Unity?

If I can work that out, I can set the fixed update to 60Hz and then push a chunk of 2 samples to LSL each frame, thereby effectively sampling at 120Hz.

rajshekarreddy97 avatar May 26 '23 20:05 rajshekarreddy97

If you can run a separate application using the HP Omnicept SDK without interfering with its usage in Unity then I'd do that. This more modular approach is more flexible, more useful for other community members, and it will be easier for you to manage sampling rate, recording, etc even if you pause Unity.

cboulay avatar May 26 '23 21:05 cboulay

I'll give this a try, thanks! If anyone comes across how to go about this in Unity, could you comment down below?

rajshekarreddy97 avatar May 26 '23 23:05 rajshekarreddy97