Commit 69914828 authored by ooctipus's avatar ooctipus Committed by Kelly Guo

Supports composite observation space with proper min max in manager based env (#2811)

This PR supports enables ManagerBasedRLEnv to properly support
gymnaisum's composite observation gym.spaces.Dict at term-level with
proper min, max specification. The benefit is that this will give
rl-library a clearer signs how to pre-process the obseravtion data.

Before:
All terms are assigned with `gym.Spaces.Box(min=-np.inf, max=np.inf)`,
one problem with this is that from rl-library side, is that some
rl-libraries network construction depends heavily on observations space
details. RL-library (e.g. sb3) looks at `gym.Spaces.Box.min` and
`gym.Spaces.Box.max` to determine if they need to normalize it at
library side.

After:
this PR utilizes on obs_terms's clip to determine if gym.Spaces.Box
should be stricter. For example, environment obs_term returning
gym.Spaces.Box(min=0, max=255) will be automatically detected by sb3,
and a proper scalling be applied automatically. whereas
gym.Spaces.Box(min=-inf, max=inf) will fail.

while no special case is treated for gym.Spaces.Box(min=-1, max=1), but
this will makes the rl-library easy to figure out that this term is
already clipped, not more transformation needed.

<!-- As you go through the list, delete the ones that are not
applicable. -->

- New feature (non-breaking change which adds functionality)

Please attach before and after screenshots of the change if applicable.

<!--
Example:

| Before | After |
| ------ | ----- |
| _gif/png before_ | _gif/png after_ |

To upload images to a PR -- simply drag and drop an image while in edit
mode and it should upload the image directly. You can then paste that
source into the above before/after sections.
-->

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./isaaclab.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

<!--
As you go through the checklist above, you can mark something as done by
putting an x character in it

For example,
- [x] I have done this task
- [ ] I have not done this task
-->
Signed-off-by: 's avatarKelly Guo <kellyg@nvidia.com>
Co-authored-by: 's avatarKelly Guo <kellyg@nvidia.com>
parent d6796446
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
name: Check Python Dependency Licenses name: Check Python Dependency Licenses
on: on:
......
[package] [package]
# Note: Semantic Versioning is used: https://semver.org/ # Note: Semantic Versioning is used: https://semver.org/
version = "0.42.29" version = "0.42.30"
# Description # Description
title = "Isaac Lab framework for Robot Learning" title = "Isaac Lab framework for Robot Learning"
......
Changelog Changelog
--------- ---------
0.42.29 (2025-07-18) 0.42.30 (2025-07-18)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
...@@ -11,7 +11,7 @@ Added ...@@ -11,7 +11,7 @@ Added
* Remove on prim deletion callback workaround * Remove on prim deletion callback workaround
0.42.28 (2025-07-21) 0.42.29 (2025-07-21)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Fixed Fixed
...@@ -20,7 +20,7 @@ Fixed ...@@ -20,7 +20,7 @@ Fixed
* Fixed rendering preset mode regression. * Fixed rendering preset mode regression.
0.42.27 (2025-07-22) 0.42.28 (2025-07-22)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Changed Changed
...@@ -29,7 +29,7 @@ Changed ...@@ -29,7 +29,7 @@ Changed
* Updated teleop scripts to print to console vs omni log. * Updated teleop scripts to print to console vs omni log.
0.42.26 (2025-07-17) 0.42.27 (2025-07-17)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Changed Changed
...@@ -38,7 +38,18 @@ Changed ...@@ -38,7 +38,18 @@ Changed
* Updated test_pink_ik.py test case to pytest format. * Updated test_pink_ik.py test case to pytest format.
0.42.25 (2025-06-25) 0.42.26 (2025-06-25)
~~~~~~~~~~~~~~~~~~~~
Added
^^^^^
* Added MangerBasedRLEnv support for composite gym observation spaces.
* A test for the composite gym observation spaces in ManagerBasedRLEnv is added to ensure that the observation spaces
are correctly configured base on the clip.
0.42.25 (2025-07-11)
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
Added Added
......
...@@ -333,10 +333,13 @@ class ManagerBasedRLEnv(ManagerBasedEnv, gym.Env): ...@@ -333,10 +333,13 @@ class ManagerBasedRLEnv(ManagerBasedEnv, gym.Env):
if has_concatenated_obs: if has_concatenated_obs:
self.single_observation_space[group_name] = gym.spaces.Box(low=-np.inf, high=np.inf, shape=group_dim) self.single_observation_space[group_name] = gym.spaces.Box(low=-np.inf, high=np.inf, shape=group_dim)
else: else:
self.single_observation_space[group_name] = gym.spaces.Dict({ group_term_cfgs = self.observation_manager._group_obs_term_cfgs[group_name]
term_name: gym.spaces.Box(low=-np.inf, high=np.inf, shape=term_dim) for term_name, term_dim, term_cfg in zip(group_term_names, group_dim, group_term_cfgs):
for term_name, term_dim in zip(group_term_names, group_dim) low = -np.inf if term_cfg.clip is None else term_cfg.clip[0]
}) high = np.inf if term_cfg.clip is None else term_cfg.clip[1]
self.single_observation_space[group_name] = gym.spaces.Dict(
{term_name: gym.spaces.Box(low=low, high=high, shape=term_dim)}
)
# action space (unbounded since we don't impose any limits) # action space (unbounded since we don't impose any limits)
action_dim = sum(self.action_manager.action_term_dim) action_dim = sum(self.action_manager.action_term_dim)
self.single_action_space = gym.spaces.Box(low=-np.inf, high=np.inf, shape=(action_dim,)) self.single_action_space = gym.spaces.Box(low=-np.inf, high=np.inf, shape=(action_dim,))
......
# Copyright (c) 2022-2025, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md).
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Test texture randomization in the cartpole scene using pytest."""
from isaaclab.app import AppLauncher
# launch omniverse app
simulation_app = AppLauncher(headless=True, enable_cameras=True).app
import gymnasium as gym
import numpy as np
import omni.usd
import pytest
from isaaclab.envs import ManagerBasedRLEnv
from isaaclab_tasks.manager_based.classic.cartpole.cartpole_camera_env_cfg import (
CartpoleDepthCameraEnvCfg,
CartpoleRGBCameraEnvCfg,
)
from isaaclab_tasks.manager_based.locomotion.velocity.config.anymal_c.rough_env_cfg import AnymalCRoughEnvCfg
@pytest.mark.parametrize(
"env_cfg_cls",
[CartpoleRGBCameraEnvCfg, CartpoleDepthCameraEnvCfg, AnymalCRoughEnvCfg],
ids=["RGB", "Depth", "RayCaster"],
)
@pytest.mark.parametrize("device", ["cpu", "cuda"])
def test_obs_space_follows_clip_contraint(env_cfg_cls, device):
"""Ensure curriculum terms apply correctly after the fallback and replacement."""
# new USD stage
omni.usd.get_context().new_stage()
# configure the cartpole env
env_cfg = env_cfg_cls()
env_cfg.scene.num_envs = 2 # keep num_envs small for testing
env_cfg.observations.policy.concatenate_terms = False
env_cfg.sim.device = device
env = ManagerBasedRLEnv(cfg=env_cfg)
for group_name, group_space in env.observation_space.spaces.items():
for term_name, term_space in group_space.spaces.items():
term_cfg = getattr(getattr(env_cfg.observations, group_name), term_name)
low = -np.inf if term_cfg.clip is None else term_cfg.clip[0]
high = np.inf if term_cfg.clip is None else term_cfg.clip[1]
assert isinstance(
term_space, gym.spaces.Box
), f"Expected Box space for {term_name} in {group_name}, got {type(term_space)}"
assert np.all(term_space.low == low)
assert np.all(term_space.high == high)
env.close()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment