diff --git a/source/isaaclab/isaaclab/envs/direct_marl_env.py b/source/isaaclab/isaaclab/envs/direct_marl_env.py index 0e7429117fc..324400db717 100644 --- a/source/isaaclab/isaaclab/envs/direct_marl_env.py +++ b/source/isaaclab/isaaclab/envs/direct_marl_env.py @@ -17,7 +17,6 @@ from dataclasses import MISSING from typing import Any, ClassVar -import isaacsim.core.utils.torch as torch_utils import omni.kit.app import omni.log import omni.physx @@ -28,6 +27,7 @@ from isaaclab.sim import SimulationContext from isaaclab.sim.utils import attach_stage_to_usd_context, use_stage from isaaclab.utils.noise import NoiseModel +from isaaclab.utils.seed import set_seed from isaaclab.utils.timer import Timer from .common import ActionType, AgentID, EnvStepReturn, ObsType, StateType @@ -462,7 +462,7 @@ def seed(seed: int = -1) -> int: except ModuleNotFoundError: pass # set seed for torch and other libraries - return torch_utils.set_seed(seed) + return set_seed(seed) def render(self, recompute: bool = False) -> np.ndarray | None: """Run rendering without stepping through the physics. diff --git a/source/isaaclab/isaaclab/envs/direct_rl_env.py b/source/isaaclab/isaaclab/envs/direct_rl_env.py index e43c4db7a28..997137db3da 100644 --- a/source/isaaclab/isaaclab/envs/direct_rl_env.py +++ b/source/isaaclab/isaaclab/envs/direct_rl_env.py @@ -17,7 +17,6 @@ from dataclasses import MISSING from typing import Any, ClassVar -import isaacsim.core.utils.torch as torch_utils import omni.kit.app import omni.log import omni.physx @@ -29,6 +28,7 @@ from isaaclab.sim import SimulationContext from isaaclab.sim.utils import attach_stage_to_usd_context, use_stage from isaaclab.utils.noise import NoiseModel +from isaaclab.utils.seed import set_seed from isaaclab.utils.timer import Timer from .common import VecEnvObs, VecEnvStepReturn @@ -414,7 +414,7 @@ def seed(seed: int = -1) -> int: except ModuleNotFoundError: pass # set seed for torch and other libraries - return torch_utils.set_seed(seed) + return set_seed(seed) def render(self, recompute: bool = False) -> np.ndarray | None: """Run rendering without stepping through the physics. diff --git a/source/isaaclab/isaaclab/envs/manager_based_env.py b/source/isaaclab/isaaclab/envs/manager_based_env.py index 9ddc538aa41..91bcabed4db 100644 --- a/source/isaaclab/isaaclab/envs/manager_based_env.py +++ b/source/isaaclab/isaaclab/envs/manager_based_env.py @@ -8,7 +8,6 @@ from collections.abc import Sequence from typing import Any -import isaacsim.core.utils.torch as torch_utils import omni.log import omni.physx from isaacsim.core.simulation_manager import SimulationManager @@ -19,6 +18,7 @@ from isaaclab.sim import SimulationContext from isaaclab.sim.utils import attach_stage_to_usd_context, use_stage from isaaclab.ui.widgets import ManagerLiveVisualizer +from isaaclab.utils.seed import set_seed from isaaclab.utils.timer import Timer from .common import VecEnvObs @@ -495,7 +495,7 @@ def seed(seed: int = -1) -> int: except ModuleNotFoundError: pass # set seed for torch and other libraries - return torch_utils.set_seed(seed) + return set_seed(seed) def close(self): """Cleanup for the environment.""" diff --git a/source/isaaclab/isaaclab/utils/seed.py b/source/isaaclab/isaaclab/utils/seed.py new file mode 100644 index 00000000000..c20ce88125b --- /dev/null +++ b/source/isaaclab/isaaclab/utils/seed.py @@ -0,0 +1,36 @@ +# 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 + +import numpy as np +import os +import random +import torch + +import warp as wp + + +def set_seed(seed: int, torch_deterministic: bool = False) -> int: + """set seed across modules""" + if seed == -1: + seed = 42 if torch_deterministic else np.random.randint(0, 10000) + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + os.environ["PYTHONHASHSEED"] = str(seed) + torch.cuda.manual_seed(seed) + torch.cuda.manual_seed_all(seed) + wp.rand_init(seed) + + if torch_deterministic: + # refer to https://docs.nvidia.com/cuda/cublas/index.html#cublasApi_reproducibility + os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + torch.use_deterministic_algorithms(True) + else: + torch.backends.cudnn.benchmark = True + torch.backends.cudnn.deterministic = False + + return seed diff --git a/source/isaaclab/test/terrains/test_terrain_generator.py b/source/isaaclab/test/terrains/test_terrain_generator.py index 46f029ab7c9..78ed6f10da3 100644 --- a/source/isaaclab/test/terrains/test_terrain_generator.py +++ b/source/isaaclab/test/terrains/test_terrain_generator.py @@ -17,11 +17,11 @@ import shutil import torch -import isaacsim.core.utils.torch as torch_utils import pytest from isaaclab.terrains import FlatPatchSamplingCfg, TerrainGenerator, TerrainGeneratorCfg from isaaclab.terrains.config.rough import ROUGH_TERRAINS_CFG +from isaaclab.utils.seed import set_seed @pytest.fixture @@ -65,7 +65,7 @@ def test_generation_reproducibility(use_global_seed, seed): Setting only locally is not tested as it is not supported. """ # set initial seed - torch_utils.set_seed(seed) + set_seed(seed) # create terrain generator cfg = ROUGH_TERRAINS_CFG @@ -77,7 +77,7 @@ def test_generation_reproducibility(use_global_seed, seed): terrain_mesh_1 = terrain_generator.terrain_mesh.copy() # set seed again - torch_utils.set_seed(seed) + set_seed(seed) # create terrain generator terrain_generator = TerrainGenerator(cfg=cfg) @@ -116,7 +116,7 @@ def test_generation_cache(output_dir, curriculum): # set a random seed to disturb the process # this is to ensure that the seed inside the terrain generator makes deterministic results - torch_utils.set_seed(12456) + set_seed(12456) # create terrain generator with cache enabled terrain_generator = TerrainGenerator(cfg=cfg)