diff --git a/docs/source/overview/gym/event_functors.md b/docs/source/overview/gym/event_functors.md index f1dfdcc7..cd101cc1 100644 --- a/docs/source/overview/gym/event_functors.md +++ b/docs/source/overview/gym/event_functors.md @@ -31,6 +31,8 @@ This page lists all available event functors that can be used with the Event Man - Randomize textures, base colors, and material properties (metallic, roughness, IOR). Implemented as a Functor class. Supports both RigidObject and Articulation assets. * - ``randomize_light`` - Vary light position, color, and intensity within specified ranges. +* - ``randomize_emission_light`` + - Randomize global emission light color and intensity. Applies the same emission light properties across all environments. * - ``randomize_camera_extrinsics`` - Randomize camera poses for viewpoint diversity. Supports both attach mode (pos/euler perturbation) and look_at mode (eye/target/up perturbation). * - ``randomize_camera_intrinsics`` diff --git a/embodichain/lab/gym/envs/embodied_env.py b/embodichain/lab/gym/envs/embodied_env.py index ca974f92..9eda098d 100644 --- a/embodichain/lab/gym/envs/embodied_env.py +++ b/embodichain/lab/gym/envs/embodied_env.py @@ -64,7 +64,7 @@ class EnvLightCfg: direct: List[LightCfg] = [] # TODO: support more types of indirect light in the future. - # indirect: Dict[str, Any] | None = None + indirect: dict[str, Any] | None = None robot: RobotCfg = MISSING @@ -498,9 +498,15 @@ def _setup_sensors(self, **kwargs) -> Dict[str, BaseSensor]: def _setup_lights(self) -> None: """Setup the lights in the environment.""" + # Set direct lights. for cfg in self.cfg.light.direct: self.sim.add_light(cfg=cfg) + # Set indirect lights. + if self.cfg.light.indirect is not None: + if "emission_light" in self.cfg.light.indirect: + self.sim.set_emission_light(**self.cfg.light.indirect["emission_light"]) + def _setup_background(self) -> None: """Setup the static rigid objects in the environment.""" for cfg in self.cfg.background: diff --git a/embodichain/lab/gym/envs/managers/randomization/visual.py b/embodichain/lab/gym/envs/managers/randomization/visual.py index a1b1a978..66d3d6fb 100644 --- a/embodichain/lab/gym/envs/managers/randomization/visual.py +++ b/embodichain/lab/gym/envs/managers/randomization/visual.py @@ -20,6 +20,8 @@ import os import random import copy +import numpy as np + from typing import TYPE_CHECKING, Literal, Union, Dict from embodichain.lab.sim.objects import ( @@ -52,6 +54,7 @@ __all__ = [ "randomize_camera_extrinsics", "randomize_light", + "randomize_emission_light", "randomize_camera_intrinsics", "set_rigid_object_visual_material", "set_rigid_object_group_visual_material", @@ -342,6 +345,50 @@ def randomize_light( light.set_intensity(new_intensity, env_ids=env_ids) +def randomize_emission_light( + env: EmbodiedEnv, + env_ids: Union[torch.Tensor, None], + color_range: tuple[list[float], list[float]] | None = None, + intensity_range: tuple[float, float] | None = None, +) -> None: + """Randomize emission light properties by adding, scaling, or setting random values. + + This function allows randomizing emission light properties in the scene. The function samples random values from the + given distribution parameters and adds, scales, or sets the values into the physics simulation based on the + operation. + + The distribution parameters are lists of two elements each, representing the lower and upper bounds of the + distribution for the r, g, b components of the light color and intensity. The function samples random values for each + component independently. + + .. attention:: + This function applied the same emission light properties for all the environments. + + color_range is the absolute r, g, b value set on the emission light. + intensity_range is the absolute intensity value set on the emission light. + """ + + color = None + if color_range: + color = torch.zeros((1, 3), dtype=torch.float32) + random_value = sample_uniform( + lower=torch.tensor(color_range[0]), + upper=torch.tensor(color_range[1]), + size=color.shape, + ) + color += random_value + + intensity = None + if intensity_range: + intensity = np.random.uniform(intensity_range[0], intensity_range[1]) + + if isinstance(color, torch.Tensor): + color_arg = color.squeeze(0).tolist() + else: + color_arg = None + env.sim.set_emission_light(color=color_arg, intensity=intensity) + + def randomize_camera_intrinsics( env: EmbodiedEnv, env_ids: Union[torch.Tensor, None], diff --git a/embodichain/lab/gym/utils/gym_utils.py b/embodichain/lab/gym/utils/gym_utils.py index d8b4427f..e9823d6e 100644 --- a/embodichain/lab/gym/utils/gym_utils.py +++ b/embodichain/lab/gym/utils/gym_utils.py @@ -430,6 +430,7 @@ class ComponentCfg: env_cfg.light.direct = [ LightCfg.from_dict(l) for l in config["light"].get("direct", []) ] + env_cfg.light.indirect = config["light"].get("indirect", None) # parser background objects config if "background" in config: