Skip to content

Hands On Sim2Real

konodoki edited this page Jul 29, 2026 · 11 revisions

手把手 8:把模型从仿真带到真机

Sim2Real 不只是替换 ONNX 路径。当前推荐把模型、动作数据、状态参数和版本约束全部封装进独立 Mod,再按阶段验证。

本页讨论模型和状态如何从仿真迁移到真机。如果目标机器人的状态消息、电机命令、关节 顺序或硬件 SDK 与 ELF3 不同,还必须配合机器人平台适配指南 实现平台边界。

1. 固定策略契约

上线前记录:

  • 关节数量、顺序和默认姿态。
  • 四元数顺序 xyzw/wxyz
  • 角速度和速度指令的坐标系。
  • observation 归一化、history 长度和控制频率。
  • action scale、kp、kd 和输出含义。
  • 模型的 start/end frame 与动作数据 fps。

这些差异应由强类型 policy 类处理,不要散落到状态逻辑。

2. Mod 资源

mods/com.customer.sim2real/
  mod.yaml
  plugin.py
  state.py
  assets/policy.onnx
POLICY = ResourceKey[CustomerPolicy]("com.customer.sim2real/policy")


def _load(context):
    return CustomerPolicy(str(context.asset("assets/policy.onnx")))

在 policy 构造器中验证模型维度、关节数和必需张量,尽量在首次加载时失败。

3. 状态模板

class CustomerWalkState(
    RobotControlState, EntryFrameProvider, RunningFrameProvider
):
    def __init__(self, name, state_id, policy):
        super().__init__(name, state_id)
        self._policy = policy

    @property
    def policy(self):
        return self._policy.get()

    def on_prepare(self, ctx, from_state):
        ctx.preheat_model(
            self.policy,
            with_cmd_vel=True,
            cmd_vel=self.get_cmd_vel(ctx),
        )

    def get_entry_frame(self, ctx):
        return self._motor_frame_from_target(ctx, self.policy.output.joints)

    def sample_running_frame(self, ctx, dt, *, advance):
        self.get_cmd_vel(ctx)
        output = self.policy.step(ctx.inference_frame, dt, advance=advance)
        return self._motor_frame_from_target(ctx, output.joints)

    def on_update(self, ctx, dt):
        if ctx.is_orientation_unsafe(ctx.current_quat_xyzw):
            ctx.request_state(
                "com.bxi.basic_actions/zero_torque", trigger="safety"
            )
            return
        self._apply_frame(
            ctx, self.sample_running_frame(ctx, dt, advance=True)
        )

4. 保守速度 profile

speed_profiles:
  safe_walk:
    vx_scale: 0.2
    vx_min: -0.1
    vx_max: 0.2
    vy_scale: 0.1
    yaw_scale: 0.15

states:
  customer_walk:
    speed_profile: safe_walk
    manifest:
      label: 客户步态
      priority: 100
      group: Customer
      confirm: true
      confirm_message: 首次真机验证,请使用吊架

速度范围随验证结果逐步放开,不要第一次真机就使用训练上限。

5. 分阶段验证

  1. 离线检查 ONNX 输入输出和默认动作。
  2. 加载 Mod,确认模型保持惰性且清单图通过。
  3. 仿真静止输入,验证关节顺序和四元数。
  4. 仿真小速度,检查方向和限幅。
  5. 验证进入/退出过渡和零力矩安全路由。
  6. 吊架真机、低增益、短时运行。
  7. 逐步提高增益、速度和连续运行时间。

进入/退出 Transition 决定模型与原状态之间如何交接电机帧。真机上必须验证它,因为仿真中不明显的 qpos/kp/kd 突变,在实机上可能表现为瞬间抽动或冲击。

6. 仿真与真机一致性

  • 相同 Mod 和模型资产。
  • 仅由 launch 改 /topic_prefix 和运行环境。
  • 不在状态里根据“仿真/真机”分叉关节顺序。
  • 记录推理耗时和 inference_timeout_count
  • 对传感器符号、单位和坐标系做自动断言。

7. 发布和回滚

模型版本跟随 Mod version。高风险客户动作需要从公开树删除时,保护整个 Mod。保留上一个经过真机验证的 Mod 目录;出现问题时替换整个目录并重启控制节点,不在运行中的控制进程里替换模型和状态机。

Clone this wiki locally