LeRobot documentation

模拟:本地或服务

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v0.7.0).
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均使用它。

Either runs locally, through the environment API, or served by lerobot-env-server, usually in its own Docker image, so that the simulator’s dependencies never meet the policy’s. Setting an endpoint selects served execution; both paths expose the same canonical observations (HWC uint8 images, flat float32 state), episode ends, and control conventions.

代码将三层分开:

  • 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() 都会将批次中每个未完成的环境推进一次。已结束的环境会保留其终止观测,直到下一次重置;对其他环境执行步进操作不会重启该环境。使用 --eval.use_async_envs=true(默认值)时,每个环境都在其自身的 worker 进程中运行,无论是在本地还是在服务器上,批次都会并行步进。服务器每个批次最多接受 max_envs 个环境(默认为 32)。--env.server.encoding=jpeg(或 --robot.env.server.encoding=jpeg,配合 --env.server.jpeg_quality,默认为 90)会将提供的相机帧作为 JPEG 发送:对于远程服务器,这意味着更小的响应和更大的批次,但代价是编码时间和有损帧。在 localhost 上,原始帧速度更快。响应携带批次中每个环境的帧,并且必须在两端都符合 max_payload_bytes(默认为 32 MiB),否则服务器在打开批次时会拒绝该批次。对于大批次或高分辨率相机,请在服务器端(YAML 的 zenoh 部分中的 max_payload_bytes,位于 listen_endpoints 旁边)和客户端(--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。
  • 某些策略需要环境的处理器(LIBERO 上的 XVLA 和 Cosmos3,Isaac Lab Arena)。lerobot-eval 会应用它们,使用 --inference.type=sync 的仿真机器人也会。远程推理不会,因此会在启动时拒绝此类检查点。
  • --robot.env.server.endpoint=tcp/... 用于在环境服务器上驱动环境,其作用类似于 --env.server.endpoint 对批量环境的作用。机器人会检查服务器是否正在运行该环境。
  • 每次调用 send_action() 都会使环境恰好推进一次。读取观测、策略推理以及等待操作均不会推进模拟;现有的控制循环负责管理实际时间节奏。
  • --fps 必须等于环境的控制频率,若进行插值,则需除以 --interpolation_multiplier,因为每条指令都会使环境推进一次。在录制时,--dataset.fps 必须等于 --fps,否则 Rollout 将拒绝启动。

仿真机器人本质上仍是一个机器人:将 --robot.type=sim --robot.env.* 替换为真实跟随器的 --robot.*,其余配置保持不变。遥操作者驱动仿真机器人的方式与驱动真实跟随器相同(对于 SO-101 孪生体,使用 --teleop.type=so101_leader),前提是环境声明了跟随器的动作名称和单位;若存在不匹配,将在执行第一个动作时报告错误。lerobot-record 会将环境声明的机体存储为数据集的 robot_type(例如 LIBERO 对应 panda),若环境未声明,则存储为 sim_robot。

录制的 episode 遵循环境的规则。lerobot-record 和 episodic rollout 策略会在每个 episode 开始时重启模拟环境,并在环境 episode 结束(成功、终止或达到步数上限)或其时长耗尽时(以先到者为准)结束该环境。因此,每个录制的 episode 都是一个从初始状态开始的模拟 episode。无需手动重置,因此请使用 --dataset.reset_time_s=0 跳过 episode 之间的重置阶段,并在采用 episodic rollout 策略时同时传入 --strategy.reset_to_initial_position=false。当 episode 结束时,机器人会停止:它忽略动作并保持最终状态,且 latest 会保留最终的奖励、终止和成功状态。随后,遥操作和 base rollout 策略会开始新的 episode(该策略还会重置策略),而 replay 则停止。sentry、highlight 和 DAgger 策略目前尚不支持模拟机器人,因为它们按时间或按需录制,而非按 episode 录制;请使用 episodic 策略进行录制。真实机器人不受影响:它们的 episode 基于时间,且场景需手动重置。要评估成功率,请使用 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

使用 远程推理设置 单独启动策略服务器。其 schema 必须与经过 --rename_map 处理后的机器人观测值相匹配。在 rollout 命令中省略 --policy.path,因为策略服务器会加载检查点。对于本地 RTC,请使用 --inference.type=rtc 并配合策略的 RTC 设置。

当策略延迟时,持有模拟机器人不会推进物理模拟。模拟器故障会传播至 rollout 关闭。

提供环境

从 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}}'

有效配置保存在 $HF_LEROBOT_HOME/sim 下,因此重启容器后仍可找到该配置。切换配置会重建服务器并结束当前活动会话。若镜像缺失则会自动构建;在修改模拟器或 LeRobot 源代码后,可添加 --build=true 以重新构建镜像,或添加 --stop=true 以关闭服务器。该容器需要 Docker GPU 访问权限以进行 EGL 渲染。EnvHub 仓库通过 --envhub=<user/repo> 提供;请参阅 EnvHub 和模拟器服务器。

如果以 Vulkan 进行渲染的模拟器(例如 Isaac Sim,或如 RoboMME 中使用的 ManiSkill/SAPIEN,其镜像自带 Vulkan 文件)在容器内出现 vkCreateInstance failed 或 ERROR_INCOMPATIBLE_DRIVER 错误,而在 Docker 外部运行正常,则说明容器内拥有 NVIDIA 驱动库,但缺少指向这些库的加载器文件(/usr/share/vulkan/icd.d/nvidia_icd.json、/usr/share/glvnd/egl_vendor.d/10_nvidia.json)。NVIDIA Container Toolkit 的默认模式(由 gpus: all 使用)可能不会挂载这些文件;其 CDI 模式 则会。请通过 CDI 请求 GPU(对于 docker run 使用 --device nvidia.com/gpu=all,或在 docker/sim/compose.server.yaml 中用 devices: [nvidia.com/gpu=all] 替换 gpus: 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 分别需要各自的 torch 以支持原生规划功能和 ManiSkill;它们的 torch 安装与策略环境相互隔离。

服务器请求永远不会重试。在发生模糊超时后,客户端会失败;请关闭它并打开一个新会话。

添加基准测试

有关模拟器模块、约定、图像和 CI 集成,请参阅 添加基准测试。

Update on GitHub