rhoyn.

Low-latency, accurate hands: measuring humanoid teleop latency to the millisecond

20.3 msrhoyn
44.5 msXRoboToolkit + ExtremControl · 2.2× slower
89.3 msXRoboToolkit + GR00T · 4.4× slower
Abstract

How long does a humanoid take to reproduce a movement of the operator’s hand? Video is limited by its frame rate and software logs stop before the motors, so we put one IMU on each hand and read both on one clock at 1 kHz. Ten estimators from six method families measure the lag and we report their median; known delays injected into the recordings come back within 0.7 ms. Across 21 recordings on a Unitree G1 EDU+, rhoyn’s VR teleop stack follows the operator 2.2× and 4.4× faster than two other stacks, with no overlap between the three, and its takes vary least.

What you can reuse

  • The rig: two MPU6050s and one ESP32, firmware included. It times hand to hand at 1 kHz, wherever the boards are taped.
  • The analysis: one command turns a recording into a latency and a picture of how all ten estimators got there.
  • The data: all 21 recordings and a video of every take, MIT licensed like the code, plus each take’s report grid. github.com/rhoyn/teleop-hands-latency-analysis

1Why 20 ms vs 90 ms shows up in your data

A person steering anything runs a closed loop: look, correct, look again. Put a delay in it and you stop correcting toward where the target is and start correcting toward where it was — the textbook recipe for overshoot. You push, nothing happens, you push harder, and then everything you asked for arrives at once. At 20 ms you don’t notice. At 90 ms you are placing the gripper by trial and error.

In teleoperation those corrections can be recorded into demonstrations — the overshoot, the re-tries, the pauses spent waiting for the robot — and a policy trained on them may learn them as part of the task. The delay also sits between the recorded command and what the camera sees: at 90 ms that is almost three frames of a 30 Hz camera, and when the delay changes from take to take, no single time shift at training time lines them up again.

2Video and software timestamps can’t resolve it

Counting frames. The ExtremControl paper estimates the latency of ten humanoid teleoperation systems, its own among them, by optical flow on their released videos — a clever way to get numbers for systems you don’t have in the room. But the result is limited by each video’s frame rate: one frame at 30 fps lasts ~33 ms, longer than rhoyn’s whole latency.

One of our takes at 60 fps: the operator’s hand enters from the left, the robot’s gloved hand from the right. At 20 ms the eye can’t tell which one is behind.

Timestamping software. It stops at the last line of code, before the motor and the limb. And it subtracts timestamps taken on two machines, so the answer includes however wrong their clock synchronisation is.

3Two hands, one clock

The measurement summarised: the operator on the left with MPU6050 number two on their raised hand as leader, the robot on the right with MPU6050 number one on its raised hand as follower, both wired down to one ESP32 labelled one clock, both hands, and the three measured results between them - 20.3 ms for rhoyn, 44.5 ms for XRoboToolkit with Genesis ExtremControl, and 89.3 ms for XRoboToolkit with NVIDIA GR00T
Figure 1. The operator’s hand leads, the robot’s hand follows, and one ESP32 reads the IMU on each, so one clock times both.

Two MPU6050s, one on each hand, are read by the same ESP32 at 1 kHz, and each pair of samples is stamped with one micros() call. There is no clock offset between devices to estimate, so the lag we measure is physical delay between the hands.

Nothing in the instrument adds lag to one hand only. Both hands travel in one packet, and both get identical filtering.

Why the instrument is fair to both hands

Both sensors are read in parallel on two I2C buses and sent in the same 31-byte packet. A lost packet loses both hands together, and a failed read can spoil a sample but never shift it, because the packet still goes out on the same tick, so the two hands can never slip apart in time. Both sensors use the same on-chip low-pass setting, and every estimator high-passes both signals at 0.3 Hz; any smoothing an estimator adds is the same on both hands, so filter delay cancels in the difference.

Mounting doesn’t matter. Every estimator works on gyroscope magnitude |ω|, which is the same however a board sits on its hand, so the boards can be taped on crooked and gravity never enters the signal.

The rig as built: an MPU6050 taped inside the operator's hand controller on the left, another taped to the robot's black gloved hand on the right, both cabled to the small ESP32 board between them, with the USB lead running off to the laptop
Figure 2. As built: one IMU taped to the VR controller, one on the robot’s gloved hand, both cabled to the ESP32 between them.

The sensors clip on fast reaches. They run at their default ±250 dps, and rhoyn’s takes clip most. Re-clipping every recording harder moves rhoyn by 0.3–1.7 ms and leaves the ranking unchanged.

The clipping stress test

All 21 recordings hit full scale. On the robot hand, rhoyn’s takes clip on 18–51% of samples, ExtremControl’s on 7–11% and GR00T’s on 1–14%. A clipped peak is flat, so it carries less timing information. We re-ran the analysis on copies of all 21 recordings clipped harder still:

clipped atrhoynXRoboToolkit + ExtremControlXRoboToolkit + GR00Tratios
250 dps (as recorded)20.3 ms44.5 ms89.3 ms2.2× / 4.4×
200 dps21.0 ms45.8 ms91.7 ms2.2× / 4.4×
150 dps21.4 ms46.8 ms97.0 ms2.2× / 4.5×
100 dps22.0 ms49.1 ms102.6 ms2.2× / 4.7×
150 dps, robot hand only20.7 ms45.8 ms94.8 ms2.2× / 4.6×
150 dps, operator hand only20.0 ms45.4 ms91.3 ms2.3× / 4.6×

Clipping both hands harder raises all three medians, the slower stacks most; clipping one hand only can move a take either way. The ranking and the gap between the stacks hold in every case. (At 100 dps one rhoyn take has 9 of 10 estimators.) This test can’t show what an unclipped recording would read — only that the conclusions don’t hinge on clipping. A recording at ±1000 dps would remove the question.

4Ten estimators, one median

A single delay estimator can hand you a confident, wrong number, and nothing in its output tells you so. So ten run over every recording, from six method families — cross-correlation, frequency-domain phase, model fitting, time warping, template and peak matching, and a Bayesian posterior — and the reported latency is their median. One method going wrong on a take can’t move a median far.

Rhoyn run 5 shows it: peak_matching read 31.5 ms while the other nine sat between 19.6 and 25.8, and the median stayed at 20.8 ms.

The results tile: 20.6 ms in large type, the note median of 10 algorithms MAD 0.9 ms, and a table of all ten algorithms sorted by latency from group delay at 18.3 ms to dtw offset at 26.0 ms

Figure 3. Every run writes one report: the result on top, then one tile per estimator showing its own internals. Run 0, rhoyn stack: median 20.6 ms, all ten between 18.3 and 26.0, typical distance from the median (MAD) 0.9 ms.

On rhoyn most of the ten land within a millisecond or two of the median, with the odd outlier like run 5. On the slower stacks they spread wider — GR00T run 1 reads anywhere from 81.5 to 115.7 ms — and the median still lands at 94.9 ms, inside the stack’s other takes.

Known delays come back within 0.7 ms. To test the whole chain, we fed it recordings with a delay we set ourselves:

injected into all 21 recordingsread back
robot hand replaced by the operator’s, delayed 0 ms0.0 ms on every recording
… delayed 20 ms20.0 ms on every recording
… delayed 90 ms89.8–90.0 ms
real robot hand, delayed a further 20 mseach result rises by 19.4–20.5 ms
real robot hand, delayed a further 50 mseach result rises by 49.4–50.7 ms

A delayed copy is easier than a real robot hand, which also shrinks and smooths the motion; the last two rows keep that reshaping and still recover the injected delay within 0.7 ms. All ten estimators reported in every case.

Three estimators up close · peak matching, group delay, Kalman bank
The peak matching tile, reading 18.4 ms: the top panel plots hand speed for both hands over six seconds with the operator and robot peaks marked on each of ten reaches, the middle panel zooms one reach and brackets the 20 ms gap between the two speed peaks, and the bottom panel plots the delay measured on every reach around their median

peak_matching — 18.4 ms. The one to show someone who doesn’t want the signal processing: find the moment each hand moves fastest in every reach and measure the gap. The middle panel is one reach, two peaks, 20 ms apart.

The group delay tile, reading 18.3 ms: the top panel plots coherence between the two hands against frequency with the fitted band marked, the middle panel plots measured phase falling with frequency and the fitted straight line whose slope is the delay, and the bottom panel plots gain in decibels for context

group_delay — 18.3 ms. A pure delay shows up as phase falling linearly with frequency; the slope is the answer. It reads phase only, so it isn’t biased when the robot shrinks your motion.

The Kalman bank tile, reading 19.6 ms: the top panel plots the filtered rotation rate of both hands, the middle panel plots log likelihood against assumed delay with a clear peak at the estimate, and the bottom panel plots which delay hypothesis is leading as the recording plays, settling within the first second

kalman_bank — 19.6 ms. 201 Kalman filters, one per delay hypothesis from 0 to 200 ms, each scoring how well its assumption explains what arrived. It thrashes for half a second, then locks on.

All ten estimators · method of each
algorithmapproach
windowed_gccwindowed cross-correlation with rest gating and Gaussian peak refinement
cross_correlationplain-weighted generalized cross-correlation, one tau per window
group_delayWelch H1 transfer function, delay from the coherence-weighted phase slope
arx_delayARX model with an explicit delay parameter, searched over a grid
kalman_bank201 Kalman filters, one per delay hypothesis, likelihood vote
dtw_offsetbanded dynamic time warping, offset of the warping path
burst_dtwsubsequence DTW per motion burst, median across bursts
matched_filterone operator burst as a template, slid over the robot burst
peak_matchingthe speed peak of each reach on both hands, and the gap between them
bayesian_posteriorposterior over tau with the amplitude gain profiled out, MAP plus 95% CI

An estimator may abstain on a take it can’t measure; none did on any of the 21 recordings. Search windows are bounded — eight of the ten look at no more than 200–250 ms of lag — so a repetitive motion can’t easily be matched a whole cycle late. Samples sit on a 1 ms grid; most estimators refine their peak below that, while the two time-warping methods report whole milliseconds.

The two model-fitting estimators (arx_delay, kalman_bank) share one model and preprocessing and agree closely, as do the two cross-correlation methods; the two time-warping methods share a method and usually agree. That is why we count six families, not ten independent opinions.

5Results: the three stacks never overlap

Three stacks on the same Unitree G1 EDU+ in the same room: 9 recordings of rhoyn and 6 of each other stack, same two IMUs, same ten estimators. rhoyn’s slowest recording (21.6 ms) is faster than the fastest recording from either other stack (37.2 ms).

The spread matters as much as the median. rhoyn’s takes stay within 17.2–21.6 ms and ExtremControl’s range over 37.2–48.5 ms; GR00T’s varies over 69.5–98.7 ms, a spread of nearly 30 ms between takes.

Figure 4. One dot per recording, each the median of ten estimators. The tick is each stack’s median. Hover a dot for its value.
Show as a table
#rhoynXRoboToolkit + ExtremControlXRoboToolkit + GR00T
020.6 ms48.5 ms88.2 ms
119.4 ms47.7 ms94.9 ms
217.2 ms45.9 ms69.5 ms
320.3 ms43.2 ms90.5 ms
417.7 ms39.1 ms87.7 ms
520.8 ms37.2 ms98.7 ms
621.6 ms——
719.2 ms——
820.7 ms——
median20.3 ms44.5 ms89.3 ms

Full names: XRoboToolkit PICO VR + Genesis ExtremControl; XRoboToolkit PICO VR + NVIDIA GR00T low-latency weights.

6Against the published field: a ranking, not a like-for-like

The ExtremControl paper ranks ten published systems, its own included, by optical flow on their videos. Every row there is bound by the video’s frame rate — at 30 fps, ~33 ms, more than rhoyn’s entire latency — so the chart below is an order-of-magnitude ranking, not twelve numbers measured the same way.

One system appears in both instruments, and that is the useful check. We measured XRoboToolkit + ExtremControl at 44.5 ms; the paper reports ~54 (MoCap) and ~64 ms (VR) for ExtremControl. Our rig reads it faster. An instrument biased against competitors would have read it slower.

Figure 5. Xiong et al., arXiv:2602.11321, Table I, re-sorted by latency, with rhoyn’s IMU-measured 20.3 ms added, rounded to the precision the other rows can support.

7Limitations

  • End to end: a compliant joint counts as much as a network hop, so it can’t tell you which link to fix.
  • The robot shrinks and smooths your motion, which biases methods that expect a clean delayed copy; group_delay reads phase only and isn’t biased.
  • It reports a magnitude, never a negative lag: the robot is assumed to follow.
  • This is the instrument. How rhoyn reaches 20 ms is a separate article.

8Measure your own stack

Everything above runs from the repository. Two MPU6050 breakouts and one ESP32 are the whole rig: tape one board to the operator’s controller and one to the robot’s hand, put each on its own I2C bus (both boards answer to the same address), and flash esp32_firmware.cpp.

wiringbus A on pins 32/33, bus B on pins 25/26, both at 400 kHz; USB to the laptop at 921600 baud
record./record.sh --port /dev/ttyUSB0 --out inputs/my_take.csv — a healthy rig shows ~1000 samples/s with bad at 0
analyse./run.sh inputs/my_take.csv outputs/my_take.jpg — prints all ten estimates and the median, and writes the report grid
needsa C++17 compiler, Eigen and the stb headers

Drive the robot in bursts, ten to twenty reaches per take, and run the same protocol on every stack you compare.

9Try it yourself

The simulation the argument in section 1 is about, with the control link starting at 90 ms. Click it, then T/G moves the control latency (this article) and R/F the camera latency (the eyes article). Set control to 20 ms, then 90 ms, and try to place a hand exactly where you meant to.

rhoyn records training data on this stack.
Free pilot: 50 episodes of your task.

Book a 15-min call or see the data