GRAIL là một pipeline tạo dữ liệu số cho humanoid loco-manipulation: thay vì dựng phòng thật, teleoperate robot thật, hoặc mocap từng cảnh, pipeline bắt đầu từ asset 3D, scene có tỷ lệ mét, camera đã biết, rồi dùng video foundation model và các bước reconstruction/retargeting để tạo demonstration cho Unitree G1. Trang dự án GRAIL của NVIDIA mô tả rõ điểm then chốt này: dữ liệu bắt đầu từ cấu hình 3D đầy đủ, sau đó được tái sử dụng xuyên suốt các bước tạo video, khôi phục 4D HOI và retarget sang robot.
Bài 1 này chỉ tập trung vào tầng đầu tiên: asset. Trong GRAIL có hai đường đi chính:
grail.pipelines.gen_terrain: tạo procedural terrain chocurb,slope,stairs, xuất mỗi asset thànhmodel.obj,model.mtl,texture.jpg.grail.pipelines.gen_3d_assets: đọc danh sách object từconfigs/gen_3d/example_objects.yamlhoặcconfigs/gen_3d/chairs.yaml, tạo ảnh tham chiếu, chạy Hunyuan3D-2.1 để sinh mesh/textures, rồi scale về kích thước thực tế.
Nếu bạn mới bắt đầu, hãy xem asset như "hợp đồng dữ liệu" của toàn pipeline. Blender cần mesh để render frame đầu tiên. FoundationPose cần hình học và texture đủ rõ để track 6D pose. Isaac Lab cần object/terrain có tỷ lệ hợp lý, collision hợp lý và không phá kịch bản locomotion. Một asset đẹp theo mắt người nhưng sai scale, đối xứng hoàn toàn, có base ảo, hoặc quá nhỏ sẽ làm hỏng các stage sau.
Roadmap series
- Tạo asset 3D và terrain cho GRAIL: hai nhánh asset, prompt object, sharding và chuẩn bị file cho downstream.
- Sinh 2D HOI từ scene 3D: cách Blender render frame điều kiện, gọi video model và quản lý kết quả 2D human-object interaction.
- Khôi phục 4D HOI có metric scale: pose, object tracking, trajectory optimization và vì sao biết trước scene giúp reconstruction ổn định hơn.
- Locomotion trên terrain tĩnh: dùng curb, slope, stairs để tạo dữ liệu đi bộ, bước lên, bước xuống và leo cầu thang.
- Retarget trajectory sang Unitree G1: chuyển motion người/object thành mục tiêu robot với ràng buộc toàn thân.
- Train policy và export dữ liệu: đóng gói demonstration, train tracker/policy và chuẩn bị dữ liệu cho sim-to-real.
Bản đồ hai nhánh asset
Hai nhánh asset phục vụ hai loại kỹ năng khác nhau. Terrain là scene-centric: robot phải đi qua hình học mặt đất. Object là object-centric: robot phải tiếp cận, định hướng tay, grasp, nâng, kéo, đẩy hoặc ngồi lên.
| Nhánh | Module | Input | Output chính | Dùng cho |
|---|---|---|---|---|
| Procedural terrain | grail.pipelines.gen_terrain |
`--type curb | slope | stairs |
| Hunyuan3D objects | grail.pipelines.gen_3d_assets |
YAML/JSON list object, OpenAI API, Hunyuan env | model.obj, model.mtl, model.jpg, ảnh trung gian |
Pickup, manipulation, sitting, object-aware policies |
Điểm đáng chú ý: nhánh terrain không cần GPU hay dịch vụ bên ngoài. Nó trực tiếp viết OBJ/MTL/texture. Nhánh Hunyuan3D thì nặng hơn: cần môi trường hunyuan, checkpoint Hunyuan3D-2.1, OpenAI API cho prompt enhancement, image generation, image verification và height estimation. Theo tài liệu Hunyuan3D, dòng model này tách bước shape generation và texture generation; GRAIL dùng đúng ý tưởng đó nhưng bọc thêm logic robotics để output dùng được trong HOI.
Nhánh 1: procedural terrain
Lệnh cơ bản:
# Tạo 300 asset cho mỗi loại: curb, slope, stairs
python -m grail.pipelines.gen_terrain \
--type all \
--num 300 \
--output_dir data/Terrain
# Tạo riêng một loại
python -m grail.pipelines.gen_terrain --type curb --num 40
python -m grail.pipelines.gen_terrain --type slope --num 100 --seed 1234
python -m grail.pipelines.gen_terrain --type stairs --num 50 --output_dir data/syn_stairs
Mỗi terrain được ghi thành một thư mục riêng:
data/Terrain/
curb_000/
model.obj
model.mtl
texture.jpg
curb_001/
model.obj
model.mtl
texture.jpg
slope_000/
model.obj
model.mtl
texture.jpg
Ba file này không phải ngẫu nhiên. model.obj chứa vertex, normal, UV và face. model.mtl khai báo material, trỏ tới texture. texture.jpg là atlas màu đơn giản để Blender/Cycles render rõ các phần hình học. Trong code, generator tạo grid texture kích thước 256, mỗi piece terrain nhận một ô màu. OBJ dùng mtllib model.mtl và usemtl terrain_material, còn MTL dùng map_Kd texture.jpg.
Curb
curb được dựng từ nhiều khối hộp có chiều cao, chiều rộng và khoảng cách thay đổi. Các range trong code cho thấy đây không phải sidewalk curb một khối duy nhất, mà là một dải obstacle có 2 đến 5 đoạn. Chiều cao nằm trong khoảng nhỏ, phù hợp bài toán bước qua/bước lên thay vì leo vật cản quá lớn. Có offset theo trục ngang để robot không chỉ đi thẳng qua một đường biên hoàn hảo.
Khi đọc kết quả, hãy tự hỏi:
- Curb có cao vừa đủ để buộc policy điều chỉnh bước chân không?
- Khoảng gap giữa các đoạn có làm robot cần chọn foot placement không?
- Mặt trên có phẳng và rõ để tránh lỗi contact bất thường không?
Nếu bạn train locomotion, curb là asset "kiểm tra phản xạ": policy phải nhận biết thay đổi độ cao ngắn, giữ thăng bằng, rồi phục hồi gait.
Slope
slope được dựng từ wedge mesh, tức mặt nghiêng extrude theo chiều ngang. Mỗi asset có 2 đến 5 segment, chiều dài và chiều rộng random, độ cao cuối segment có thể tăng hoặc giảm. Code giữ surface height tối thiểu để tránh mặt phẳng rơi xuống hoặc đi qua gốc không mong muốn.
Slope khác curb ở chỗ contact liên tục. Robot không cần đặt chân lên một bậc rời rạc, nhưng COM, torso pitch và friction margin đều bị thử thách. Trong render và simulation, slope nên có:
- bề rộng đủ cho humanoid đặt hai chân;
- độ dốc không quá cực đoan so với controller ban đầu;
- mesh sạch, không có cạnh gãy vô nghĩa ở mặt tiếp xúc.
Stairs
stairs tạo 3 đến 8 step. Mỗi step là một box, có rise và tread random; option --uniform làm rise/tread cố định trong cùng staircase. Đây là lựa chọn quan trọng:
# Cầu thang đều, dễ debug foot placement
python -m grail.pipelines.gen_terrain \
--type stairs \
--num 50 \
--uniform \
--output_dir data/syn_stairs_uniform
Với beginner, hãy dùng --uniform để kiểm tra pipeline trước. Cầu thang không đều tốt cho robustness, nhưng khi lỗi xảy ra bạn khó biết nguyên nhân nằm ở reconstruction, controller hay asset.
Vì sao code "bake" scale cho G1?
Trong gen_terrain.py, comment nói kích thước đã được pre-scale cho character retargeted theo G1, khoảng 70% chiều cao SMPL-X người. Trước đây downstream YAML có thể dùng obj_scale: [0.6, 0.6, 0.6]; giờ scale được bake vào mesh để render với obj_scale: [1.0, 1.0, 1.0].
Điều này có lợi cho beginner: khi thấy model.obj, bạn có thể giả định nó đã ở scale phù hợp với G1 trong ngữ cảnh GRAIL. Không nên tùy tiện scale terrain lại trong Blender chỉ vì nhìn "hơi thấp" trên viewport. Hãy kiểm tra bằng đơn vị mét và robot height, không kiểm tra bằng cảm giác thẩm mỹ.
Nhánh 2: Hunyuan3D object assets
Lệnh smoke test:
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/example_objects.yaml \
-o data/gen_example
File example_objects.yaml là list 6 item:
- Wooden dining chair with slat back
- Metal bar stool with wooden seat
- Classic leather armchair brown
- Cordless power drill
- Red ceramic coffee mug
- Hardcover book standing upright
File chairs.yaml có 70 biến thể ghế, từ chair iconic, traditional, rustic, modern, industrial đến outdoor. Đây là config quan trọng cho sitting demos, vì ghế cần vừa là object rõ hình học, vừa có contact surface cho người/robot ngồi.
Về mặt thao tác, gen_3d_assets không đưa prompt thô trực tiếp vào Hunyuan3D rồi chờ mesh. Pipeline thực tế có nhiều bước hơn:
- Đọc YAML/JSON và sort danh sách object.
- Chia job nếu có
--num_job_chunksvà--job_chunk_idx. - Dùng OpenAI chat để rewrite prompt theo phong cách phù hợp 3D reconstruction.
- Tạo ảnh tham chiếu 1024 x 1024.
- Dùng vision model kiểm tra ảnh có khớp mô tả và phù hợp HOI không.
- Xóa nền, resize object vào canvas 512 x 512.
- Chạy Hunyuan3D shape generation, lưu
mesh.glb. - Chạy Hunyuan3D paint, xuất textured
model.objvà material. - Ước lượng chiều cao thực tế bằng vision model.
- Scale vertex trong
model.objđể chiều cao mesh khớp height estimate. - Dọn file trung gian, giữ các file cần thiết.
Output cuối thường nằm theo slug object:
data/gen_example/
cordless_power_drill/
model.obj
model.mtl
model.jpg
generated_512.png
generated_raw.png
red_ceramic_coffee_mug/
model.obj
model.mtl
model.jpg
generated_512.png
generated_raw.png
model_original.obj có thể được giữ làm backup nếu pipeline đã scale model.obj. Khi debug scale, hãy so sánh bounding box giữa model_original.obj và model.obj.
Cách chọn prompt để tránh failure mode
Prompt tốt trong robotics khác prompt tốt cho hình ảnh marketing. Bạn không cần asset "ngầu"; bạn cần asset có geometry rõ, scale hợp lý, pose canonical và không làm hỏng contact.
| Nên chọn | Vì sao |
|---|---|
| Object cứng, một khối rigid | Hunyuan3D xuất single mesh; downstream giả định object không có articulation thật |
| Kích thước lớn nhất khoảng 5-150 cm | Đủ thấy trong render, vừa workspace người/robot |
| Bề mặt có đặc trưng bất đối xứng | FoundationPose dễ khóa orientation hơn |
| Object có chân, đáy hoặc mặt tiếp xúc tự nhiên | Giảm rủi ro base ảo cắt vào bàn/sàn |
| Mô tả vật liệu và hình dáng cụ thể | Ảnh tham chiếu nhất quán hơn, texture dễ nhận dạng hơn |
| Nên tránh | Failure mode |
|---|---|
| Spoons, screws, paperclips, single coins | Quá nhỏ trong render 1280 x 720, contact khó rõ |
| Fridge, sofa lớn, vehicle | Quá lớn cho indoor scene và reachable workspace |
| Scissors, drawers, foldable chairs, fridge doors | Articulation bị bake thành mesh cứng |
| Plain sphere, generic ball, orb | Đối xứng quay, 6D pose orientation bị suy biến |
| "Minimalist cube", "pedestal", "display block" | Dễ sinh plinth/base ảo dưới object |
Ví dụ prompt yếu và prompt tốt hơn:
# Yếu: quá chung, dễ sinh vật thể đối xứng hoặc base lạ
- Cube stool
- Ball
- Tool
- Chair
# Tốt hơn: có scale, vật liệu, front/back, contact surface
- Compact concrete cube side table on four small recessed rubber feet
- Soccer ball with visible panel seams and asymmetric colored logo
- Cordless power drill with black rubber grip and red battery pack
- Wooden dining chair with slat back and four straight legs
Một mẹo thực dụng: hãy tưởng tượng bạn phải đặt trục object bằng tay trong Blender. Nếu prompt không cho bạn biết đâu là mặt trước, đâu là đáy, đâu là phần robot sẽ chạm, prompt đó chưa đủ tốt.
Shard generation bằng job chunks
Tạo 70 ghế hoặc vài trăm object trên một GPU sẽ mất thời gian. gen_3d_assets hỗ trợ chia việc bằng slicing:
python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml \
-o data/gen_chairs \
--num_job_chunks 4 \
--job_chunk_idx 0
Chạy song song trên 4 worker:
# Worker 0
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml -o data/gen_chairs \
--num_job_chunks 4 --job_chunk_idx 0
# Worker 1
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml -o data/gen_chairs \
--num_job_chunks 4 --job_chunk_idx 1
# Worker 2
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml -o data/gen_chairs \
--num_job_chunks 4 --job_chunk_idx 2
# Worker 3
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml -o data/gen_chairs \
--num_job_chunks 4 --job_chunk_idx 3
Trong code, danh sách object được sort rồi lấy objects[job_chunk_idx :: num_job_chunks]. Vì vậy cùng input, cùng số chunk và cùng output sẽ ổn định. Nếu một worker chết giữa chừng, mặc định pipeline skip object đã có model.obj. Bạn có thể chạy lại cùng lệnh để tiếp tục.
Checklist khi shard:
- Dùng cùng
-ivà-ocho mọi worker. - Đảm bảo
job_chunk_idxchạy từ0đếnN - 1, không chạyN. - Không đổi nội dung YAML giữa lúc các worker đang chạy.
- Theo dõi quota OpenAI API vì mỗi object có thể gọi chat, image và vision nhiều lần.
- Nếu cần regenerate asset đã tồn tại, dùng
--no-skip-existing, nhưng chỉ nên dùng cho batch nhỏ.
Chuẩn bị asset cho Blender
GRAIL dùng Blender ở stage 2D HOI để render scene điều kiện. Với asset terrain/object, các lỗi thường gặp là đường dẫn texture sai, normal xấu, object không ở origin, hoặc scale lệch.
Checklist nhanh:
[ ] Thư mục object có model.obj, model.mtl, texture/model.jpg.
[ ] MTL dùng đường dẫn relative, không trỏ về máy cá nhân.
[ ] Bounding box theo mét hợp lý với mô tả object.
[ ] Đáy object nằm gần mặt sàn, không bay hoặc chìm.
[ ] Mesh có front/back rõ nếu task cần approach direction.
[ ] Texture không toàn trắng/đen, đủ feature để render và tracking.
Với terrain procedural, hãy ưu tiên giữ nguyên output. Với Hunyuan3D object, bạn có thể mở nhanh trong Blender để kiểm tra scale và orientation, nhưng không nên chỉnh sửa thủ công hàng loạt nếu chưa lưu lại quy tắc. Pipeline dữ liệu cần reproducibility; chỉnh tay một vài asset có thể làm bạn khó debug về sau.
Chuẩn bị cho FoundationPose
FoundationPose là model 6D pose estimation/tracking có thể dùng CAD/mesh model hoặc reference images. Với GRAIL, điều đó nghĩa là mesh không chỉ để render đẹp; nó còn giúp object pose trở nên quan sát được. Nếu object tròn hoàn toàn, một pose quay 0 độ và 90 độ có thể nhìn giống nhau. Tracker không có đủ tín hiệu để biết orientation đúng.
Để thân thiện với FoundationPose:
- chọn object bất đối xứng hoặc có texture định hướng;
- tránh surface quá bóng nếu render gây highlight giả;
- giữ model ở scale thực, vì pose metric cần khớp scene;
- tránh mesh có chi tiết mảnh dễ biến mất sau resize;
- giữ ảnh
generated_raw.pngvàgenerated_512.pngđể kiểm tra vì sao mesh có hình dạng như vậy.
Một cái mug đỏ có quai là object tốt hơn một cái cốc trụ trắng trơn. Một cordless drill có pin màu khác grip tốt hơn một khối hộp "toolbox" không có front rõ.
Chuẩn bị cho Isaac Lab
Isaac Lab có thể spawn asset từ USD, URDF hoặc OBJ trong scene; tài liệu Isaac Lab cũng nhấn mạnh hướng cấu hình để spawn prim và tham chiếu asset. Trong GRAIL, asset ban đầu là OBJ/MTL/texture, nhưng về sau bạn thường cần chuyển hoặc wrap sang USD để simulation ổn định hơn, đặc biệt khi thêm collision, mass, friction và material physics.
Beginner hay nhầm visual mesh với collision mesh. Visual mesh có thể nhiều triangle, lỗ nhỏ, texture đẹp. Collision mesh nên đơn giản, kín, ổn định và phù hợp contact. Với object nhỏ như drill/mug/book, collision convex hoặc decomposition đơn giản thường tốt hơn dùng trực tiếp mesh visual. Với stairs/curb/slope, collision cần khớp mặt bước và mặt nghiêng, vì sai vài centimet cũng đủ làm foot contact nhiễu.
Checklist Isaac Lab:
[ ] Asset có scale mét đúng trước khi chuyển USD.
[ ] Up-axis và origin được kiểm tra trong tool chuyển đổi.
[ ] Collision mesh không quá phức tạp.
[ ] Mass/friction/restitution được đặt theo task.
[ ] Terrain không có mặt ngược normal hoặc non-manifold rõ ràng.
[ ] Object không có base ảo làm robot chạm sai vị trí.
Nếu bạn cần nền tảng Isaac Lab từ đầu, xem thêm NVIDIA Isaac Lab: GPU-accelerated RL training từ zero. Nếu mục tiêu là policy whole-body với G1 và dữ liệu thị giác, bài GR00T Visual Sim-to-Real trên G1 và Isaac Lab là mảnh ghép ngoài series rất gần GRAIL.
Workflow khuyến nghị cho người mới
Đừng bắt đầu bằng 70 ghế. Hãy chạy một batch nhỏ, kiểm tra file, rồi mới shard.
# 1. Terrain nhỏ để kiểm tra output path
python -m grail.pipelines.gen_terrain \
--type stairs \
--num 3 \
--uniform \
--output_dir data/debug_stairs
# 2. Object smoke test
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/example_objects.yaml \
-o data/debug_objects \
--max-image-retries 2
# 3. Chair batch sau khi smoke test ổn
conda run -n hunyuan python -m grail.pipelines.gen_3d_assets \
-i configs/gen_3d/chairs.yaml \
-o data/gen_chairs \
--num_job_chunks 2 \
--job_chunk_idx 0
Sau mỗi bước, kiểm tra:
find data/debug_stairs -maxdepth 2 -type f | sort
find data/debug_objects -maxdepth 2 -type f | sort
Bạn muốn thấy cấu trúc file nhất quán trước khi đưa sang Blender hoặc reconstruction. Nếu thiếu model.mtl, texture không load. Nếu thiếu model.obj, downstream gần như chắc chắn fail. Nếu object folder có ảnh raw trông sai prompt, regenerate object đó trước khi tốn thêm thời gian ở HOI.
Nguồn kỹ thuật
Các điểm chính trong bài dựa trên tài liệu và code công khai của NVlabs/GRAIL, trang dự án GRAIL, tài liệu Hunyuan3D-2, repo FoundationPose và tài liệu Isaac Lab spawning prims. Khi triển khai thật, hãy ưu tiên phiên bản docs đi kèm commit GRAIL bạn đang chạy, vì checkpoint, model path và Docker image có thể thay đổi.
Kết luận
Asset là bước dễ bị xem nhẹ vì nó chưa có robot chuyển động. Nhưng trong GRAIL, asset quyết định chất lượng của mọi thứ phía sau: video condition, 4D reconstruction, retargeting, tracking policy và sim-to-real. Với terrain, hãy kiểm soát loại hình học, seed, số lượng và scale G1. Với object, hãy chọn prompt rigid, bất đối xứng, đúng kích thước và có contact surface tự nhiên. Khi cần scale batch, dùng --num_job_chunks và --job_chunk_idx thay vì nhân bản config thủ công.
Bài tiếp theo sẽ đi từ asset sang scene: dùng Blender và video model để sinh 2D HOI, nơi object/terrain bắt đầu trở thành tương tác người-vật thể có thể khôi phục thành 4D trajectory.