Skip to content

Model And Launch

konodoki edited this page Aug 2, 2026 · 15 revisions

模型、资源与 launch

模型和动作数据属于使用它们的 Mod,放在该 Mod 的 assets/。运行时通过资源管理器按声明的 startup/on_demand 策略准备,不再把模型对象动态挂到 BxiExample

文件布局

mods/com.example.motion/
  mod.yaml
  plugin.py
  state.py
  assets/
    motion.npz
    policy.onnx

setup.py 会递归安装整个 mods/,同时跳过 __pycache__.pyc.pyo

注册资源

from bxi_example_py_elf3.framework.mod_api import (
    ModDefinition,
    ModLoadContext,
    ResourceKey,
    ResourceLoadContext,
)

POLICY = ResourceKey[MotionPolicy]("com.example.motion/policy")


def _load(context: ResourceLoadContext) -> MotionPolicy:
    return MotionPolicy(
        str(context.asset("assets/motion.npz")),
        str(context.asset("assets/policy.onnx")),
    )


def create_mod(context: ModLoadContext) -> ModDefinition:
    context.register_resource(POLICY, _load, policy="startup")
    policy = context.resource(POLICY)
    return ModDefinition(
        state_factories={
            "motion": lambda state: MotionState(
                state.name, state.state_id, policy
            )
        }
    )

ResourceKey 必须全局命名。context.asset() 会拒绝逃出当前 Mod assets/ 的路径,并确认文件存在。

加载策略

context.resource(POLICY) 只返回 ResourceHandlepolicy="startup" 在框架启动、 控制定时器开始前完成准备,适合初始状态和启动时必须校验的模型; policy="on_demand" 在第一次请求需要它的状态时由资源工作线程异步准备,适合 不常进入的动作。准备完成后 handle.get() 始终返回同一个实例;它不会触发加载, 也不会等待资源。准备策略硬编码在资源注册代码中,不写入 mod.yaml

节点关闭时,资源管理器会按逆序调用已加载实例的 close()(若存在),然后清空缓存。

多个状态共享模型时,让它们持有同一个 handle。多个 Mod 共享模型时,优先拆出一个无状态资源 Mod,并用 requires 声明依赖。

状态内使用

from bxi_example_py_elf3.framework.mod_api import PolicyState


class MotionState(PolicyState[MotionPolicy]):
    def __init__(self, name, state_id, policy):
        super().__init__(name, state_id, policy)

    def reset_policy(self, ctx, policy):
        policy.reset(ctx.inference_frame)

    def policy_entry_position(self, ctx, policy):
        return policy.output.joints.position

    def policy_gains(self, ctx, policy):
        return policy.output.joints.kp, policy.output.joints.kd

    def infer_position(self, ctx, policy, dt, *, advance):
        output = policy.step(ctx.inference_frame, dt, advance=advance)
        return output.joints.position

PolicyState 自动把 handle 声明为状态资源依赖,并统一实现进入帧、运行帧、正常 on_update()、资源解析和预热。策略有特殊重置或预热要求时覆盖对应方法;不要在插件 加载或状态构造阶段执行推理。

当前资产路径

基础动作模型位于 mods/com.bxi.basic_actions/assets/。后空翻、前空翻、芭蕾舞和深度感知行走资产分别位于各自独立 Mod 的 assets/

深度感知行走的模型和策略都属于 com.bxi.normal_depth Mod;策略实现位于 mods/com.bxi.normal_depth/depth.py,只依赖通用 framework/inference,公共 policies 不会 反向导入它。可替换的相机或感知节点通过标准 ROS 话题接入,不属于模型 Resource。

深度模型的 RKNN INT8 校准

量化校准必须使用模型真正收到的输入分布。不要拿随机数组或原始相机帧直接 校准:深度策略的输入还包含 observation history、深度裁剪、归一化和多帧选择。

使用通用采集工具包装控制器。它在应用进程外注入采集代理,并把样本写入指定目录:

python3 tools/benchmark/collect_calibration.py \
  --output /tmp/bxi_rknn_calibration \
  --every 5 \
  --max-samples 500 \
  --skip-first 10 \
  -- ros2 launch bxi_example_py_elf3 example_demo_hw.launch.py

参数含义:

  • --output:校准集根目录。
  • --every:每多少次真实推进的策略调用采一组。
  • --max-samples:每个模型最多保留多少组。
  • --skip-first:跳过启动后的前若干次推理。

每个模型独立生成 <root>/<model>/dataset.txtcapture.json 和每个输入对应的 .npy。一行严格对应一次推理,文件顺序就是 ONNX 输入顺序,因此同样支持未来 的 N 输入模型。预览过渡使用的 advance=False 不会污染校准集。

只有实际运行的策略才会产生样本。当前默认 mode: origin_camera 对应 dagger2.onnx;要采集 normal_depth.onnx,需切换为 mode: depth_walk 另跑一次。

把校准目录复制到安装了 RKNN Toolkit2 2.3.2 的 x86_64 转换机后执行:

PYTHONNOUSERSITE=1 python3 tools/benchmark/quantize_rknn.py \
  src/bxi_example_py_elf3/mods/com.bxi.normal_depth/assets/dagger2.onnx \
  src/bxi_example_py_elf3/mods/com.bxi.normal_depth/assets/normal_depth.onnx \
  --calibration-root /path/to/bxi_rknn_calibration \
  --install

工具会在转换前校验输入数量与顺序、shape、float32、NaN/Inf 和最少样本数, 然后强制重建 W8A8 缓存并原子安装到 ONNX 旁边。量化模型仍必须在 RK3588 上 重新做后端延迟测试和真实输入/闭环动作验证;校准成功不等于控制策略精度自动 合格。

example_walk.launch.py 和硬件版本中给独立 MJLab 节点使用的模型路径是:

mods/com.bxi.basic_actions/assets/model_normal.onnx

launch 的职责

launch 负责启动仿真或硬件、设置 /topic_prefix、覆盖 /state_machine_config 和状态信息参数。Mod 自己使用的模型路径不应硬编码进 launch;由资源加载函数相对 Mod 根解析。

验证

colcon build --packages-select bxi_example_py_elf3 --symlink-install --merge-install
find install/share/bxi_example_py_elf3/mods -name mod.yaml -o -path '*/assets/*'

若工作区此前使用过不同 install layout 或旧资产目录,请使用新的 build/install 路径,或只清理该包的旧构建缓存。

Clone this wiki locally