-
Notifications
You must be signed in to change notification settings - Fork 12
Model And 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) 只返回 ResourceHandle。policy="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.positionPolicyState 自动把 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。
量化校准必须使用模型真正收到的输入分布。不要拿随机数组或原始相机帧直接 校准:深度策略的输入还包含 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.txt、capture.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 负责启动仿真或硬件、设置 /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 路径,或只清理该包的旧构建缓存。