# Utilities Helper functions and utilities for GenesisLab. ## Overview Utility modules provide commonly used functions and tools: - **ConfigClass**: Configuration system decorator - **Math**: Mathematical operations and transformations - **Timing**: Performance profiling and timing - **I/O**: File loading and saving - **Typing**: Type definitions and hints ## ConfigClass The configuration system using `@configclass` decorator. ### Usage ```python from genesislab.utils.configclass import configclass from dataclasses import field @configclass class MyConfig: # Basic types name: str = "default" value: float = 1.0 count: int = 10 enabled: bool = True # Collections values: list[float] = field(default_factory=lambda: [1.0, 2.0]) mapping: dict[str, float] = field(default_factory=dict) # Nested configs sub_config: SubConfig = SubConfig() ``` ### Critical Rule **ALWAYS use `@configclass`, NEVER use `@dataclass`.** ```python # ✅ Correct from genesislab.utils.configclass import configclass @configclass class MyCfg: value: float = 1.0 # ❌ Incorrect - Will cause errors! from dataclasses import dataclass @dataclass class MyCfg: value: float = 1.0 ``` ## Math Utilities ### Quaternion Operations ```python from genesislab.utils.math import ( quat_mul, quat_conjugate, quat_rotate, quat_to_euler, euler_to_quat ) # Quaternion multiplication (WXYZ format) q1 = torch.tensor([1.0, 0.0, 0.0, 0.0]) q2 = torch.tensor([0.707, 0.0, 0.707, 0.0]) q_result = quat_mul(q1, q2) # Rotate vector by quaternion vec = torch.tensor([1.0, 0.0, 0.0]) rotated = quat_rotate(q1, vec) # Convert to Euler angles (roll, pitch, yaw) euler = quat_to_euler(q1) # [roll, pitch, yaw] # Convert from Euler angles quat = euler_to_quat(euler) ``` **Note**: GenesisLab uses **WXYZ quaternion format** throughout. ### Transformations ```python from genesislab.utils.math import ( transform_points, inverse_transform, homogeneous_transform ) # Transform points points = torch.randn(100, 3) # [N, 3] position = torch.tensor([1.0, 2.0, 3.0]) orientation = torch.tensor([1.0, 0.0, 0.0, 0.0]) # WXYZ quat transformed = transform_points(points, position, orientation) ``` ### Sampling ```python from genesislab.utils.math import ( sample_uniform, sample_gaussian, sample_uniform_sphere ) # Uniform sampling in range samples = sample_uniform(low=-1.0, high=1.0, size=(1000, 3)) # Gaussian sampling samples = sample_gaussian(mean=0.0, std=1.0, size=(1000, 3)) # Uniform sampling on sphere directions = sample_uniform_sphere(size=1000) # [1000, 3] ``` ## Timing Utilities ### Timer ```python from genesislab.utils.timing import Timer # Context manager with Timer("simulation_step"): env.step(actions) # Manual timing timer = Timer("my_operation") timer.start() # ... operation ... elapsed = timer.stop() print(f"Elapsed: {elapsed:.3f}s") ``` ### Performance Profiling ```python from genesislab.utils.timing import profile_function @profile_function def my_expensive_function(): # ... computation ... pass # Call function - timing info is automatically logged result = my_expensive_function() ``` ### FPS Counter ```python from genesislab.utils.timing import FPSCounter fps_counter = FPSCounter(window_size=100) for _ in range(1000): # ... simulation step ... fps_counter.tick() if fps_counter.frame_count % 100 == 0: print(f"FPS: {fps_counter.fps:.0f}") ``` ## I/O Utilities ### Loading Assets ```python from genesislab.utils.io import load_urdf, load_mesh # Load URDF robot = load_urdf("path/to/robot.urdf") # Load mesh mesh = load_mesh("path/to/mesh.obj") ``` ### Saving/Loading Checkpoints ```python from genesislab.utils.io import save_checkpoint, load_checkpoint # Save checkpoint = { "policy": policy.state_dict(), "optimizer": optimizer.state_dict(), "episode": episode } save_checkpoint(checkpoint, "checkpoint.pt") # Load checkpoint = load_checkpoint("checkpoint.pt") policy.load_state_dict(checkpoint["policy"]) ``` ### Configuration Files ```python from genesislab.utils.io import save_config, load_config # Save configuration cfg = MyTaskCfg() save_config(cfg, "config.yaml") # Load configuration cfg = load_config("config.yaml", MyTaskCfg) ``` ## Typing Common type definitions used throughout GenesisLab. ```python from genesislab.utils.typing import ( TensorType, ObsDict, InfoDict, ConfigType ) # Type hints def compute_reward( observations: ObsDict, actions: TensorType ) -> TensorType: """ Compute reward. Args: observations: Dictionary of observation tensors actions: Action tensor [num_envs, action_dim] Returns: Reward tensor [num_envs] """ pass ``` ## Logging ### Logger Setup ```python from genesislab.utils.logging import setup_logger, get_logger # Setup logger setup_logger( log_dir="logs/", log_level="INFO", log_to_file=True ) # Get logger logger = get_logger(__name__) logger.info("Training started") logger.warning("Learning rate adjusted") ``` ### TensorBoard Integration ```python from genesislab.utils.logging import TensorBoardLogger # Create logger tb_logger = TensorBoardLogger(log_dir="logs/tensorboard") # Log scalars tb_logger.log_scalar("reward/mean", mean_reward, step) tb_logger.log_scalar("policy/lr", learning_rate, step) # Log histogram tb_logger.log_histogram("actions", actions, step) # Log image tb_logger.log_image("observation/camera", image, step) ``` ### WandB Integration ```python from genesislab.utils.logging import WandbLogger # Create logger wandb_logger = WandbLogger( project="genesislab", name="go2_flat", config=vars(cfg) ) # Log metrics wandb_logger.log({ "reward": mean_reward, "episode_length": mean_length }, step=iteration) ``` ## Random Seed ### Setting Seeds ```python from genesislab.utils.random import set_seed # Set all random seeds (Python, NumPy, PyTorch, Genesis) set_seed(42) ``` ## Device Management ### Device Utilities ```python from genesislab.utils.device import get_device, to_device # Get default device device = get_device() # Returns cuda if available # Move data to device data = to_device(data, device) ``` ## Debugging Utilities ### Tensor Checks ```python from genesislab.utils.debug import check_tensor, print_tensor_stats # Check for NaN/Inf check_tensor(tensor, name="my_tensor") # Raises if invalid # Print statistics print_tensor_stats(tensor, name="my_tensor") # Output: # my_tensor: shape=(4096, 48), min=-1.23, max=2.45, mean=0.12, std=0.89 ``` ### Visualization Helpers ```python from genesislab.utils.vis import ( plot_observations, plot_rewards, plot_trajectories ) # Plot observation distribution plot_observations(observations, save_path="obs.png") # Plot reward components plot_rewards(reward_terms, save_path="rewards.png") # Plot robot trajectories plot_trajectories(positions, save_path="trajectories.png") ``` ## Common Patterns ### Noise Application ```python from genesislab.utils.noise import add_noise # Add noise to observations obs_noisy = add_noise( obs, noise_type="gaussian", noise_params={"mean": 0.0, "std": 0.1} ) ``` ### Clamping and Scaling ```python from genesislab.utils.math import scale_transform, saturate # Scale from [-1, 1] to [a, b] scaled = scale_transform( actions, input_range=(-1, 1), output_range=(-0.5, 0.5) ) # Clamp values clamped = saturate(values, min_val=-1.0, max_val=1.0) ``` ## Example: Complete Utility Usage ```python from genesislab.utils.configclass import configclass from genesislab.utils.timing import Timer, FPSCounter from genesislab.utils.logging import setup_logger, get_logger from genesislab.utils.random import set_seed from genesislab.utils.math import quat_to_euler import torch # Setup set_seed(42) setup_logger(log_dir="logs/") logger = get_logger(__name__) # Configuration @configclass class TrainCfg: num_envs: int = 4096 learning_rate: float = 3e-4 max_iterations: int = 1000 cfg = TrainCfg() logger.info(f"Starting training with {cfg.num_envs} environments") # Training loop fps_counter = FPSCounter() for iteration in range(cfg.max_iterations): with Timer("iteration"): # ... training step ... pass fps_counter.tick() if iteration % 100 == 0: logger.info(f"Iteration {iteration}, FPS: {fps_counter.fps:.0f}") ``` ## Next Steps - See [engine API](../engine/index.md) for core components - Check [manager API](../managers/index.md) for manager details - Review [examples](../../user_guide/tutorials/index.md) for usage patterns