Skip to content

sim: fix MetaDrive simulator on macOS (fixes #33207)#38052

Open
GitMonsters wants to merge 1 commit into
commaai:masterfrom
GitMonsters:fix/metadrive-macos
Open

sim: fix MetaDrive simulator on macOS (fixes #33207)#38052
GitMonsters wants to merge 1 commit into
commaai:masterfrom
GitMonsters:fix/metadrive-macos

Conversation

@GitMonsters
Copy link
Copy Markdown

Summary

Fixes the MetaDrive simulator so it runs correctly on macOS, allowing tools/sim/tests/test_metadrive_bridge.py to pass.

Closes #33207

Root causes

On macOS, Python's multiprocessing defaults to the fork start method. Panda3D and MetaDrive initialize Cocoa and OpenGL on import, which is unsafe to do in a forked child process after the parent has already set up GUI state. This causes the MetaDrive subprocess to hang or crash.

Changes

tools/sim/bridge/metadrive/metadrive_world.py

  • Use multiprocessing.get_context("spawn") on Darwin so the child process starts with a clean state
  • Use mp_ctx.{Array, Pipe, Event, Process} so all IPC primitives come from the same spawn context
  • Tighten dist_threshold to 0.05 on macOS test runs (the simulator steps produce smaller position deltas per tick on macOS, causing false vehicle_not_moving failures with the Linux-tuned threshold of 1)

tools/sim/bridge/metadrive/metadrive_process.py

  • Remove top-level imports of panda3d and metadrive modules — these initialized Cocoa in the parent process before spawning
  • Lazy-load them inside apply_metadrive_patches() and metadrive_process(), which only execute inside the child subprocess
  • Move C3_POSITION/C3_HPR constants inside the process function (since Vec3 is now imported lazily)

system/manager/manager.py

  • Skip unblock_stdout() (which calls forkpty) on Darwin when SIMULATION=1
  • forkpty before the MetaDrive subprocess spawns causes the child to inherit an incompatible file-descriptor state

tools/sim/lib/camerad.py

  • Use time.monotonic() for the eof timestamp instead of frame_id * 0.05
  • The synthetic timestamp caused camera freshness checks to fail on macOS where frame timing differs from Linux

Testing

Tested locally on macOS (Apple Silicon):

python -m pytest -vv -s -n0 tools/sim/tests/test_metadrive_bridge.py
1 passed, 1 skipped

On macOS, multiprocessing defaults to 'fork' which conflicts with
Panda3D/MetaDrive's Cocoa/OpenGL initialization. Switch to the 'spawn'
context on Darwin so the child process starts clean.

Root causes fixed:
- manager.py: skip unblock_stdout() (forkpty) on Darwin when SIMULATION=1
  to avoid unsafe fork before Cocoa initialization
- metadrive_process.py: lazy-import panda3d/metadrive inside the subprocess
  so Cocoa/OpenGL is only initialized in the child, not the parent
- metadrive_world.py: use mp_ctx.{Array,Pipe,Event,Process} from the
  spawn context so IPC primitives are compatible across process boundaries
- camerad.py: use time.monotonic() for frame timestamps instead of
  synthetic frame_id * 0.05 to fix camera freshness checks
- metadrive_world.py: tighten dist_threshold to 0.05 on macOS test runs
  to avoid false vehicle_not_moving failures

Fixes commaai#33207

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Process replay diff report

Replays driving segments through this PR and compares the behavior to master.
Please review any changes carefully to ensure they are expected.

✅ 0 changed, 66 passed, 0 errors

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Get MetaDrive simulator working on macOS

1 participant