fix: 3D joint view drifting out of sync during long teleoperation ses…#73
Open
ZouzouWP wants to merge 1 commit into
Open
fix: 3D joint view drifting out of sync during long teleoperation ses…#73ZouzouWP wants to merge 1 commit into
ZouzouWP wants to merge 1 commit into
Conversation
…sions
The live 3D arm view in the browser would drift further and further behind the real robot the longer a session ran, and it never recovered on its own — restarting the connection only reset it temporarily.
## Root cause
Joint-position frames were pushed onto a FIFO queue and broadcast in order. If the browser tab ever fell even slightly behind the ~30fps producer — a GC pause, a slow render, a backgrounded tab — frames piled up faster than they drained. Every future frame then had to wait behind a growing backlog of stale ones, so the lag only ever grew, never shrank.
```mermaid
flowchart LR
subgraph before["Before: FIFO queue"]
P1["Producer ~30fps"] --> Q["Queue\n(grows if consumer is slow)"] --> C1["Consumer"]
end
subgraph after["After: latest-wins slot"]
P2["Producer ~30fps"] -->|overwrites| S["Single slot\n(always newest)"] --> C2["Consumer\n(never behind)"]
end
```
## Fix
- Joint updates now go into a single-slot "latest-wins" buffer instead of the FIFO queue: a new frame overwrites whatever hasn't been sent yet, so a slow consumer skips straight to the most recent pose instead of catching up through a backlog.
- Broadcast poll interval tightened from 20fps to 30fps to match the teleoperation loop's own rate.
- Added support for a per-arm `urdf_view_zero.json` (a zero pose captured by the user against the URDF's own rest pose), which takes priority over the previous hardcoded correction — that one assumed a canonical calibration and was off by ~200° for this arm.
## Testing
Measured 17.5ms median WebSocket-to-render latency with zero drift over a long session (previously drifted continuously and never recovered).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The live 3D arm view in the browser would drift further and further behind the real robot the longer a session ran, and it never recovered on its own — restarting the connection only reset it temporarily.
Root cause
Joint-position frames were pushed onto a FIFO queue and broadcast in order. If the browser tab ever fell even slightly behind the ~30fps producer — a GC pause, a slow render, a backgrounded tab — frames piled up faster than they drained. Every future frame then had to wait behind a growing backlog of stale ones, so the lag only ever grew, never shrank.
flowchart LR subgraph before["Before: FIFO queue"] P1["Producer ~30fps"] --> Q["Queue\n(grows if consumer is slow)"] --> C1["Consumer"] end subgraph after["After: latest-wins slot"] P2["Producer ~30fps"] -->|overwrites| S["Single slot\n(always newest)"] --> C2["Consumer\n(never behind)"] endFix
urdf_view_zero.json(a zero pose captured by the user against the URDF's own rest pose), which takes priority over the previous hardcoded correction — that one assumed a canonical calibration and was off by ~200° for this arm.Testing
Measured 17.5ms median WebSocket-to-render latency with zero drift over a long session (previously drifted continuously and never recovered).