Repository navigation
feat: support optional rng for deterministic scene placement sampling - #300
Open
akushonkamen wants to merge 1 commit into
Open
akushonkamen wants to merge 1 commit into
akushonkamen wants to merge 1 commit into
Conversation
…jam#232) Reset-time object placement sampling relied on the global numpy random state (np.random.uniform/choice in rlbench/backend/spawn_boundary.py), so resets were not reproducible even with a fixed global seed, and the number of draws changes when Scene.init_episode retries (max_attempts). Add an optional rng to SpawnBoundary/BoundaryObject, Scene, DomainRandomizationScene and Environment. When rng is provided (e.g. np.random.default_rng(seed)), all placement sampling draws are taken from it, making placements reproducible independent of the global numpy state. When omitted, behavior is unchanged (np.random global). Includes a CoppeliaSim-free unit test for SpawnBoundary determinism (same seed => identical placements; different seed => different), RandomState support, unchanged global-np.random fallback, and BoundaryError accounting.
This branch has not been deployed
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.
Summary
Resets in RLBench are not reproducible even when the global numpy seed is fixed: object placement sampling at reset time draws exclusively from the global numpy random state, and the number of draws varies with
max_attemptsretries. This PR adds an optional, explicitrngthat is threaded through the placement-sampling call chain, making resets deterministic when a seeded generator is supplied, while leaving all existing callers byte-identical in behavior.Fixes #232
Root cause
Reset-time object placement sampled exclusively from the global numpy random state:
np.random.uniform(...)inBoundaryObject._get_position_within_boundaryand in the rotation sample (rlbench/backend/spawn_boundary.py:72-83,103pre-PR),np.random.choice(...)for boundary selection inSpawnBoundary.sample(rlbench/backend/spawn_boundary.py:159pre-PR),consumed via
Scene.init_episode/Scene._place_task(rlbench/backend/scene.py:127-146,529-537). Two consequences:np.random.seed(...)fixed, any other consumer of the global state (task code, other libraries, unrelated resets) shifts every subsequent placement, so episode resets cannot be replayed.max_attemptsretries consumes extra draws, so a later sampling call's value depends on earlier retries.Fix
An optional
rngparameter (acceptsnp.random.Generator,np.random.RandomState, or any object exposinguniform+choice) is threaded through the chain:DomainRandomizationScenepasses it through as well. Defaultrng=Nonefalls back to thenp.randommodule, so all ~30 existing taskSpawnBoundary(...)sites,tools/task_builder.py:289andtools/task_validator.py:142behave exactly as before, with no changes required.Changes
rlbench/backend/spawn_boundary.py:SpawnBoundary.__init__/BoundaryObject.__init__acceptrng=None;uniform/choicecalls route to it; docstring documents the parameter.rlbench/backend/scene.py:Scene.__init__acceptsrng=Noneand forwards it to everySpawnBoundaryconstruction.rlbench/sim2real/domain_randomization_scene.py: passthrough.rlbench/environment.py:Environment.__init__acceptsrng=Noneand forwards toScene.tests/unit/test_spawn_boundary.py(new): CoppeliaSim-free regression tests.Example
Testing
New tests in
tests/unit/test_spawn_boundary.pyrun without CoppeliaSim/PyRep (pyrep is stubbed only when it is unimportable, so CI with PyRep installed is unaffected). 7 tests: same-seed placements identical across repeatedSpawnBoundaryinstances; different seed yields different placements; positions stay within boundary;RandomStatesupported; global-np.randombackward-compat fallback; boundary-selection accounting;BoundaryErrorstill raised for oversized objects.Red → green, verified locally (macOS arm64, no CoppeliaSim/PyRep):
python3 -m unittest tests.unit.test_spawn_boundary→
Ran 7 tests ... FAILED (errors=6)— allTypeError: SpawnBoundary.__init__() got an unexpected keyword argument 'rng'; the global-np.randombackward-compat guard passed.python3 -m unittest tests.unit.test_spawn_boundary -v→
Ran 7 tests ... OK(7/7).python3 -m py_compileon the 5 touched files → OK.Not run: the repo CI unit suite (
pytest -v -n auto tests/unitper.github/workflows/unit_tests.yml) requires CoppeliaSim + PyRep, which are not installable on this machine; all other pre-existingtests/unitmodules fail at import here withModuleNotFoundError: No module named 'gymnasium'(verified on untouchedtest_task_sets, pre-existing/environmental). No lint config exists in the repo (nosetup.cfg/.flake8/pyproject.toml/tox.ini).AI disclosure
This fix was developed with the assistance of an AI coding agent (code changes, tests, and PR description drafted by the agent, reviewed and submitted by me).