Direct and Manager MDP#
A reinforcement learning task defines a Markov decision process (MDP): the actions an agent can take, the observations it receives, its rewards, and when an episode ends. In Isaac Lab, you can write this logic directly in an environment class or assemble it from terms coordinated by managers.
Both approaches use Isaac Lab’s simulation, scene, assets, and sensors. The choice is how you organize the task code; it does not select a physics backend.
Choosing an approach#
Direct |
Manager-based |
|
|---|---|---|
Task logic |
Implement methods on an environment class. |
Configure reusable terms; managers run them. |
Changing a task |
Edit the methods and helpers that implement its behavior. |
Add, replace, or tune terms in its configuration. |
A good fit |
Closely coupled logic, custom optimization, or multi-agent tasks. |
Tasks that share observations, rewards, actions, or reset behavior. |
For a new single-agent task, manager-based environments are a useful starting point: you can reuse existing terms and add your own where needed. Choose direct when you prefer to keep the task logic together or need more control over its implementation. Performance depends on the work your task does, so profile before choosing a workflow for speed alone.
Direct environments#
Subclass envs.DirectRLEnv and implement the methods that define the task.
The base class handles the simulation loop and calls your methods at the appropriate
point in each step.
_pre_physics_step()processes incoming actions;_apply_action()applies them._get_observations()and_get_rewards()return observations and rewards._get_dones()reports terminations and timeouts;_reset_idx()resets selected environments.
Use envs.DirectRLEnvCfg for the environment configuration. For multi-agent
tasks, use envs.DirectMARLEnv and envs.DirectMARLEnvCfg.
The methods can call shared helpers or optimized PyTorch or Warp code. Keeping the task in one class does not mean every calculation must be written inline. This structure is also familiar when porting tasks from IsaacGymEnvs or OmniIsaacGymEnvs.
Cartpole rewards: direct
Cartpole computes its reward in _get_rewards().
def _get_rewards(self) -> torch.Tensor:
return compute_rewards(
self.cfg.rew_scale_alive,
self.cfg.rew_scale_terminated,
self.cfg.rew_scale_pole_pos,
self.cfg.rew_scale_cart_vel,
self.cfg.rew_scale_pole_vel,
self.joint_pos[:, self._pole_dof_idx],
self.joint_vel[:, self._pole_dof_idx],
self.joint_vel[:, self._cart_dof_idx],
self.reset_terminated,
self.step_dt,
)
The calculation lives in a separate, TorchScript-compiled compute_rewards() function.
@torch.jit.script
def compute_rewards(
rew_scale_alive: float,
rew_scale_terminated: float,
rew_scale_pole_pos: float,
rew_scale_cart_vel: float,
rew_scale_pole_vel: float,
pole_pos: torch.Tensor,
pole_vel: torch.Tensor,
cart_vel: torch.Tensor,
reset_terminated: torch.Tensor,
step_dt: float,
) -> torch.Tensor:
pole_pos = wrap_to_pi(pole_pos)
rew_alive = rew_scale_alive * (1.0 - reset_terminated.float())
rew_termination = rew_scale_terminated * reset_terminated.float()
rew_pole_pos = rew_scale_pole_pos * torch.sum(torch.square(pole_pos), dim=-1)
rew_cart_vel = rew_scale_cart_vel * torch.sum(torch.abs(cart_vel), dim=-1)
rew_pole_vel = rew_scale_pole_vel * torch.sum(torch.abs(pole_vel), dim=-1)
total_reward = (rew_alive + rew_termination + rew_pole_pos + rew_cart_vel + rew_pole_vel) * step_dt
return total_reward
Manager-based environments#
Use envs.ManagerBasedRLEnv with a envs.ManagerBasedRLEnvCfg to
assemble a task from configured terms. A term defines a piece of behavior, such as
an observation or reward. Its configuration selects the implementation and supplies
parameters; the corresponding manager coordinates execution and combines the results.
For example, a reward manager evaluates reward terms and combines their weighted contributions. An observation manager collects observation terms into groups. Other managers handle actions, terminations, events such as resets, commands, and curricula.
To change one part of the task, replace a term or adjust its parameters. The same term can serve several tasks, and custom terms can contain whatever calculation the task needs.
Cartpole rewards: manager-based
Cartpole combines reward terms in RewardsCfg. Each term specifies a function,
a weight, and any parameters the function needs.
@configclass
class RewardsCfg:
"""Reward terms for the MDP."""
# (1) Constant running reward
alive = RewTerm(func=mdp.is_alive, weight=1.0)
# (2) Failure penalty
terminating = RewTerm(func=mdp.is_terminated, weight=-2.0)
# (3) Primary task: keep pole upright
pole_pos = RewTerm(
func=mdp.joint_pos_target_l2,
weight=-1.0,
params={"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"]), "target": 0.0},
)
# (4) Shaping tasks: lower cart velocity
cart_vel = RewTerm(
func=mdp.joint_vel_l1,
weight=-0.01,
params={"asset_cfg": SceneEntityCfg("robot", joint_names=["slider_to_cart"])},
)
# (5) Shaping tasks: lower pole angular velocity
pole_vel = RewTerm(
func=mdp.joint_vel_l1,
weight=-0.005,
params={"asset_cfg": SceneEntityCfg("robot", joint_names=["cart_to_pole"])},
)
# (6) Success rate tracking (zero-weight, metric only)
success_rate = RewTerm(func=mdp.survival_success_rate, weight=0.0)
For environments that do not need RL rewards and terminations, use
envs.ManagerBasedEnv with envs.ManagerBasedEnvCfg.
Where to go next#
Build a task with the direct or manager-based tutorial.
Follow the SO-101 vial-placement tutorial for a complete manager-based manipulation task, including its scene, MDP terms, reset curriculum, and agent configuration.
See Reinforcement Learning to connect a task to a training library.