Pi 0.5 / OpenPI 接入#

项目提供基于 OpenPI 的 Pi 0.5 数据适配、微调和远程推理示例。本章说明数据如何对齐,以及接入时需要核对的文件。它使用独立 OpenPI 路径,与 LeRobot 内置同名策略的运行方式不同。

重要

现有示例仍引用旧 LeKiwiClient 和 lekiwi_host 接口,而当前统一软件导出的是 AlohaMiniClient 与 alohamini_host。此外,示例 README 提到的 scripts/serve_policy_http.py 不在该示例目录中。因此本章作为进阶接入说明;在补齐版本匹配和服务启动入口之前,不将原始部署命令标为当前版本可直接执行的官方流程。

1. 系统由哪几部分组成#

部分

作用

已采集的 LeRobot 数据集

提供图像、状态、动作和任务描述

OpenPI 训练环境

加载 Pi 0.5 基础权重并微调

数据适配器

把机器人字段映射到示例使用的模型接口

HTTP 策略服务

接收当前观测,返回动作或动作序列

本地执行客户端

获取真机观测,调用服务,再发送动作

机器人 Host

驱动实际硬件与回传状态

本节中的“18 维内部空间”指该 AlohaMini 示例适配层的空间,不能据此推断所有 Pi 0.5 配置都采用相同维度。

2. 示例文件#

目录位于 AlohaMini/examples/pi0.5_openpi/:

文件

作用

alohamini_policy.py

输入、输出和 16/18 维动作适配

data_loader.py

数据读取相关适配

http_policy_server.py

HTTP 服务实现

evaluate_bi.py

本地执行与远程策略调用示例

README.md

训练配置与历史部署说明

查看全部示例文件。这些文件需要按 OpenPI 与机器人软件的实际版本接入,单独复制 README 命令不足以完成部署。

3. 对齐机器人维度#

机器人

原始接口维度

示例适配方式

AlohaMini 1

16

加入虚拟关节位置,对齐到适配层的 18 维空间

AlohaMini 2 / Pro

18

按匹配的字段顺序直接通过

维度相同还不够,必须检查 state 和 action 的名称、顺序、坐标含义与单位。二代比一代多出的手腕关节不能通过随意补零到数组末尾来替代正确映射。

原始配置中 robot_dof 和 dataset_action_dim 应与实际数据对应。训练和执行必须采用同一种适配,输出才能正确映射回机器人。

4. 映射相机、状态与动作#

原始示例使用三个图像槽位:

OpenPI 示例键

示例中的数据集来源

cam_high

observation.images.chest,另一默认示例使用 head_top

cam_left_wrist

observation.images.wrist_left

cam_right_wrist

observation.images.wrist_right

state

observation.state

actions

action

prompt

数据中的任务描述

当前整机相机配置使用 forward 等名称,默认也没有开启胸部与左腕。接入前先读取实际数据集字段,再修改 RepackTransform,不能把上表原样套在任意数据集上。

示例强调需要映射 prompt;缺少这个字段会使训练没有按预期包含任务描述。

5. 绝对动作与增量动作#

二代 Pro 配置示例让左右臂各六个运动关节使用增量,两个夹爪、三个底盘分量与升降保持绝对表示:

delta_action_mask = [
    True, True, True, True, True, True, False,
    True, True, True, True, True, True, False,
    False, False, False, False,
]

这里的 18 个布尔值必须与适配层的字段顺序一致。输入侧 DeltaActions 和输出侧 AbsoluteActions 成对使用;只修改一侧会导致执行语义错误。

图像还涉及 BGR/RGB 和可选翻转。应对照数据实际存储及训练解码结果验证,而不是凭 OpenCV 或相机名称猜测颜色顺序。

6. 微调准备顺序#

  1. 在兼容的 OpenPI 环境中加入项目的 AlohaMini 策略适配器。

  2. 按示例在 src/openpi/training/config.py 注册数据配置和训练配置。

  3. 设置数据路径、机器人维度、图像映射与任务描述。

  4. 核对增量动作掩码及输出恢复流程。

  5. 按所用 OpenPI 版本,通过 scripts/compute_norm_stats.py 计算归一化统计。

  6. 指向实际可用的 Pi 0.5 基础权重,再开始微调。

原始二代 Pro 示例使用 action_horizon=10、num_train_steps=50000、batch_size=4、num_workers=2。这些是示例配置,不是适用于所有数据规模与设备的推荐值。

7. 远程推理的地址与数据流#

推理服务和机器人 Host 是不同的端点:server_url 指策略服务器,remote_ip 指机器人。服务部署在另一台机器时,客户端的 localhost 指向客户端自己,不能代替服务器 IP。

接入后应先验证服务能读取请求、返回正确维度与顺序的有限数值动作,再核对机器人客户端如何处理单位、预处理、过期反馈与暂停恢复。

当前服务实现返回 action、actions 与 server_timing 等字段,分别用于单步动作、动作序列和服务器耗时。使用哪个字段应由执行客户端的实际协议决定。

8. 完成兼容性检查后再上机#

需要逐一确认:

  • OpenPI 适配器导入位置与注册配置正确。

  • HTTP 启动脚本存在并加载了正确检查点。

  • 本地客户端与当前 AlohaMiniClient 接口兼容。

  • robot_model 能正确配置 16/18 维硬件。

  • 三路图像映射与实际数据一致。

  • 训练和推理采用相同的颜色、归一化与动作变换。

  • 执行阶段保留当前 Host 的控制权与反馈检查。

已经完成标准遥操作、ACT 训练和评估的用户,再进入此路径更便于区分适配问题与基础硬件问题。

9. 完整配置代码与历史部署流程#

OpenPI 配置参考 包含 LeRobotAlohaMiniDataConfig 完整定义、Pro 的 TrainConfig、远端服务和 16/18 维客户端示例。下面保留配置代码,便于逐项对照修改。

数据配置工厂#

把项目的 alohamini_policy.py 放进匹配 OpenPI 版本的策略目录,并在 src/openpi/training/config.py 中补齐相应导入与配置注册。下面代码依赖该文件已有的 dataclasses、tyro、Sequence 等上下文,不是可独立执行的脚本。

@dataclasses.dataclass(frozen=True)
class LeRobotAlohaMiniDataConfig(DataConfigFactory):
    default_prompt: str | None = None
    bgr_to_rgb: bool = False
    flip_images_hw: bool = False
    robot_dof: int = 16  # 16 or 18
    dataset_action_dim: int = 16
    use_delta_actions: bool = True

    delta_action_mask: tyro.conf.Suppress[Sequence[bool]] = dataclasses.field(
        default_factory=lambda: [True] * 18
    )

    repack_transforms: tyro.conf.Suppress[_transforms.Group] = dataclasses.field(
        default=_transforms.Group(
            inputs=[
                _transforms.RepackTransform(
                    {
                        "images": {
                            "cam_high": "observation.images.head_top",
                            "cam_left_wrist": "observation.images.wrist_left",
                            "cam_right_wrist": "observation.images.wrist_right",
                        },
                        "state": "observation.state",
                        "actions": "action",
                    }
                )
            ]
        )
    )

    action_sequence_keys: Sequence[str] = ("action",)

    @override
    def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
        if self.robot_dof not in (16, 18):
            raise ValueError(f"robot_dof must be 16 or 18, got {self.robot_dof}")

        expanded_dim = 18  # Pi0.5 internal action space
        data_transforms = _transforms.Group(
            inputs=[
                alohamini_policy.AlohaMiniInputs(bgr_to_rgb=self.bgr_to_rgb),
                alohamini_policy.AlignToPi05ActionSpace(robot_dof=self.robot_dof),
            ],
            outputs=[
                alohamini_policy.AlohaMiniOutputs(internal_dim=18, robot_dof=self.robot_dof)
            ],
        )
        if self.flip_images_hw:
            data_transforms = _transforms.Group(
                inputs=[
                    alohamini_policy.AlohaMiniInputs(bgr_to_rgb=self.bgr_to_rgb),
                    _transforms.FlipImages(flip_h=True, flip_w=True),
                    alohamini_policy.AlignToPi05ActionSpace(robot_dof=self.robot_dof),
                ],
                outputs=data_transforms.outputs,
            )

        if self.use_delta_actions:
            mask = list(self.delta_action_mask)
            if len(mask) != 18:
                raise ValueError(
                    f"delta_action_mask length must be 18, got {len(mask)}")
            data_transforms = data_transforms.push(
                inputs=[_transforms.DeltaActions(mask)],
                outputs=[_transforms.AbsoluteActions(mask)],
            )

        model_transforms = ModelTransformFactory(
            default_prompt=self.default_prompt)(model_config)

        return dataclasses.replace(
            self.create_base_config(assets_dirs, model_config),
            repack_transforms=self.repack_transforms,
            data_transforms=data_transforms,
            model_transforms=model_transforms,
            action_sequence_keys=self.action_sequence_keys,
        )

Pro 训练配置#

以下配置条目,需要放入相应配置集合。name="alohamini2pro" 是 OpenPI 训练配置名;它与整机 Host 的 robot_model 属于不同程序的参数。

TrainConfig(
        name="alohamini2pro",
        model=pi0_config.Pi0Config(pi05=True, action_horizon=10),
        data=LeRobotAlohaMiniDataConfig(
            repo_id="/path/to/your/dataset_root",
            base_config=DataConfig(prompt_from_task=True),
            default_prompt="your job description",
            robot_dof=18,
            dataset_action_dim=18,
            use_delta_actions=True,
            repack_transforms=_transforms.Group(
                inputs=[
                    _transforms.RepackTransform(
                        {
                            "images": {
                                "cam_high": "observation.images.chest",
                                "cam_left_wrist": "observation.images.wrist_left",
                                "cam_right_wrist": "observation.images.wrist_right",
                            },
                            "state": "observation.state",
                            "actions": "action",
                            "prompt": "prompt", # This parameter must be added, otherwise the model training will not include the task description
                        }
                    )
                ]
            ),
            # AlohaMini2Pro is native 18D: arm joints are trained as deltas,
            # grippers/base/lift stay absolute.
            delta_action_mask=[
                True, True, True, True, True, True, False,
                True, True, True, True, True, True, False,
                False, False, False, False,
            ],
            assets=AssetsConfig(
                assets_dir="/path/to/your/asset/path",
                asset_id="/dataset/file/name", # assets_dir and assed_id form your dataset path, the path is equivalent to repo_id
            ),
        ),
        weight_loader=weight_loaders.CheckpointWeightLoader(
            "gs://openpi-assets/checkpoints/pi05_base/params",
        ),
        num_train_steps=50000,
        batch_size=4,
        num_workers=2,
        wandb_enabled=False,
    ),

按顺序完成微调与部署#

  1. 替换 repo_id、assets_dir、asset_id 和任务描述,确保组合后的路径指向真实数据。

  2. 检查 prompt 映射与三路图像名称;二代 / Pro 使用 18 维配置,一代使用对应 16→18 适配。

  3. 用所安装 OpenPI 版本的 scripts/compute_norm_stats.py 计算统计量,检查资产输出位置。

  4. 按该版本训练入口选择已注册配置并加载 Pi0.5 基础权重。运行前需确认依赖版本与训练入口参数;当前示例尚未提供完整的环境锁定文件。

  5. 选择实际生成的检查点,在远端准备 HTTP 服务启动入口,再验证请求与返回动作。

  6. 补齐当前 AlohaMiniClient 的接口适配后,先进行离线维度与单位核验,再接入真机。

该示例目录未提供 scripts/serve_policy_http.py,其中的 lekiwi_host 和 LeKiwiClient 与当前接口也存在差异。运行前需要补齐服务入口、适配客户端接口,并在对应设备上完成验证。