Skip to content

feat(go2): joystick, tele_cmd_vel and cmd_vel plots, live and in replay, with a dataset - #4224

Open
KrishnaH96 wants to merge 4 commits into
mainfrom
krishna/feat/go2-record-joystick-cmdvel
Open

KrishnaH96 wants to merge 4 commits into
mainfrom
krishna/feat/go2-record-joystick-cmdvel

Conversation

@KrishnaH96

@KrishnaH96 KrishnaH96 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Dataset sample with displaying of cmd_vel and joystock

Problem

--record already stores tele_cmd_vel and cmd_vel, but the viewer never shows them: Twist has no to_rerun(), so the Rerun bridge drops it. The viewer's WASD input is also not published in raw form.

Solution

  • RerunWebSocketServer publishes the viewer's twist message as joystick: Out[Joy] before converting it to tele_cmd_vel.
  • Twist.to_rerun() and Joy.to_rerun() return rr.Scalars, so these streams plot in any viewer config. Replaces the _plot_cmd_vel override from feat: replay blueprint - dimos --replay-db <memory.db> run replay #3738.
  • Go2 layout: joystick, tele_cmd_vel, cmd_vel boxes under the camera, one color per axis, step interpolation so silent gaps do not draw as ramps.
  • Replay fallback layout: one plot box per recorded Twist or Joy stream.
  • LFS dataset go2_teleop_sf_office_2026-09-18 (379 MB): 3 min real Go2 run, WASD driving, then two click-to-go nav goals at 2:23 and 2:44.

Note: dimos-viewer converts keys to velocities itself, so today joystick equals tele_cmd_vel value for value. tele_cmd_vel vs cmd_vel is the pair that diverges, whenever nav drives.

No new blueprint needed: unitree-go2 already publishes all three streams.

How to Test

dimos --replay-db go2_teleop_sf_office_2026-09-18 run replay
Screencast_2026-09-18_14-50-29.mp4

Recorded and replayed on a real Go2 over WebRTC. Dataset recorded with #3914 applied, so the camera frustum shows in replay.

AI assistance

Claude Code (Claude Fable 5.1) helped survey the code, draft the change and run the checks. I reviewed and tested the code on hardware.

Checklist

  • I have read and approved the CLA.

@codecov

codecov Bot commented Sep 18, 2026

Copy link
Copy Markdown

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
6091 1 6090 103
View the full list of 1 ❄️ flaky test(s)
dimos.e2e_tests.test_voice_browser::test_hold_to_talk_ships_a_decodable_recording[firefox]

Flake rate in main: 68.75% (Passed 5 times, Failed 11 times)

Stack Traces | 22.8s run time
voice_bridge = ('http://127.0.0.1:63461/', [])
fake_mic_page = <Page url='http://127.0.0.1:63461/'>

    def test_hold_to_talk_ships_a_decodable_recording(
        voice_bridge: tuple[str, list[AudioChunk]], fake_mic_page: Page
    ) -> None:
        url, chunks = voice_bridge
        chunks.clear()  # the module fixture is shared across both engines
        fake_mic_page.goto(url)
        mic = fake_mic_page.get_by_test_id("chat-audio_in-mic")
        # Enabled == transport connected; the manifest already placed the panel.
        expect(mic).to_be_enabled(timeout=120_000)
        expect(mic).to_have_attribute("data-state", "idle")
    
        mic.hover()
        fake_mic_page.mouse.down()
>       expect(mic).to_have_attribute("data-state", "recording", timeout=15_000)
E       AssertionError: Locator expected to have attribute 'recording'
E       Actual value: arming 
E       Call log:
E         - Expect "to_have_attribute" with timeout 15000ms
E         - waiting for get_by_test_id("chat-audio_in-mic")
E       
E       Aria snapshot:
E       - button "hold to talk": talk

chunks     = []
fake_mic_page = <Page url='http://127.0.0.1:63461/'>
mic        = <Locator frame=<Frame name= url='http://127.0.0.1:63461/'> selector='internal:testid=[data-testid="chat-audio_in-mic"s]'>
url        = 'http://127.0.0.1:63461/'
voice_bridge = ('http://127.0.0.1:63461/', [])

dimos/e2e_tests/test_voice_browser.py:104: AssertionError

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@greptile-apps

greptile-apps Bot commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

Safe to merge; there are no blocking issues.

Summary

The PR adds live and replay visualization for joystick and velocity-command telemetry, publishes raw viewer controls as Joy, supplies scalar conversions for Joy and Twist, and adds a recorded Go2 dataset. The replay layout now retains command plots for recordings that have no image stream.

Reviews (2) · Last reviewed commit: "fix(replay): keep plots in the fallback ..."

@greptile-apps

This comment has been minimized.

@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Sep 18, 2026
Base automatically changed from feat/replay-cmd to main September 19, 2026 10:13
@KrishnaH96
KrishnaH96 force-pushed the krishna/feat/go2-record-joystick-cmdvel branch from 7889c00 to 4fb3363 Compare September 19, 2026 19:25
@github-actions github-actions Bot removed the ready-to-merge Required CI checks have passed on this PR label Sep 19, 2026
@KrishnaH96

Copy link
Copy Markdown
Contributor Author

Fixed in 4fb3363: the replay fallback layout now keeps the plot boxes when a recording has no image stream, with a test (test_rerun_layout_keeps_plots_without_an_image_stream). Also rebased onto main now that #3738 is merged, so the diff is back to just this PR's changes.

@KrishnaH96

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review.

@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Sep 19, 2026
RerunWebSocketServer publishes the viewer's raw twist message as
joystick: Out[Joy], six axes in the viewer's field order, before it
converts it to tele_cmd_vel, so --record stores both.
Three time series boxes under the camera, fed by converters in the Go2
viewer config like the odom plot: one color per axis across all three
and step interpolation, since command streams go silent between bursts.
Replay reuses this config, so the boxes show there too.
…cording

run replay picks the viewer layout from the recording's run folder name,
so a dataset pulled from LFS gets the generic layout: no odom plot, no
joystick or velocity plots. unitree-go2-replay pairs the replay module
with the Go2 viewer config directly, same pattern as spot-replay.
Three minute Go2 run recorded with dimos --record run unitree-go2: WASD
driving from the viewer, then two click-to-go nav goals. Carries
joystick, tele_cmd_vel, cmd_vel, nav_cmd_vel, lidar, global_map,
color_image, camera_info, odom and tf.
@KrishnaH96
KrishnaH96 force-pushed the krishna/feat/go2-record-joystick-cmdvel branch from 4fb3363 to df0be26 Compare September 19, 2026 22:58
@github-actions github-actions Bot removed the ready-to-merge Required CI checks have passed on this PR label Sep 19, 2026
@github-actions github-actions Bot added the ready-to-merge Required CI checks have passed on this PR label Sep 19, 2026
@KrishnaH96

Copy link
Copy Markdown
Contributor Author

Alternative: #4242 keeps the default unitree-go2 window untouched and adds a dedicated unitree-go2-joystick blueprint instead. Both are tested on hardware;
@spomichter pick either and I will close the other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Required CI checks have passed on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant