-
Notifications
You must be signed in to change notification settings - Fork 12
Debugging
本文覆盖从输入设备、Mod 加载、状态切换、推理资源、Mod 子节点到构建部署的常见故障。 机器人状态订阅、电机输出或硬件看门狗问题请转到机器人平台适配指南; 控制周期超时请转到框架控制调度。
先定位故障层,再查看具体章节。 不要同时修改输入 YAML、Mod route、Transition 和状态代码。
| 现象 | 首先检查 |
|---|---|
| 节点启动时 Mod 加载失败 | Mod 清单、factory、依赖和参数 |
| 按键没有消息 | sources -> controls -> outputs |
有 /motion_commands 但不切状态 |
Mod events 和当前状态的 route |
| 状态已切换但没有正确输出 |
on_enter/on_update 和 MotorFrame |
| 切换过程跳变或报 capability 错误 | Transition 与 Entry/RunningFrameProvider |
| 修改后没有生效 | 是否重新构建并重启了对应节点 |
| 模型文件报错 | Resource asset 路径、loader 和预热阶段 |
colcon build --packages-select remote_controller bxi_example_py_elf3 \
--symlink-install --merge-install
source install/setup.bash若提示 install layout 不一致,使用匹配的 --merge-install,或换一组全新的 build/install/log 目录。旧构建缓存仍引用已删除模型目录时,只清理对应包缓存。
ros2 topic echo /motion_commands
ros2 topic echo /simulation/state_machine_info硬件前缀时将 simulation/ 换成 hardware/。状态信息 JSON 包含 current、pending、
preparing、active transition、事件和图快照;action 的显示信息位于 graph.actions[],
Mod 的 loaded/unavailable/disabled 状态位于 mods[],Mod 节点的
running/stopped/restarting/faulted/unavailable 状态位于 nodes[]。
-
mod.yaml是否位于内置mods/或mod_paths子树。 - 安装后的
share/bxi_example_py_elf3/mods/是否包含文件。 - 12 个描述头字段是否全部显式填写,
runtime_requirements是否包含python/ros/system,schema是否为1,api是否与当前框架兼容,name、id 和版本是否合法。 - 是否出现重复 id。
- 日志是否以 Mod logger 打印
loaded v<version>: <root>。
-
needs factory: module:Class:使用entrypoint: null的状态漏写约定 factory。 -
factory ... must name a RobotControlState class:模块、类名或继承关系错误。 -
entrypoint module does not exist:entrypoint 与文件名不一致。 -
entrypoint is not callable:冒号后的工厂不存在。 -
state manifest/factory mismatch:states和state_factories键不同。 -
requires missing/version:依赖缺失或版本不匹配。 -
dependency cycle:Mod 依赖形成环。 -
enabled Mods conflict:两个已启用 Mod 命中至少一方的conflicts声明。 -
missing Python module/ROS package/system library:runtime_requirements不满足;检查 Mod 自带vendor/或目标机器运行环境。 -
status: unavailable:依赖检查阶段未通过,框架没有导入对应 Mod 或节点模块,也不会消耗重启次数。 -
unknown params:清单参数未被StateBuildContext消费。 -
missing required param/must be ...:dataclass 参数缺失或 YAML 类型错误。
- 资产必须在当前 Mod 的
assets/。 -
context.asset()路径应写assets/file.onnx。 -
policy="startup"的资源在控制循环启动前准备;失败会阻止启动。 -
policy="on_demand"的资源在第一次请求目标状态时异步准备;状态信息会显示preparing。 - 状态必须通过
resources=(handle,)声明依赖;ResourceHandle.get()不会触发加载或阻塞等待。 - 在
on_prepare()预热,不要在插件 import 时创建推理 Session。 - 替换模型后需要重启控制节点;启动失败时查看具体资源加载异常。
-
/motion_commands的槽位和值是否与mod.yaml events一致。 - 当前完整状态名是否存在对应 route。
- 跨 Mod名称是否含
/且依赖存在。 - 是否正在等待
delay、资源preparing或处于活动过渡。 - 同一状态是否存在可同时触发的输入;加载器会提前拒绝。
正常状态只写 manifest.priority。数值越大越靠前,相同 priority 按完整状态名升序排列,框架会自动生成 index。
ValueError: duplicate explicit state manifest index N: 'state-a' and 'state-b'
只有确实需要固定绝对位置时才显式写 manifest.index。两个显式 index 重复会直接终止启动;负数、布尔值和字符串同样是配置错误。
Transition 负责状态切换期间的电机帧,用来避免源、目标状态的 qpos/kp/kd 不连续时直接产生突跳。因此这类错误要同时检查 route 选用的过渡以及两端状态提供的帧能力。
-
must implement EntryFrameProvider:目标没有进入帧。 -
must implement RunningFrameProvider:动态采样侧没有运行帧能力。 -
unknown transition type:业务过渡模块未被 Mod entrypoint 导入。 -
unknown fields:ConfigReader.finish()发现字段拼写错误。 - 发生突跳:检查进入帧与
on_enter()后第一帧是否一致。
- Mod、系统 YAML、模型资产和遥控器 YAML 都只在对应节点启动时读取。
- 修改源码后先重新构建工作区,再重启控制节点或
remote_controller。 - 使用
--symlink-install时 Python 源码可能直接生效,但仍然必须重启进程。 - 已部署的非 symlink
install/可以直接向share/bxi_example_py_elf3/mods/复制完整 Mod 目录;重启后自动发现,不需要在目标机器重新构建。 - 启动失败不会进入控制循环;根据首个加载异常修正清单、依赖、模块或资源路径。
python3 tools/sanitize_release.py --out /tmp/public_release --self-check若报告公开 Mod 依赖 protected Mod,检查显式 requires 和跨 Mod route。共享资源应移到 public 资源 Mod。
下面的检查会加载所有 startup 资源,但不会请求 on_demand 资源,可用于验证 Mod、
启动资源和状态图:
from pathlib import Path
import yaml
from bxi_example_py_elf3.framework.runtime.mod_loader import load_mod_runtime
package = Path("src/bxi_example_py_elf3")
base = yaml.safe_load((package / "config/elf3_state_machine.yaml").read_text())
runtime = load_mod_runtime(base, built_in_root=package / "mods")
print([mod.id for mod in runtime.mods])
print(sorted(runtime.state_factories))
runtime.close()当前默认树应发现 7 个 Mod 和 17 个状态。
com.bxi.normal_depth 不再内置 RealSense 节点。真机相机由独立
bxi_depth_camera 包管理,硬件示例 launch 默认包含其 cameras.launch.py。
先检查节点和标准话题:
ros2 node list
ros2 topic list | grep body_depth_camera
ros2 topic hz /hardware/body_depth_camera/depth/image_rect_raw
ros2 topic echo /hardware/body_depth_camera/depth/camera_info --once仿真把 hardware 换成 simulation。继续确认:
-
cameras.body_depth_camera.serial_no是否与实际设备对应;单相机回退只适合确实只连接一台设备的情况。 - 深度图和
CameraInfo是否同时存在,且属于相同分辨率 profile。 - 图像编码是否为
16UC1、mono16或32FC1。 -
mod.yaml中camera_name、显式topic/camera_info_topic是否互相一致。 - 日志是否出现
waiting for CameraInfo、非法内参、错误 shape 或深度超时。
状态不可进入时查看 /hardware/state_machine_info:相机数据不新鲜会让
is_available() 返回 False;模型资源仍在准备时会出现 preparing。两者不是同一个
问题,前者检查 ROS 数据,后者检查 Resource 状态和加载错误。
若运行用户是 root、构建用户是普通用户,旧版本可能在 Mod 或 vendor 目录生成 root 所有的 __pycache__/*.pyc,随后构建会报 Permission denied: '*.pyc'。当前框架禁止 Mod 主进程、依赖探测进程和内置节点子进程向 Mod 目录写 Python 字节码;升级前已经生成的文件仍需一次性修正工作区属主:
cd ~/bxi_ws/bxi_rl_controller_ros2_example
sudo chown -R bxi:bxi src build install log
./build.sh不希望修改整个工作区时,可先用 find src build install log -user root -print 定位 root 所有的文件。运行命令也可显式加 PYTHONDONTWRITEBYTECODE=1,进一步阻止 ROS launch 自身生成缓存:
PYTHONDONTWRITEBYTECODE=1 ros2 launch \
bxi_example_py_elf3 example_demo_hw.launch.py