Skip to content

Model And Launch

konodoki edited this page May 14, 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 --symlink-install --packages-select bxi_example_py_elf3

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

两个文件都有:

npz_file_dict = {
    "recover": "data/recover.npz",
    "dance": "data/dance.npz",
}

onnx_file_dict = {
    "normal": "data/amp_terrain.onnx",
    "dance": "data/dance.onnx",
}

然后转成绝对路径:

for key, value in npz_file_dict.items():
    npz_file_dict[key] = os.path.join(get_package_share_path("bxi_example_py_elf3"), value)

再作为 ROS 参数传给节点:

{"/npz_file_dict": json.dumps(npz_file_dict)}
{"/onnx_file_dict": json.dumps(onnx_file_dict)}

3. BxiExample 如何读取模型字典

在:

src/bxi_example_py_elf3/bxi_example_py_elf3/bxi_example_demo.py

load_files() 中:

self.declare_parameter('/npz_file_dict', json.dumps({}))
npz_file_json = self.get_parameter('/npz_file_dict').value
self.npz_file_dict = json.loads(npz_file_json)

self.declare_parameter('/onnx_file_dict', json.dumps({}))
onnx_file_json = self.get_parameter('/onnx_file_dict').value
self.onnx_file_dict = json.loads(onnx_file_json)

所以模型 key 必须在 launch 字典里存在。

如果代码写:

self.wave_motion = DanceMotionPolicyGravityIsaaclab(
    self.npz_file_dict["wave_motion"],
    self.onnx_file_dict["wave_motion"],
)

而 launch 没有 "wave_motion",启动就会 KeyError

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

改 launch:

  • 新增 .npz / .onnx 模型文件。
  • 新增 BxiExample 中要加载的模型对象。
  • 仿真和硬件都要能用这个模型。

改状态机 YAML:

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

改遥控器 YAML:

  • 绑定按键。
  • 改组合键。
  • 改输出到哪个 btn_N=value

5. 模型对象命名规范

推荐三处使用同一个 key:

launch dict key: wave_motion
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_enter(self, ctx, from_state, transition):
    super().on_prepare_enter(ctx, from_state, transition)
    policy = self._policy(ctx)
    policy.timestep = policy.start_frame
    if hasattr(policy, "timeinit"):
        policy.timeinit = 0.0
    ctx.preheat_model(policy)

预热作用:

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

8. 第一帧

模型状态应该实现:

def get_first_frame(self, ctx):
    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:
        return None
    return self._motor_frame(qpos, policy.kps, policy.kds)

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

9. 发布保护和 model_keys

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

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

model_keys 会影响:

  • launch 中的 npz_file_dict
  • launch 中的 onnx_file_dict
  • demo node 中的 self.<model_key> = ... 初始化块。

10. 常见错误

KeyError: '<model_key>'

  • launch 字典没加 key。
  • 只改了仿真 launch,没改硬件 launch。
  • 没重新 build。

模型文件找不到:

  • 文件不在 data/
  • 文件名和 launch 字典不一致。
  • 没重新 build。

状态进入时第一帧为空:

  • 没调用 ctx.preheat_model(policy)
  • policy 没有 target_dof_posdefault_dof_pos

发布版还残留模型:

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

Clone this wiki locally