Some checks failed
nightly / Test against latest dependencies (py3.10) (push) Has been cancelled
nightly / Test against latest dependencies (py3.13) (push) Has been cancelled
tests / tests (3.13, locked) (push) Has been cancelled
tests / tests (3.13, unlocked) (push) Has been cancelled
tests / pyright (3.10) (push) Has been cancelled
tests / lint-format (push) Has been cancelled
tests / tests (3.10, locked) (push) Has been cancelled
tests / tests (3.11, locked) (push) Has been cancelled
tests / tests (3.12, locked) (push) Has been cancelled
tests / pyright (3.11) (push) Has been cancelled
tests / pyright (3.12) (push) Has been cancelled
tests / pyright (3.13) (push) Has been cancelled
tests / ty-check (3.10) (push) Has been cancelled
tests / ty-check (3.11) (push) Has been cancelled
tests / ty-check (3.12) (push) Has been cancelled
tests / ty-check (3.13) (push) Has been cancelled
tests / stubs (push) Has been cancelled
tests / smoke-test (push) Has been cancelled
Docker / check_paths (push) Has been cancelled
docs / build (push) Has been cancelled
Docker / build (push) Has been cancelled
Upstream: https://github.com/michaelgillett/mjlab Upstream-Commit: c19f713c415a699a79d71cd96aa13c3104a05047 Upstream-Branch: main
111 lines
4.1 KiB
ReStructuredText
111 lines
4.1 KiB
ReStructuredText
.. _metrics:
|
|
|
|
Metrics
|
|
=======
|
|
|
|
The metrics manager logs per-step scalar values as episode averages. Unlike
|
|
rewards, metrics carry no weight and are not scaled by the step duration.
|
|
They exist purely for diagnostics: tracking quantities such as tracking
|
|
error, contact forces, or energy consumption alongside reward curves
|
|
without influencing the optimization.
|
|
|
|
Metrics are computed every environment step, accumulated per environment,
|
|
and averaged over the episode length when the environment resets. The
|
|
resulting averages are written to the training logger (TensorBoard or
|
|
Weights & Biases) under the ``Episode_Metrics/`` prefix.
|
|
|
|
If the ``metrics`` dictionary on ``ManagerBasedRlEnvCfg`` is empty, the
|
|
environment substitutes a lightweight no-op manager with zero overhead.
|
|
|
|
|
|
Registration
|
|
------------
|
|
|
|
Each metric term is registered by name in the ``metrics`` dictionary of
|
|
``ManagerBasedRlEnvCfg``. The configuration is minimal: a callable and an
|
|
optional ``params`` dictionary.
|
|
|
|
.. code-block:: python
|
|
|
|
from mjlab.managers.metrics_manager import MetricsTermCfg
|
|
|
|
metrics = {
|
|
"base_height": MetricsTermCfg(
|
|
func=base_height,
|
|
params={"asset_cfg": SceneEntityCfg("robot")},
|
|
),
|
|
}
|
|
|
|
The callable receives ``env`` as its first argument and any entries in
|
|
``params`` as keyword arguments. It must return a tensor of shape
|
|
``[num_envs]``, one scalar per environment per step.
|
|
|
|
|
|
How metrics are computed
|
|
-------------------------
|
|
|
|
The manager maintains a running sum and a step counter for each
|
|
environment. On every call to ``compute()``:
|
|
|
|
1. The step counter increments for all environments.
|
|
2. Each term function is called with the current environment state.
|
|
3. The returned per-environment values are added to the running sums.
|
|
|
|
When an environment resets, the manager reduces each term's accumulated
|
|
values to a scalar, averages the result across all resetting environments,
|
|
and returns it under the key ``Episode_Metrics/<term_name>``. The sums and
|
|
counters are then zeroed for the reset environments.
|
|
|
|
The reduction is controlled by the ``reduce`` field on ``MetricsTermCfg``:
|
|
|
|
- ``"mean"`` (default): divides the accumulated sum by the step count for
|
|
each environment. Division is per-environment, so environments that
|
|
terminated early are not diluted by longer-running ones.
|
|
- ``"last"``: reports the value from the final step of the episode. This is
|
|
useful for binary success metrics (such as whether the robot is standing)
|
|
that should not be averaged over time.
|
|
- ``"max"``: reports the highest value seen during the episode, useful for
|
|
peak quantities such as maximum power draw or contact force.
|
|
- ``"sum"``: reports the accumulated total over the episode without dividing
|
|
by the step count. Use it for quantities that are inherently cumulative,
|
|
such as episodic reward or total distance traveled. Note that the value
|
|
grows with episode length, so it is not comparable across episodes of
|
|
differing duration.
|
|
|
|
These scalars flow through ``env.extras["log"]`` into the training runner,
|
|
which writes them to the configured logger. In a typical training run they
|
|
appear as:
|
|
|
|
.. code-block:: text
|
|
|
|
Episode_Metrics/base_height
|
|
Episode_Metrics/contact_force
|
|
|
|
alongside the ``Episode_Reward/`` entries produced by the reward manager.
|
|
|
|
|
|
Writing custom metric functions
|
|
--------------------------------
|
|
|
|
A metric function follows the same pattern as reward and observation
|
|
functions. It takes the environment as its first argument, reads whatever
|
|
state it needs, and returns a ``[num_envs]`` tensor.
|
|
|
|
.. code-block:: python
|
|
|
|
import torch
|
|
from mjlab.envs import ManagerBasedRlEnv
|
|
from mjlab.managers.scene_entity_config import SceneEntityCfg
|
|
|
|
def base_height(
|
|
env: ManagerBasedRlEnv,
|
|
asset_cfg: SceneEntityCfg = SceneEntityCfg("robot"),
|
|
) -> torch.Tensor:
|
|
robot = env.scene[asset_cfg.name]
|
|
return robot.data.root_link_pos_w[:, 2]
|
|
|
|
For metrics that require cached setup or per-episode state, implement the
|
|
term as a class with ``__init__(self, cfg, env)`` and a ``__call__``
|
|
method. If the class defines a ``reset(env_ids)`` method, the manager
|
|
calls it automatically on episode resets.
|