Downloads · 30 days
20
38% of all-time downloads
maskjp/groot-n17-relative-joints-all10-30k
groot-n17-relative-joints-all10-30k is a robotics model from maskjp. Use it for the robotics task on the model card, and read the license before you ship it in a product. It is set up for lerobot. The card lists the license as other.
Fine-tune of nvidia/GR00T-N1.7-3B on all ten L5vel/ datasets, with actions expressed relative to the observation state at the start of each chunk. Step 30K of 30K — the full run.
Downloads · 30 days
20
38% of all-time downloads
All-time downloads
52
Public
Parameters
3.1B
12.6 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors12.6 GB · 100%
From the Hugging Face model README
Fine-tune of nvidia/GR00T-N1.7-3B on all ten
L5vel/* datasets, with actions expressed relative to the observation state at the start of each
chunk. Step 30K of 30K — the full run.
5% of episodes per task are held out (75 of 1499 episodes, all 11 tasks).
| step | eval_loss |
|---|---|
| 5K | 0.0211 |
| 10K | 0.0149 |
| 15K | 0.0130 |
| 20K | 0.0104 |
| 25K | 0.0099 |
| 30K | 0.0097 |
Still decreasing at 30K, and the run covers only 0.66 epochs of the mixture, so this checkpoint is undertrained rather than converged. Longer training is the obvious next step.
Do not compare this number to the
pi05-relative-*repos. Both are MSE on the flow-matching velocity, but the normalisation differs: pi05 usesQUANTILES(q01/q99), GR00T N1.7 uses per-horizon min/max of the relative offsets. On this mixture the min–max span is 3.0x the q01–q99 span (median) on the arm dims and 5.0x (up to 49.7x) on the base dims, so GR00T's targets live in a compressed space and its loss is smaller by roughly the square of that factor for reasons that have nothing to do with fit quality.
use_relative_actions=true with relative_exclude_joints=["gripper"]:
action[t+k] -= observation.state[anchor] for all dims EXCEPT gripper
gripper absolute (it is a command, not a pose)
Action dim 10: joint1..joint6, gripper, base_x, base_y, base_yaw — 9 of 10 dims relative, gripper absolute.
Normalisation uses GR00T's native per-horizon relative statistics, computed from this mixture's
own relative offsets (a separate min/max per chunk position, shape [40, d]) and baked into
policy_preprocessor.json. The checkpoint is self-contained: it does not need the training data or
the base model's statistics.json to normalise correctly.
The run requested chunk_size=50 to match the pi05 arms, and GR00T N1.7 overrode it to 40:
GrootConfig.__post_init__ remaps 50 as a legacy N1.5-era default, and the action head's
delta_indices are clamped to the N1.7 horizon of 40 regardless. So the lookahead is 0.8 s at 50
fps rather than pi05's 1.0 s. n_action_steps=10 (0.2 s executed per replan) is unchanged, so the
control cadence still matches.
11 language-conditioned tasks, 1499 episodes, 3,089,476 frames (17.2 h at 50 fps), one u850 arm on a mobile base, three cameras (left / right / wrist).
| task | episodes | frames |
|---|---|---|
| grab a drink from the fridge | 250 | 968,523 |
| pick up the bag on the ground and place it on the table | 200 | 477,058 |
| open the door and move inside | 200 | 506,473 |
| clean the table with the green towel | 199 | 534,608 |
| pick up the blue cup from the table | 102 | 75,870 |
| pick up the green bottle from the table | 100 | 69,748 |
| open the fridge door | 100 | 118,990 |
| place the blue cup on the table | 100 | 61,416 |
| pick up the grocery bag from the ground | 100 | 92,672 |
| move the croissant to the empty plate | 98 | 155,517 |
| place the green cup on the table | 50 | 28,601 |
The mixture is skewed: the four largest tasks are ~82% of frames. Sampling is uniform over frames, so it is not rebalanced.
meta/)meta/info.json and meta/stats.json are the training dataset's own files, byte for byte.
They are here so a deployment-side fingerprint guard can bind this checkpoint to real column names
and real statistics instead of inferring them. The datasets (all10-multitask-eef-merged-v30) were merged locally from the
ten L5vel/* sources and never pushed, so the repo_id in train_config.json 404s on the Hub.
| file | sha256 |
|---|---|
meta/info.json | 60dbd55e6fcb9fe31961ea7cdaa90cf826c685cec8f4e981773e0dee7870b6e1 |
meta/stats.json | 8e918355307246578c786d76d69e7da631e51906e5d18d55e51409985cc700cb |
The statistics bind exactly. The preprocessor step groot_n1_7_pack_inputs_v1 carries
config.raw_stats with three modalities -- state, action, relative_action. The first two are
this dataset's absolute statistics, copied verbatim. Concatenating the groups in modality order
(single_arm, gripper, single_arm_2) and casting both sides to float32 reproduces
stats.json exactly, for min, max, mean and std alike:
action float32-cast exact = True
observation.state float32-cast exact = True
Compare in float32, not float64: that is the storage precision on the checkpoint side, and a float64 comparison leaves residuals up to 5.8e-08 relative on some columns.
relative_action is the modality with no on-disk counterpart. Those per-horizon [40, d] min/max
are computed at training time from the relative offsets and never written as a dataset.
names is the grouped v3 form, {"motors": [...]}, not a flat list, so list(names)
yields ["motors"] -- one name for 10 columns. Flatten it
(lerobot.utils.feature_utils.flatten_feature_names). These files are shipped unmodified on
purpose, so the flattening is the reader's job.action this checkpoint was trained on, meta/info.json describes a 13-dim
action.eef (eef_x ... eef_yaxis_z, gripper, base_*) recorded from the same episodes, and the
checkpoint's output_features lists both. Here the dims differ (10 vs 13) so they are easy to
tell apart, but a binding should still name action explicitly rather than take the first
action-like feature it finds.| init | nvidia/GR00T-N1.7-3B |
| regime | projector + action head (DiT) + VL layernorms; LLM and vision tower frozen |
| batch | 16/rank x 4 ranks = 64 effective |
| lr | 1e-4, 5% warmup, cosine decay |
| chunk_size / n_action_steps | 40 (see above) / 10 |
| precision | bf16 compute, fp32 parameters |
| embodiment tag | new_embodiment |
| seed | 1000 |
| wall clock | 7.2 h on 4x A100-class GPUs |
from lerobot.policies.groot.modeling_groot import GrootPolicy
policy = GrootPolicy.from_pretrained("maskjp/groot-n17-relative-joints-all10-30k")
base_model_path in config.json points at nvidia/GR00T-N1.7-3B; the architecture is rebuilt from there
and the fine-tuned weights come from model.safetensors in this repo.
NVIDIA License, inherited from the base model — research and evaluation use only (section 3.3).
A complete copy ships as LICENSE in this repo, as section 3.1 requires.
maskjp/groot-n17-relative-eef-all10-30k — the same run in end-effector space.maskjp/pi05-relative-joints-all10-full-ft-100k — pi0.5 on the same mixture and the same
relative-action scheme. See the loss caveat above before comparing numbers.