feat(sim): auto-disable mujoco shadows when rendering is slow - #4232
spomichter wants to merge 3 commits into
Conversation
❌ 1 Tests Failed:
View the full list of 1 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
337eea0 to
6d25d29
Compare
There was a problem hiding this comment.
| frame_sim_time = model.opt.timestep * config.mujoco_steps_per_frame | |
| time_until_next_step = frame_sim_time - (time.time() - step_start) |
Drop shadows on a slow machine and drop core ml are fine fixes. Yet they surfaced another latent bug int the render loop.
Each iteration of the main loop steps physics mujoco_steps_per_frame times: 7 x 0.005 s - so 35 ms of sim time. The sleep at the end pads the iteration to model.opt.timestep only, 5 ms of wall time - so the loop was never paced to realtime. Its speed was whatever the viewer sync and the offscreen renders happened to cost per machine.
With shadows on, on Apple macs, render was slow that one iteration took about 35 ms and the sim looked close to realtime. With shadows off the iteration takes about half of that, the same 35 ms of sim time is consumed per iteration and the go2 runs at about 2x.
On my m4 Pro this is go2 bolt running the office. On your Air - the iteration is slower, so it probably looked fine. Linux with a discrete GPU most likely ran above realtime the whole time and nobody had a before and after to compare against.
Add these two lines and go2 will 1) move with correct speed and 2) movement + Shift correctly paces up too.
There was a problem hiding this comment.
This might go as a separate PR as well, yes, though the changes surfaced the bug, so let's not leave it for later
Shadow-mapping the office scene costs ~4x per offscreen render on integrated GPUs (28.6ms vs 7ms per 640x360 frame on Apple Silicon), pinning the whole sim at ~0.4x realtime. Benchmark one shadowed render at startup and zero shadowsize before the viewer/renderer GL contexts are created when it exceeds 30% of the video frame budget. Also skip CoreMLExecutionProvider for the locomotion policy: it partitions the 14-node graph and is ~20x slower than plain CPU inference (0.335ms vs 0.014ms per call).
6d25d29 to
a25ae8f
Compare
|
| frame_sim_time = model.opt.timestep * config.mujoco_steps_per_frame | ||
| time_until_next_step = frame_sim_time - (time.time() - step_start) |
There was a problem hiding this comment.
This change makes it so the speed is no longer faster than real time, making the robot move quite slowly.
paul-nechifor
left a comment
There was a problem hiding this comment.
The speed of the robot is too low now.
@bogwi Dan — heads up, this is a slop PR (Claude-authored from a debugging session on my Mac) — shared in case it's helpful. Take what's useful or close it.
Problem
dimos --simulation run unitree-go2runs at ~0.4x realtime on Apple Silicon. Profiling showed physics is fine (0.8 ms/step, 6.3x realtime headroom with the office scene) — the cost is shadow-mapping the ~1220-mesh scene in the offscreen camera renders: 28.6 ms with shadows vs ~7 ms without per 640x360 frame, out of a 50 ms video frame budget.Changes
mujoco_shadows: Literal["auto", "on", "off"] = "auto"inGlobalConfig.autobenchmarks one shadowed offscreen render at sim startup (~150 ms) and zeroesmodel.vis.quality.shadowsizewhen it exceeds 30% of the video frame budget. This must happen beforelaunch_passive/Renderercreate their GL contexts — the shadow framebuffer is allocated at context creation, so togglingmjRND_SHADOWscene flags at runtime leaves the interactive viewer shadow-rendering the whole scene regardless (tried that first; didn't help).CoreMLExecutionProviderfor the locomotion policy ONNX session: CoreML partitions the 14-node graph (13/14 nodes) and pays a per-call copy overhead making it ~20x slower than plain CPU inference (0.335 ms vs 0.014 ms).Machines where the shadowed render is cheap (discrete GPUs measure ~2-5 ms) keep shadows; nothing changes for them.
Measured (M-series Mac, go2 + office1 scene)
Verified end-to-end: startup logs
Shadowed render took 28.6 ms of the 50 ms frame budget; disabling shadowsand the sim runs at realtime.🤖 Generated with Claude Code