Skip to main content
SYS.ONLINE

Fine-Tuning NVIDIA Isaac GR00T N1.7 on a Jetson AGX Thor for the Seeed Studio reBot Arm B601-RS

· 9 min read
Chiwai Chan
Tinkerer

Seeed Studio reBot Arm B601-RS on a desk: a six-axis arm in black and lime green with machined aluminium joints, a gripper at one end and a camera mounted above the wrist

I always assumed any form of model tuning meant a big hardware investment, or renting a huge compute instance in the cloud.

Then, in a separate project with nothing to do with this arm, I used supervised fine-tuning and distillation on Amazon Bedrock to build custom Amazon Nova models. It cost far less than I expected. First assumption gone.

NVIDIA Jetson AGX Thor Developer Kit: a compact dark grey unit with a ribbed black panel on top

The second one lasted longer: I was sure my Jetson AGX Thor couldn't train GR00T. Not enough hardware.

So I wanted one question answered: can this hardware train the model at all?

That's why I borrowed someone else's dataset rather than recording my own — it keeps my arm, my calibration and my teleoperation out of the experiment, so the only thing being tested is the Thor.

It worked.

One machine, not two​

Diagram: the usual setup trains on an x86 workstation then copies a 23 GB checkpoint to the Thor, which only runs inference. Below it, the Thor doing both, with the workstation and copy step gone

The workstation and the 23 GB checkpoint copy both drop out. Everything runs from NVIDIA/Isaac-GR00T on the Thor, against nvidia/GR00T-N1.7-3B.

The dataset​

I borrowed prateeks-iu/rebot_b601_rs_sugar off HuggingFace — Apache-2.0, published July 2026.

Task"Pick up one sugar cube and put it in the cup"
Episodes103
Frames77,694 at 60 fps — 21.6 minutes of robot time
Robot typeseeed_b601_rs_follower
State / action7-dim each
Camerasscene, wrist, plus depth for both
FormatLeRobot v3.0, converted to v2.1 for GR00T
Size on disk1.0 GB without the raw depth .mkv files

robot_type is the exact string the Seeed Studio LeRobot fork writes, and the joint names line up with my arm one for one — shoulder_pan, shoulder_lift, elbow_flex, wrist_flex, wrist_yaw, wrist_roll, gripper. A dataset from a different arm, or with a different state shape, needs the modality config rewritten first. I trained on scene + wrist and ignored the depth streams.

Does it actually learn?​

Line chart: training loss drops steeply from 1.155 over the first few hundred steps, then declines slowly to 0.022 by step 10,000

Loss 1.155 → 0.022 across 10,000 steps, mean 0.059.

Three stacked panels: step time flat at 2.31 seconds except two spikes where checkpoints are written, learning rate warming up to 1e-4 then decaying to near zero, and gradient norm settling around 0.31 with no divergence

Step time is flat — 2.31 s median across 11,000 samples, never drifting. The two red lines are the checkpoint writes at steps 5,000 and 10,000, each stalling the run for about 84 seconds while 24 GB goes to disk.

Gradient norm settles at 0.31 after an early spike to 3.6 and never diverges, which is the other thing worth checking before trusting a loss curve.

open_loop_eval.py replays trajectories from the dataset and scores predicted joint actions against ground truth. No robot required.

CheckpointMSEMAE
20 steps (smoke test)4,225.439.96
5,000 steps4.311.39
10,000 steps4.361.16

Plot of predicted versus ground-truth joint positions from the 20-step checkpoint: the predicted lines bear no relation to the true trajectories

20 steps: predictions are noise.

Plot of predicted versus ground-truth joint positions from the finished 10,000-step model: the predicted lines follow the true trajectories closely

Finished model: predictions track ground truth. MSE 969x lower than the floor.

What the model actually outputs​

One inference doesn't return a command. It returns a chunk of 16 future actions, seven joints each, in degrees. Here are the first three steps:

Jointt+0t+1t+2
shoulder_pan0.270.270.39
shoulder_lift−85.78−84.13−83.27
elbow_flex1.56−0.102.91
wrist_flex3.242.362.40
wrist_yaw1.901.041.19
wrist_roll0.740.780.66
gripper0.000.000.00

I handed it a neutral pose with shoulder_lift at −90°. It came back with −85.78, −84.13, −83.27 — a trajectory that starts where the arm already is and lifts from there. It reads the current pose and continues it.

The gripper is 0.00 on all 16 steps. In this dataset the gripper only closes once the arm is over the cube, so from a neutral start there's nothing to grip. But a row that never moves also looks exactly like a dead output head, and I can't separate those two without the arm.

Bar chart of control rate against denoising steps: 198 Hz at 1 step, 163 at 2, 124 at 4, 80 at 8, down to 47 Hz at 16, with a dashed line marking the 60 Hz data rate that only the 16-step bar falls below

A chunk takes 129 ms at the default 4 denoising steps. Sixteen actions out of that chunk is 8.1 ms each — 124 Hz, against a dataset recorded at 60 Hz. The Thor can run this model at twice the rate the demonstrations were captured.

Denoising steps buy smoothness and cost rate. Eight steps still clears 60 Hz; sixteen doesn't. So there's quality left to spend before real time is at risk — on the same machine that did the training.

The hardware was never the constraint​

Bar chart of peak values against their limits: junction temperature 83 of 109 degrees, GPU temperature 82 of 109, memory 82 of 122 GB, CPU load 9.2 of 14 cores

Thor throttles at 109 °C, not the ~95 °C usually quoted. Fan steps start at 80 °C, shutdown is 114 °C. Read the trip points off the device yourself — they are in /sys/devices/virtual/thermal/thermal_zone*/trip_point_*_temp, and tegrastats reports the live values. The run peaked at 83 °C junction — 26 °C of margin.

Spot checks lie. Across 1,787 samples it caught an 82 GB memory peak, a CPU load spike of 9.2 across 14 cores, and a 192 W total draw — 1.5× the devkit's 130 W nominal. None of those showed up in a single reading.

Five stacked timelines over the six-hour run: GPU utilisation holding near 98 percent with periodic dips to as low as 3 percent, junction GPU and CPU temperatures between 60 and 83 degrees against a dashed 109 degree throttle line, memory sawtoothing between 60 and 82 GB, total power spiking to 192 watts, and CPU load cycling between 1 and 9

The whole run, sampled every 10 seconds. The sawtooth in all five is the same cycle: the data loader caches the next shard, CPU load and memory climb, GPU utilisation drops to as low as 3% while it waits, then everything snaps back. Step time never moved off 2.29 s through any of it.

Temperature chart over a training run showing junction, GPU and CPU all between 70 and 83 degrees against a dashed reference line at the 109 degree throttle point

Junction, GPU and CPU against the real 109 °C throttle point.

What it costs to run​

Terminal: GR00T fine-tuning finished at step 10000 of 10000 in 6 hours 34 minutes at 13.5 samples per second, with checkpoint-5000 and checkpoint-10000 written to a 60 GB output directory

GPUBlackwell, 2,560-core, sm_110
Memory122 GB unified · 82 GB peak
Bandwidth273 GB/s
Throughput2.29 s/step · 13.5 samples/s
10,000 steps6 h 34 m
Energy0.63 kWh (~NZ$0.19)

GPU sat at 92–98% throughout, dipping only while the data loader cached the next shard. Training occupies the Thor completely — it can't serve inference while it trains.

The GPU rail is only 40 W of the 95 W mean — 42%. More than half the draw is CPU, SoC and the rest of the board, which is worth knowing before sizing a supply around GPU figures alone.

Output came to 60 GB: two checkpoints at 24 GB each, plus the final model.

That changes how I'll use the cloud rather than whether I use it. Experiments run locally now, with no instance to spin up and no meter running. The cloud becomes what I reach for when I'm genuinely bottlenecked — several configs in parallel, a job too big for 122 GB, or Cosmos3-Super augmentation needing 4× A100. Offloading when I hit a wall, rather than renting by default.

What this does not prove: the checkpoint has never driven a motor. It was scored against recorded trajectories, not on the arm. Proving the Thor can train the model and proving the model can do the task are two different things, and only the first one is done.

Both assumptions were wrong. The Thor on my desk could do it all along. All I had to do was start the job and wait 6 h 34 m. It trained GR00T N1.7 for 10,000 steps, on about NZ$0.19 of electricity. No x86 box, no rented GPU, and no reflash of JetPack 7.1.