LeRobot documentation

시뮬레이션: 로컬 또는 서빙

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

시뮬레이션: 로컬 또는 서빙

시뮬레이션된 환경은 두 가지 방식으로 구동될 수 있습니다:

  • 배치된 환경 (--env.*)으로: 하나의 작업을 위한 여러 환경이 각 step() 호출에 의해 함께 진행됩니다. lerobot-eval과 학습 중 평가에 사용됩니다.
  • sim robot (--robot.type=sim)로: Robot 인터페이스 뒤에 하나의 환경을 두고 실제 하드웨어와 교체 가능합니다. lerobot-rollout, lerobot-record, lerobot-teleoperate, lerobot-replay가 이를 사용합니다.

로컬에서 실행되거나, 환경 API를 통해 실행되거나, lerobot-env-server에 의해 서빙됩니다. 보통 시뮬레이터의 종속성이 정책의 종속성과 충돌하지 않도록 자체 Docker 이미지에서 실행됩니다. endpoint를 설정하면 서빙 실행이 선택되며, 두 경로 모두 동일한 정준 관찰값(HWC uint8 이미지, 평탄한 float32 상태), 에피소드 종료 조건 및 제어 규약을 노출합니다.

코드는 세 가지 계층을 분리합니다:

  • env(lerobot.envs, --env.type)는 LeRobot 명령이 실행하는 대상이며, EnvConfig로 구성됩니다. 모든 env가 시뮬레이터는 아닙니다. gym_manipulator는 실제 로봇을 제어합니다.
  • sim(lerobot.sim)은 시뮬레이션된 환경 뒤의 시뮬레이터입니다. 통합을 지정하는 SimConfig를 가지며, LocalVectorEnv에 의해 단계가 진행되고 torch를 사용하지 않습니다.
  • env server(lerobot.env_server)는 시뮬레이션을 제공합니다. RemoteVectorEnv는 LocalVectorEnv와 동일한 API를 사용하여 이를 제어합니다.

체크포인트 평가

로컬에서는 LeRobot 옆에 시뮬레이터를 설치해야 합니다(LIBERO 참고):

lerobot-eval \
  --policy.path=lerobot/smolvla_libero \
  --policy.pretrained_revision=a24f1f380461b665158d52acd140152c79e8b36d \
  --policy.device=cuda \
  --env.type=libero --env.task=libero_spatial --env.task_ids='[0]' \
  --rename_map='{"observation.images.image": "observation.images.camera1", "observation.images.image2": "observation.images.camera2"}' \
  --eval.n_episodes=1 --eval.batch_size=1 \
  --output_dir=outputs/eval_libero

Served: 동일한 환경으로 서버를 시작합니다(환경 서빙 참조)하고, 해당 엔드포인트를 추가합니다:

lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true
lerobot-eval ... --env.server.endpoint=tcp/127.0.0.1:7448

서버의 모든 옵션은 --env.server.* 아래에 있으며, 로컬 실행에는 적용되지 않습니다. 클라이언트는 서버 구성에서 지정한 이름으로 --env.type에 따라 배포를 요청합니다. 다른 배포를 사용하려면 --env.server.deployment를 전달하세요. 잘못된 엔드포인트 또는 배포는 --env.server.handshake_timeout_s(10초) 이내에 실패하며, 해당 엔드포인트가 제공하는 내용을 명시합니다. TLS로 보호된 서버에 대해 원격 추론과 마찬가지로 --env.server.zenoh_config_path로 해당 Zenoh JSON5 파일을 전달하세요. 서버는 명령이 설명하는 환경을 실행해야 합니다: 동일한 유형, 작업, 제어 규칙 및 시뮬레이션된 본체(robot_type)가 아니면 평가가 시작을 거부하고 차이를 나열합니다. 다른 옵션의 차이(해상도, 에피소드 길이)는 경고로 기록됩니다.

관찰 이름은 환경에서 가져옵니다(observation.images.<camera>, observation.state). 체크포인트가 다른 카메라 이름으로 학습된 경우, 모든 로봇과 마찬가지로 --rename_map으로 이름을 매핑하고, 여러 카메라가 동일한 형태를 가질 때도 각 카메라의 정체성을 유지하세요. 플레이스홀더 카메라(empty_cameras)는 체크포인트와 함께 저장되는 정책 설정이며, 필요한 경우에만 --policy.empty_cameras로 오버라이드하세요.

첫 단계 전에, 이름 변경 후 모든 체크포인트 입력이 환경에 존재해야 하며, 상태 및 동작 차원과 RGB 채널 수가 일치해야 합니다. 이미지의 높이와 너비는 다를 수 있습니다. 리사이즈는 정책 전처리에서 담당합니다. 컨트롤러 규약(델타 동작 대 절대 동작, 회전 형식)은 검사되지 않습니다. 환경의 규약으로 학습된 체크포인트를 사용하세요.

각 step()은 배치 내 모든 미완료 환경을 한 번씩 진행합니다. 종료된 환경은 다음 reset까지 터미널 관측값을 유지하며, 다른 환경을 step해도 해당 환경이 다시 시작되지 않습니다. --eval.use_async_envs=true(기본값)을 사용하면 각 환경은 로컬 또는 서버에서 자체 워커 프로세스로 실행되며, 배치는 병렬로 step됩니다. 서버는 배치당 최대 max_envs개의 환경을 허용합니다(기본값 32). --env.server.encoding=jpeg(또는 --env.server.jpeg_quality와 함께 --robot.env.server.encoding=jpeg, 기본값 90)를 사용하면 제공되는 카메라 프레임을 JPEG로 전송합니다. 원격 서버의 경우 응답 크기가 작아져 더 큰 배치를 처리할 수 있지만, 인코딩 시간 증가와 손실 압축 프레임이라는 단점이 있습니다. 로컬호스트에서는 원시 프레임이 더 빠릅니다. 응답에는 배치 내 모든 환경의 프레임이 포함되며, 양쪽 끝에서 max_payload_bytes(기본값 32 MiB)에 맞아야 하며, 그렇지 않으면 서버가 배치 열기 시 배치를 거부합니다. 큰 배치나 고해상도 카메라를 사용하는 경우, 서버(YAML의 zenoh 섹션에서 listen_endpoints 옆에 있는 max_payload_bytes)와 클라이언트(--env.server.max_payload_bytes 또는 --robot.env.server.max_payload_bytes)에서 해당 값을 높여야 합니다.

시뮬레이션 로봇 실행

batched env와 sim robot과 동일한 환경:

lerobot-eval    --env.type=libero --env.task=libero_spatial --env.task_ids='[0]' ...
lerobot-rollout --robot.type=sim --robot.env.type=libero --robot.env.task=libero_spatial --robot.task_id=0 ...

예를 들어:

lerobot-rollout \
  --robot.type=sim --robot.env.type=libero --robot.env.task=libero_spatial --robot.task_id=0 \
  --task="pick up the black bowl between the plate and the ramekin and place it on the plate" \
  --policy.path=lerobot/smolvla_libero \
  --policy.pretrained_revision=a24f1f380461b665158d52acd140152c79e8b36d \
  --rename_map='{"observation.images.image": "observation.images.camera1", "observation.images.image2": "observation.images.camera2"}' \
  --device=cuda --fps=20 --inference.type=sync \
  --display_data=true --display_mode=rerun \
  --return_to_initial_position=false --play_sounds=false
  • --robot.env.*는 평가에서 --env.*와 동일한 옵션을 사용합니다. --robot.task_id는 로봇이 실행할 단일 작업을 선택하며, 평가에서는 스위트의 모든 작업 또는 --env.task_ids에 포함된 작업을 실행합니다. EnvHub 환경은 --robot.env.type=envhub --robot.env.hub_path=<user/repo> --robot.env.trust_remote_code=true입니다.
  • 일부 정책은 환경의 프로세서가 필요합니다(XVLA와 Cosmos3의 경우 LIBERO, Isaac Lab Arena). lerobot-eval은 이를 적용하며, --inference.type=sync을 사용하는 시뮬레이션 로봇도 마찬가지입니다. 원격 추론은 이를 적용하지 않으므로, 시작 시 이러한 체크포인트를 거부합니다.
  • --robot.env.server.endpoint=tcp/...은 --env.server.endpoint이 배치된 환경에 대해 수행하는 것과 유사하게, 로봇 환경을 env 서버에서 구동합니다. 로봇은 해당 서버가 해당 환경을 실행하는지 확인합니다.
  • 각 send_action()은 환경을 정확히 한 번만 진행시킵니다. 관측 읽기, 정책 추론, 대기 동작은 시뮬레이션을 진행하지 않으며, 기존 제어 루프가 실제 시간 배치를 담당합니다.
  • --fps는 모든 명령이 환경을 한 번씩 진행시키기 때문에 보간을 수행하는 경우 --interpolation_multiplier로 나눈 환경의 제어 속도와 같아야 합니다. 녹화 시에는 --dataset.fps가 --fps와 같아야 합니다. 그렇지 않으면 Rollout이 시작되지 않습니다.

Sim robot은 robot입니다: --robot.type=sim --robot.env.*를 실제 follower의 --robot.*로 교체하면 나머지는 그대로 유지됩니다. Teleoperator는 실제 follower를 조작하는 것과 동일한 방식으로 이를 조작하며(--teleop.type=so101_leader는 SO-101 twin의 경우), 환경이 follower의 action 이름과 단위를 선언할 때 동작합니다. 불일치가 발생하면 첫 번째 action에서 보고됩니다. lerobot-record는 환경이 선언한 body를 dataset의 robot_type로 저장합니다(LIBERO의 경우 panda), 선언된 것이 없으면 sim_robot로 저장합니다.

녹화된 에피소드는 환경의 에피소드를 따릅니다. lerobot-record와 episodic rollout 전략은 각 에피소드 시작 시 시뮬레이션 환경을 재시작하고, 환경의 에피소드가 종료될 때(성공, 종료 또는 스텝 제한) 또는 지속 시간이 만료될 때(둘 중 먼저 발생하는 경우) 환경을 종료합니다. 따라서 각 녹화된 에피소드는 초기 상태에서 시작되는 하나의 시뮬레이션 에피소드입니다. 수동으로 초기화할 필요가 없으므로, 에피소드 사이의 reset 단계를 --dataset.reset_time_s=0으로 건너뛰고, episodic rollout 전략을 사용하는 경우 --strategy.reset_to_initial_position=false도 함께 전달하세요. 에피소드가 종료되면 로봇은 멈춥니다. 액션을 무시하고 최종 상태를 유지하며, latest는 최종 보상, 종료 및 성공 상태를 유지합니다. 이후 Teleoperation과 base rollout 전략이 새로운 에피소드를 시작합니다(전략은 정책도 초기화하며), replay는 중단됩니다. sentry, highlight, DAgger 전략은 아직 시뮬레이션 로봇을 지원하지 않습니다. 에피소드별로 녹화하는 것이 아니라 시간 또는 요청 기반으로 녹화하기 때문입니다. 녹화를 위해 episodic 전략을 사용하세요. 실제 로봇에는 영향이 없습니다. 실제 로봇의 에피소드는 시간 기반으로 측정되며, 씬은 수동으로 초기화됩니다. 성공률을 평가하려면 lerobot-eval과 배치된 환경을 사용하세요.

로봇 카메라 기능은 실제 하드웨어 녹화와 동일한 observation.images.<camera> 이름을 사용합니다. 이름이 없는 단일 카메라는 observation.images.image입니다. 배치 평가에서는 단일 카메라의 경우 observation.image와 같이 환경 자체의 키를 유지합니다. 해당 이름의 체크포인트를 SimRobot을 통해 배포할 때는 --rename_map='{"observation.images.image": "observation.image"}'를 사용하세요.

원격 추론의 경우, 동일한 --robot.* 옵션을 유지하고 로컬 정책 및 추론 옵션을 다음으로 교체합니다:

--inference.type=remote \
--inference.endpoint=tcp/127.0.0.1:7447 \
--inference.deployment=libero \
--inference.semantics=libero-delta-v1

remote inference setup를 사용하여 정책 서버를 별도로 시작합니다. 스키마는 --rename_map 적용 후 로봇의 관측값과 일치해야 합니다. 정책 서버가 체크포인트를 로드하므로 rollout 명령에서 --policy.path를 생략합니다. 로컬 RTC의 경우, 정책의 RTC 설정과 함께 --inference.type=rtc를 사용합니다.

정책이 지연되면 시뮬레이션 로봇을 보유하더라도 물리 시뮬레이션이 진행되지 않습니다. 시뮬레이터 실패는 롤아웃 종료로 전파됩니다.

환경 서빙

LeRobot 소스 체크아웃(이미지가 이 소스로 빌드됨)에서 저장소 루트 디렉터리에서 다음을 실행합니다:

lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true

--docker=true는 docker/sim/compose.server.yaml을 사용하며, sim.type에서 이미지를 선택하고, 유효한 YAML을 마운트한 뒤 호스트 네트워크에서 컨테이너를 실행합니다. 따라서 --zenoh.listen_endpoints에 다른 설정이 없는 한 서버는 localhost:7448에서 리스닝합니다. 다른 시뮬레이터를 선택하려면 YAML을 교체하세요. 각 시뮬레이터의 제어 주기, 액션 규약, 컴포넌트 이름 및 로봇 유형은 해당 통합의 conventions()에서 가져오므로, YAML에는 작업 이름과 시뮬레이터 옵션만 명시하면 됩니다.

lerobot-policy-server의 경우 모든 YAML 필드가 중첩된 커맨드 라인 오버라이드를 지원하며, 파일은 변경되지 않습니다. sim.kwargs와 같은 딕셔너리 값은 YAML의 다음 값과 병합됩니다:

lerobot-env-server --config_path=docker/sim/configs/libero.yaml --docker=true \
  --sim.task=libero_goal \
  --sim.kwargs='{gym_kwargs: {observation_height: 256, observation_width: 256}}'

The effective configuration is kept under $HF_LEROBOT_HOME/sim, so a restarted container finds it. Switching configuration recreates the server and ends active sessions. The image is built when missing; add --build=true to rebuild it after changing the simulator or LeRobot source, or --stop=true to shut down the server. The container requires Docker GPU access for EGL rendering. EnvHub repositories are served with --envhub=<user/repo>; see EnvHub and the simulator server.

Vulkan으로 렌더링하는 시뮬레이터(Isaac Sim, 또는 RoboMME의 ManiSkill/SAPIEN처럼 자체 Vulkan 파일을 포함하는 이미지를 사용하는 경우)가 Docker 컨테이너 외부에서는 정상 작동하지만 컨테이너 내에서 vkCreateInstance failed 또는 ERROR_INCOMPATIBLE_DRIVER 오류로 실패한다면, 컨테이너에는 NVIDIA 드라이버 라이브러리는 있지만 해당 라이브러리를 가리키는 로더 파일(/usr/share/vulkan/icd.d/nvidia_icd.json, /usr/share/glvnd/egl_vendor.d/10_nvidia.json)이 없는 상태입니다. gpus: all에서 사용되는 NVIDIA Container Toolkit의 기본 모드에서는 이러한 파일이 마운트되지 않을 수 있지만, CDI 모드에서는 마운트됩니다. CDI를 통해 GPU를 요청하세요(docker run의 경우 --device nvidia.com/gpu=all, docker/sim/compose.server.yaml의 gpus: all 대신 devices: [nvidia.com/gpu=all] 사용) 또는 두 파일을 이미지에 추가하세요.

--docker=true 없이 실행하면 동일한 명령이 현재 환경에서 서버를 실행합니다. 이 경우 시뮬레이터의 네이티브 종속성을 격리된 환경에 설치하고, --no-deps 옵션으로 LeRobot을 설치한 뒤 docker/sim/requirements.txt를 설치합니다. 어느 경우든 localhost에서 리스닝합니다. 다른 머신에서 접속을 허용하려면 해당 머신이 도달할 수 있는 네트워크 인터페이스의 주소를 전달해야 하며, 예를 들어 --zenoh.listen_endpoints='[tcp/192.168.1.20:7448]'처럼 지정합니다. 또한 YAML에 zenoh.config_file을 추가하여 TLS와 액세스 제어를 구성할 수 있습니다.

LIBERO 런타임 이미지는 변환된 NumPy 초기 상태 파일을 사용합니다. 이미지 빌드는 scripts/ci/convert_libero_init_states.py를 사용하여 신뢰할 수 있는 업스트림 자산을 변환하며, 서버는 변환된 파일이 누락된 경우 거부합니다. RoboTwin과 RoboMME은 각각 네이티브 플래닝과 ManiSkill을 위해 자체 torch가 필요하며, 해당 torch 설치 환경은 정책 환경과 격리되어 있습니다.

Server 요청은 절대 재시도되지 않습니다. 모호한 타임아웃이 발생하면 클라이언트가 실패하며, 이 경우 클라이언트를 닫고 새 세션을 열어야 합니다.

벤치마크 추가

시뮬레이터 모듈, 컨벤션, 이미지 및 CI 통합에 대한 내용은 벤치마크 추가를 참고하세요.

Update on GitHub