rl¶
rl rolls out an actor trained by create_trainer("ppo" | "fast_sac" | "fast_td3"), or an rsl_rl run from Isaac Lab, from disk or the Hub.
By the end of this page you can load an actor the RL trainers or Isaac Lab wrote and drive a robot through the run_policy path every provider shares.
What it is¶
RLCheckpointPolicy is the inference half of the RL loop. create_trainer("ppo" | "fast_sac" | "fast_td3") trains against a SimEnv and writes policy.pt plus policy_meta.json; this provider presents that pair as a Policy. Rollout is the actor's mean action. requires_images is False.
The checkpoint's actor_obs_keys are read from the observation by name, in trained order (part of the weights); a missing key is refused, never defaulted to a zero commanding a robot from a fabricated state.
Three shapes of checkpoint_dir¶
from strands_robots.policies import create_policy
create_policy("rl", checkpoint_dir=result.checkpoint_dir) # strands checkpoint dir
create_policy("rl", checkpoint_dir="logs/rsl_rl/h1_rough") # rsl_rl run, or one model_<n>.pt
create_policy("rl", checkpoint_dir="owner/name@main") # Hub repo id; @revision optional
An rsl_rl actor (what isaaclab trains: ELU layers plus observation normalizer) is rebuilt once into <run>/strands_policy/ and reused while newer than the model. action_names in a record.json beside it name the actions when counts match. From the Hub only model_*.pt, params/agent.yaml, record.json and the strands pair are fetched; a repo that cannot be downloaded is a RuntimeError naming the id.
Constructor keywords¶
| keyword | type | default |
|---|---|---|
checkpoint_dir |
str |
'' |
device |
str |
'cpu' |
raw_actions |
bool |
False |
joint_map |
dict[str, str] \| None |
None |
command |
list[float] \| None |
None |
obs_terms |
dict[str, list[float]] \| None |
None |
**kwargs |
unknown keywords are ignored |
device defaults to cpu: PPO on MuJoCo declares no GPU floor.
Train, then roll out¶
import tempfile
from strands_robots.simulation import create_simulation
from strands_robots.simulation.predicates import _joint_progress
from strands_robots.training import create_trainer
from strands_robots.training.rl import RLTrainSpec, SimEnv
def make_env() -> SimEnv:
sim = create_simulation("mujoco")
sim.create_world()
sim.add_robot("so101")
return SimEnv(sim, actor_obs_keys=["1", "2", "3", "4", "5", "6"], reward_terms=[_joint_progress("1", 0.5)], max_episode_steps=50, action_scale=0.15)
spec = RLTrainSpec(env_factory=make_env, output_dir=tempfile.mkdtemp(), total_timesteps=96, rollout_steps=24, learning_rate=3e-4)
result = create_trainer("ppo").train(spec)
print(result.status)
sim = create_simulation("mujoco")
sim.create_world()
sim.add_robot("so101")
out = sim.run_policy(robot_name="so101", policy_provider="rl", policy_config={"checkpoint_dir": result.checkpoint_dir}, n_steps=20, control_frequency=50.0)
print(out["status"])
sim.cleanup()
You should see success twice, plus a few [sim] action value ... outside the range gripper warnings: six iterations train nothing; the point is that a trainer's checkpoint is what rl takes.
Trainers and policy_meta.json fields: RL training. Isaac Lab runs: Isaac Lab training.
rsl_rl_onnx¶
policy="rsl_rl_onnx" loads an actor exported by the mjlab trainer (train_policy(provider="rsl_rl")): onnx_path (local or hf://repo/file.onnx) and robot. The ONNX metadata carries joint names, default pose, action scale and observation terms, so one file runs on mujoco, mjlab and hardware; velocity tasks take target_velocity, reach tasks target_pose.
Limits¶
- The observation must carry every
actor_obs_keysname unless an Isaac Lab export builds it from robot state (command=sets the velocity command; on MuJoCo torque motors the run's PD drives joints); differently named joints are refused. - Deterministic mean action only.
- Only strands pairs and rsl_rl 5.x actors (
actor_state_dict,mlp.<i>layers) load; anything else isFileNotFoundError.