Implementation:Isaac sim IsaacGymEnvs RLGPUAlgoObserver Metrics
| Sources | Domains | Last Updated |
|---|---|---|
| IsaacGymEnvs, rlgames_utils.py | Logging, Evaluation | 2026-02-15 00:00 GMT |
Overview
The RLGPUAlgoObserver class implements the rl_games AlgoObserver interface to collect, aggregate, and report per-episode metrics from IsaacGymEnvs environments.
Description
RLGPUAlgoObserver hooks into the training loop via the observer pattern. Its process_infos() method intercepts episode completion data, and after_print_stats() aggregates and writes the collected metrics to TensorBoard. It handles both standard rl_games metrics (rewards, episode lengths) and custom task-specific metrics passed through the extras dict.
Usage
Instantiated during build_runner() and passed as the algo_observer parameter. Operates transparently -- no user configuration required.
Code Reference
Source Location: Repository: NVIDIA-Omniverse/IsaacGymEnvs, File: isaacgymenvs/utils/rlgames_utils.py (L130-209)
Import:
from isaacgymenvs.utils.rlgames_utils import RLGPUAlgoObserver
Signature:
class RLGPUAlgoObserver(AlgoObserver):
def __init__(self):
"""Initialize empty metric accumulators."""
def after_init(self, algo): # L140-147
"""Called after algorithm init; stores reference to algo for writer access."""
def process_infos(self, infos, done_indices): # L149-181
"""Process episode info dicts on done signals; accumulate custom metrics."""
def after_print_stats(self, frame, epoch_num, total_time): # L183-209
"""Aggregate accumulated metrics and write to TensorBoard."""
I/O Contract
Inputs:
| Input | Type | Description |
|---|---|---|
| infos | dict | Episode info dict from env.step(); contains extras with custom metrics |
| done_indices | Tensor | Indices of environments that completed episodes this step |
| frame | int | Current training frame number (for TensorBoard x-axis) |
| epoch_num | int | Current training epoch number |
| total_time | float | Total elapsed training time in seconds |
Outputs:
| Output | Type | Destination |
|---|---|---|
| Mean episode reward | float | TensorBoard: Episode/reward |
| Mean episode length | float | TensorBoard: Episode/length |
| Custom task metrics | float (per key) | TensorBoard: Episode/<key> for each key in extras |
Key Methods
process_infos (L149-181)
Intercepts the infos dict after each environment step. For environments that have completed episodes (identified by done_indices), it extracts custom metrics from infos['extras'] and appends them to internal accumulators:
def process_infos(self, infos, done_indices):
if not infos:
return
if 'extras' in infos:
extras = infos['extras']
for key, value in extras.items():
# Accumulate per-episode metrics for completed episodes
if isinstance(value, torch.Tensor):
# Index into done environments only
self.episode_data[key].append(value[done_indices].mean().item())
else:
self.episode_data[key].append(value)
after_print_stats (L183-209)
Called at the end of each training epoch. Computes means across all accumulated episode data and writes to the TensorBoard SummaryWriter:
def after_print_stats(self, frame, epoch_num, total_time):
writer = self.writer
if len(self.episode_data) > 0:
for key, values in self.episode_data.items():
if len(values) > 0:
mean_val = sum(values) / len(values)
writer.add_scalar(f'Episode/{key}', mean_val, frame)
# Clear accumulators for next epoch
self.episode_data.clear()
Extras Dict Convention
Tasks populate the extras dict in their post_physics_step() method to expose custom metrics:
# Example from a task's post_physics_step():
self.extras['consecutive_successes'] = self.consecutive_successes.mean()
self.extras['goal_distance'] = self.goal_distance.mean()
These keys automatically appear as Episode/consecutive_successes and Episode/goal_distance in TensorBoard.