Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sail-sg/envpool
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.1.0
Choose a base ref
...
head repository: sail-sg/envpool
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.1.1
Choose a head ref
  • 6 commits
  • 82 files changed
  • 1 contributor

Commits on Apr 5, 2026

  1. [atari] add mode and difficulty options (#379)

    ## Summary
    - Problem: EnvPool's Atari environments do not expose ALE `mode` and
    `difficulty`, so callers cannot select game variants through
    `envpool.make` as requested in #290.
    - Scope: Add `mode` / `difficulty` config plumbing for Atari env
    creation, cover it with tests, and document the new options. This does
    not add extra argument-validation behavior beyond the existing
    pass-through style.
    - Outcome: `envpool.make(..., mode=..., difficulty=...)` now selects ALE
    variants, and derived action spaces stay aligned with the requested
    settings.
    
    This exposes ALE's Atari variant controls through EnvPool while
    preserving the existing default behavior when callers do not opt in.
    
    ## Technical Details
    - Approach: Add `mode=-1` and `difficulty=-1` to the Atari config, and
    only forward non-negative values to ALE during both action-space
    inference and runtime environment initialization.
    - Code pointers:
    - `envpool/atari/atari_env.h`: adds the new config keys and forwards
    them into ALE in both spec and env construction paths.
    - `envpool/atari/api_test.py`: verifies the default values and explicit
    overrides.
    - `envpool/atari/atari_envpool_test.py`: checks that non-default Atari
    variants change reset observations.
      - `docs/env/atari.rst`: documents the new Atari options.
    - Notes: Keeping the default as `-1` preserves current behavior unless
    users explicitly request a mode or difficulty.
    
    ## Test Plan
    ### Automated
    - `bazel test --action_env=PATH="$PATH" //envpool/atari:api_test
    //envpool/atari:atari_env_test //envpool/atari:atari_envpool_test`:
    passed
    ### Suggested Manual
    - `python -c "from envpool.registration import make_gym; env =
    make_gym('Breakout-v5', mode=4, difficulty=1);
    print(env.action_space)"`: confirm a non-default Atari variant
    constructs correctly.
    - Compare `make_gym('Freeway-v5')` against `make_gym('Freeway-v5',
    mode=1)`: verify variant-specific behavior is only enabled when
    requested.
    Trinkle23897 authored Apr 5, 2026
    Configuration menu
    Copy the full SHA
    cae0792 View commit details
    Browse the repository at this point in the history
  2. [mujoco] add native frame_stack across Gym, DMC, and robotics (#380)

    ## Summary
    - Problem: MuJoCo frame stacking was missing from the native env
    observation path, so users needed Python-side wrappers and DMC/robotics
    did not preserve native multi-leaf observation structure.
    - Scope: Adds native C++ `frame_stack` support for Gym MuJoCo,
    dm_control suite envs, and Gymnasium-Robotics envs. This does not add
    pixel observations to the main obs pipeline.
    - Outcome: `frame_stack > 1` prepends a stack dimension per observation
    leaf, reset fills the stack with the first frame, step rolls and appends
    the latest frame, and `frame_stack = 1` preserves existing shapes and
    values.
    
    This diff adds native frame stacking for MuJoCo state observations
    across Gym, DMC, and robotics env families.
    
    ## Technical Details
    - Approach: Add a shared MuJoCo frame-stack helper that keeps one
    rolling buffer per observation key, then wire each env family to call it
    from C++ `WriteState`.
    - Code pointers:
    - `envpool/mujoco/frame_stack.h`: shared `StackSpec` and per-key
    `FrameStackBuffer`.
    - `envpool/mujoco/gym/mujoco_env.h`: Gym MuJoCo single-observation
    frame-stack path.
    - `envpool/mujoco/dmc/mujoco_env.h`: DMC multi-leaf observation
    frame-stack plumbing.
    - `envpool/mujoco/robotics/mujoco_env.h`: robotics multi-leaf
    observation frame-stack plumbing.
    - `envpool/mujoco/robotics/kitchen.h`: per-goal-leaf stack handling for
    Franka Kitchen.
    - Notes: `frame_stack = 1` is intentionally a no-op in both spec shape
    and write-path behavior.
    
    ## Test Plan
    ### Automated
    - `git diff --check`: passed.
    - `bazel test //envpool/mujoco:mujoco_envpool_test`: passed.
    - `bazel test //envpool/mujoco:mujoco_gym_deterministic_test
    --test_filter=frame_stack`: passed.
    - `bazel test //envpool/mujoco:mujoco_dmc_suite_deterministic_test
    --test_filter=frame_stack`: passed.
    - `bazel test //envpool/mujoco:robotics_test --test_filter=frame_stack`:
    passed.
    
    ### Suggested Manual
    - `python - <<'PY'`
      `from envpool.registration import make_gymnasium`
      `env = make_gymnasium("HalfCheetah-v5", num_envs=1, frame_stack=4)`
      `obs, _ = env.reset()`
      `print(obs.shape)`
      `PY`
    Verify a simple Gym MuJoCo env reports the expected stacked observation
    shape.
    Trinkle23897 authored Apr 5, 2026
    Configuration menu
    Copy the full SHA
    487ab61 View commit details
    Browse the repository at this point in the history

Commits on Apr 6, 2026

  1. [mujoco] add native pixel observations (#381)

    ## Summary
    - Problem: MuJoCo tasks did not expose a native pixel-observation path,
    and the earlier Python render-wrapper approach was slower and only
    covered part of the suite.
    - Scope: Add native C++ pixel observations for MuJoCo DMC, Gym, and
    Gymnasium-Robotics tasks, including BCHW frame stacking,
    render-alignment tests, and user docs. This change does not alter
    non-pixel observation paths.
    - Outcome: `from_pixels=True` now returns native `uint8` pixel
    observations across all MuJoCo families and stays aligned with
    `render()` across reset and step transitions.
    
    This change moves MuJoCo pixel observations onto the native C++ path
    instead of relying on Python-side render wrappers.
    
    ## Technical Details
    - Approach: extend the shared MuJoCo frame-stack helpers to support
    native pixel observations, export pixel `EnvSpec` and `EnvPool` variants
    for each MuJoCo family, and route `from_pixels=True` through
    registry-based variant selection. Keep a render cache only for robotics,
    where render callbacks mutate visualization state.
    - Code pointers:
    - `envpool/mujoco/frame_stack.h`: shared pixel observation spec, BCHW
    conversion, and frame-stack buffer implementation.
    - `envpool/registration.py`: `from_pixels` variant resolution plus
    wrapper/render configuration handling.
    - `envpool/mujoco/dmc/mujoco_env.h`: representative native pixel write
    path; Gym and robotics follow the same pattern.
    - `envpool/mujoco/pixel_observation_test_utils.py`: shared
    render-alignment checks used by the family-specific pixel observation
    tests.
    - Notes: pixel observations are exposed as `uint8` in BCHW layout;
    robotics keeps a render cache so `obs == render()` remains stable within
    the same step.
    
    ## Test Plan
    ### Automated
    - `python -m py_compile envpool/registration.py`: passed
    - `ruff check envpool/registration.py`: passed
    - `bazel test --config=test
    //envpool/mujoco:mujoco_dmc_pixel_observation_test
    //envpool/mujoco:mujoco_gym_pixel_observation_test
    //envpool/mujoco:robotics_pixel_observation_test
    //envpool/mujoco:mujoco_render_test
    //envpool/mujoco:mujoco_dmc_render_test //envpool/mujoco:robotics_test`:
    passed
    ### Suggested Manual
    - Create one env from each MuJoCo family with `from_pixels=True`,
    `render_mode="rgb_array"`, and `frame_stack>1`; verify the returned
    observation layout is `(B, 3 * frame_stack, H, W)`.
    - For one representative task, step a few times and confirm the latest
    observation channels match `env.render(env_ids=[...])`.
    Trinkle23897 authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    9973397 View commit details
    Browse the repository at this point in the history
  2. [minigrid] inline bindings into pybind extension (#383)

    ## Summary
    - Problem: `minigrid` bindings lived in a standalone `cc_library`, so
    `//envpool/minigrid_bindings:minigrid_bindings` picked up its own very
    slow clang-tidy action.
    - Scope: Move the binding implementation into the existing
    `pybind_extension`, delete the standalone `minigrid_bindings` BUILD
    target, and keep `minigrid_bindings.cc` changes out of the clang-tidy
    target resolver while still letting `minigrid.cc` and core
    implementation changes select `minigrid_env`.
    - Outcome: Minigrid bindings now build as part of `minigrid_envpool`,
    and binding-only edits no longer trigger a separate binding clang-tidy
    run.
    
    This folds the minigrid binding implementation back into the
    package-local pybind module and preserves the intended clang-tidy
    behavior for binding-only changes.
    
    ## Technical Details
    - Approach: Add `minigrid_bindings.cc` to `minigrid_envpool`, depend on
    `:minigrid_env` and `//envpool/core:py_envpool` directly, and remove the
    obsolete `envpool/minigrid_bindings` package.
    - Code pointers:
    - `envpool/minigrid/BUILD`: `minigrid_envpool` now owns both binding
    sources and no longer depends on a separate binding library.
    - `envpool/minigrid/minigrid_bindings.cc`: binding implementation moved
    under the `minigrid` package.
    - `scripts/clang_tidy_targets.py`: binding-only file filtering now skips
    `envpool/minigrid/minigrid_bindings.cc` while keeping `minigrid.cc`
    clang-tidy-relevant.
    - Notes: `minigrid.cc` still resolves to
    `//envpool/minigrid:minigrid_env`; only `minigrid_bindings.cc` is
    filtered out.
    
    ## Test Plan
    ### Automated
    - `git diff --check`: pass
    - `bazelisk query 'kind("cc_(library|test)", //envpool/minigrid:*)'`:
    returns only `//envpool/minigrid:minigrid_env`
    - `python3 scripts/clang_tidy_targets.py
    envpool/minigrid/minigrid_bindings.cc`: returns no targets
    - `python3 scripts/clang_tidy_targets.py envpool/minigrid/minigrid.cc`:
    returns `//envpool/minigrid:minigrid_env`
    ### Suggested Manual
    - `bazelisk build --config=test //envpool/minigrid:minigrid_envpool`:
    verify the merged binding target still builds cleanly
    - Run the clang-tidy workflow on a binding-only diff to confirm there is
    no standalone binding clang-tidy action
    Trinkle23897 authored Apr 6, 2026
    Configuration menu
    Copy the full SHA
    78eaa96 View commit details
    Browse the repository at this point in the history

Commits on Apr 7, 2026

  1. [release] Keep Linux x86_64 cp312 wheel under PyPI's 100 MB limit (#384)

    ## Why
    
    Fixes #382. The Linux `x86_64` `cp312` wheel can exceed PyPI's 100 MB
    upload limit, so the release path needs both a smaller wheel and a guard
    that catches regressions before a tagged release.
    
    ## Summary
    
    - prune 41 unused Gymnasium-Robotics assets at the Bazel `third_party`
    layer so they never enter the wheel
    - add Linux wheel optimization and size-check scripts and wire them into
    `make pypi-wheel`
    - fold the wheel-size guard into the existing `release.yml` flow by
    making the Linux matrix dynamic: full matrix on `main` and release tags,
    `x86_64 + py3.12` only on PRs and non-release pushes
    - bump the package version to `1.1.1`
    
    ## Testing
    
    - `ruff check scripts/check_wheel_size.py
    scripts/optimize_linux_wheel.py`
    - `python3 -m compileall scripts/check_wheel_size.py
    scripts/optimize_linux_wheel.py`
    - `ruby -e 'require "yaml";
    YAML.load_file(".github/workflows/release.yml"); puts "release.yml OK"'`
    - `actionlint .github/workflows/release.yml`
    - `python3 scripts/check_wheel_size.py --limit-bytes 100000000
    /tmp/envpool-1.1.0-cp312-cp312-linux_x86_64.whl` on `dev` (`82,513,674`
    bytes)
    - `bazelisk query "labels(srcs,
    @gymnasium_robotics_assets//:gymnasium_robotics_assets)"` on `dev`
    confirmed 137 exported files after excluding 41 unused assets
    - `make release-test2` on `dev`
    
    ## Notes
    
    - `make release-test1` currently segfaults in the VizDoom smoke
    (`test_make_vizdoom`) on `dev`; I did not use it as a validation signal
    for this packaging-only change.
    Trinkle23897 authored Apr 7, 2026
    Configuration menu
    Copy the full SHA
    be0c079 View commit details
    Browse the repository at this point in the history
  2. [release] Reduce Linux wheel size by excluding Qt (#385)

    ## Summary
    - Problem: Linux Procgen wheels were close to the PyPI size limit
    because auditwheel bundled Qt/ICU runtime libraries, and missing system
    Qt produced a poor `task not supported` path.
    - Scope: Exclude Linux Qt from repaired wheels, add release size flags,
    route all release platforms through `make pypi-wheel`, document the
    Procgen Qt requirement, add release smoke coverage, and disable
    test-cache pruning.
    - Outcome: Linux Procgen wheels rely on system Qt with a direct runtime
    error when Procgen is used without Qt, while non-Procgen envs such as
    Atari continue to work.
    
    This keeps release wheels below the stricter 100,000,000 byte limit
    without making Qt a global runtime dependency.
    
    ## Technical Details
    - Approach: Add release-size Bazel configs, make `pypi-wheel`
    platform-aware, and pass auditwheel `--exclude` for Linux Qt libraries.
    - Code pointers:
      - `.bazelrc`: release-size compiler/linker flags for Linux and macOS.
    - `Makefile`: unified platform-aware `pypi-wheel`, 100,000,000 byte size
    limit, and Procgen Qt release smoke target.
    - `.github/workflows/release.yml`: run `make pypi-wheel` on
    Linux/macOS/Windows and verify the Linux no-Qt runtime behavior after
    uninstalling Qt.
    - `.github/workflows/test.yml`: comment out test cache pruning so
    multiple test cache generations can coexist.
    - `envpool/procgen/__init__.py`: defer Linux Qt import failures so
    Procgen tasks still register and `envpool.make(...)` reports the Qt
    runtime hint.
    - `scripts/release_procgen_qt_smoke.py`: release smoke coverage for
    Qt-present and Qt-absent Procgen behavior.
    - Notes: Windows still bundles the Qt DLLs next to the Procgen
    extension; Linux intentionally does not vendor Qt.
    
    ## Test Plan
    ### Automated
    - `make COMMIT_HASH=be0c079 RELEASE_PYTHON=3.12
    PYPI_WHEEL_PLAT=manylinux_2_39_x86_64 pypi-wheel`: passed on devbox
    proxy build; final wheel was 70,468,911 bytes.
    - Installed the devbox-built wheel and ran a 200-step Procgen smoke
    test: passed.
    - `python3 -m compileall envpool/procgen/__init__.py
    scripts/release_procgen_qt_smoke.py`: passed.
    - Inline Python smoke with simulated missing `libQt5Core.so.5`: passed,
    including direct `envpool.make("CoinrunEasy-v0", ...)` Qt hint.
    - `make -n release-test`
    - `make -n release-test-procgen-qt PROCGEN_QT_RUNTIME=present`
    - `make -n release-test-procgen-qt PROCGEN_QT_RUNTIME=absent`
    - PyYAML parsed `.github/workflows/release.yml`,
    `.github/workflows/test.yml`, and `.github/workflows/clang-tidy.yml`:
    passed.
    - `doc8 docs`: passed.
    - `git diff --check` and `git diff --cached --check`: passed.
    
    ### Suggested Manual
    - Let the release Linux CI jobs run in GitHub Actions to verify the real
    manylinux_2_28 wheel and the post-uninstall Qt smoke step.
    Trinkle23897 authored Apr 7, 2026
    Configuration menu
    Copy the full SHA
    53aaa0c View commit details
    Browse the repository at this point in the history
Loading