
오늘은 요즘 AI 분야에서 핫한 키워드 중 하나인 VLA(Vision-Language-Action) 튜토리얼 가이드를 적어보려고 한다.
실물 로봇이 없어도 할 수 있는 방법으로, Isaac Sim에서 오픈소스 VLA 모델인 Isaac-Gr00t를 파인튜닝하고, LeIsaac에 셋팅된 환경 태스크(Orange PickNPlace)를 수행하는 과정을 정리한다.
사실 train 코드는 LeRobot이나 Gr00t 깃허브에 제공되어 있기 때문에 (호환되는 오픈소스 VLA를 파인튜닝한다는 전제로), 실제로 활용할 때는 어떻게 데이터를 수집하고 학습 데이터 형식을 맞춰 주는 것이 더 중요하다.
하지만 이번 포스팅에서는 VLA 모델을 로봇에 맞게 튜닝하고 적용해 보는것에 초점을 맞춘다.
추후 시간이 된다면, 커스텀 데이터 수집과 데이터 포맷팅, 그리고 다른 오픈 소스 VLA 파인튜닝도 작성해 보겠다 ! (이거 하려고 조이스틱 삼 ㅎ)
먼저 두 개의 가상환경을 준비한다. 왜 귀찮게 2개씩이나? 할 수 있지만 해보면 안다.. 하나로 하는게 훨씬 더 귀찮을 수도 있다. (왜인지는 나도 알고 싶지 않았다.. )
- Leisaac Installation
Leisaac 공식 도큐먼트의 설치 가이드 참조
- Gr00t Installation
Isaac Gr00t 깃헙 참조
LeRobot은 하드웨어 리소스 관리, 효율성 등의 측면에서 Policy Server(모델 추론) 와 Client(Isaac Sim 내부 로봇 제어)를 분리하여 두고, API를 통해 서로 통신하도록 되어 있다.
Leisaac 또한 LeRobot 구조를 기반으로 하므로, Gr00t가 서버, Leisaac이 클라이언트 역할로 따로 실행되기 때문에 괜히 pip install 갈겼다가 의존성 충돌 날 걱정 없이 가상환경 따로 구축해서 쓰면 된다.
여기서 VLA로 수행해 볼 태스크는 Leisaac에서 지원하고 있는, Kitchen 환경에서 Orange를 집어 접시로 옮기는 태스크(LeIsaac-SO101-PickOrange-v0)이다.
가상환경 설정이 완료되었으면 로컬에 leisaac repo가 클론되어있을 텐데, 그 안에 에셋 파일들을 다운받아서 아래와 같이 셋팅해주면 된다.

현재 leisaac (v0.2.0) 기준으로 웬만한 정보는 leisaac 도큐먼트로 넘어가고, 깃허브 리드미에서 링크로 에셋을 받을 수 있었는데 그게 없어졌다. 이전 버전 릴리즈 링크 <여기>에서 leisaac-example-scene (v0.1.0) 의 asset 압축 파일(kitchen_with_orange.zip)과 usd (so101_follower.usd)를 내려 받으면 된다. (아래 참조)

물론 teleop으로 데이터를 직접 수집해도 되지만, 여기서는 허깅페이스에 이미 올라온 데이터셋을 활용하기로 한다. teleop으로 데이터 직접 수집하는 방법은 이제 <여기>를 참조...
- 학습할 데이터 다운로드 (leisaac-pick-orange)
lsaac-Gr00t의demo_data디렉토리 내부에 데이터를 다운로드한다. (아래 커맨드 실행 전,huggingface-cli에 로그인 되어 있어야 함)
huggingface-cli download --repo-type dataset LightwheelAI/leisaac-pick-orange --local-dir ./demo_data/leisaac-pick-orange
간단하게 데이터 구조와 형식을 살펴보면 아래와 같다.

data 폴더 : 데이터셋 분할(chunk) 단위에 각 episode 수행 과정 정보가 .parquet 형식으로 저장되어 있음. chunk를 쓰는 이유는 대용량 데이터 관리를 위함인데 위 데이터셋은 총 에피소드 개수가 많지 않기 때문에 chunk가 1개 뿐이다.
meta 폴더 : 여기에 수집된 데이터셋 핵심 정보가 들어 있는데, meta/info.json을 보면 robot_type, 총 에피소드와 프레임, 태스크, 관절 제어값 등이 포함되어 있다. 이 meta의 형식은 lerobot codebase 버전이나 모델에 따라 상이한 것 같다.
video 폴더 : 수행된 에피소드의 카메라 영상이 담겨져 있다. (.mp4) 위 데이터셋에서는 전방, 손목 카메라 2개 사용되었으므로 같은 에피소드에 대해 2개의 영상이 존재한다.
이제 Gr00t를 파인튜닝하기 위해 필요한 메타 데이터인 modality를 기존 Gr00t 파일에서 가져와서, /meta 디렉토리 내부에 붙여 넣어야 한다.

# 다운 받은 데이터셋 내부 /meta/ 디렉토리 안에 복사 (Gr00t 루트 디렉토리에서 진행)
cp ./examples/SO-100/so100_dualcam__modality.json ./demo_data/leisaac-pick-orange/meta/modality.json
파인튜닝 전 데이터가 잘 설정 되었는지 디버깅을 해볼 수 있는데, 아래 명령어를 실행하면 된다 (modality 복붙 후 실행).
python scripts/load_dataset.py --dataset-path ./demo_data/leisaac-pick-orange/ --plot-state-action --video-backend torchvision_av

로딩이 잘 됐으면 위 사진처럼 학습 데이터 시각화 화면이 플로팅된다.
위 디버깅 단계에서 이상이 없었다면 이제 튜닝을 할 차례~
아래 명령어로 이제 학습을 돌려볼 수 있다.
python3 scripts/gr00t_finetune.py --dataset-path ./demo_data/leisaac-pick-orange/ --num-gpus 1 --output-dir ./so101-checkpoints --max-steps 10000 --data-config so100_dualcam --video-backend torchvision_av
wandb를 활성화한 경우, 아래처럼 학습 과정에서 train loss나 gpu usage 등을 대시보드형태로 모니터링할 수 있다.

위 옵션대로 10000 스텝 학습할 때 5090 기준 한시간 반? 정도 소요된 듯
학습을 했으면 평가를 해야겠지? 아래 코드로 사용한 so-arm 모델이 6-DoF 이기 때문에 6개의 action space에 대해서 GT/Pred를 비교하고, 시각화 해 볼 수 있다.
python scripts/eval_policy.py --plot \
--embodiment_tag new_embodiment \
--model_path ./so101-checkpoints \
--data_config so100_dualcam \
--dataset_path ./demo_data/leisaac-pick-orange/ \
--video_backend torchvision_av \
--modality_keys single_arm gripper

자 이제 학습한 모델을 inference server에 올리고, Sim에서 태스크가 잘 수행되는지 관찰해 볼 차례이다.
python3 scripts/inference_service.py --server --model_path ./so101-checkpoints --embodiment-tag new_embodiment --data-config so100_dualcam --denoising-steps 4
python scripts/evaluation/policy_inference.py \
--task=LeIsaac-SO101-PickOrange-v0 \
--eval_rounds=10 \
--policy_type=gr00tn1.5 \
--policy_host=localhost \
--policy_port=5555 \
--policy_timeout_ms=5000 \
--policy_action_horizon=16 \
--policy_language_instruction="Pick up the orange and place it on the plate" \
--device=cuda \
--enable_cameras

위 옵션으로 하면 eval_round 횟수 동안 에피소드를 수행하고, 평가하게 되는데 (타임아웃 되면 실패로 처리됨) 허깅페이스 데이터셋으로 학습하면 에피소드 수가 적어서 그런지 성공률은.... pretty 처참쓰


그래도 나름 발발거리면서 움직이는게 귀여움...ㅋ
다음엔 커스텀 데이터셋 수집해서 학습하고, 궁극적으로는 커스텀 환경도 셋팅해서 굴려보려고 한다.
아래 블로그 포스팅은 심 환경은 아니고, 실물 로봇으로 gr00t 파인튜닝 한 건데 참조하면 좋다.