Skip to content

Model And Launch

konodoki edited this page Jul 23, 2026 · 15 revisions

模型、动作数据与 launch 工程参考

本页解释模型文件、动作数据、launch 参数和 BxiExample 之间的关系。它补足一个常见缺口:状态类写好了,但模型路径、数据文件、发布保护没有接完整。

1. 文件安装路径

模型和动作数据放在:

src/bxi_example_py_elf3/data/

setup.py 中:

def get_data_files():
    source_dir = 'data'
    target_dir = os.path.join('share', package_name, 'data')

这会把 data/ 下所有文件安装到:

install/bxi_example_py_elf3/share/bxi_example_py_elf3/data/

因此新增 .npz / .onnx 后需要重新:

colcon build --packages-select bxi_example_py_elf3

如果正在使用热重载,不建议用 --symlink-install。普通 build 会在修改完成后更新 install/ 目录,从而触发一次热重载;--symlink-install 会让编辑器自动保存直接触发重载。

2. launch 负责运行环境

仿真 launch:

src/bxi_example_py_elf3/launch/example_demo.launch.py

硬件 launch:

src/bxi_example_py_elf3/launch/example_demo_hw.launch.py

launch 只负责启动环境和节点参数,例如:

{"/topic_prefix": "simulation/"}
{"/state_machine_config": state_machine_config}
{"/hot_reload": True}

模型路径不再通过 launch 的 npz_file_dict / onnx_file_dict 传入。

3. BxiExample 如何声明模型

模型在:

src/bxi_example_py_elf3/bxi_example_py_elf3/bxi_example_demo.py

load_models() 中直接声明:

self.withoutarm: HumanoidGaitPolicyLiteIsaaclab = HumanoidGaitPolicyLiteIsaaclab(
    model_file("isaaclab_model/withoutarm.onnx")
)

model_file() 会从包的 data/ 目录解析文件路径,并记录当前模型文件。记录到的 .onnx / .npz 会参与热重载监控。热重载调试时推荐普通 build,不使用 --symlink-install,避免自动保存导致频繁重载。

如果要换模型,直接改这里:

self.withoutarm: HumanoidGaitPolicyLiteIsaaclab = HumanoidGaitPolicyLiteIsaaclab(
    model_file("isaaclab_model/new_withoutarm.onnx")
)

热重载细节看 热重载

4. 什么时候改 launch,什么时候改 YAML

改 launch:

  • 切换仿真或硬件入口。
  • 调整 topic_prefix
  • 调整 state_machine_config
  • 调整 /hot_reload 默认值。
  • 调整硬件启动时需要附带的底层节点或辅助节点。

bxi_example_demo.py

  • 新增或替换 .npz / .onnx 模型文件。
  • 新增 BxiExample 中要加载的模型对象。
  • 调整模型构造参数,例如 start_frame

改状态机 YAML:

  • 新增状态。
  • 新增状态切换。
  • 调整 transition。
  • 调整状态构造参数。

改遥控器 YAML:

  • 绑定按键。
  • 改组合键。
  • 改输出到哪个 btn_N=value
  • 调整 system.* 动作,让遥控器触发启动、停止或其他运维命令。

硬件入口通常还会包含单实例保护,避免同一个硬件控制链被重复启动。如果启动时报已有实例在运行,先通过停止动作或手动清理已有进程,再重新启动。

遥控器的 system action 可以同时编排主控制节点和辅助节点。文档不要依赖某条具体命令;实际部署以 src/remote_controller/config/xbox_default.yaml 中的 systemsystem_mutexessystem_reset_motion_after 为准。

5. 模型对象命名规范

推荐两处使用同一个 key:

BxiExample member: self.wave_motion
state params policy_attr: wave_motion

好处:

  • 状态类可以通过 getattr(ctx, policy_attr) 找到模型。
  • 发布保护的 model_keys 可以直接写同一个名字。
  • 脚本能删除 self.wave_motion = ... 初始化块。

6. 状态类如何引用模型

推荐:

class WaveMotionState(RobotControlState):
    def __init__(self, name: str, state_id: int, policy_attr: str = "wave_motion"):
        super().__init__(name, state_id)
        self.policy_attr = policy_attr

    def _policy(self, ctx: BxiExample):
        return getattr(ctx, self.policy_attr)

YAML:

wave_motion:
  behavior: WaveMotionState
  params:
    policy_attr: wave_motion

这样同一个状态类可以复用到多个模型:

wave_left:
  behavior: WaveMotionState
  params:
    policy_attr: wave_left

wave_right:
  behavior: WaveMotionState
  params:
    policy_attr: wave_right

7. 模型预热

进入模型状态前推荐:

def on_prepare(self, ctx, from_state):
    policy = self._policy(ctx)
    policy.timestep = policy.start_frame
    if hasattr(policy, "timeinit"):
        policy.timeinit = 0.0
    ctx.preheat_model(policy)

预热作用:

  • 用当前观测先推理一次。
  • 填充模型历史观测。
  • get_entry_frame() 能拿到更合理的 target_dof_pos

如果模型预热也需要速度命令,使用状态自己的 get_cmd_vel(ctx)

ctx.preheat_model(
    policy,
    with_cmd_vel=True,
    cmd_vel=self.get_cmd_vel(ctx),
)

这样会使用当前状态 YAML 中配置的 speed_profile。没有 speed_profile 时得到零速度,避免未声明速度能力的状态被遥控速度影响。

8. 进入帧

需要进入帧过渡的模型状态应继承 EntryFrameProvider 并实现:

def get_entry_frame(self, ctx: BxiExample) -> MotorFrame:
    policy = self._policy(ctx)
    qpos = getattr(policy, "target_dof_pos", None)
    if qpos is None:
        qpos = getattr(policy, "default_dof_pos", None)
    if qpos is None:
        raise ValueError(f"state '{self.name}' policy has no entry position")
    return self._motor_frame(qpos, policy.kps, policy.kds)

这样 first_frame_switch 或自定义进入过渡可以平滑进入模型状态。

9. 发布保护和 model_keys

如果动作是高危内部动作,写:

protected_states:
  wave_motion:
    behavior: WaveMotionState
    model_keys: [wave_motion]
    files:
      - ../data/wave_motion.npz
      - ../data/wave_motion.onnx

model_keys 会影响:

  • demo node 中的 self.<model_key> = ...self.<model_key>: Type = ... 初始化块。

要删除的 .npz / .onnx 必须显式写在 files 中。model_keys 不会隐式删除模型文件。

10. 常见错误

模型成员不存在:

  • bxi_example_demo.py 没声明 self.<model_key>
  • YAML 的 policy_attrBxiExample 成员名不一致。
  • 热重载失败后仍在使用旧代码,查看日志中的 hot reload failed

模型文件找不到:

  • 文件不在 data/
  • model_file("...") 里的文件名写错。
  • 当前运行环境没有看到新增文件;普通 build 场景下需要重新 colcon build --packages-select bxi_example_py_elf3

状态进入时第一帧为空:

  • 没调用 ctx.preheat_model(policy)
  • 模型预热需要速度输入,但没传 cmd_vel=self.get_cmd_vel(ctx)
  • policy 没有 target_dof_posdefault_dof_pos

发布版还残留模型:

  • release_protection.yaml 没写 model_keys
  • files 没写对应 .npz / .onnx
  • self.<model_key> 名字和 model key 不一致,脚本无法匹配。

Clone this wiki locally