Learning¶
eden.learning holds learning-side code that is not a task: policy export, and algorithms that extend an RL
library. A task selects an algorithm in its runner_options through an options class whose class_name names the
implementation, so eden train --task <name> trains it and a saved config.json resumes through it. The
training runs guide explains runners and custom algorithms; the runner options
themselves are on the learning options page.
Policy export¶
eden export writes policy.onnx, policy.pt (TorchScript) and policy_spec.json for a runtime outside Eden.
See the policy export guide.
Export a trained policy for a runtime outside Eden: an ONNX / TorchScript graph plus policy_spec.json.
eden export (:func:eden.utils.cli.tasks.export_task) builds the checkpoint's own env, loads the runner, and
hands both to :func:export_policy, which writes
policy.onnx— inputobs(the actor's observation groups, concatenated, un-normalized), outputactions(the raw policy output, before the action terms scale it), with a dynamic batch axis. A recurrent policy also takesh_in(andc_infor an LSTM), shaped(num_layers, batch, hidden), and returnsh_out(c_out): the caller threads the state, starting from zeros;policy.pt— the same composition as TorchScript, batch 1 when recurrent: its hidden state lives in the module, andreset()zeroes it;policy_spec.json— the contract around the graph (:func:build_policy_spec): what fillsobs, howactionsbecomes joint targets, the control rate, and where the graph came from.
The observation normalizer is part of both graphs. The graph comes from the policy model's own as_onnx() /
as_jit() (rsl-rl-lib >= 4's export hooks), which is also how a learner overrides the default: RMA's
:class:~eden.learning.wrappers.rsl_rl.rma.model.RmaActorModel defines both to export its deployment composition
(estimator injected). An inherited hook can export something other than what the model runs, so every export is
checked against the runner's inference policy on the env's own observations before anything is written
(:func:verify_export). The files are written into a staging directory and moved into place only once checked, so a
failed export leaves the output directory as it was.
The spec records the robot's nominal command: the joint-zero offset domain randomization draws per env is left out
of the action offset, and an env whose default pose itself was randomized at startup is refused
(:func:disable_contract_randomization strips those terms from a config before it is built).
Attributes¶
Classes¶
Functions:¶
export_policy
¶
export_policy(runner: Any, env: RslRlVecEnvWrapper, out_dir: str, *, formats: tuple[str, ...] = EXPORT_FORMATS, task: str, checkpoint: str, verify: bool = True) -> dict[str, str]
Export runner's policy to out_dir and write policy_spec.json beside it.
| PARAMETER | DESCRIPTION |
|---|---|
runner
|
An rsl_rl runner with
TYPE:
|
env
|
The env the runner was built on: the observations the export is checked on, and what the spec describes.
TYPE:
|
out_dir
|
Directory to write into (created if missing). An earlier export there is replaced, and a graph of a format not exported this time is removed with it; on a failure the directory is left as it was.
TYPE:
|
formats
|
Any of :data:
TYPE:
|
task
|
The registered task name, recorded in the spec.
TYPE:
|
checkpoint
|
The checkpoint path, hashed into the spec.
TYPE:
|
verify
|
Check every exported graph against the runner's inference policy (:func:
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict[str, str]
|
|
Source code in eden/learning/export.py
check_export_dependencies
¶
Raise ImportError if a package formats needs is missing: onnx for the ONNX graph's spec, and
onnxruntime to check it.
eden export calls this before it builds anything, so a missing extra costs no env build.
Source code in eden/learning/export.py
disable_contract_randomization
¶
disable_contract_randomization(config: EdenRLConfig) -> list[str]
Disable config's event terms that would randomize what the spec records as nominal; return their names.
Call it before the env is built: eden export does. :func:export_policy refuses an env built with them.
Source code in eden/learning/export.py
refuse_randomized_contract
¶
refuse_randomized_contract(env: RLEnvBase) -> None
Raise ValueError if env was built with an event term that randomizes what the spec records as nominal.
Source code in eden/learning/export.py
policy_obs_groups
¶
The observation groups policy concatenates into its input, in order — the layout of the graph's obs.
Source code in eden/learning/export.py
verify_export
¶
verify_export(files: dict[str, str], inference_policy: Any, env: RslRlVecEnvWrapper, obs_groups: list[str]) -> None
Check every exported graph reproduces inference_policy over :data:VERIFY_STEPS real control steps.
The env is stepped by inference_policy from its current state, under torch.inference_mode as rsl_rl's
rollout steps it; each graph then replays the same observations from a zero recurrent state.
inference_policy is what eden inference runs, so a learner whose export hook exports anything else — an
inherited as_onnx() that skips the model's own forward — fails here, before a spec is written next to it.
| RAISES | DESCRIPTION |
|---|---|
RuntimeError
|
Naming the format, the step and the largest deviation, when a graph disagrees. |
Source code in eden/learning/export.py
build_policy_spec
¶
build_policy_spec(env: RLEnvBase, policy: Any, files: dict[str, str], *, task: str, checkpoint: str, runner_env: RslRlVecEnvWrapper | None = None) -> dict[str, Any]
The policy_spec.json contract for policy as built on env.
Sections: model (the files and their tensors), observations (what fills obs, slice by slice),
actions (how actions becomes a command), entities (each commanded entity's DOFs in column order,
with default positions and PD gains), rate and provenance. runner_env is the rsl_rl wrapper, for
its action clip. env must pass :func:refuse_randomized_contract, as :func:export_policy checks first.
Source code in eden/learning/export.py
rsl-rl-lib algorithms¶
eden.learning.wrappers.rsl_rl holds one subpackage per algorithm. Each has an options module (what a task
configures) next to the implementation.
Models, algorithms and runners for rsl-rl-lib 5, selected through their options' class_name.
- :mod:
.simba— a SimBaV2 actor / critic behind one encoder per observation group. - :mod:
.muon_ppo— PPO whose optimizer is Muon for the 2-D weights and AdamW for the rest. - :mod:
.him— HIMLoco (OpenHomie'sHIMPPO): a self-supervised history estimator feeding the actor, plus rollout-time symmetry and mirror losses. - :mod:
.amp_ppo— PPO plus an adversarial-motion-prior style reward (HUSKY). - :mod:
.rma— the RMA teacher (actor with estimator + scan / privileged / history encoders, PPO with privileged-latent regularization and DAgger) and its depth-student distillation runner (extreme parkour).
Each subpackage ships an options class subclassing the rsl_rl option it replaces (RslRlModelOptions /
RslRlPpoAlgorithmOptions / RslRlBaseRunnerOptions) whose class_name defaults to its implementation, so a
task selects it with actor=<Options>(...), algorithm=<Options>(...) or runner_options=<Options>(...).
SimBaV2 actor-critic¶
Actor / critic options for :class:~eden.learning.wrappers.rsl_rl.simba.model.SimBaModel.
Declarative only — importing this module does not pull in rsl_rl's model API, so a task config that uses it still
imports under any rsl_rl Eden supports. The model its class_name names needs rsl-rl-lib >= 5 and says so when
imported without it. The defaults are Weave's G1-Inspire-HOI networks.
Classes¶
RslRlSimBaCriticOptions
¶
Bases: _SimBaFields
Critic: a deterministic SimBaV2 value network (Weave: 2 blocks).
| PARAMETER | DESCRIPTION |
|---|---|
num_blocks
|
Number of SimBaV2 residual blocks.
TYPE:
|
Source code in eden/options/options.py
RslRlSimBaActorOptions
¶
Bases: _SimBaFields, RslRlModelWithDistributionOptions
Actor: a SimBaV2 policy with a state-independent Gaussian std (Weave: 1 block, scalar std 1.0).
| PARAMETER | DESCRIPTION |
|---|---|
num_blocks
|
Number of SimBaV2 residual blocks.
TYPE:
|
distribution_cfg
|
Output distribution; Weave's is a learned per-action scalar std initialised at 1.0. |
Source code in eden/options/options.py
Attributes¶
distribution_cfg
class-attribute
instance-attribute
¶
distribution_cfg: RslRlGaussianDistributionOptions = RslRlGaussianDistributionOptions(init_std=1.0, std_type='scalar')
SimBaModel
¶
SimBaModel(obs: TensorDict, obs_groups: dict[str, list[str]], obs_set: str, output_dim: int, hidden_dim: int = 512, num_blocks: int = 2, expansion: int = 4, latent_dim: int = 128, encoder_hidden_dims: dict[str, list[int]] | None = None, default_encoder_hidden_dims: list[int] | tuple[int, ...] = (256,), c_shift: float = 3.0, compile: bool = False, hidden_dims: list[int] | tuple[int, ...] = (), activation: str = 'swish', obs_normalization: bool = True, distribution_cfg: dict | None = None)
Bases: MLPModel
Per-group MLP encoders feeding a SimBaV2 backbone, as an rsl_rl >= 5 model.
| PARAMETER | DESCRIPTION |
|---|---|
obs
|
A batch of observations; only the group widths are read.
TYPE:
|
obs_groups
|
Observation set -> groups, as resolved by rsl_rl. |
obs_set
|
The set this model reads (
TYPE:
|
output_dim
|
Output width (action dimension, or 1 for the critic).
TYPE:
|
hidden_dim
|
Width of the SimBaV2 hypersphere.
TYPE:
|
num_blocks
|
Number of SimBaV2 residual blocks.
TYPE:
|
expansion
|
Inner-layer width multiplier of each block.
TYPE:
|
latent_dim
|
Output width of every group encoder.
TYPE:
|
encoder_hidden_dims
|
Per-group hidden widths of the group encoders. A key must name an observation group the env provides; a
group of this set without a key uses |
default_encoder_hidden_dims
|
Hidden widths for groups not in |
c_shift
|
Input shift of the SimBaV2 embedder.
TYPE:
|
compile
|
TYPE:
|
hidden_dims
|
Inherited from rsl_rl's |
activation
|
Activation between the layers of the group encoders (Weave: SiLU, which rsl_rl names
TYPE:
|
obs_normalization
|
Normalise the concatenated observation with
TYPE:
|
distribution_cfg
|
Output distribution (actor), or
TYPE:
|
Source code in eden/learning/wrappers/rsl_rl/simba/model.py
Attributes¶
mlp
instance-attribute
¶
mlp = nn.Sequential(encoder, SimBa(encoder.out_features, trunk_output_dim, hidden_dim, num_blocks, expansion, c_shift))
Methods:¶
forward
¶
forward(obs: TensorDict, masks: Tensor | None = None, hidden_state: Any = None, stochastic_output: bool = False) -> Tensor
Source code in eden/learning/wrappers/rsl_rl/simba/model.py
PPO with Muon¶
Algorithm options for :class:~eden.learning.wrappers.rsl_rl.muon_ppo.ppo.MuonPPO.
Declarative only — importing this module pulls in neither rsl_rl's algorithm API nor torch.optim.Muon, so a task
config that uses it still imports under any rsl_rl Eden supports. The algorithm its class_name names needs
rsl-rl-lib >= 5 and torch >= 2.10, and says so when imported without them.
Classes¶
RslRlMuonPpoAlgorithmOptions
¶
Bases: RslRlPpoAlgorithmOptions
PPO with Muon (2-D weights) + AdamW (the rest), Weave's hyperparameters as defaults.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The algorithm class rsl_rl resolves; leave at the default.
TYPE:
|
learning_rate
|
Initial learning rate of both optimizers (then adapted to
TYPE:
|
entropy_coef
|
Entropy bonus coefficient.
TYPE:
|
weight_decay
|
AdamW weight decay.
TYPE:
|
muon_weight_decay
|
Muon weight decay (Weave leaves
TYPE:
|
Source code in eden/options/options.py
Attributes¶
MuonPPO
¶
Bases: PPO
rsl_rl PPO whose Adam is replaced by :class:MuonAdamW over the actor and critic.
| PARAMETER | DESCRIPTION |
|---|---|
*args
|
Forwarded to
TYPE:
|
weight_decay
|
AdamW weight decay (Weave: 0.01).
TYPE:
|
muon_weight_decay
|
Muon weight decay (Weave: torch's default, 0.1).
TYPE:
|
**kwargs
|
Forwarded to
TYPE:
|
Source code in eden/learning/wrappers/rsl_rl/muon_ppo/ppo.py
Attributes¶
optimizer
instance-attribute
¶
optimizer = MuonAdamW([self.actor, self.critic], lr=self.learning_rate, weight_decay=weight_decay, muon_weight_decay=muon_weight_decay)
Methods:¶
update
¶
Run the stock PPO update, and log the value function's explained variance (Weave's extra metric).
| RETURNS | DESCRIPTION |
|---|---|
dict[str, float]
|
rsl_rl's loss dict plus |
Source code in eden/learning/wrappers/rsl_rl/muon_ppo/ppo.py
PPO with an adversarial motion prior¶
Algorithm options for :class:~eden.learning.wrappers.rsl_rl.amp_ppo.ppo.AmpPPO.
Declarative only — importing this module pulls in neither rsl_rl's algorithm API nor the discriminator, so a task
config that uses it still imports under any rsl_rl Eden supports. The algorithm its class_name names needs
rsl-rl-lib >= 5.5.1 and says so when imported without it.
Classes¶
RslRlAmpPpoAlgorithmOptions
¶
Bases: RslRlPpoAlgorithmOptions
PPO plus an adversarial motion prior (AMP) style reward; defaults are the HUSKY release's.
The env must publish the observation group amp_obs_group as [joint positions x amp_num_frames (oldest
first), style gate]: the style reward is added only where the gate is set (> 0.5), and every window is banked as
a policy sample for the discriminator.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The algorithm class rsl_rl resolves; leave at the default.
TYPE:
|
amp_motion_file
|
Asset path (resolved by
TYPE:
|
amp_obs_group
|
Observation group carrying the window and the gate.
TYPE:
|
amp_num_frames
|
Frames per window; must equal the group's joint-position
TYPE:
|
amp_reward_coef
|
Scale inside the LSGAN style reward
TYPE:
|
amp_reward_scale
|
Extra multiplier on the style reward before it is added to the env reward.
TYPE:
|
amp_replay_size
|
Capacity of the policy-window replay buffer.
TYPE:
|
amp_discr_hidden_dims
|
Hidden widths of the spectral-norm discriminator MLP. |
amp_grad_pen_scale
|
Gradient-penalty weight at the expert samples.
TYPE:
|
amp_trunk_weight_decay
|
Weight decay of the discriminator trunk.
TYPE:
|
amp_head_weight_decay
|
Weight decay of the discriminator head.
TYPE:
|
amp_warm_start
|
Allow loading a checkpoint without AMP state (one trained as plain PPO): its actor-critic loads and the discriminator starts fresh. Off, such a checkpoint is refused rather than resumed under a changed reward.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
amp_discr_hidden_dims
class-attribute
instance-attribute
¶
Methods:¶
for_inference
¶
for_inference() -> RslRlPpoAlgorithmOptions
Stock PPO with the same PPO fields — what replays an AMP checkpoint (the AMP state only shapes training).
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/options.py
preflight
¶
Load the expert clips (eden train calls this before building the env), so a bad file fails first.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/options.py
AmpPPO
¶
AmpPPO(actor, critic, storage, *, amp_motion_file: str, amp_obs_group: str = 'amp', amp_num_frames: int = 5, amp_reward_coef: float = 5.0, amp_reward_scale: float = 0.02, amp_replay_size: int = 100000, amp_discr_hidden_dims: tuple[int, ...] = (256, 256), amp_grad_pen_scale: float = 5.0, amp_trunk_weight_decay: float = 0.001, amp_head_weight_decay: float = 0.1, amp_warm_start: bool = False, **ppo_kwargs)
Bases: PPO
PPO + an adversarial motion prior on gated windows of joint positions.
The amp_* keyword arguments are documented on
:class:~eden.learning.wrappers.rsl_rl.amp_ppo.options.RslRlAmpPpoAlgorithmOptions; the rest go to rsl_rl's PPO.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
Attributes¶
amp_expert
instance-attribute
¶
amp_expert = AmpMotionSampler(amp_motion_file, amp_num_frames, self.device)
discriminator
instance-attribute
¶
discriminator = AmpDiscriminator(window_dim, tuple(amp_discr_hidden_dims)).to(self.device)
amp_normalizer
instance-attribute
¶
amp_normalizer = FrameNormalizer(self.amp_expert.frame_dim).to(self.device)
amp_replay
instance-attribute
¶
amp_replay = AmpReplayBuffer(window_dim, amp_replay_size, self.device)
amp_optimizer
instance-attribute
¶
amp_optimizer = torch.optim.Adam([{'params': self.discriminator.trunk.parameters(), 'weight_decay': amp_trunk_weight_decay}, {'params': self.discriminator.head.parameters(), 'weight_decay': amp_head_weight_decay}], lr=self.learning_rate)
Methods:¶
construct_algorithm
staticmethod
¶
rsl_rl's PPO construction, then the AMP group checked against the env's first observation.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
process_env_step
¶
process_env_step(obs: TensorDict, rewards: Tensor, dones: Tensor, extras: dict[str, Tensor]) -> None
Add the gated style reward and bank the policy window, then defer to PPO.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
update
¶
Run the PPO update, then the discriminator's LSGAN updates.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
broadcast_parameters
¶
PPO's broadcast, plus the discriminator (spectral-norm vectors included) and the frame normalizer.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
load
¶
PPO's load, plus the discriminator, its optimizer and the frame normalizer.
A checkpoint without them was trained as plain PPO. Continuing it under AMP changes the reward under a value
function trained without the style term, so it is refused unless amp_warm_start says that is the intent
(the discriminator then starts fresh).
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/ppo.py
train_mode
¶
Adversarial-motion-prior components used by :class:~eden.learning.wrappers.rsl_rl.amp_ppo.ppo.AmpPPO.
Ports the adversarial-motion-prior machinery of TeleHuman/humanoid_skateboarding
(its vendored rsl_rl fork: DiscriminatorMulti, G1_AMPLoader,
ReplayBufferMulti, Normalizer):
- :class:
AmpMotionSamplerdraws windows ofnum_framesconsecutive frames (linear interpolation between recorded frames) from expert motion clips. A frame is one joint-position vector, in the order the env's AMP observation group emits it (HUSKY: the G1's 23 no-wrist joints in MJCF order). - :class:
AmpDiscriminatoris the LSGAN discriminator (spectral-norm MLP, expert target +1, policy target -1); its raw outputdmaps to the style rewardcoef * clamp(1 - 0.25 (d - 1)^2, min=0). - :class:
AmpReplayBufferis a flat ring buffer of policy windows. - :class:
FrameNormalizeris a running mean/std over single frames, applied per-frame to whole windows before the discriminator.
Deviation from the source: the source updated its normalizer with already-normalized batches (a bug that decays the statistics toward identity); this one updates from raw frames.
Classes¶
AmpMotionSampler
¶
Samples expert windows of num_frames consecutive frames from motion clips.
| PARAMETER | DESCRIPTION |
|---|---|
motion_file
|
Asset path of the
TYPE:
|
num_frames
|
Frames per window. The window spans
TYPE:
|
device
|
Device the sampled windows live on.
TYPE:
|
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
Attributes¶
motions
instance-attribute
¶
motions = [torch.as_tensor(data[f'motion_{i}'], dtype=torch.float32, device=device) for i in range(int(data['num_motions']))]
Methods:¶
sample
¶
sample(batch_size: int) -> Tensor
Return expert windows, shape (batch_size, num_frames, frame_dim), oldest frame first.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
AmpReplayBuffer
¶
Flat ring buffer of policy windows (one row = one flattened window).
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
Methods:¶
insert
¶
Insert a batch of flattened windows, overwriting the oldest entries.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
FrameNormalizer
¶
Bases: Module
Running mean/std over single frames, applied per-frame to windows.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
Attributes¶
Methods:¶
update
¶
Fold a batch of raw frames (..., frame_dim) into the running statistics.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
normalize
¶
Normalize frames or windows of frames (..., frame_dim).
AmpDiscriminator
¶
Bases: Module
LSGAN discriminator over flattened windows (spectral-norm MLP + linear head).
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
Attributes¶
Methods:¶
forward
¶
style_reward
¶
style_reward(windows: Tensor, coef: float) -> Tensor
Per-window style reward coef * clamp(1 - 0.25 (d - 1)^2, min=0), shape (N,).
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
gradient_penalty
¶
gradient_penalty(expert_windows: Tensor, scale: float) -> Tensor
Penalize the discriminator's gradient norm at the expert samples.
Source code in eden/learning/wrappers/rsl_rl/amp_ppo/amp.py
Functions:¶
RMA teacher and depth-student distillation¶
Options for the RMA teacher (actor model + PPO) and its depth-student distillation.
Declarative only — importing this module pulls in neither rsl_rl's model/algorithm API nor torch modules, so a task
config that uses it still imports under any rsl_rl Eden supports. The classes their class_name fields name need
rsl-rl-lib >= 5.5.1 and say so when imported without it. Defaults are the extreme-parkour teacher's (Cheng et al. 2023).
Classes¶
RslRlRmaActorOptions
¶
Bases: RslRlModelWithDistributionOptions
The RMA actor: estimator + scan / privileged / history encoders + backbone over one flat observation.
The actor observation set must concatenate to [prop | scan | priv_explicit | priv_latent | num_hist x prop]
with the widths below (checked when the model is built).
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The model class rsl_rl resolves; leave at the default.
TYPE:
|
num_prop
|
Chunk widths of the flat observation (
TYPE:
|
num_scan
|
Chunk widths of the flat observation (
TYPE:
|
num_priv_explicit
|
Chunk widths of the flat observation (
TYPE:
|
num_priv_latent
|
Chunk widths of the flat observation (
TYPE:
|
num_hist
|
Chunk widths of the flat observation (
TYPE:
|
scan_encoder_dims
|
Scan encoder widths; the last is the scan latent width (Tanh-bounded). |
priv_encoder_dims
|
Privileged encoder widths; the last is the adaptation latent width, which the history encoder matches. |
hidden_dims
|
Actor backbone hidden widths. |
activation
|
Activation of every encoder and the backbone.
TYPE:
|
estimator_hidden_dims
|
Hidden widths of the base-velocity estimator (proprioception -> privileged-explicit chunk). |
tanh_backbone_output
|
Squash the action mean with Tanh.
TYPE:
|
obs_normalization
|
Must stay
TYPE:
|
distribution_cfg
|
A state-independent Gaussian ( |
Source code in eden/options/options.py
Attributes¶
estimator_hidden_dims
class-attribute
instance-attribute
¶
distribution_cfg
class-attribute
instance-attribute
¶
distribution_cfg: RslRlGaussianDistributionOptions = RslRlGaussianDistributionOptions(init_std=1.0, std_type='scalar')
RslRlRmaPpoAlgorithmOptions
¶
Bases: RslRlPpoAlgorithmOptions
PPO for an RMA actor: concurrent estimator, privileged-latent regularization, DAgger, optional mirror loss.
Needs actor=RslRlRmaActorOptions(...). The PPO defaults are the extreme-parkour teacher's.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The algorithm class rsl_rl resolves; leave at the default.
TYPE:
|
estimator_learning_rate
|
Learning rate of the estimator's own Adam.
TYPE:
|
train_with_estimated_states
|
Act on the estimator's prediction of the privileged-explicit chunk during rollouts (storage keeps the truth).
TYPE:
|
dagger_update_freq
|
Every this-many learning iterations, roll out with the history latent and regress the history encoder onto the privileged latent afterwards.
TYPE:
|
priv_reg_coef_schedule
|
|
symmetry_coef
|
Weight of the mirror-equivariance loss (0 disables it).
TYPE:
|
mirror_class_name
|
TYPE:
|
Source code in eden/options/options.py
RslRlRmaDepthDistillationAlgorithmOptions
¶
Bases: ConfigurableOptions
DAgger distillation of an RMA teacher into a depth student (recurrent depth encoder + copied actor net).
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The algorithm class the runner resolves; leave at the default.
TYPE:
|
learning_rate
|
Adam learning rate of the student (depth actor + depth encoder).
TYPE:
|
max_grad_norm
|
Gradient-norm clip on the depth actor.
TYPE:
|
gru_hidden_dim
|
Hidden width of the depth encoder's GRU.
TYPE:
|
update_interval
|
Control steps between depth-encoder passes; must equal the env's depth refresh cadence.
TYPE:
|
yaw_scale
|
Stretch of the Tanh-bounded yaw head.
TYPE:
|
yaw_slots
|
|
num_pretrain_iters
|
Iterations driven by the teacher's actions before the student takes over.
TYPE:
|
depth_obs_group
|
Observation group carrying the processed depth frame.
TYPE:
|
yaw_gate_obs_group
|
Observation group whose flag (> 0.5) lets the student see its own yaw prediction.
TYPE:
|
Source code in eden/options/options.py
RslRlRmaDepthDistillationRunnerOptions
¶
Bases: RslRlBaseRunnerOptions
Runner options selecting the depth-student DAgger loop; train with --checkpoint <teacher checkpoint>.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The runner
TYPE:
|
actor
|
The teacher's architecture — it must match the teacher checkpoint being distilled.
TYPE:
|
algorithm
|
The distillation's knobs. |
Source code in eden/options/options.py
RmaActorModel
¶
RmaActorModel(obs: TensorDict, obs_groups: dict[str, list[str]], obs_set: str, output_dim: int, num_prop: int = 53, num_scan: int = 132, num_priv_explicit: int = 9, num_priv_latent: int = 29, num_hist: int = 10, scan_encoder_dims: tuple[int, ...] | list[int] = (128, 64, 32), priv_encoder_dims: tuple[int, ...] | list[int] = (64, 20), hidden_dims: tuple[int, ...] | list[int] = (512, 256, 128), activation: str = 'elu', estimator_hidden_dims: tuple[int, ...] | list[int] = (128, 64), tanh_backbone_output: bool = False, obs_normalization: bool = False, distribution_cfg: dict | None = None)
Bases: MLPModel
RMA actor over one flat [prop | scan | priv_explicit | priv_latent | history] observation.
Subclasses rsl_rl's MLPModel for its distribution plumbing (output_*, log-prob, KL, entropy) and its
recurrent no-ops, but replaces the trunk: there is no self.mlp, and observation normalization is refused —
the task's terms carry hand-tuned fixed scales, and the chunks are sliced by position.
| PARAMETER | DESCRIPTION |
|---|---|
obs
|
rsl_rl's model arguments; the groups of
TYPE:
|
obs_groups
|
rsl_rl's model arguments; the groups of
TYPE:
|
obs_set
|
rsl_rl's model arguments; the groups of
TYPE:
|
output_dim
|
rsl_rl's model arguments; the groups of
TYPE:
|
num_prop
|
Chunk widths (:class:
TYPE:
|
num_scan
|
Chunk widths (:class:
TYPE:
|
num_priv_explicit
|
Chunk widths (:class:
TYPE:
|
num_priv_latent
|
Chunk widths (:class:
TYPE:
|
num_hist
|
Chunk widths (:class:
TYPE:
|
scan_encoder_dims
|
Encoder widths; the last entry of each is its latent width. |
priv_encoder_dims
|
Encoder widths; the last entry of each is its latent width. |
hidden_dims
|
Actor backbone hidden widths. |
activation
|
Activation everywhere but the scan latent (Tanh) and the estimator output (linear).
TYPE:
|
estimator_hidden_dims
|
Hidden widths of the base-velocity estimator. |
tanh_backbone_output
|
Squash the action mean with Tanh.
TYPE:
|
obs_normalization
|
Must be
TYPE:
|
distribution_cfg
|
The output distribution (a state-independent Gaussian for the RMA teacher).
TYPE:
|
Source code in eden/learning/wrappers/rsl_rl/rma/model.py
Attributes¶
dims
instance-attribute
¶
net
instance-attribute
¶
net = RmaActor(self.dims, output_dim, list(scan_encoder_dims), list(priv_encoder_dims), list(hidden_dims), act, tanh_backbone_output=tanh_backbone_output)
estimator
instance-attribute
¶
estimator = Estimator(num_prop, num_priv_explicit, list(estimator_hidden_dims), act)
Methods:¶
forward
¶
forward(obs: TensorDict, masks: Tensor | None = None, hidden_state=None, stochastic_output: bool = False, *, hist_encoding: bool = True, estimate: bool = True) -> Tensor
Action (mean, or a sample with stochastic_output); the switches are described in the module docstring.
Source code in eden/learning/wrappers/rsl_rl/rma/model.py
mean
¶
Action mean from the flat observation (no distribution update).
Source code in eden/learning/wrappers/rsl_rl/rma/model.py
with_estimate
¶
A copy of flat whose privileged-explicit chunk is the estimator's prediction (detached).
Detached: the policy loss never trains the estimator — it has its own regression loss and optimizer.
Source code in eden/learning/wrappers/rsl_rl/rma/model.py
get_flat_obs
¶
The concatenated observation groups of this model's set.
policy_parameters
¶
Every parameter but the estimator's — what the PPO optimizer and its gradient clip cover.
get_latent
¶
as_jit
¶
RmaPPO
¶
RmaPPO(actor: RmaActorModel, critic, storage, *, estimator_learning_rate: float = 0.0001, train_with_estimated_states: bool = True, dagger_update_freq: int = 20, priv_reg_coef_schedule: tuple[float, float, int, int] | list = (0.0, 0.1, 2000, 3000), symmetry_coef: float = 0.0, mirror_class_name: str | None = None, optimizer: str = 'adam', **ppo_kwargs)
Bases: PPO
PPO + estimator + privileged-latent regularization + DAgger (+ mirror loss) for an :class:RmaActorModel.
The extra keyword arguments are documented on
:class:~eden.learning.wrappers.rsl_rl.rma.options.RslRlRmaPpoAlgorithmOptions; the rest go to rsl_rl's PPO.
Source code in eden/learning/wrappers/rsl_rl/rma/ppo.py
Attributes¶
distributed_unsupported
class-attribute
instance-attribute
¶
distributed_unsupported = 'RmaPPO trains on one GPU: its estimator and history-encoder optimizers have no gradient reduction, so a distributed launch would train them independently per rank. Launch the RMA teacher as one process (without torchrun).'
optimizer
instance-attribute
¶
optimizer = resolve_optimizer(optimizer)(chain(self.actor.policy_parameters(), self.critic.parameters()), lr=self.learning_rate)
estimator_optimizer
instance-attribute
¶
estimator_optimizer = torch.optim.Adam(self.actor.estimator.parameters(), lr=estimator_learning_rate)
hist_encoder_optimizer
instance-attribute
¶
hist_encoder_optimizer = torch.optim.Adam(self.actor.net.history_encoder.parameters(), lr=self.learning_rate)
train_with_estimated_states
instance-attribute
¶
mirror
instance-attribute
¶
mirror = resolve_callable(mirror_class_name)(self.actor.dims, self.device) if symmetry_coef > 0.0 else None
is_dagger_iteration
property
¶
is_dagger_iteration: bool
Whether the current rollout uses the history latent and is followed by a DAgger update.
Methods:¶
act
¶
Sample actions — through the estimator and, on DAgger iterations, the history latent — and record them.
Source code in eden/learning/wrappers/rsl_rl/rma/ppo.py
update
¶
PPO epochs with the estimator, priv-reg and mirror terms; then DAgger on DAgger iterations.
Source code in eden/learning/wrappers/rsl_rl/rma/ppo.py
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | |
update_dagger
¶
update_dagger() -> float
Regress the history (adaptation) encoder onto the privileged latent over the stored rollout.
Source code in eden/learning/wrappers/rsl_rl/rma/ppo.py
load
¶
PPO's load — with the actor checked key for key whatever strict says — plus the RMA state.
Eden loads with strict=False to tolerate drift, but a partially loaded RMA actor (another model's
checkpoint, e.g. a plain MLP actor's mlp.*) would run with random encoders or estimator.
Source code in eden/learning/wrappers/rsl_rl/rma/ppo.py
DAgger depth distillation of an RMA teacher into a depth-camera student (rsl-rl-lib >= 5.5.1).
Port of the vision distillation loop from "Extreme Parkour with Legged Robots" (Cheng et al. 2023). The frozen
teacher (:class:~eden.learning.wrappers.rsl_rl.rma.model.RmaActorModel, history-latent path, true scandots, ground
truth privileged-explicit chunk) labels every step; the student — depth_actor (a copy of the teacher's actor net)
fed by a recurrent depth_encoder whose latent replaces the scan latent — acts and drives the environment from
its depth latent and its own prediction of the delta-yaw slots; one optimizer step per iteration regresses
student -> teacher actions plus the yaw prediction, backpropagating through the whole iteration's graph.
That loop fits neither rsl_rl's Distillation (which stores observations and trains on mini-batches) nor its runner
loop (which collects under torch.inference_mode), so this module ships its own runner,
:class:RmaDepthDistillationRunner — what
:class:~eden.learning.wrappers.rsl_rl.rma.options.RslRlRmaDepthDistillationRunnerOptions's class_name names, so
eden train --task extreme_parkour_student --checkpoint <teacher model_<it>.pt> runs it.
Cadence contract: the depth encoder runs only on control steps where the env refreshed the depth observation
(common_step_counter % update_interval == 0); between refreshes the cached latent/yaw are reused. Every
observation term of the student's groups that declares an update_interval must run at the same cadence (checked
against the live env at construction), and num_steps_per_env must be a positive multiple of it so an iteration
boundary never splits a cadence window (the update would otherwise backprop into the previous iteration's freed graph).
Checkpoints carry the teacher (actor_state_dict, estimator included — the same key a teacher checkpoint has) plus
depth_actor_state_dict / depth_encoder_state_dict / depth_optimizer_state_dict. load() accepts
either: a teacher checkpoint starts a fresh distillation (student actor re-copied from the teacher), a student
checkpoint resumes one. Only a student checkpoint (or a student trained in this process) replays:
:meth:RmaDepthDistillationRunner.get_inference_policy refuses an untrained depth encoder.
Like the source, the student reads the privileged-explicit chunk (base linear velocity) as the env provides it — in
sim, the ground truth — in distillation and in replay alike. It is an in-sim policy: eden deploy refuses this
runner, and a hardware port would have to substitute the frozen teacher's estimator for that chunk (in distillation
too, so the student trains on what it would see).
Attributes¶
RMA_DEPTH_DISTILLATION_RUNNER_CLASS_NAME
module-attribute
¶
RMA_DEPTH_DISTILLATION_RUNNER_CLASS_NAME = 'eden.learning.wrappers.rsl_rl.rma.distillation:RmaDepthDistillationRunner'
RMA_DEPTH_DISTILLATION_CLASS_NAME
module-attribute
¶
RMA_DEPTH_DISTILLATION_CLASS_NAME = 'eden.learning.wrappers.rsl_rl.rma.distillation:RmaDepthDistillation'
Classes¶
RmaDepthDistillation
¶
RmaDepthDistillation(teacher: RmaActorModel, *, depth_obs_group: str = _STUDENT_GROUP_KEYS['depth_obs_group'], yaw_gate_obs_group: str = _STUDENT_GROUP_KEYS['yaw_gate_obs_group'], yaw_slots: tuple[int, int] | list[int] = (6, 8), update_interval: int = 5, num_pretrain_iters: int = 0, gru_hidden_dim: int = 512, learning_rate: float = 0.001, max_grad_norm: float = 1.0, yaw_scale: float = 1.5, device: str = 'cpu', multi_gpu_cfg: dict | None = None)
The student stage's modules and optimizer; :meth:update applies one DAgger regression.
Holds the frozen teacher (an :class:RmaActorModel, kept whole — estimator included — so a student checkpoint
stays self-contained), the trainable depth_encoder and the trainable depth_actor (initialized as a copy of
the teacher's actor net). The rollout loop lives in :class:RmaDepthDistillationRunner. The keyword arguments are
documented on :class:~eden.learning.wrappers.rsl_rl.rma.options.RslRlRmaDepthDistillationAlgorithmOptions.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
Attributes¶
depth_encoder
instance-attribute
¶
depth_encoder = RecurrentDepthEncoder(num_prop=self.dims.num_prop, latent_dim=teacher.net.scan_latent_dim, gru_hidden_dim=gru_hidden_dim).to(device)
depth_actor
instance-attribute
¶
optimizer
instance-attribute
¶
optimizer = torch.optim.Adam([*self.depth_actor.parameters(), *self.depth_encoder.parameters()], lr=learning_rate)
Methods:¶
construct_algorithm
staticmethod
¶
construct_algorithm(obs: TensorDict, env, cfg: dict, device: str) -> RmaDepthDistillation
Build the teacher from cfg["actor"] (it must match the teacher checkpoint) and the student around it.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
encode
¶
encode(depth_frame: Tensor, flat: Tensor) -> tuple[Tensor, Tensor]
One depth-encoder pass: (depth latent, scaled 2-d yaw prediction).
The proprioception chunk is fed with the yaw slots hidden (the student must recover heading from depth); the
Tanh-bounded yaw head is stretched by yaw_scale. Shared by the training loop and the inference policy so
the encoding contract cannot drift between them.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
teacher_actions
¶
The teacher's label: history latent, true scandots, ground-truth privileged-explicit chunk (no estimator).
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
student_actions
¶
The student's action from the (yaw-substituted) flat observation and the depth latent.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
update
¶
One optimizer step on the iteration's teacher - student actions and true - predicted yaw errors.
Both losses are mean per-sample L2 norms; the gradient clip covers the actor only (faithful to the source).
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
train_mode
¶
eval_mode
¶
load
¶
Load the teacher, and the student halves when present; True when it resumed a student.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
RmaDepthDistillationRunner
¶
Bases: ProgressFileMixin, AgentIterationLogMixin, CheckpointRetentionMixin, OnPolicyRunner
Runs :class:RmaDepthDistillation's DAgger loop; see the module docstring for the loop and its contracts.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
Attributes¶
checkpoint_required
class-attribute
instance-attribute
¶
checkpoint_required = "Depth distillation needs a teacher: pass --checkpoint <the teacher run's model_<it>.pt> (or --resume / --checkpoint <a student checkpoint> to continue a distillation)."
Methods:¶
learn
¶
The vision DAgger loop; init_at_random_ep_len spreads the envs' episode clocks, as rsl_rl's loop does.
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | |
load
¶
Load a teacher checkpoint (fresh distillation) or a student checkpoint (resume).
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
get_inference_policy
¶
The deployed student: depth encoder every update_interval steps, its yaw in the yaw slots.
The yaw prediction replaces the yaw slots unconditionally (the source's play behavior — the gate is a training-time aid), and the privileged-explicit chunk stays as the env provides it (in-sim ground truth; a hardware deployment would substitute the teacher's estimator here).
Source code in eden/learning/wrappers/rsl_rl/rma/distillation.py
HIMLoco¶
The :class:~eden.learning.wrappers.rsl_rl.him.ppo.HIMPPO algorithm options.
Classes¶
HIMPPOAlgorithmOptions
¶
Bases: RslRlPpoAlgorithmOptions
PPO options for OpenHomie's HIMLoco learner.
Built by rsl-rl-lib's own OnPolicyRunner on any major Eden supports (3, 4, 5), so eden train
and eden inference need nothing algorithm-specific; :meth:adapt_runner_dict routes the
construction for the installed major. The task supplies the two things that tie
HIMPPO to an observation layout:
- the observation groups:
obs_groups["actor"]one group of stacked frames,obs_groups["critic"]one group of a single frame + the true base linear velocity (3, last); - the mirror,
data_augmentation_func.
| PARAMETER | DESCRIPTION |
|---|---|
data_augmentation_func
|
|
use_flip
|
Also train the estimator on mirrored observations and add the actor and critic mirror losses
(OpenHomie
|
symmetry_scale
|
Weight of the two mirror losses.
|
target_skip_dim
|
Leading entries of the next critic observation the SwAV target encoder leaves out (OpenHomie drops the three velocity commands a frame starts with).
|
Source code in eden/options/options.py
Attributes¶
class_name
class-attribute
instance-attribute
¶
class_name: str = 'eden.learning.wrappers.rsl_rl.him.ppo:HIMPPO'
Methods:¶
adapt_runner_dict
¶
Point the version-translated runner dict at HIM's constructors for rsl-rl-lib major.
4 and 5 build the algorithm through class_name → construct_algorithm, which reads the
translated dict as it is. 3 builds the model from policy.class_name and calls the algorithm
class with it, so both go to HIM's v3 factories, and the model gets target_skip_dim.
| PARAMETER | DESCRIPTION |
|---|---|
runner_dict
|
The dict :func:
TYPE:
|
major
|
The installed rsl-rl-lib major version.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
dict
|
|
Source code in eden/learning/wrappers/rsl_rl/him/options.py
HIMPPO
¶
HIMPPO(actor_critic: HIMActorCritic, use_flip: bool = True, num_learning_epochs: int = 5, num_mini_batches: int = 4, clip_param: float = 0.2, gamma: float = 0.99, lam: float = 0.95, value_loss_coef: float = 1.0, entropy_coef: float = 0.01, learning_rate: float = 0.001, max_grad_norm: float = 1.0, use_clipped_value_loss: bool = True, schedule: str = 'adaptive', desired_kl: float = 0.01, device: str = 'cpu', symmetry_scale: float = 1.0, env=None, data_augmentation_func: Callable | None = None)
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
Attributes¶
optimizer
instance-attribute
¶
optimizer = HIMOptimizer(optim.Adam(self.actor_critic.parameters(), lr=learning_rate), self.actor_critic.estimator.optimizer)
Methods:¶
construct_algorithm
classmethod
¶
rsl-rl-lib 4 / 5's construction hook: build the actor-critic, the storage and the algorithm.
The mirror is run once on these observations' widths, so a layout it does not cover fails here, before a rollout.
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
from_rsl_rl_v3
classmethod
¶
from_rsl_rl_v3(actor_critic: HIMActorCritic, storage, device: str, multi_gpu_cfg=None, **alg_cfg) -> HIMPPO
rsl-rl-lib 3's construction call, alg_class(actor_critic, storage, device=, **alg_cfg, multi_gpu_cfg=).
Reached through the algorithm.class_name that HIMPPOAlgorithmOptions.adapt_runner_dict writes;
the runner has already built actor_critic (HIMActorCritic.from_rsl_rl_v3). Its stock rollout
storage is only read for its size. v3 hands the algorithm no env, so the mirror gets env=None.
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
init_storage
¶
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
train_mode
¶
eval_mode
¶
get_policy
¶
save
¶
save() -> dict
rsl-rl-lib 4 / 5's checkpoint contents (v3's runner saves policy and optimizer itself).
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
load
¶
Load what load_cfg selects (everything when None); return whether to restore the iteration.
The weights always load strictly, whatever strict says. Eden's checkpoint loader passes
strict=False so stock PPO can take older rsl-rl layouts, but a HIM checkpoint has one layout: a
missing or extra key means the wrong checkpoint, and loading past it would leave those weights at
their random init. ValueError, not KeyError, so the loader does not reword it as an
rsl-rl version mismatch.
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
act
¶
process_env_step
¶
Record the step; obs is the observation after it, post-reset for the envs that ended.
The estimator's target is the true next critic observation, so the ended envs take their
pre-reset one from extras["final_observations"] — OpenHomie's
next_critic_obs[termination_ids] = termination_privileged_obs.
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
compute_returns
¶
update
¶
Source code in eden/learning/wrappers/rsl_rl/him/ppo.py
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 | |
HIMActorCritic
¶
HIMActorCritic(num_actor_obs: int, num_critic_obs: int, num_one_step_obs: int, actor_history_length: int, num_actions: int, actor_hidden_dims=(512, 256, 256), critic_hidden_dims=(512, 256, 256), activation: str = 'elu', init_noise_std: float = 1.0, dynamic_latent_dim: int = 32, obs_group: str = 'policy', target_skip_dim: int = 3, critic_obs_group: str = 'critic')
Bases: Module
Source code in eden/learning/wrappers/rsl_rl/him/actor_critic.py
Attributes¶
actor_proprioceptive_obs_length
instance-attribute
¶
estimator
instance-attribute
¶
estimator = HIMEstimator(temporal_steps=actor_history_length, num_one_step_obs=num_one_step_obs, num_height_points=0, latent_dim=dynamic_latent_dim, target_skip_dim=target_skip_dim)
Methods:¶
from_groups
classmethod
¶
from_groups(obs, actor_group: str, critic_group: str, num_actions: int, *, actor_hidden_dims, critic_hidden_dims, activation: str, init_noise_std: float, target_skip_dim: int) -> HIMActorCritic
Size the networks off the observation TensorDict, checking it has the layout HIM assumes.
The actor_group holds a whole number of stacked frames, the critic_group one frame followed
by the true base linear velocity (VELOCITY_DIM).
Source code in eden/learning/wrappers/rsl_rl/him/actor_critic.py
from_rsl_rl_v3
classmethod
¶
from_rsl_rl_v3(obs, obs_groups: dict, num_actions: int, **policy_cfg) -> HIMActorCritic
rsl-rl-lib 3's construction call, policy_class(obs, obs_groups, num_actions, **policy_cfg).
Reached through the policy.class_name that HIMPPOAlgorithmOptions.adapt_runner_dict writes.
Source code in eden/learning/wrappers/rsl_rl/him/actor_critic.py
reset
¶
forward
¶
The deterministic action for an observation TensorDict: what rsl-rl-lib 4/5's get_inference_policy
serves.
update_distribution
¶
act
¶
get_actions_log_prob
¶
act_inference
¶
The deterministic action, from the history tensor or the whole observation TensorDict.
rsl-rl-lib 3's get_inference_policy hands out this method itself, called on the TensorDict.
Source code in eden/learning/wrappers/rsl_rl/him/actor_critic.py
evaluate
¶
FlashSAC¶
Off-policy SAC from the external rsl-rl-flashsac package, which is not on PyPI: install it with
uv sync --inexact --extra flashsac --group flashsac-git in a checkout.
Runner options for FlashSAC (github.com/Holiday-Robot/rsl_rl_flashsac): off-policy SAC with SimBa-style residual networks, a distributional critic and a large GPU replay buffer.
Declarative only — importing this module pulls in neither rsl_rl_flashsac nor rsl_rl, so a task config that uses
it imports anywhere. Training needs the flashsac extra
(uv sync --inexact --extra flashsac --group flashsac-git; rsl-rl-lib >= 5.4).
The class names are the ones rsl_rl_flashsac resolves (its own modules first, then rsl_rl's).
Classes¶
RslRlFlashSacActorOptions
¶
Bases: ConfigurableOptions
The FlashSAC actor: a tanh-squashed Gaussian on residual blocks.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The model class
TYPE:
|
num_blocks
|
Residual blocks.
TYPE:
|
hidden_dim
|
Block width.
TYPE:
|
log_std_min
|
Bounds of the log standard deviation.
TYPE:
|
log_std_max
|
Bounds of the log standard deviation.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
RslRlFlashSacCriticOptions
¶
Bases: ConfigurableOptions
The FlashSAC critic: a distributional (categorical) double Q on residual blocks.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The model class
TYPE:
|
num_blocks
|
Residual blocks.
TYPE:
|
hidden_dim
|
Block width.
TYPE:
|
num_bins
|
Return bins.
TYPE:
|
min_v
|
Support of the (normalised) return.
TYPE:
|
max_v
|
Support of the (normalised) return.
TYPE:
|
Source code in eden/options/options.py
Attributes¶
RslRlFlashSacAlgorithmOptions
¶
Bases: ConfigurableOptions
FlashSAC's hyperparameters (rsl_rl_flashsac.algorithms.FlashSAC).
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The algorithm class
TYPE:
|
replay_buffer_size
|
Transitions kept, over all envs.
TYPE:
|
buffer_min_length
|
Transitions before the first update (random actions until then).
TYPE:
|
buffer_optimize_memory_usage
|
Store each observation once (next observations by index).
TYPE:
|
buffer_device
|
Where the buffer lives;
TYPE:
|
buffer_obs_dtype
|
Observation storage dtype (e.g.
TYPE:
|
num_learning_epochs
|
Gradient updates per runner iteration = their product.
TYPE:
|
num_mini_batches
|
Gradient updates per runner iteration = their product.
TYPE:
|
mini_batch_size
|
Transitions per update.
TYPE:
|
learning_rate_init
|
Warm-up start, peak and final learning rate.
TYPE:
|
learning_rate_peak
|
Warm-up start, peak and final learning rate.
TYPE:
|
learning_rate_end
|
Warm-up start, peak and final learning rate.
TYPE:
|
learning_rate_warmup_steps
|
Updates of linear warm-up.
TYPE:
|
learning_rate_decay_steps
|
Updates of decay;
TYPE:
|
actor_bc_alpha
|
Behaviour-cloning weight on the actor loss.
TYPE:
|
actor_noise_zeta_mu
|
Exploration-noise schedule.
TYPE:
|
actor_noise_zeta_max
|
Exploration-noise schedule.
TYPE:
|
actor_update_period
|
Critic updates per actor update.
TYPE:
|
critic_target_update_tau
|
Polyak rate of the target critic.
TYPE:
|
temp_initial_value
|
Entropy temperature start and target action standard deviation.
TYPE:
|
temp_target_sigma
|
Entropy temperature start and target action standard deviation.
TYPE:
|
temp_target_entropy
|
Explicit target entropy;
TYPE:
|
gamma
|
Discount.
TYPE:
|
n_steps
|
n-step return length.
TYPE:
|
normalize_reward
|
Normalise rewards by a running return scale.
TYPE:
|
normalized_G_max
|
Return bound after normalisation (should match the critic's support).
TYPE:
|
use_compile
|
TYPE:
|
use_amp
|
TYPE:
|
compile_mode
|
TYPE:
|
Source code in eden/options/options.py
Attributes¶
buffer_optimize_memory_usage
class-attribute
instance-attribute
¶
buffer_optimize_memory_usage: bool = True
learning_rate_decay_steps
class-attribute
instance-attribute
¶
learning_rate_decay_steps: int | None = None
RslRlFlashSacRunnerOptions
¶
Bases: RslRlBaseRunnerOptions
rsl_rl_flashsac's OffPolicyRunner: each iteration steps every env num_steps_per_env times, then
runs num_learning_epochs x num_mini_batches updates; eden train selects it from this class.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The runner class.
TYPE:
|
max_iterations
|
The run's length in iterations;
TYPE:
|
num_env_steps
|
The run's length in env steps, over all envs of every rank:
TYPE:
|
log_interval
|
Iterations per log line (one iteration is one env step by default).
TYPE:
|
start_training
|
Iterations before the first update.
TYPE:
|
action_bound_scale
|
The policy's tanh output is scaled to
TYPE:
|
actor
|
The actor. |
critic
|
The critic. |
algorithm
|
The algorithm. |
Source code in eden/options/options.py
Attributes¶
class_name
class-attribute
instance-attribute
¶
class_name: Literal['OffPolicyRunner'] = 'OffPolicyRunner'
actor
class-attribute
instance-attribute
¶
critic
class-attribute
instance-attribute
¶
critic: RslRlFlashSacCriticOptions = RslRlFlashSacCriticOptions()
algorithm
class-attribute
instance-attribute
¶
algorithm: RslRlFlashSacAlgorithmOptions = RslRlFlashSacAlgorithmOptions()
Methods:¶
for_num_envs
¶
for_num_envs(num_envs: int, *, world_size: int) -> RslRlFlashSacRunnerOptions
These options with max_iterations sized for num_envs envs on each of world_size ranks when
:attr:num_env_steps sets the run.
Every rank runs max_iterations iterations of its own num_envs envs, so the run's env steps are split
across the ranks rather than repeated on each. With algorithm.learning_rate_decay_steps=None the
learning-rate decay spans the derived run too.
Source code in eden/learning/wrappers/rsl_rl/flashsac/options.py
The Eden side of FlashSAC: the VecEnv adapter and the runner factory eden train and eden inference use for
:class:~eden.learning.wrappers.rsl_rl.flashsac.options.RslRlFlashSacRunnerOptions.
Classes¶
FlashSacVecEnvWrapper
¶
FlashSacVecEnvWrapper(env: RLEnvBase, options: RslRlFlashSacRunnerOptions)
Bases: RslRlVecEnvWrapper
:class:RslRlVecEnvWrapper plus what FlashSAC needs of the env.
- The action bounds FlashSAC reads (
action_bias/action_scale), applied here: the policy emits tanh actions in[-1, 1]and the env receivesaction_bias + action_scale * a, i.e.[-action_bound_scale, action_bound_scale]. - On time-outs, the observation before the reset (
extras["time_outs_obs"]), so a truncated episode bootstraps from its true last state. The env must record it (EnvOptions.record_final_observations), or every truncation would bootstrap from the next episode's first observation. - The run sized for this env count over every rank (:meth:
RslRlFlashSacRunnerOptions.for_num_envs): readrunner_options.max_iterationsoff the wrapper, not the config.
For training, a mimic env whose motion terms mine hard motions (adaptive_motion_weights) is refused: FlashSAC's
runner does not step that curriculum.
Source code in eden/learning/wrappers/rsl_rl/flashsac/runner.py
Attributes¶
action_scale
instance-attribute
¶
action_scale = torch.full((self.num_actions,), float(options.action_bound_scale), device=self.device)
Methods:¶
from_config
classmethod
¶
from_config(cfg, *, show_viewer: bool = False, eval_mode: bool = False, apply_seed: bool = True) -> FlashSacVecEnvWrapper
:meth:RslRlVecEnvWrapper.from_config, refusing what FlashSAC cannot do before the env is built.
The task's own :meth:~eden.utils.configs.EdenConfig.check_bindings runs first: it can name the variant flag
that sets these fields (flashdexretarget: --learner flashsac).
Source code in eden/learning/wrappers/rsl_rl/flashsac/runner.py
step
¶
Source code in eden/learning/wrappers/rsl_rl/flashsac/runner.py
Functions:¶
make_flashsac_runner
¶
make_flashsac_runner(env: FlashSacVecEnvWrapper, checkpoint: str | None = None, log_dir: str | None = None, *, inference: bool = False)
Build rsl_rl_flashsac's OffPolicyRunner, with Eden's runner features (:func:_runner_class), on
env, optionally loading checkpoint.
| PARAMETER | DESCRIPTION |
|---|---|
env
|
The env.
TYPE:
|
checkpoint
|
A FlashSAC checkpoint (
TYPE:
|
log_dir
|
The run directory;
TYPE:
|
inference
|
Only the policy will run (
TYPE:
|
Source code in eden/learning/wrappers/rsl_rl/flashsac/runner.py
ConTrack CMDP-PPO¶
Constrained-MDP PPO trained through the external rsl_rl_contrack fork of rsl_rl.
Runner/algorithm options for the external rsl_rl_contrack CMDP-PPO backend.
Declarative only — importing this module needs neither the backend nor rsl_rl's runner API, so the contrack
task config that selects it imports on any install. The runner its class_name names
(:class:~eden.learning.wrappers.rsl_rl_contrack.runner.ContrackOnPolicyRunner) needs the backend and raises with
the install command when it is missing, so eden train --task contrack is the training entry point.
ConTrack (https://github.com/EmptyBlueBox/ConTrack) trains tracking policies as
a constrained MDP: rewards are split into task (rg), style (rs), and
penalty (rp) groups, the critic outputs two values for the (rg+rp, rs+rp)
channels, and a dual variable mixes the two advantage streams with
w_task = sigmoid(λ) updated toward a target task ratio alpha. The reward
groups are declared on the env config (RewardGroupOptions); these options
carry only the learning hyperparameters. Defaults match the ConTrack release.
Attributes¶
Classes¶
RslRlContrackAlgorithmOptions
¶
Bases: RslRlPpoAlgorithmOptions
PPO options extended with ConTrack's dual-controller (CMDP) parameters.
| PARAMETER | DESCRIPTION |
|---|---|
cmdp_alpha
|
Target task ratio
|
cmdp_lambda_lr
|
Dual step size for
|
cmdp_warmup_iters
|
Updates with
|
cmdp_vg_window
|
Episodes in the running mean of the task return
|
cmdp_vg_star_window
|
Updates in the running max defining the normalizer
|
cmdp_lambda_init
|
Initial
|
Source code in eden/options/options.py
Attributes¶
RslRlContrackRunnerOptions
¶
Bases: RslRlOnPolicyRunnerOptions
On-policy runner options that select the rsl_rl_contrack backend.
The actor / critic model options are consumed by
rsl_rl_contrack.modules.ActorCritic (MLP-only; the critic automatically
outputs the two CMDP value channels). Defaults mirror the ConTrack release
hyperparameters, so RslRlContrackRunnerOptions() is training-ready.
| PARAMETER | DESCRIPTION |
|---|---|
class_name
|
The runner
TYPE:
|
Source code in eden/options/options.py
Attributes¶
obs_groups
class-attribute
instance-attribute
¶
obs_groups: dict = {'actor': ['policy'], 'critic': ['critic']}
actor
class-attribute
instance-attribute
¶
actor: RslRlModelWithDistributionOptions = RslRlModelWithDistributionOptions(hidden_dims=[256, 256, 128], distribution_cfg=RslRlGaussianDistributionOptions(init_std=1.0, std_type='scalar'))
critic
class-attribute
instance-attribute
¶
critic: RslRlModelOptions = RslRlModelOptions(hidden_dims=[256, 256, 128])
algorithm
class-attribute
instance-attribute
¶
algorithm: RslRlContrackAlgorithmOptions = RslRlContrackAlgorithmOptions()
Runner for the external rsl_rl_contrack backend (ConTrack's CMDP-PPO fork of rsl_rl).
rsl_rl_contrack is a standalone RL library installed separately (it is not an Eden extra).
:class:ContrackOnPolicyRunner is what
:class:~eden.learning.wrappers.rsl_rl_contrack.options.RslRlContrackRunnerOptions's class_name names, so
eden train / eden inference build it. Importing this module raises with the install command when the backend
is missing — eden train resolves the runner before building the env, so that happens in seconds.
Attributes¶
CONTRACK_RUNNER_CLASS_NAME
module-attribute
¶
Classes¶
ContrackOnPolicyRunner
¶
ContrackOnPolicyRunner(env: RslRlVecEnvWrapper, train_cfg: dict, log_dir: str | None = None, device: str = 'cpu')
Bases: CheckpointRetentionMixin, OnPolicyRunner
The fork's OnPolicyRunner behind Eden's runner signature, with Eden's checkpoint retention.
eden train hands it a plain :class:~eden.envs.wrappers.rsl_rl_env.RslRlVecEnvWrapper and the
version-translated runner dict; the fork needs neither. It re-wraps the same built env in
:class:ContrackVecEnvWrapper (which adds the CMDP reward-group extras the fork's PPO reads) and rebuilds the
fork's train_cfg from the env's runner options. Checkpoint retention matters because the fork saves
model_<it>.pt the same way rsl_rl does, and keep_last_checkpoints would otherwise be silently ignored.
Source code in eden/learning/wrappers/rsl_rl_contrack/runner.py
Methods:¶
Functions:¶
contrack_train_cfg
¶
contrack_train_cfg(options: RslRlContrackRunnerOptions) -> dict
The fork's train_cfg dict, assembled directly from the runner options.
No rsl-rl-lib version translation — the fork has a single, known API.
Source code in eden/learning/wrappers/rsl_rl_contrack/runner.py
VecEnv wrapper that feeds ConTrack's CMDP-PPO (rsl_rl_contrack) its per-step reward-group extras.
ConTrack's CMDP-PPO consumes three per-step reward-group scalars from
extras — rg (task), rs (style), rp (penalty) — and trains a
two-channel critic on (rg + rp, rs + rp). :class:ContrackVecEnvWrapper
forwards :meth:RewardManager.get_group_reward for the task's declared reward
groups (see RewardGroupOptions in the task config); the per-episode group
returns are logged by the reward manager itself (Episode_Reward_Group/<g>
in the reset extras).
It also applies runner_options.check_for_nan (the fork's runner has no NaN check of its own), and maintains the
object-tracking-error running sums the
ConTrack OnPolicyRunner logs unconditionally (it_obj_pos_err_sum /
it_obj_rot_err_sum / it_step_count).
Needs no backend: :class:~eden.learning.wrappers.rsl_rl_contrack.runner.ContrackOnPolicyRunner wraps the env in it.
Attributes¶
Classes¶
ContrackVecEnvWrapper
¶
ContrackVecEnvWrapper(env: RLEnvBase, options: RslRlContrackRunnerOptions)
Bases: RslRlVecEnvWrapper
RslRl wrapper that injects the per-step CMDP reward-group extras.
Requires the wrapped env's reward terms to be declared in exactly the CMDP
groups (rg / rs / rp via RewardGroupOptions) — enforced at
construction so a term outside the three channels (which the CMDP critic
would never see) fails before training starts.