πR², đọc là "pi R squared", là một cách làm rất thực dụng để biến một VLA lớn kiểu GR00T-N1.7 thành policy manipulation có phản xạ thời gian thực. Vấn đề mà paper nhắm tới rất gần với robot thật: các model VLA hiện đại thường sinh action chunk dài bằng diffusion hoặc flow matching. Chúng thông minh hơn policy nhỏ vì có vision-language backbone lớn, nhưng khi chạy trên robot, mỗi lần suy luận lại mất nhiều thời gian. Trong lúc model đang tính chunk mới, robot vẫn phải thực thi chunk cũ gần như open-loop. Nếu vật trượt, tay chạm lệch, sách rơi, hoặc contact force đổi nhanh, policy dễ phản ứng muộn.
πR² không cố thu nhỏ GR00T-N1.7 thành một model đơn giản hơn. Ý tưởng của nó là giữ lại backbone lớn, giữ lại action chunking, nhưng thay đổi cách conditioning và denoising để robot dùng được tín hiệu mới ở từng control tick. Theo paper gốc, khi fine-tune từ GR00T-N1.7 trên hệ xArm6 + XHand, πR² đạt khoảng 25 Hz trên RTX A5000, tức mỗi 40 ms có thể phát action dựa trên proprioception mới, thay vì replanning ở khoảng 7 Hz như pipeline flow chuẩn. Trên các task simulation và real-world manipulation, tác giả báo cáo mức cải thiện success rate lên tới 23% trong simulation và 30% trên robot thật so với baseline mạnh nhất.
Bài này viết cho người mới đã biết cơ bản về imitation learning hoặc VLA, nhưng chưa cần hiểu sâu toàn bộ toán diffusion. Mục tiêu là giúp bạn đọc được paper, hiểu repo chính thức, biết cài đặt pipeline, biết train biến thể pir2, và biết khi nào nên dùng πR² thay vì chỉ chạy GR00T-N1.7 gốc.

Nguồn gốc và vấn đề paper giải quyết
Paper gốc có tên πR²: Reactive Real-time Flow Policies, tác giả Sungjae Park và Shubham Tulsiani từ Carnegie Mellon University. Project page tóm tắt rất rõ: πR² làm cho large-scale action-chunking flow policies như VLA trở nên reactive và real-time bằng ba thành phần: fast proprioception channel, asynchronous vision-language channel, và latency-adaptive flow schedule. Code chính thức nằm ở repo pi-r2-flow/pi-r2-flow; phần training là một fork của NVIDIA Isaac-GR00T, pinned vào branch pir2, thêm logic πR² vào action head flow-matching của GR00T-N1.7.
Để thấy vì sao cần cách này, hãy nhìn pipeline VLA thông thường. Robot nhận ảnh camera, language prompt và robot state. Vision-language backbone trích xuất semantic features, sau đó action head dùng nhiều bước denoising để sinh một chunk gồm nhiều action tương lai. Chunk giúp motion mượt hơn và train ổn định hơn, nhưng có một cái giá: robot phải cam kết thực thi một đoạn hành động đã dự đoán từ observation cũ. Nếu control loop chạy 25 Hz mà inference chỉ kịp khoảng 7 Hz, robot có thể đi qua 3-4 tick trước khi model kịp nhìn lại trạng thái mới.
Trong robot manipulation, 40-160 ms là khoảng thời gian rất dài. Một quả bóng có thể lăn, một cuốn sách có thể trượt khỏi đầu ngón tay, một object đang nghiêng có thể đổ hẳn. VLA có thể hiểu instruction tốt, nhưng nếu phản hồi contact bị chậm, thao tác vẫn fail. πR² coi vấn đề này là sự kết hợp của hai lỗi: reactivity thấp vì chunk chạy open-loop, và latency cao vì mỗi action phụ thuộc vào observation đã cũ.
Kiến trúc: giữ GR00T, đổi nhịp phản xạ
GR00T-N1.7 là VLA 3B parameter của NVIDIA. Theo tài liệu Isaac-GR00T và bài giới thiệu của NVIDIA trên Hugging Face, model dùng kiến trúc Action Cascade: System 2 là vision-language module với backbone Cosmos-Reason2-2B / Qwen3-VL để xử lý image token và language instruction; System 1 là Diffusion Transformer action head, nhận output semantic của VLM cùng robot state rồi denoise thành continuous robot actions. Inputs gồm RGB frames, text instruction và proprioceptive state như joint position, velocity hoặc end-effector pose. Outputs là action vector liên tục theo embodiment.
πR² không thay toàn bộ stack đó. Nó tận dụng một bất đối xứng tự nhiên trong VLA: vision-language rất đắt, proprioception rất rẻ. Ảnh và text cần đi qua backbone lớn, thường mất hàng chục mili giây. Trong paper, tác giả dùng chi phí GR00T-N1.7 làm chuẩn: vision/text VLM processing khoảng 60 ms, còn 4-step denoising khoảng 80 ms. Ngược lại, joint state, torque hoặc fingertip force có thể lấy liên tục từ robot và xử lý nhanh hơn nhiều. Vì vậy πR² tách conditioning thành hai kênh:
| Kênh | Dữ liệu | Tốc độ cập nhật | Vai trò |
|---|---|---|---|
| Fast channel | Proprioception, joint state, force/touch nếu có | Mỗi control tick | Phản xạ local khi contact thay đổi |
| Slow channel | Vision features, language features | Async, có thể stale | Định hướng semantic và mục tiêu task |
Điểm hay là πR² chấp nhận vision-language bị trễ thay vì cố làm nó nhanh bằng mọi giá. Vision thường cho ngữ cảnh coarse: vật nào cần lấy, rổ ở đâu, mục tiêu cuối là gì. Proprioception cho thông tin local: ngón tay đã chạm chưa, object có trượt không, joint hiện lệch bao nhiêu, force có spike không. Với manipulation phản xạ, nhiều correction ngắn hạn có thể dựa vào proprioception mới, miễn là semantic plan tổng thể vẫn đúng.
Thành phần thứ hai là diffusion forcing theo từng vị trí trong chunk. Diffusion/flow policy chuẩn thường dùng cùng noise level cho cả chunk trong một bước denoising. Diffusion forcing cho phép mỗi vị trí action trong buffer có noise level riêng. πR² dùng ý tưởng này để tạo lịch "staircase": phần đầu buffer là các action đang bay hoặc vừa thực thi, được clamp như inpainting conditioning; phần giữa ramp từ clean sang noisy; phần đuôi là slot mới để sinh action tương lai. Khi đo được độ trễ inference là d tick, schedule tự reshape để mỗi call chỉ cần một denoising step nhưng vẫn phát ra d action sạch tiếp theo.
Nói bằng ngôn ngữ hệ thống, bạn có thể hình dung vòng lặp như sau:
camera + language ──> VLM worker chậm ──> cached slow features
robot state ──> fast channel mới ở từng tick
cached slow features + fresh proprioception + action buffer
|
v
πR² flow action head, 1 NFE/call
|
v
emit action(s), slide buffer, repeat at 25 Hz
Với GR00T-N1.7 gốc, mỗi call thường phải chạy VLM và nhiều bước denoising. Với πR², VLM có thể chạy async trên GPU riêng hoặc worker riêng; action head dùng slow feature cache gần nhất và proprioception mới. Đây là lý do repo hỗ trợ chế độ 2-GPU split: VLM server trên port 5555, DiT/action server trên port 5556, dùng --async-vlm cho biến thể πR².
Phần cứng và repo bạn cần
Repo chính thức triển khai trên hệ dexterous manipulation gồm:
| Thành phần | Cấu hình trong repo |
|---|---|
| Arm | UFactory xArm6, 6 DoF |
| Hand | XHand, 12 DoF, RS485 |
| Camera | Intel RealSense overhead |
| Action space | 18 chiều: 6 joint xArm6 + 12 joint XHand |
| Inference | Remote GPU chạy GR00T |
Nếu bạn chưa có phần cứng y hệt, vẫn có thể dùng repo để học cách cấu trúc policy và fine-tune. Nhưng để tái lập kết quả thật, bạn cần arm, dexterous hand, camera, robot machine và GPU machine. Paper dùng RTX A5000 cho training/inference real-world; phần hyperparameter ghi batch size 512, bf16 + tf32, fused AdamW, peak learning rate 1e-4, weight decay 1e-5, gradient clip 1.0, và 8 GPU A5000/A6000 cho training. Đây không phải một setup laptop.
Điểm beginner cần nhớ: πR² là kỹ thuật cho large flow policy đã có pretrained checkpoint. Nó không phải một controller PID, không phải một script teleop, và cũng không phải "prompt engineering" cho VLA. Bạn cần dataset demonstration theo format GR00T/LeRobot, modality config đúng action/state, và checkpoint GR00T-N1.7-3B làm base.

Cài đặt môi trường
Theo README chính thức, bạn clone repo với submodule để lấy fork Isaac-GR00T:
git clone --recursive https://github.com/pi-r2-flow/pi-r2-flow.git
cd pi-r2-flow
Nếu đã clone thiếu submodule:
git submodule update --init --recursive
Phần deployment trên robot machine nằm trong thư mục deployment:
cd deployment
pip install -e .
pip install -e ".[camera]"
Tùy phần cứng, bạn cần thêm driver RealSense, thư viện điều khiển xArm6, cấu hình RS485 cho XHand, quyền truy cập serial/USB, và network ổn định giữa robot machine và GPU server. Với hệ thật, hãy kiểm tra từng lớp trước khi chạy VLA:
- Camera server trả frame đúng resolution và timestamp.
- Arm có thể chạy joint command ở tốc độ an toàn.
- Hand có thể nhận 12 joint command, không bị đảo chiều hoặc sai scale.
- Robot state logging đồng bộ với action logging.
- Emergency stop độc lập với policy process.
Phần training nằm ở:
cd learning/Isaac-GR00T
README nói thư mục này là fork của NVIDIA Isaac-GR00T pinned vào branch pir2, thêm πR² vào flow-matching action head. Bạn cần cài theo README Isaac-GR00T, tải base checkpoint GR00T-N1.7-3B, chuẩn bị dataset theo GR00T/LeRobot format và viết modality_config.py cho embodiment của bạn.
Chuẩn bị dataset và modality config
Training data dùng standard GR00T LeRobot format. Mỗi episode cần có video observation, robot state, action và task text. Với xArm6 + XHand, action là vector 18 chiều:
action[0:6] = xArm6 joints
action[6:18] = XHand joints
State nên chứa tối thiểu joint position hiện tại của arm và hand. Nếu bạn có velocity, torque hoặc tactile/fingertip force, đó là tín hiệu rất phù hợp với triết lý πR², vì fast channel cần dữ liệu phản xạ mới ở từng tick. Tuy vậy, modality config phải nhất quán: key trong dataset, normalization stats, dimension và thứ tự joint phải khớp hoàn toàn với model.
Một lỗi phổ biến là train được nhưng inference sai vì action order lệch. Ví dụ joint index của XHand trong dataset là thumb-index-middle..., nhưng robot driver lại nhận index-middle-thumb... Khi đó policy nhìn có vẻ "không học được", trong khi lỗi thực ra nằm ở mapping. Với VLA/action policy, thứ tự vector là API contract. Hãy viết test nhỏ để phát một action one-hot chậm, quan sát đúng joint nào di chuyển, rồi mới collect data.
Paper real-world dùng 4 task:
| Task | Prompt training/deployment | Điểm khó |
|---|---|---|
| Don't Spill | "put the ball in the bowl and put them on the cutting board" | Giữ bowl/ball không đổ |
| Tidy Up Book | "put the books in the basket" | Kéo sách ra khỏi pile rồi bỏ vào rổ |
| Insert Box | "put the box in the basket" | Đẩy, dựng, grasp, insert giữa sách |
| Catch Book | "catch the book" | Phản ứng nhanh khi sách rơi |
Các task này được chọn không chỉ vì semantic manipulation, mà vì chúng buộc policy phản ứng với contact. Catch Book là ví dụ rõ nhất: nếu policy đợi vision-language pipeline chậm, sách đã trượt khỏi tay; nếu dùng proprioception mới, ngón tay có thể điều chỉnh grip gần như ngay khi force thay đổi.
Fine-tune biến thể πR²
Repo dùng cùng entrypoint launch_finetune.py cho ba biến thể: standard flow, Train-Time RTC và PI-R2. Command mẫu từ README:
cd learning/Isaac-GR00T
export GR00T_IMAGE_DELAY_MAX=5
torchrun --nproc_per_node=8 gr00t/experiment/launch_finetune.py \
--base-model-path <path/to/GR00T-N1.7-3B> \
--dataset-path <path/to/lerobot_dataset> \
--modality-config-path <path/to/modality_config.py> \
--embodiment-tag NEW_EMBODIMENT \
--num-gpus 8 \
--global-batch-size 512 \
--max-steps 40000 \
--output-dir <path/to/output> \
--streaming \
--streaming-constant-weight 0.2 \
--streaming-chunk-wise-weight 0.8 \
--streaming-schedule-mode pir2 \
--streaming-chunk-size-max 5 \
--streaming-mask-clean-end \
--image-delay-max 5 \
--image-delay-embed-dim 64
Các flag quan trọng:
| Flag | Ý nghĩa thực hành |
|---|---|
--streaming |
Bật training theo kiểu streaming/action buffer |
--streaming-schedule-mode pir2 |
Chọn latency-adaptive schedule của πR² |
--streaming-chunk-size-max 5 |
Giới hạn sub-chunk theo delay/action buffer |
--streaming-mask-clean-end |
Mask phần action đã clean để làm inpainting conditioning |
--image-delay-max 5 |
Train model chịu được slow vision bị trễ tối đa 5 tick |
--image-delay-embed-dim 64 |
Thêm embedding cho độ trễ image vào DiT |
GR00T_IMAGE_DELAY_MAX=5 |
Env var tương ứng cho image delay |
Theo appendix, real-world πR² fine-tune giữ frozen VLM backbone và vision encoder, chỉ fine-tune action head gồm projectors + DiT. Per-position AdaLN parameters được khởi tạo từ shared pair của pretrained model, để mỗi position trong action horizon bắt đầu từ schedule đồng nhất rồi tự chuyên hóa trong fine-tuning. Chunk length H=50, observation history n_obs=1, control rate 25 Hz, NFE per call của πR² là 1, trong khi baseline Flow/Train-Time RTC dùng 4.
Điểm quan trọng là training phải mô phỏng latency thật. Mỗi batch sample một delay d, xây staircase schedule, clamp d slot đầu làm ground-truth in-flight actions, rồi chỉ tính loss trên các slot còn lại. Với real-world training, slow channel còn bị delay ngẫu nhiên d_vis từ 0 đến d_vis_max, tương ứng image cũ trong demonstration, còn proprioception vẫn là hiện tại. Nhờ vậy, deployment không bị sốc khi VLM feature cache trễ 1-5 tick.
Chạy inference trên robot
Sau khi có checkpoint, bạn khởi động GR00T inference server trên GPU machine. README đưa hai chế độ:
# Single GPU cho baseline
python gr00t/eval/run_gr00t_server.py \
--model-path <checkpoint> \
--port 5555 \
--host 0.0.0.0
Với πR² async VLM, repo dùng split 2 GPU:
MODEL_PATH=<checkpoint> bash scripts/gr00t_inference_2gpu.sh
Nếu GPU server nằm trong cluster, forward port về robot machine:
ssh -N -L 5555:<compute-node>:5555 <username>@<cluster-login>
ssh -N -L 5556:<compute-node>:5556 <username>@<cluster-login>
Sau đó chạy camera server trên robot machine:
python deployment/apps/run_camera_server.py --port 5000
Repo hỗ trợ ba query mode:
| Query mode | Khi nào dùng |
|---|---|
sync |
Debug đơn giản; robot hold command trong lúc đợi inference, dễ thấy pause |
pipelined |
Bắt đầu query chunk mới khi chunk hiện tại sắp hết; cần chunk-len lớn hơn latency |
continuous |
Worker query liên tục, swap chunk mới nhất khi có; latency thấp nhất, dùng cho πR² |
Với πR², mục tiêu là continuous hoặc pipeline tương đương, cộng với async VLM. Action worker query back-to-back; chunk mới thay active chunk ở swap boundary; các action đang thực thi được đưa vào input như inpainting conditioning. πR² còn thêm VLM-cache worker để refresh visual feature background. Đây là điểm khác baseline naive async: naive async chạy chunk mới trong lúc chunk cũ thực thi, nhưng không model hóa đúng các action đang bay; πR² biết phần nào của buffer đã được commit và biến nó thành conditioning.
Kết quả và cách đọc bảng
Trong simulation, paper test under VLA-level inference delay bằng cách dùng cost GR00T-N1.7: VLM/text khoảng 60 ms, 4-step denoising khoảng 80 ms. Baseline end-to-end như naive async và Train-Time RTC chịu effective delay 1.75 d0; πR² không async chịu 1.0 d0; πR² full async giữ proprioception delay ở khoảng 1 tick, còn visual delay tăng riêng. Kết quả simulation cho thấy πR² full thắng ở mọi d0 được test, với success khoảng 0.43, 0.42, 0.45, trong khi naive async giảm từ 0.33 xuống 0.22 và Train-Time RTC giảm từ 0.36 xuống 0.19 khi delay tăng.
Trên real-world xArm6 + XHand, paper so sánh bốn chế độ đều fine-tune từ GR00T-N1.7 với cùng data và budget:
| Method | Latency đo bằng tick 25 Hz | Đặc điểm |
|---|---|---|
| Flow, Synchronous | d=4-5 |
Robot dừng/hold trong lúc inference |
| Flow, Naive Async + TE | d=4-5 |
Chạy liên tục nhưng dùng observation/action stale |
| Train-Time RTC | d=4-5 |
Smooth boundary hơn, vẫn chịu full pipeline latency |
| πR² async | d=1-2 |
Fresh proprioception, VLM cache async, 1 NFE/call |
Bảng kết quả trong paper cho thấy πR² dẫn đầu trên mọi task. Một vài số đáng chú ý:
| Task | Baseline mạnh đáng chú ý | πR² |
|---|---|---|
| Don't Spill | Train-Time RTC 9/20 SR |
15/20 SR |
| Tidy Up Book | Train-Time RTC 8/20 SR |
14/20 SR |
| Insert Box | Naive Async 12/20 SR |
17/20 SR |
| Catch Book | Train-Time RTC 5/20 SR |
11/20 SR |
Ở các metric progress theo subgoal, πR² cũng cao hơn. Điều này quan trọng vì manipulation không chỉ đúng/sai ở cuối episode. Với Insert Box, chẳng hạn, policy có thể hoàn thành push và stand nhưng fail ở insert; progress score cho thấy policy có học được các giai đoạn trung gian hay không. πR² cải thiện cả success và progress, nghĩa là nó không chỉ "ăn may" ở vài trial.
Khi nào nên dùng πR²?
Bạn nên cân nhắc πR² nếu bài toán có ít nhất một trong các dấu hiệu sau:
| Dấu hiệu | Vì sao πR² hữu ích |
|---|---|
| Contact-rich manipulation | Proprioception mới giúp điều chỉnh grip/force nhanh |
| Object có thể trượt/rơi | Open-loop chunk dễ stale trước khi model nhìn lại |
| VLA backbone lớn | Async slow channel giảm cost mỗi control tick |
| Cần giữ motion mượt | In-flight action conditioning tránh boundary giật |
| Có pretrained flow policy | πR² fine-tune từ checkpoint, không cần train từ đầu |
Ngược lại, nếu task gần như quasi-static, object không thay đổi nhanh, và bạn chỉ chạy pick-and-place đơn giản trong môi trường rất ổn định, standard action chunking có thể đủ. πR² thêm complexity: cần code streaming, delay schedule, cache worker, logging latency, và training data đủ tốt để model học phản xạ. Với team nhỏ, hãy bắt đầu bằng baseline GR00T-N1.7 hoặc policy flow chuẩn, đo latency và failure mode trước. Nếu lỗi chính là phản ứng muộn, πR² mới là nâng cấp đúng chỗ.
Checklist triển khai cho lab nhỏ
Một lộ trình thực tế:
- Chạy GR00T-N1.7 inference chuẩn với checkpoint đã fine-tune cho robot của bạn.
- Log đầy đủ timestamp: camera frame, state read, policy request, policy response, action sent.
- Đo control tick thực tế. Đừng giả định 25 Hz nếu driver hoặc network chỉ ổn định ở 15-20 Hz.
- Chạy baseline
sync,pipelined,continuousđể xem failure mode. - Fine-tune
plain_flowvàrtccùng dataset để có baseline công bằng. - Fine-tune
pir2vớiimage-delay-maxgần latency thật của hệ thống. - Khi deploy, bắt đầu speed thấp, limit joint/hand command, bật E-stop và chỉ tăng tốc sau khi action order đã kiểm chứng.
Một lỗi dễ mắc là chỉ nhìn FPS trung bình. πR² quan tâm đến tail latency và effective delay. Nếu trung bình 40 ms nhưng thỉnh thoảng spike 200 ms, robot có thể fail đúng lúc contact. Hãy log histogram latency, số tick trễ d, và frame age của slow visual feature. Khi failure xảy ra, xem policy đang dùng visual feature cũ bao nhiêu tick và proprioception có bị drop không.
Kết luận
πR² là một bước quan trọng vì nó không phủ nhận lợi ích của large VLA. Thay vì nói "model lớn quá chậm, hãy dùng model nhỏ", paper hỏi: nếu vision-language chậm nhưng proprioception nhanh, ta có thể tổ chức inference để robot vẫn phản xạ không? Câu trả lời là có: tách fast/slow conditioning, dùng diffusion forcing theo vị trí, và dùng latency-adaptive schedule để mỗi call phát action mới với một denoising step.
Với GR00T-N1.7, điều này biến một VLA mạnh nhưng chậm thành manipulation policy có thể chạy gần 25 Hz trên robot thật. Kết quả xArm6 + XHand cho thấy lợi ích rõ nhất ở những task contact-rich và dynamic như Catch Book, Don't Spill, Tidy Up Book và Insert Box. Đây chưa phải lời giải cuối cùng cho humanoid manipulation: paper cũng thừa nhận reactive data khó thu, proprioception conditioning còn hạn chế, và replan hiện chủ yếu là local. Nhưng với người làm robot thật, πR² đưa ra một nguyên tắc rất đáng học: semantic reasoning có thể chậm, còn phản xạ điều khiển phải nhanh.
Bài viết liên quan
- NVIDIA GR00T + SONIC Whole-Body VLA
- π0-FAST và training VLA trong LeRobot
- WholeBodyVLA: teleop, train, deploy



