Notice how stratified the time series latency is. Looking at this histogram, most of the transfers occur between 0 and 1ms. I expected to see all of the transfers centred over 5ms, as this is the stated sample rate of the Myo device. In fact, the average latency is exactly 5ms.
It seems that most events happen in rapid succession, followed by longer delays. The duplicate logged values I was seeing were likely due to some form of buffering issue in Myosharp. Many data packets build up and are all released at once. This buffer/release format is an issue for our real-time robotic control interface since it grabs values at fixed intervals. Say Myosharp sends ten packets in rapid succession, each packet overwrites the previous packet, and only the last packet is available to our application. If Myosharp then delays 50ms (since it just sent 50ms worth of data packets), for those 50ms, our application will repeatedly read the last value.
By keeping a history of data values sent, this problem can be mitigated. I implemented a queue (First In First Out, e.g., a lineup at a movie) data structure into the MultiMyoManager class. Each time an EMG data acquired event is triggered, the oldest value in each queue is removed, and the newest is added. This way, when Myosharp dumps a bunch of data packets simultaneously, the queue shifts correspondingly. The queue is read at a fixed, known time interval to get the current real-time data. A separate index variable keeps track of where in the queue we are currently reading from. Each time it reads a value, it increments the index variable forward in the queue to point to the next newest value. Simultaneously, each time a new data packet is added to the queue, this index variable shifts backward to account for the queue shifting.