Unverified Commit e637753a authored by Mayank Mittal's avatar Mayank Mittal Committed by GitHub

Puts all tasks unit tests into subTest context (#500)

# Description

This MR moves all environment tasks names into `with.subTest()` context
manager to report per sub test as well.

## Type of change

- Bug fix (non-breaking change which fixes an issue)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] I have run all the tests with `./orbit.sh --test` and they pass
- [ ] 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

---------
Co-authored-by: 's avatarDavid Hoeller <dhoeller@ethz.ch>
parent 40cdf401
...@@ -75,7 +75,7 @@ def convert_to_torch( ...@@ -75,7 +75,7 @@ def convert_to_torch(
tensor = array tensor = array
elif isinstance(array, np.ndarray): elif isinstance(array, np.ndarray):
if array.dtype == np.uint32: if array.dtype == np.uint32:
array = array.astype(np.int64) array = array.astype(np.int32)
# need to deal with object arrays (np.void) separately # need to deal with object arrays (np.void) separately
tensor = torch.from_numpy(array) tensor = torch.from_numpy(array)
elif isinstance(array, wp.array): elif isinstance(array, wp.array):
......
...@@ -309,11 +309,9 @@ class TestCamera(unittest.TestCase): ...@@ -309,11 +309,9 @@ class TestCamera(unittest.TestCase):
self.assertEqual(output["rgb"].shape, hw_3c_shape) self.assertEqual(output["rgb"].shape, hw_3c_shape)
self.assertEqual(output["distance_to_image_plane"].shape, hw_1c_shape) self.assertEqual(output["distance_to_image_plane"].shape, hw_1c_shape)
self.assertEqual(output["normals"].shape, hw_3c_shape) self.assertEqual(output["normals"].shape, hw_3c_shape)
# FIXME: No idea why it does not work here. The raw buffers are of type int64 than int32 -> need to investigate self.assertEqual(output["semantic_segmentation"].shape, hw_3c_shape)
# It works fine when run_usd_camera.py tutorial is run. self.assertEqual(output["instance_segmentation_fast"].shape, hw_3c_shape)
# self.assertEqual(output["semantic_segmentation"].shape, hw_3c_shape) self.assertEqual(output["instance_id_segmentation_fast"].shape, hw_3c_shape)
# self.assertEqual(output["instance_segmentation_fast"].shape, hw_3c_shape)
# self.assertEqual(output["instance_id_segmentation_fast"].shape, hw_3c_shape)
# access image data and compare dtype # access image data and compare dtype
output = camera.data.output output = camera.data.output
...@@ -368,11 +366,9 @@ class TestCamera(unittest.TestCase): ...@@ -368,11 +366,9 @@ class TestCamera(unittest.TestCase):
self.assertEqual(output["rgb"].dtype, torch.uint8) self.assertEqual(output["rgb"].dtype, torch.uint8)
self.assertEqual(output["distance_to_image_plane"].dtype, torch.float) self.assertEqual(output["distance_to_image_plane"].dtype, torch.float)
self.assertEqual(output["normals"].dtype, torch.float) self.assertEqual(output["normals"].dtype, torch.float)
# FIXME: No idea why it does not work here. The raw buffers are of type int64 than int32 -> need to investigate self.assertEqual(output["semantic_segmentation"].dtype, torch.int32)
# It works fine when run_usd_camera.py tutorial is run. self.assertEqual(output["instance_segmentation_fast"].dtype, torch.int32)
# self.assertEqual(output["semantic_segmentation"].dtype, torch.int32) self.assertEqual(output["instance_id_segmentation_fast"].dtype, torch.int32)
# self.assertEqual(output["instance_segmentation_fast"].dtype, torch.int32)
# self.assertEqual(output["instance_id_segmentation_fast"].dtype, torch.int32)
def test_throughput(self): def test_throughput(self):
"""Checks that the single camera gets created properly with a rig.""" """Checks that the single camera gets created properly with a rig."""
......
...@@ -54,12 +54,13 @@ class TestEnvironments(unittest.TestCase): ...@@ -54,12 +54,13 @@ class TestEnvironments(unittest.TestCase):
use_gpu = True use_gpu = True
# iterate over all registered environments # iterate over all registered environments
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# check environment print(f">>> Running test for environment: {task_name}")
self._check_random_actions(task_name, use_gpu, num_envs, num_steps=100) # check environment
# close the environment self._check_random_actions(task_name, use_gpu, num_envs, num_steps=100)
print(f">>> Closing environment: {task_name}") # close the environment
print("-" * 80) print(f">>> Closing environment: {task_name}")
print("-" * 80)
def test_single_instance_gpu(self): def test_single_instance_gpu(self):
"""Run all environments with single instance and check environments return valid signals.""" """Run all environments with single instance and check environments return valid signals."""
...@@ -68,12 +69,13 @@ class TestEnvironments(unittest.TestCase): ...@@ -68,12 +69,13 @@ class TestEnvironments(unittest.TestCase):
use_gpu = True use_gpu = True
# iterate over all registered environments # iterate over all registered environments
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# check environment print(f">>> Running test for environment: {task_name}")
self._check_random_actions(task_name, use_gpu, num_envs, num_steps=100) # check environment
# close the environment self._check_random_actions(task_name, use_gpu, num_envs, num_steps=100)
print(f">>> Closing environment: {task_name}") # close the environment
print("-" * 80) print(f">>> Closing environment: {task_name}")
print("-" * 80)
""" """
Helper functions. Helper functions.
......
...@@ -22,7 +22,7 @@ import unittest ...@@ -22,7 +22,7 @@ import unittest
import omni.usd import omni.usd
from omni.isaac.orbit.envs import RLTaskEnv, RLTaskEnvCfg from omni.isaac.orbit.envs import RLTaskEnvCfg
import omni.isaac.orbit_tasks # noqa: F401 import omni.isaac.orbit_tasks # noqa: F401
from omni.isaac.orbit_tasks.utils import parse_env_cfg from omni.isaac.orbit_tasks.utils import parse_env_cfg
...@@ -56,35 +56,40 @@ class TestRecordVideoWrapper(unittest.TestCase): ...@@ -56,35 +56,40 @@ class TestRecordVideoWrapper(unittest.TestCase):
def test_record_video(self): def test_record_video(self):
"""Run random actions agent with recording of videos.""" """Run random actions agent with recording of videos."""
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# create a new stage print(f">>> Running test for environment: {task_name}")
omni.usd.get_context().new_stage() # create a new stage
omni.usd.get_context().new_stage()
# parse configuration
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs) # parse configuration
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs)
# create environment
env: RLTaskEnv = gym.make(task_name, cfg=env_cfg, render_mode="rgb_array") # create environment
env = gym.make(task_name, cfg=env_cfg, render_mode="rgb_array")
# directory to save videos
videos_dir = os.path.join(self.videos_dir, task_name) # directory to save videos
# wrap environment to record videos videos_dir = os.path.join(self.videos_dir, task_name)
env = gym.wrappers.RecordVideo( # wrap environment to record videos
env, videos_dir, step_trigger=self.step_trigger, video_length=self.video_length, disable_logger=True env = gym.wrappers.RecordVideo(
) env,
videos_dir,
# reset environment step_trigger=self.step_trigger,
env.reset() video_length=self.video_length,
# simulate environment disable_logger=True,
with torch.inference_mode(): )
for _ in range(500):
# compute zero actions # reset environment
actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1 env.reset()
# apply actions # simulate environment
_ = env.step(actions) with torch.inference_mode():
for _ in range(500):
# close the simulator # compute zero actions
env.close() actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1
# apply actions
_ = env.step(actions)
# close the simulator
env.close()
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -41,8 +41,8 @@ class TestRlGamesVecEnvWrapper(unittest.TestCase): ...@@ -41,8 +41,8 @@ class TestRlGamesVecEnvWrapper(unittest.TestCase):
cls.registered_tasks.append(task_spec.id) cls.registered_tasks.append(task_spec.id)
# sort environments by name # sort environments by name
cls.registered_tasks.sort() cls.registered_tasks.sort()
# only pick the first three environments to test # only pick the first four environments to test
cls.registered_tasks = cls.registered_tasks[:3] cls.registered_tasks = cls.registered_tasks[:4]
# print all existing task names # print all existing task names
print(">>> All registered environments:", cls.registered_tasks) print(">>> All registered environments:", cls.registered_tasks)
...@@ -54,36 +54,37 @@ class TestRlGamesVecEnvWrapper(unittest.TestCase): ...@@ -54,36 +54,37 @@ class TestRlGamesVecEnvWrapper(unittest.TestCase):
def test_random_actions(self): def test_random_actions(self):
"""Run random actions and check environments return valid signals.""" """Run random actions and check environments return valid signals."""
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# create a new stage print(f">>> Running test for environment: {task_name}")
omni.usd.get_context().new_stage() # create a new stage
# parse configuration omni.usd.get_context().new_stage()
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs) # parse configuration
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs)
# create environment
env = gym.make(task_name, cfg=env_cfg) # create environment
# wrap environment env = gym.make(task_name, cfg=env_cfg)
env = RlGamesVecEnvWrapper(env, "cuda:0", 100, 100) # wrap environment
env = RlGamesVecEnvWrapper(env, "cuda:0", 100, 100)
# reset environment
obs = env.reset() # reset environment
# check signal obs = env.reset()
self.assertTrue(self._check_valid_tensor(obs)) # check signal
self.assertTrue(self._check_valid_tensor(obs))
# simulate environment for 100 steps
with torch.inference_mode(): # simulate environment for 100 steps
for _ in range(100): with torch.inference_mode():
# sample actions from -1 to 1 for _ in range(100):
actions = 2 * torch.rand(env.num_envs, *env.action_space.shape, device=env.device) - 1 # sample actions from -1 to 1
# apply actions actions = 2 * torch.rand(env.num_envs, *env.action_space.shape, device=env.device) - 1
transition = env.step(actions) # apply actions
# check signals transition = env.step(actions)
for data in transition: # check signals
self.assertTrue(self._check_valid_tensor(data), msg=f"Invalid data: {data}") for data in transition:
self.assertTrue(self._check_valid_tensor(data), msg=f"Invalid data: {data}")
# close the environment
print(f">>> Closing environment: {task_name}") # close the environment
env.close() print(f">>> Closing environment: {task_name}")
env.close()
""" """
Helper functions. Helper functions.
......
...@@ -41,8 +41,8 @@ class TestRslRlVecEnvWrapper(unittest.TestCase): ...@@ -41,8 +41,8 @@ class TestRslRlVecEnvWrapper(unittest.TestCase):
cls.registered_tasks.append(task_spec.id) cls.registered_tasks.append(task_spec.id)
# sort environments by name # sort environments by name
cls.registered_tasks.sort() cls.registered_tasks.sort()
# only pick the first three environments to test # only pick the first four environments to test
cls.registered_tasks = cls.registered_tasks[:3] cls.registered_tasks = cls.registered_tasks[:4]
# print all existing task names # print all existing task names
print(">>> All registered environments:", cls.registered_tasks) print(">>> All registered environments:", cls.registered_tasks)
...@@ -54,72 +54,76 @@ class TestRslRlVecEnvWrapper(unittest.TestCase): ...@@ -54,72 +54,76 @@ class TestRslRlVecEnvWrapper(unittest.TestCase):
def test_random_actions(self): def test_random_actions(self):
"""Run random actions and check environments return valid signals.""" """Run random actions and check environments return valid signals."""
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# create a new stage print(f">>> Running test for environment: {task_name}")
omni.usd.get_context().new_stage() # create a new stage
# parse configuration omni.usd.get_context().new_stage()
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs) # parse configuration
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs)
# create environment
env = gym.make(task_name, cfg=env_cfg) # create environment
# wrap environment env = gym.make(task_name, cfg=env_cfg)
env = RslRlVecEnvWrapper(env) # wrap environment
env = RslRlVecEnvWrapper(env)
# reset environment
obs, extras = env.reset() # reset environment
# check signal obs, extras = env.reset()
self.assertTrue(self._check_valid_tensor(obs)) # check signal
self.assertTrue(self._check_valid_tensor(extras)) self.assertTrue(self._check_valid_tensor(obs))
self.assertTrue(self._check_valid_tensor(extras))
# simulate environment for 1000 steps
with torch.inference_mode(): # simulate environment for 1000 steps
for _ in range(1000): with torch.inference_mode():
# sample actions from -1 to 1 for _ in range(1000):
actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1 # sample actions from -1 to 1
# apply actions actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1
transition = env.step(actions) # apply actions
# check signals transition = env.step(actions)
for data in transition: # check signals
self.assertTrue(self._check_valid_tensor(data), msg=f"Invalid data: {data}") for data in transition:
self.assertTrue(self._check_valid_tensor(data), msg=f"Invalid data: {data}")
# close the environment
print(f">>> Closing environment: {task_name}") # close the environment
env.close() print(f">>> Closing environment: {task_name}")
env.close()
def test_no_time_outs(self): def test_no_time_outs(self):
"""Check that environments with finite horizon do not send time-out signals.""" """Check that environments with finite horizon do not send time-out signals."""
for task_name in self.registered_tasks[0:5]: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# create a new stage print(f">>> Running test for environment: {task_name}")
omni.usd.get_context().new_stage() # create a new stage
# parse configuration omni.usd.get_context().new_stage()
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs) # parse configuration
# change to finite horizon env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs)
env_cfg.is_finite_horizon = True # change to finite horizon
env_cfg.is_finite_horizon = True
# create environment
env = gym.make(task_name, cfg=env_cfg) # create environment
# wrap environment env = gym.make(task_name, cfg=env_cfg)
env = RslRlVecEnvWrapper(env) # wrap environment
env = RslRlVecEnvWrapper(env)
# reset environment
_, extras = env.reset() # reset environment
# check signal _, extras = env.reset()
self.assertNotIn("time_outs", extras, msg="Time-out signal found in finite horizon environment.") # check signal
self.assertNotIn("time_outs", extras, msg="Time-out signal found in finite horizon environment.")
# simulate environment for 10 steps
with torch.inference_mode(): # simulate environment for 10 steps
for _ in range(10): with torch.inference_mode():
# sample actions from -1 to 1 for _ in range(10):
actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1 # sample actions from -1 to 1
# apply actions actions = 2 * torch.rand(env.action_space.shape, device=env.unwrapped.device) - 1
extras = env.step(actions)[-1] # apply actions
# check signals extras = env.step(actions)[-1]
self.assertNotIn("time_outs", extras, msg="Time-out signal found in finite horizon environment.") # check signals
self.assertNotIn(
# close the environment "time_outs", extras, msg="Time-out signal found in finite horizon environment."
print(f">>> Closing environment: {task_name}") )
env.close()
# close the environment
print(f">>> Closing environment: {task_name}")
env.close()
""" """
Helper functions. Helper functions.
......
...@@ -43,8 +43,8 @@ class TestStableBaselines3VecEnvWrapper(unittest.TestCase): ...@@ -43,8 +43,8 @@ class TestStableBaselines3VecEnvWrapper(unittest.TestCase):
cls.registered_tasks.append(task_spec.id) cls.registered_tasks.append(task_spec.id)
# sort environments by name # sort environments by name
cls.registered_tasks.sort() cls.registered_tasks.sort()
# only pick the first three environments to test # only pick the first four environments to test
cls.registered_tasks = cls.registered_tasks[:3] cls.registered_tasks = cls.registered_tasks[:4]
# print all existing task names # print all existing task names
print(">>> All registered environments:", cls.registered_tasks) print(">>> All registered environments:", cls.registered_tasks)
...@@ -56,36 +56,37 @@ class TestStableBaselines3VecEnvWrapper(unittest.TestCase): ...@@ -56,36 +56,37 @@ class TestStableBaselines3VecEnvWrapper(unittest.TestCase):
def test_random_actions(self): def test_random_actions(self):
"""Run random actions and check environments return valid signals.""" """Run random actions and check environments return valid signals."""
for task_name in self.registered_tasks: for task_name in self.registered_tasks:
print(f">>> Running test for environment: {task_name}") with self.subTest(task_name=task_name):
# create a new stage print(f">>> Running test for environment: {task_name}")
omni.usd.get_context().new_stage() # create a new stage
# parse configuration omni.usd.get_context().new_stage()
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs) # parse configuration
env_cfg: RLTaskEnvCfg = parse_env_cfg(task_name, use_gpu=self.use_gpu, num_envs=self.num_envs)
# create environment
env = gym.make(task_name, cfg=env_cfg) # create environment
# wrap environment env = gym.make(task_name, cfg=env_cfg)
env = Sb3VecEnvWrapper(env) # wrap environment
env = Sb3VecEnvWrapper(env)
# reset environment
obs = env.reset() # reset environment
# check signal obs = env.reset()
self.assertTrue(self._check_valid_array(obs)) # check signal
self.assertTrue(self._check_valid_array(obs))
# simulate environment for 1000 steps
with torch.inference_mode(): # simulate environment for 1000 steps
for _ in range(1000): with torch.inference_mode():
# sample actions from -1 to 1 for _ in range(1000):
actions = 2 * np.random.rand(env.num_envs, *env.action_space.shape) - 1 # sample actions from -1 to 1
# apply actions actions = 2 * np.random.rand(env.num_envs, *env.action_space.shape) - 1
transition = env.step(actions) # apply actions
# check signals transition = env.step(actions)
for data in transition: # check signals
self.assertTrue(self._check_valid_array(data), msg=f"Invalid data: {data}") for data in transition:
self.assertTrue(self._check_valid_array(data), msg=f"Invalid data: {data}")
# close the environment
print(f">>> Closing environment: {task_name}") # close the environment
env.close() print(f">>> Closing environment: {task_name}")
env.close()
""" """
Helper functions. Helper functions.
......
...@@ -13,6 +13,4 @@ TESTS_TO_SKIP = [ ...@@ -13,6 +13,4 @@ TESTS_TO_SKIP = [
# orbit_tasks # orbit_tasks
"test_data_collector.py", # Failing "test_data_collector.py", # Failing
"test_record_video.py", # Failing "test_record_video.py", # Failing
"test_rsl_rl_wrapper.py", # Timing out (10 minutes)
"test_sb3_wrapper.py", # Timing out (10 minutes)
] ]
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