LeRobot documentation
模拟:本地或服务
模拟:本地或服务
模拟环境可以通过两种方式驱动:
- 作为批量环境(
--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_liberoServed:使用相同的环境启动服务器(参见 提供环境),并添加其端点:
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