Nodes
Four executables in the rosetta package. The recorder, policy runner and
human-in-the-loop launch files read a params file from params/ and expose
deployment values as launch arguments. For the recorder and policy runner, an
empty launch argument keeps the params-file value, except contract_path,
which is passed as given. hil_launch.py fills its defaults from the params
files up front, so an empty argument is an empty value.
ros2 launch rosetta <launch_file> --show-args
Lifecycle
episode_recorder_node, policy_runner_node and hil_manager_node are
lifecycle nodes. episode_keyboard_node is a plain node.
Transition |
Effect |
|---|---|
|
Load the contract, create subscriptions and inactive publishers. An error returns the node to |
|
Enable publishers, then accept goals. |
|
Stop accepting goals, stop in-progress work (waits up to 5 s, 10 s for |
|
Refused while work is in progress. Otherwise release resources. |
|
Stop, secure, release. |
The three lifecycle launch files take configure (default true) and
activate (default true), which drive the transitions at start.
A node runs one goal at a time. A goal sent while busy or while not active is
rejected. Work stopped by deactivate ends ABORTED with termination_reason: node_deactivated. A cancelled goal ends CANCELED. Each node also exposes a
~/start_* service that starts the same work without a goal, and a
~/cancel_* service that cancels the running goal the way a client would.
A cancel service with nothing running returns success: false.
episode_recorder_node
Records bags. Node name episode_recorder. Launch
episode_recorder_launch.py.
Parameter |
Type |
Default |
Meaning |
|---|---|---|---|
|
string |
|
Required. The launch file defaults to |
|
string |
|
Relative to the current directory. |
|
string |
|
Passed to rosbag2 unchecked. Any installed storage plugin works. |
|
bool |
|
Record every topic on the graph. |
|
string[] |
none |
Regex list, |
|
string[] |
none |
Regex list. Matches are recorded despite |
|
string |
|
Used when a goal or service leaves |
|
double |
|
Zero or less records until stopped. |
|
double |
|
0.1 to 1000. |
|
bool |
|
Write the contract text into |
|
bool |
|
Also records |
Launch arguments: params_file, contract_path, bag_base_dir,
storage_id, use_sim_time, log_level, configure, activate.
Interface |
Type |
|---|---|
|
action |
|
service |
|
service |
|
service |
With the default namespace these are /record_episode and
/episode_recorder/....
Topic rules:
Contract topics are every source in every section, plus
tasksandadjunctchannels, plus/clockunderuse_sim_time. The recorder subscribes to them at configure. A type that does not import fails configure, or the first episode for a transient-local topic. A contract topic with no messages at episode end is logged with(!). Nothing stops an episode from starting without it.With
record_all, every other topic on the graph is discovered at each episode start. A topic is skipped if it matchesexclude_topics, unless it matchesinclude_topics./rosoutand/parameter_eventsare always skipped. QoS is adapted to what every publisher offers.One stream per raw
sensor_msgs/msg/Imagetopic and its transports, in preference/compressed,/zstd,/theora,/compressedDepth, raw. A transport named in the contract or ininclude_topicswins.Transient-local topics such as
/tf_staticare re-subscribed per episode so their latched messages land in every bag.The bag stamp is the node clock at receipt. Under
use_sim_timethat is sim time.A write failure ends the episode
ABORTEDwithtermination_reason: error.
Output: <bag_base_dir>/<seconds>_<nanoseconds>/, zero-padded to ten and
nine digits. After close, metadata.yaml holds custom_data keys
rosetta.contract_yaml with embed_contract, lerobot.operator_prompt when
the prompt is non-empty, and rosetta.goal_id for goals.
Result termination_reason: stopped, timeout, cancelled,
node_deactivated, error. bag_path is set on every path.
episode_keyboard_node
Drives the recorder from a terminal. Needs a TTY. Node name
episode_keyboard. Launch episode_keyboard_launch.py.
Parameter |
Default |
Meaning |
|---|---|---|
|
|
Where the recorder’s services live. |
|
|
Prompt for the next episode. |
Key |
Calls |
|---|---|
|
|
|
|
|
|
|
Edit the prompt. Enter applies, Esc cancels. |
|
Help |
|
Quit |
policy_runner_node
Runs a policy on the live robot. Node name policy_runner. Launch
policy_runner_launch.py.
Parameter |
Type |
Default |
Meaning |
|---|---|---|---|
|
string |
|
Empty resolves the contract from the checkpoint. The launch file defaults to |
|
string |
|
Adapter, by entry-point name under |
|
bool |
|
Serve the |
|
string |
|
|
|
double |
|
|
|
double |
|
Contract resolution with an empty contract_path: pretrained_name_or_path,
then its train_config.json, then the training dataset’s root or repo id,
then meta/rosetta_contract.yaml there. Local paths first, then the Hugging
Face Hub. A missing link is an error. A non-empty contract_path is used as
given and never compared with the checkpoint’s.
The LeRobot adapter adds these. Defaults in the second column are the
adapter’s. params/policy_runner.yaml sets the third.
Parameter |
Adapter default |
Params file |
Meaning |
|---|---|---|---|
|
|
|
Local path or Hub model id. |
|
|
|
One of |
|
|
|
Falls back to |
|
|
same |
|
|
|
|
Start |
|
|
|
Configure waits this long for the server socket. |
|
|
|
Actions returned per inference. |
|
|
|
Queue fill ratio at which the next observation is sent. |
|
|
same |
How a new chunk merges with the queue: |
|
|
|
Negative disables. Ignored by stock LeRobot 0.6.0. |
Launch arguments: params_file, contract_path,
pretrained_name_or_path, policy_type, server_address,
launch_local_server, use_sim_time, log_level, configure, activate.
policy_device is not a launch argument. Set it in the params file.
With use_sim_time, observations and actions pace on the sim clock at the
contract fps.
Interface |
Type |
|---|---|
|
action |
|
service |
|
service |
Under hil_launch.py the runner sits in namespace robot_policy, so the
action is /robot_policy/run_policy.
hil_manager_node
Runs human-in-the-loop episodes: a policy, a teleop input muxed against it,
an optional reward classifier, and the recorder. Node name hil_manager.
Launch hil_launch.py, which also starts the recorder, a policy runner in
namespace robot_policy and, when enabled, a second runner in namespace
reward_classifier. Defaults come from params/hil_manager.yaml.
Parameter |
Default |
Meaning |
|---|---|---|
|
|
Required. The launch file defaults to |
|
|
Send a |
|
|
Send and cancel a |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The runner publishes actions to |
|
|
Same for the classifier. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The launch file validates that action_remap_from names an action topic of
the contract. It exposes the policy runner’s model and chunking parameters,
and the reward classifier’s, as launch arguments. Run --show-args for the
list. launch_local_server is fixed to true. One feedback_rate_hz,
default 30.0, goes to the manager, the recorder and both runners.
Interface |
Type |
Effect |
|---|---|---|
|
action |
|
|
service |
|
|
service |
Ends the episode. |
|
service |
Abandons the episode. The goal ends |
|
service |
|
|
service |
Labels without ending. |
|
service |
|
|
topic |
|
Teleop events from the contract are edge-triggered: is_intervention press
hands control to teleop and release hands it back, start_episode starts an
episode with default_prompt, success and failure set the label,
end_success and end_failure end the episode. A label holds until the
other button, ~/clear_reward_override, or the next episode. No event
deletes a bag.
Result termination_reason: stopped, timeout, reward_threshold,
cancelled, node_deactivated, error. outcome: success, failure,
unlabeled. With success_reward_threshold above zero on the goal, reaching
it ends the episode and an unlabeled outcome becomes success.