
RDT-1B is a 1.2B diffusion transformer for bimanual manipulation. Its 128-dim unified action space, the real fine-tuning commands, hardware needs and honest limits.
What you need to know
- •RDT-1B is a 1.2 billion parameter Diffusion Transformer for bimanual manipulation, arXiv 2410.07864 by Liu et al. of the TSAIL group at Tsinghua, an ICLR 2025 poster.
- •It predicts 64 future actions at once from a language instruction, up to three RGB views with two frames of history, proprioception and the control frequency.
- •Its core idea is a 128-dimensional physically interpretable unified action space: every robot writes joint angles, gripper width, end effector pose and base velocity into fixed slots. That is what let 46 datasets train one model.
- •Pre-training took 1M+ trajectories and 21 TB on 48 H100 80 GB GPUs for a month. You are not repeating that; fine-tuning is the realistic path.
- •The checkpoint is 2.46 GB and MIT licensed, but T5-XXL rides along with it. On a 24 GB card you must precompute language embeddings or the text encoder alone will not fit.
- •RDT-1B is not one of the five policies AY-Robots trains. It is in the comparison arena, not the trainer.
What RDT-1B actually is
RDT-1B stands for Robotics Diffusion Transformer. It is a vision-language-action model from the TSAIL group at Tsinghua University, released in October 2024 and presented as a poster at ICLR 2025. The goal is narrower than the phrase foundation model suggests. The paper puts it directly: multi-robot data is there to improve generalisation in bimanual manipulation, not to build a cross-embodiment model. Multi-robot pre-training is the means, a dual-arm policy is the end.
The design choice worth reading about is not the parameter count. It is how the model handles the fact that a Franka arm, an ALOHA rig and a wheeled manipulator all describe motion differently. RDT does not learn a head per robot, and it does not discretise actions into text tokens the way RT-2 does. It writes every robot into one fixed 128-slot vector where each slot has a physical meaning, then trains a diffusion model on that vector.
| Property | Value | Where it is stated |
|---|---|---|
| Parameters | 1.2 B | paper, Table 9 |
| Layers / hidden size / heads | 28 / 2048 / 32 | paper Table 9 and configs/base.yaml |
| Action chunk size | 64 future actions | configs/base.yaml (action_chunk_size) |
| Camera views | 3 (exterior, right wrist, left wrist) | configs/base.yaml (num_cameras) |
| Image history | 2 frames | configs/base.yaml (img_history_size) |
| Vision encoder | google/siglip-so400m-patch14-384, frozen | paper Table 8 and README |
| Language encoder | google/t5-v1_1-xxl, frozen | paper Table 8 and README |
| Action / state vector | 128 dimensions | configs/base.yaml (state_dim), configs/state_vec.py |
| Released checkpoint | pytorch_model.bin, 2,456,755,578 bytes (about 2.46 GB) | Hugging Face file listing |
| Licence | MIT for code, weights and data | repo README |
| Smaller sibling | RDT-170M: hidden 1024, depth 14, 332,520,250 bytes | RDT-170M model card and config.json |
RDT-170M is the paper's ablation model, released two weeks later as a lower-VRAM option. Expect one discrepancy across sources: the paper calls it RDT (small) at 166 M parameters, the model card calls it RDT-170M. Same model. Both sizes have entries in the model arena: RDT-1B and RDT-170M.
The architecture: three modifications to a Diffusion Transformer
The backbone is a DiT with cross-attention, the same family as the image diffusion transformers, adapted for a time series of joint commands rather than a pixel grid. The paper lists exactly three key modifications to the standard block, each with a stated reason and an ablation behind it.
- QKNorm and RMSNorm together. Robot physical quantities arrive in an unstable numerical range, so query-key normalisation goes into every attention layer. LayerNorm becomes RMSNorm because its centering step causes token shift and attention shift, which the authors argue destroys the symmetry of a time series. Figure 4 shows the loss curve going unstable without these.
- MLP decoder instead of a linear head. The projection from latent space back to physical action space is a nonlinear MLP, because robot dynamics are nonlinear and a linear readout loses the dexterity that depends on them.
- Alternating condition injection. Image tokens vastly outnumber language tokens, so injecting both into one cross-attention layer lets the images overshadow the instruction. The blocks alternate instead: one layer attends to language, the next to images.
# configs/base.yaml (excerpt, thu-ml/RoboticsDiffusionTransformer)
common:
img_history_size: 2
action_chunk_size: 64
num_cameras: 3
state_dim: 128
model:
lang_adaptor: mlp2x_gelu
img_adaptor: mlp2x_gelu
state_adaptor: mlp3x_gelu
lang_token_dim: 4096 # T5-XXL
img_token_dim: 1152 # SigLIP so400m
state_token_dim: 128
rdt:
# 1B: num_head 32 hidden_size 2048
hidden_size: 2048
depth: 28
num_heads: 32
cond_pos_embed_type: multimodal
noise_scheduler:
type: ddpm
num_train_timesteps: 1000
num_inference_timesteps: 5
beta_schedule: squaredcos_cap_v2 # Critical choice
prediction_type: sample
clip_sample: FalseThe low-dimensional inputs, proprioception, the noisy action chunk, the control frequency and the diffusion timestep, are each encoded by MLPs with Fourier features and concatenated along the sequence axis, giving a token sequence of length 1 + Ta + 1 + 1 that the paper calls in-context conditioning. Language and images are cross-attention conditions, outside that sequence.
RDT trains on datasets recorded at very different rates, from 3 Hz for RT-1 to 15 Hz for DROID. Feeding the control frequency c in as a conditioning variable tells the model how far apart in time the 64 actions in a chunk are meant to be. Every dataset declares its rate in configs/dataset_control_freq.json; the agilex placeholder sits at 25, which is why the example deployment script passes --ctrl_freq=25. Fine-tune at one rate and deploy at another and that mismatch is yours, not the model's.
Training uses a DDPM scheduler with 1000 timesteps and a squared-cosine beta schedule. At sampling time the paper reports DPM-Solver++ cutting the denoising loop from 100 steps to 5, and the shipped config sets num_inference_timesteps to 5 to match. On the robot's onboard RTX 4090 24 GB that gave 6 Hz of action chunks and 381 Hz of individual actions, since each chunk holds 64. During training each input modality is independently masked with probability 0.1, which is what buys tolerance for a missing camera.
The 128-dimensional unified action space
This is the part worth stealing even if you never run the model. Instead of normalising every dataset into an anonymous [-1, 1] box, RDT defines one 128-slot vector where slot 30 always means right end effector x in metres and slot 10 always means right gripper opening. A robot fills the slots it has and pads the rest. The mapping is in configs/state_vec.py and in Table 4 of the paper.
| Index range | Physical quantity |
|---|---|
| 0 to 9 | Right arm joint positions (arm_joint_0_pos and up) |
| 10 to 14 | Right gripper joint positions (index 10 is also the alias gripper_open) |
| 15 to 24 | Right arm joint velocities |
| 25 to 29 | Right gripper joint velocities |
| 30 to 32 | Right end effector position, x y z |
| 33 to 38 | Right end effector 6D pose, the six rotation components eef_angle_0 to eef_angle_5 |
| 39 to 41 | Right end effector linear velocities |
| 42 to 44 | Right end effector angular velocities, roll pitch yaw |
| 45 to 49 | Reserved |
| 50 to 99 | The same eight blocks again for the left arm |
| 100 to 101 | Base linear velocities |
| 102 | Base angular velocity |
| 103 to 127 | Reserved |
The consequences are practical. An arm with fewer than ten joints fills only the leading slots of its block: a six degree of freedom arm fills the first six. A single-arm follower fills the right arm block, never the left, because that is how the single-arm pre-training data was mapped. Units are SI units, which the README notes keeps most values inside [-1, 1] anyway. The one quantity that gets normalised is gripper width, min-max scaled to [0, 1], because gripper travel is arbitrary across hardware.
1. Do not normalise. No physical quantity except gripper width is normalised during pre-training. Z-score your joint angles first and you hand the model numbers whose physical meaning no longer matches any of the 46 pre-training datasets, so the prior stops helping. 2. Zero is not padding. A velocity of 0 means standing still. RDT concatenates a 0/1 vector marking padded dimensions onto the action and proprioception vectors before encoding, giving a 256-dimensional input. Write your own loader and you must keep that mask honest. 3. Single-arm goes right. A single arm in the left block silently costs you most of the pre-training benefit.
# data/hdf5_vla_dataset.py, the part you actually write (around L180-194).
# See configs/state_vec.py for the full name -> index mapping.
from configs.state_vec import STATE_VEC_IDX_MAPPING
import numpy as np
def fill_in_state(values):
# values: (T, n_joints) joint angles in radians, gripper last
n_arm = values.shape[1] - 1
uni_vec = np.zeros((values.shape[0], 128), dtype=np.float32)
idx = [STATE_VEC_IDX_MAPPING[f"arm_joint_{i}_pos"] for i in range(n_arm)]
uni_vec[:, idx] = values[:, :n_arm]
# gripper width, min-max normalised to [0, 1] - the one exception
uni_vec[:, STATE_VEC_IDX_MAPPING["gripper_open"]] = values[:, -1]
return uni_vecIf your action space carries end effector rotation, the repo requires the 6D representation from Zhou et al. rather than Euler angles or quaternions, and ships docs/test_6drot.py to convert. The README notes the mapping is not reversible: different Euler angles can be equivalent and land on the same 6D vector.
What went into pre-training, and why you will not repeat it
The pre-training collection is 46 datasets, more than 1 million trajectories and 21 TB on disk. Each dataset starts at a sampling weight of the square root of its size, so the RT-1 dataset with its 130K trajectories does not swamp a 1K-trajectory bimanual set, and the authors then raised the weights of datasets whose intermediate loss converged slowly. Familiar names include Open X-Embodiment, DROID, BridgeData V2, RH20T and RoboSet.
| Stage | Data | Compute | Steps |
|---|---|---|---|
| Pre-training | 46 datasets, 1M+ trajectories, 21 TB | 48 x H100 80 GB, about one month | 1,000,000 |
| Fine-tuning (paper) | 6K+ self-collected bimanual trajectories, 300+ tasks, 3M+ frames | the same 48 GPUs, about three days | 130,000 |
| Fine-tuning (your run) | your own recorded episodes | one GPU is enough to start | 150,000 recommended minimum |
One appendix detail is worth flagging because papers usually bury it: the reported fine-tune did not start from the 1M-step pre-trained checkpoint. Scheduling forced the authors to branch from the 500K-step one. The published RDT-1B weights are nonetheless the 1M-step checkpoint, while RDT-170M is a 500K-step checkpoint.
Their fine-tuning dataset is instructive: 300+ tasks, 100+ rigid and non-rigid objects, 15+ rooms with different lighting, and GPT-4-Turbo generating 100 expanded instructions plus one simplified one per task, so the language side sees many phrasings of the same job. That last trick is nearly free and worth copying when you build your own LeRobot dataset, as argued in how to collect high-quality VLA training data.
What it takes to run RDT-1B
The checkpoint is small by 2026 standards. The problem is the frozen encoder riding along with it: T5-XXL is by a wide margin the largest component in the pipeline, and the README says outright that on an RTX 4090 or lower it may not fit. That is the most common reason a first RDT run dies.
| What you need | Detail |
|---|---|
| Python | 3.10.0, conda env named rdt in the README |
| PyTorch | 2.1.0 with torchvision 0.16.0, CUDA 12.1 wheels |
| Pinned in requirements.txt | deepspeed 0.14.2, accelerate 0.30.1, diffusers 0.27.2, transformers 4.41.0, timm 1.0.3, h5py 3.11.0, wandb 0.17.0 |
| flash-attn | installed with --no-build-isolation, after packaging 24.0 |
| Weights to download | rdt-1b (2.46 GB), google/t5-v1_1-xxl, google/siglip-so400m-patch14-384 |
| Disk buffer | buf_path of at least 400 GB, used during pre-training only |
| Distributed launcher | DeepSpeed, ZeRO-2 by default via configs/zero2.json |
| Under 24 GB VRAM | precompute language embeddings, drop to RDT-170M, or move to ZeRO-3 with offload |
- A physical action representation. Joint angles stay in radians, positions stay in metres, so the pre-training prior transfers instead of being rescaled away.
- Native bimanual support: a left block and a right block from the start, unlike policies retrofitted from single-arm setups.
- Diffusion handles multi-modal action distributions, the actual failure mode when two arms could each reasonably do the task.
- MIT licence on code, weights and data, which is rare in this space.
- A 170M sibling with the same interfaces and the same 128-slot action space, so you can prototype the pipeline on a small card.
- T5-XXL is a heavy dependency for a 1.2 B action model, and it is the component that will not fit on 24 GB.
- No LeRobot integration and no generic adapter: only an HDF5 example you edit into a loader yourself.
- The repo publishes no single-GPU wall-clock figure to plan a 150,000 step run against.
- Swapping to RDT-170M is not just a checkpoint id. You must edit hidden_size and depth in configs/base.yaml, the same file the README tells you not to touch.
- Upstream attention has moved to RDT2. The RDT-1B repo was last pushed on 21 January 2026.
Fine-tuning RDT-1B on your own data
This is the real path. Nobody outside a large lab pre-trains this model. What follows is the upstream fine-tuning flow as documented in the repo README at the state of the main branch on 23 August 2026.
- 1Install the environment
Python 3.10, CUDA 12.1 wheels, flash-attn last because it compiles against the installed torch.
bashgit clone git@github.com:thu-ml/RoboticsDiffusionTransformer.git cd RoboticsDiffusionTransformer conda create -n rdt python=3.10.0 conda activate rdt pip install torch==2.1.0 torchvision==0.16.0 --index-url https://download.pytorch.org/whl/cu121 pip install packaging==24.0 pip install flash-attn --no-build-isolation pip install -r requirements.txt - 2Link the two frozen encoders
The repo expects them under a google/ directory at the root. Symlinks keep the weights out of your git tree.
bashmkdir -p google ln -s /path/to/t5-v1_1-xxl google/t5-v1_1-xxl ln -s /path/to/siglip-so400m-patch14-384 google/siglip-so400m-patch14-384 - 3Register your dataset
Three JSON files carry the registration, with an agilex placeholder in all three. Replace it with your dataset name and give the control frequency in Hz. The sampling weight is irrelevant while you have one dataset.
bashcd data && mkdir -p datasets ln -s /path/to/my_cool_dataset datasets/my_cool_dataset # then edit, replacing the agilex placeholder: # configs/dataset_control_freq.json "agilex": 25 -> {"my_cool_dataset": 30} # configs/finetune_datasets.json ["agilex"] -> ["my_cool_dataset"] # configs/finetune_sample_weights.json {"agilex":100}-> {"my_cool_dataset": 100} - 4Write the loader
Edit HDF5_DIR and DATASET_NAME at lines 21 and 22 of data/hdf5_vla_dataset.py, then implement parse_hdf5_file() and parse_hdf5_file_state_only(). Despite the name you need not use HDF5; only the class contract matters. Lines 180 to 194 hold the 128-slot mapping.
bash$EDITOR data/hdf5_vla_dataset.py # L21 HDF5_DIR, L22 DATASET_NAME # L148 path to precomputed lang embeddings # L180-194 fill the unified action vector - 5Compute dataset statistics
One command from the repo root. It writes the per-dimension statistics the trainer needs.
bashpython -m data.compute_dataset_stat_hdf5 - 6Precompute language embeddings if you are under 24 GB
Set TASK_NAME and INSTRUCTION in scripts/encode_lang.py, and point OFFLOAD_DIR at a real directory if T5-XXL still does not fit. Then add --precomp_lang_embed to the training script.
bash# scripts/encode_lang.py # MODEL_PATH = "google/t5-v1_1-xxl" # CONFIG_PATH = "configs/base.yaml" # SAVE_DIR = "outs/" # OFFLOAD_DIR = None # set an existing path if VRAM < 24GB python -m scripts.encode_lang # batch version for a whole dataset: scripts/encode_lang_batch.py - 7Launch the fine-tune
finetune.sh is the shipped example and the flags below are its values on main. Point pretrained_model_name_or_path at the Hugging Face id and it pulls the 1M-step checkpoint.
bashdeepspeed --hostfile=hostfile.txt main.py \ --deepspeed="./configs/zero2.json" \ --pretrained_model_name_or_path="robotics-diffusion-transformer/rdt-1b" \ --pretrained_text_encoder_name_or_path="google/t5-v1_1-xxl" \ --pretrained_vision_encoder_name_or_path="google/siglip-so400m-patch14-384" \ --output_dir="./checkpoints/rdt-finetune-1b" \ --train_batch_size=32 \ --sample_batch_size=64 \ --max_train_steps=200000 \ --checkpointing_period=1000 \ --sample_period=500 \ --checkpoints_total_limit=40 \ --lr_scheduler="constant" \ --learning_rate=1e-4 \ --mixed_precision="bf16" \ --dataloader_num_workers=8 \ --image_aug \ --dataset_type="finetune" \ --state_noise_snr=40 \ --load_from_hdf5 \ --report_to=wandb
The README says it in plain words: on an RTX 4090 or lower, GPU memory may be too low to load the t5-v1_1-xxl encoder. The failure lands as an out-of-memory while that encoder loads, after the job has queued and pulled gigabytes of weights, so it feels like a training bug rather than a configuration one. Fix it before you launch: precompute the embeddings with scripts/encode_lang_batch.py, point HDF5VLADataset at the embedding path instead of the raw instruction, and add --precomp_lang_embed. The repo FAQ lists further options in its own order: RDT-170M, a more memory-efficient ZeRO stage, use_8bit_adam=True, 4-bit or 8-bit quantisation, XFormers, hand-implemented gradient checkpointing, and a larger --gradient_accumulation_steps, which costs running time in exact proportion. The same symptom on our trainer is at out of memory during training.
Monitor two numbers: a long-window moving average of loss and overall_avg_sample_mse. The README reports that empirically the lower this sample MSE the better the model performs, and that fine-tuning is over when it converges. The paper's appendix carries the reasoning, a positive correlation between that MSE and deployment performance on the robot, with the caveat that an unusually low value can mean overfitting. The repo FAQ asks for at least 150,000 steps regardless of batch size; the example script sets max_train_steps to 200,000.
Deploying the fine-tuned checkpoint
Inference is wrapped in a class called RoboticDiffusionTransformerModel in scripts/agilex_model.py, and you call its step() method. Two functions must be rewritten for your hardware: _format_joint_to_state() at line 164, which packs joint readings into the 128-slot vector, and _unformat_action_to_joint() at line 196, which unpacks the output into servo commands. The control frequency defaults in the same file and is passed on the command line.
python -m scripts.agilex_inference \
--use_actions_interpolation \
--pretrained_model_name_or_path=checkpoints/rdt-finetune-1b/checkpoint-<STEP> \
--lang_embeddings_path=outs/lang_embeddings/your_instr.pt \
--ctrl_freq=25The README puts this in bold, and it is the second most common way a working checkpoint produces nonsense on hardware. When you feed images into step(), the order MUST be [ext_{t-1}, right_wrist_{t-1}, left_wrist_{t-1}, ext_{t}, right_wrist_{t}, left_wrist_{t}]. History first, then current, and within each timestep exterior, right wrist, left wrist. Swap two and the model still runs, still produces smooth trajectories, and reaches for the wrong place. The general version is at policy only works in one setup.

Two ways to get a policy onto an arm
You clone thu-ml/RoboticsDiffusionTransformer, download three sets of weights, write a loader that maps your robot into the 128-slot vector, and rent or own a machine big enough for a 150,000 step run. Everything is MIT licensed, and you own the data pipeline, the GPU, the checkpoint storage and the deployment glue.
- Full control over the action mapping, which matters if your robot has an unusual gripper or an extra wrist joint.
- Debug the loader on RDT-170M first, as long as you also set hidden_size to 1024 and depth to 14 in configs/base.yaml to match its config.json.
- Pre-train from scratch with pretrain.sh and a 400 GB disk buffer, if you really want to.
# the three things that must be true before you launch
python -c "import torch, flash_attn; print(torch.__version__)"
ls google/t5-v1_1-xxl google/siglip-so400m-patch14-384
python -m data.compute_dataset_stat_hdf5Being direct about the boundary: AY-Robots does not train RDT-1B. What the platform covers is everything on either side of the model choice, plus the comparison data that tells you whether RDT is the right target at all.
- Record the data with the desktop client from the download page: episodes, camera streams and joint states in LeRobot format, straight out of a teleoperation session.
- Browse or publish datasets in the public dataset directory, or bring a Hugging Face repo id.
- Compare 85 VLA models with 332 benchmark results in the arena, including RDT-1B, RDT-170M, RDT2-VQ and RDT2-FM.
- Train one of the five supported policies on the same data: GR00T N1.7, GR00T N1.5, Pi0.5, SmolVLA or ACT. GR00T and Pi0.5 are cloud-only; SmolVLA and ACT also run locally.
- Serve the result.
/api/inference/podprovisions a GPU pod for the policy, and an idle watchdog destroys the pod after an idle period so nothing bills silently.
| GPU tier | Models | Run time | Cost per run |
|---|---|---|---|
| A100 80 GB or H100 80 GB | GR00T N1.7, GR00T N1.5, Pi0.5 | 3 to 6 h | about 4 to 12 USD |
| RTX 4090 or any 24 GB card | SmolVLA, ACT | 2 to 5 h | about 1 to 3 USD |
Spot market prices, so those are ranges rather than quotes. The breakdown is on the pricing page and the model-by-arm matrix at the training hub.
Where RDT-1B sits against the policies you can actually train here
The comparison below mixes two kinds of number. The five AY-Robots rows are platform figures for the per-action-step latency of a served policy; the RDT row is the paper's own throughput measurement on the robot's onboard RTX 4090. Different metrics, not a ranking.

| Model | Params | Action representation | Reported speed | Trainable on AY-Robots |
|---|---|---|---|---|
| RDT-1B | 1.2 B | Diffusion over a 64-step chunk in a 128-dim unified space | 6 chunks/s and 381 actions/s on an onboard RTX 4090 (paper) | no |
| RDT-170M | 170 M | the same, at half depth and half width | not published | no |
| GR00T N1.7 | ~3 B, ~40 M trained during fine-tuning | VLA with a diffusion action head | 152 ms per action step | yes, A100 or H100 |
| GR00T N1.5 | ~3 B | VLA, the predecessor | 165 ms per action step | yes, A100 or H100 |
| Pi0.5 | ~3 B, PaliGemma backbone | flow matching | 485 ms per action step | yes, A100 or H100 |
| SmolVLA | ~450 M | compact VLA | 245 ms per action step | yes, 24 GB card |
| ACT | ~80 M | action chunking transformer, trained from scratch | 20 ms per action step | yes, 24 GB card |
Two structural similarities are worth naming. RDT's chunk of 64 actions is the same idea as action chunking in ACT, unsurprising since the paper devotes an appendix to the technique and cites ACT for it. And RDT's diffusion head addresses the same multi-modality problem that flow matching addresses in Pi0.5, by a different route, compared in our Pi-Zero flow matching article.

What the reported numbers say
The 56 percent improvement in success rate that gets quoted everywhere comes from the paper's introduction, not its abstract, and is measured on a Cobot Mobile ALOHA with two 7 degree of freedom arms against ACT, OpenVLA and Octo. The ManiSkill simulation results, added to the repo in December 2024, are easier to read because the protocol is fixed: 250 trials per task, 10 seeds with 25 trials each, RDT fine-tuned from the released checkpoint for 300K iterations.
| Method | PegInsertionSide | PickCube | StackCube | PlugCharger | PushCube | Mean |
|---|---|---|---|---|---|---|
| RDT | 13.2% | 77.2% | 74.0% | 1.2% | 100% | 53.6% |
| Diffusion Policy | 0.0% | 40.0% | 80.0% | 0.0% | 88.0% | 30.2% |
| OpenVLA | 0.0% | 8.0% | 8.0% | 0.0% | 8.0% | 4.8% |
| Octo | 0.0% | 0.0% | 0.0% | 0.0% | 0.0% | 0.0% |
Read the PlugCharger column before the mean. 1.2 percent is a failure, and PegInsertionSide at 13.2 percent is not a working policy either: contact-rich insertion is unsolved for all four methods, and the mean is carried by the easy tasks. The ablation is more useful to practitioners: removing pre-training dropped unseen-object success from 50 percent to 0, while the 166 M small variant dropped it to 37.5 percent. Pre-training scale mattered more than model size.
The repo points at the RoboTwin 2.0 leaderboard, a 50-task dual-arm benchmark on an Aloha-AgileX, and says RDT ranks second only to Pi0, excluding DP3 because DP3 uses ground-truth point clouds. That held for the five single-task baselines listed there in August 2025, and the repo has not been touched since January 2026. At the board's 18 August 2026 update it carries 18 entries: RDT sits eleventh on the hard clean2random ranking at 13.72 percent, behind pi0 at 16.34 percent, which is still the best of the original single-task group, and behind a row of 2026 co-trained models led by GigaBrain-0.7 at 67.9 percent. Most of those newer entries are co-trained across all 50 tasks while RDT and pi0 are single-task fine-tunes, so it is no longer a like-for-like board. Either way, read the README claim as a 2025 snapshot, not a current standing.
The honest limits
Three things about RDT-1B are routinely overstated when the paper gets cited, and one thing about running any policy over a network applies here too.
- It is not a zero-shot cross-embodiment model. The model card says it plainly: because of the embodiment gap, RDT cannot yet generalise to robot platforms absent from the pre-training data, and the recommendation is to collect a small target-robot dataset and fine-tune. The unified action space makes multi-robot training possible; it does not make a new arm free.
- The bimanual results are one robot. All real-robot evaluation is on a Cobot Mobile ALOHA, and the appendix states the mobile base was used only to move between rooms, never during training or inference. These are static bimanual tasks.
- The pre-training scale is the contribution. The ablation shows the from-scratch variant collapsing to 0 percent on unseen objects. If you fine-tune on a handful of episodes and it works, that is the 21 TB doing the work.
- Latency is local or it is nothing. The paper's 6 Hz chunk rate is measured on a GPU bolted to the robot. A public-internet round trip between the cameras and the policy adds tens to hundreds of milliseconds per decision, turning a working policy into a hesitant one. Remote inference suits slow pick-and-place, not fast reactive motion. That is true of our inference pods too, and we would rather say it than sell around it.
One practical limit has nothing to do with the model: RDT does not read LeRobot datasets natively. Checked on 23 August 2026, the lerobot policies directory holds act, diffusion, pi0, pi05, pi0_fast, smolvla, groot, xvla and about a dozen more, and no rdt. If your episodes came from the LeRobot toolchain, you write that conversion yourself. Recording is where the platform helps: see record your first dataset and teleoperation.
RDT2, and what it means for RDT-1B
The same group released RDT2 in September 2025, with the paper following in February 2026. It is a different bet: instead of scaling robot teleoperation data, RDT2 scales UMI-style handheld gripper data, more than 10,000 hours of human manipulation video in over 100 indoor scenes, collected with redesigned higher-strength UMI hardware. Two variants shipped. RDT2-VQ is a VLA adapted from Qwen2.5-VL-7B-Instruct that uses residual vector quantisation as its action tokenizer; RDT2-FM is an improved RDT used as a flow-matching action expert, with much lower inference latency.
RDT2 claims zero-shot deployment on unseen embodiments for simple open-vocabulary tasks such as picking, placing, shaking and wiping, verified on bimanual UR5e and bimanual Franka Research 3. That is precisely the claim RDT-1B declined to make. RDT-1B is still the better paper for understanding the unified action space, which RDT2 builds on rather than replaces, and it is still MIT licensed and still runs. But its last push was 21 January 2026 and new work happens in the RDT2 repository, which ships under Apache-2.0 rather than MIT. Plan accordingly.
For a broader map of how these families relate, our overview of vision-language-action models covers the lineage, and the policies page covers what is trainable here today. If you are choosing hardware rather than a model, start at the SO-100 page or the SO-100 complete guide.
Can I fine-tune RDT-1B on a single RTX 4090?▾
Yes, but not naively. The README states that on an RTX 4090 or lower the GPU memory may be too low to load T5-XXL, so precompute language embeddings with scripts/encode_lang_batch.py and pass --precomp_lang_embed. Beyond that the repo FAQ offers RDT-170M, a more memory-efficient ZeRO stage, use_8bit_adam, 4-bit or 8-bit quantisation, XFormers, gradient checkpointing and a larger --gradient_accumulation_steps. The repo asks for at least 150,000 steps and publishes no single-GPU wall-clock time, so plan for a long run.
Does RDT-1B work with a single-arm robot like an SO-100?▾
Architecturally yes. The unified action vector reserves ten slots for right-arm joint positions and five for the right gripper, and the README instructs you to fill a single arm into the right-arm portion so it matches the mostly single-arm pre-training data; a six-joint arm fills the first six slots. Practically, you write the loader yourself, there is no LeRobot integration, and the released evaluation is entirely on a dual-arm ALOHA. For a policy you can train and serve today on an SO-100 class arm, the five trainer options are documented on the policies page.
What is the difference between RDT-1B and RDT-170M?▾
RDT-170M has a hidden size of 1024 and a depth of 14, exactly half of RDT-1B's 2048 and 28, with the same 32 heads and the same 128-dimensional action space. It is the RDT (small) ablation from the paper, which counts it as 166 M parameters. It is a 500K-step checkpoint of 332,520,250 bytes against RDT-1B's 1M-step 2,456,755,578 bytes. In the ablation it scored 37.5 percent on unseen objects against 50 percent for the full model, and 25 percent on instruction following against 100 percent. Use it to debug your data pipeline, and change hidden_size and depth in configs/base.yaml when you load it.
Is RDT-1B available on the AY-Robots trainer?▾
No. The trainer supports GR00T N1.7, GR00T N1.5, Pi0.5, SmolVLA and ACT. RDT-1B and RDT-170M appear in the arena for comparison, alongside RDT2-VQ and RDT2-FM, but are not trainable here. To run RDT, the upstream repo is the path and the fine-tuning section above applies.
How many demonstrations do I need to fine-tune RDT-1B?▾
The paper's fine-tune used more than 6,000 trajectories across 300+ tasks, and the few-shot claim of 1 to 5 demonstrations applies to new skills learned on top of that fine-tune, not to the raw pre-trained checkpoint. For a single task from the released weights, treat a few thousand demonstrations as the reference point rather than five. On the AY-Robots trainer the minimums are 30 episodes for SmolVLA and 50 for the others, a different regime because those assume one narrow task.
85 VLA models, 332 benchmark results, every number linked to its source
RDT-1B, RDT-170M, RDT2-VQ, RDT2-FM, GR00T, Pi0.5, OpenVLA, Octo and the rest in one sortable table. No marketing numbers, just what the papers and model cards report, with a link back to each claim.
Open the arenaSources
- RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation (Liu, Wu, Li, Tan, Chen, Wang, Xu, Su, Zhu; arXiv 2410.07864, v2 1 March 2025)
- RDT-1B full text with appendices: unified action space Table 4, pre-training datasets, ablation Table 2, model config Table 9
- thu-ml/RoboticsDiffusionTransformer, the official PyTorch implementation, README and FAQ
- configs/base.yaml: model architecture, chunk size, noise scheduler, 400 GB buffer
- finetune.sh: the shipped fine-tuning flags and their values
- configs/state_vec.py: the name to index mapping of the 128-slot unified action vector
- RDT-1B model card, config.json and the 1M-step checkpoint on Hugging Face
- RDT-170M model card: hidden size 1024, depth 14, the RDT (small) ablation checkpoint
- rdt-ft-data, the 6K+ trajectory bimanual fine-tuning dataset, MIT licensed
- ICLR 2025 poster listing for RDT-1B
- RoboTwin 2.0 leaderboard, 50 dual-arm tasks on Aloha-AgileX, updated 18 August 2026
- lerobot policies directory, checked 23 August 2026: no rdt implementation
- thu-ml/RDT2, the successor with RDT2-VQ and RDT2-FM
- RDT2: Exploring the Scaling Limit of UMI Data Towards Zero-Shot Cross-Embodiment Generalization (arXiv 2602.03310, 3 February 2026)
- Zhou et al., On the Continuity of Rotation Representations in Neural Networks (the 6D rotation RDT requires)
Ready for high-quality robotics data?
AY-Robots connects your robots to skilled operators worldwide.
Get Started