Skip to content

Name the PyBullet client in every env call so envs can share a process - #199

Merged
yichao-liang merged 1 commit into
masterfrom
fix-robodisco-cross-env-leak
Oct 3, 2026
Merged

yichao-liang merged 1 commit into
masterfrom
fix-robodisco-cross-env-leak

Conversation

@yichao-liang

Copy link
Copy Markdown
Collaborator

Summary

The bug.
Building robodisco/Circuit-v0, Laser-v0 or Switch-v0 after any other environment in the same process failed, with "getJointState failed; invalid jointIndex" for Circuit and Switch and "GetJointInfo failed." for Laser.
scripts/robodisco_getting_started.py reset only 19 of the 22 environments.
Each env owns a PyBullet client, but these three looked up their switch joints without physicsClientId, so PyBullet answered from client 0, the first world the process built.

The same omission, without a crash.

  • Laser created its beam bodies in client 0. During planning, the planner's world (the option model's env, built after the executing env) drew its beams into the executing env's world, and its bookkeeping then removed bodies with those ids from its own world. This is the "beams from planning contaminate the test videos" problem the old comment in pybullet_laser.py described.
  • Coffee joined its cord segments and its plugged-in plug with constraints in client 0 (with coffee_machine_has_plug).
  • The Domino fan component read its switch joints from client 0.

The fix.
Each of these calls now names the env's client, as do the five calls that passed it positionally.
tests/test_pybullet_client_ids.py parses the package and requires physicsClientId= on every PyBullet call that reaches a physics server; on the old code it flags every site above.
The envs README and the smoke script no longer describe the failure, and the smoke script numbers its seven steps out of seven.

Test plan

  • The reported repro (build Blocks, then Circuit, Laser or Switch, in one process): all three now reset and step.
  • scripts/robodisco_getting_started.py: 22/22 environments reset.
  • The new tests fail on the old code and pass here: tests/test_pybullet_client_ids.py, tests/envs/test_pybullet_laser.py (beam bodies stay in Laser's own world) and tests/envs/test_robodisco.py::test_env_builds_after_another_env.
  • yapf 0.32.0, isort 5.10.1, docformatter 1.4, mypy 1.8.0 and pylint on the whole repo.
  • The full test suite on the top of this stack (Keep each PyBullet world's body ids on its own Objects #202), in CI's Ubuntu 24.04 container.

This is the first of four stacked PRs fixing the environment bugs found while auditing the envs README in #197: this one, #200 (Domino and Fan), #201 (Grow's and Coffee's NSRT samplers) and #202 (Coffee's cups).

🤖 Generated with Claude Code

Circuit, Laser and Switch looked up their switch joints without
physicsClientId, so PyBullet answered from client 0, the first world
the process built. Built after any other env (through the RoboDisco
wrapper, in a test session, or in scripts/robodisco_getting_started.py)
they read the wrong world and failed with "getJointState failed;
invalid jointIndex" or "GetJointInfo failed.".

The same omission sat in calls that never crash. Laser created its beam
bodies in client 0, so the planner's world drew beams into the
executing env's world, and its bookkeeping then removed bodies from its
own. Coffee joined its cord segments and its plugged-in plug with
constraints in client 0, and the Domino fan component read its switch
joints from client 0.

Each of these calls now names the env's client, as do the few calls that
passed it positionally, so tests/test_pybullet_client_ids.py can require
physicsClientId= on every PyBullet call that reaches a physics server.
Regression tests build Circuit, Laser and Switch after Blocks in one
process and check that Laser's beams appear in its own world only.

The envs README and the smoke script no longer describe the failure, and
the smoke script numbers its seven steps out of seven.
@yichao-liang
yichao-liang merged commit abea45a into master Oct 3, 2026
14 checks passed
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.

1 participant