跳转至

仿真、测试、调试与安全回滚

飞控测试不是“刷进去能启动,再试飞看看”。正确顺序是先用低成本、可重复、不会产生动力的环境排除问题,再逐级增加真实硬件和物理风险。

飞控固件分层验证阶梯

六层验证

1. 静态检查

检查:

  • 编译警告;
  • 格式和代码规范;
  • 静态分析;
  • 未定义行为;
  • 越界和空指针;
  • 单位和类型;
  • 未使用或不可达代码;
  • 依赖和许可证变化。

静态检查不能证明运行时正确,但能用较低成本排除一类缺陷。

2. 主机端单元测试

适合验证:

  • 数学函数;
  • 协议解析;
  • 参数范围和迁移;
  • 滤波器;
  • 坐标变换;
  • 控制器边界;
  • 故障状态机。

测试应覆盖正常值、边界值、无效值、溢出、非数值和状态切换。

3. 软件在环

软件在环(SITL,Software In The Loop)让飞控逻辑在主机系统上与仿真模型交互,适合:

  • 自动任务;
  • 模式切换;
  • 参数行为;
  • 失联和传感器故障;
  • 回归场景;
  • 批量自动化。

软件在环通常不会真实复现处理器时序、总线电气、电源、缓存和全部驱动行为。

4. 硬件在环

硬件在环(HITL,Hardware In The Loop)或硬件环仿真让真实飞控硬件运行固件,由仿真器提供传感器或环境反馈。

它可以增加对真实处理器、调度、输入输出和部分驱动的覆盖,但测试能力取决于具体注入边界。只把姿态数据发给飞控,不代表已经验证真实IMU总线。

5. 拆桨台架

在真实接线和供电条件下验证:

  • 启动和恢复;
  • 传感器方向;
  • 接收机和失联;
  • 电压、电流和温度;
  • 电机编号和方向;
  • 输出范围;
  • 日志完整性;
  • 看门狗和故障上报。

必须拆除螺旋桨。软件界面中的“电机测试”按钮不会消除物理风险。

6. 受控飞行

只验证前五层无法覆盖的空气动力、振动、真实链路和整机行为。需要:

  • 合法、隔离且有足够缓冲区的场地;
  • 明确测试卡;
  • 受控飞行包线;
  • 观察员和中止条件;
  • 基线与修改版对照;
  • 完整日志;
  • 每次只增加有限风险。

软件在环和硬件在环不能互相替代

能力 SITL HITL 拆桨台架 受控飞行
算法逻辑
自动化回归
真实处理器时序
真实传感器总线 通常无 取决于注入边界
电源和接线 部分
空气动力和振动 模型 模型
人身和财产风险 低至中

表中的“强”表示相对覆盖能力,不代表单次测试已经充分。

PX4 v1.17.0的可执行测试路线

以下命令在已经完成可执行基线构建后运行:

目标 命令或操作 通过标准 失败后
工作区完整 git status --short 只有本次预期修改 停止并识别额外差异
文本差异 git diff --check 无空白错误,退出码0 修正后重跑
主机测试 make tests 全部测试结束且退出码0 保留第一个失败用例和日志
启动SITL make px4_sitl sihsim_quadx 出现pxh>且无启动错误 保留完整构建与启动输出
核对版本 ver all 报告与固定基线一致 停止,检查目录和构建缓存
运行示例 hello start 出现hello、五次Doing work...goodbye 检查构建注册与源码差异
读取主题 listener vehicle_acceleration 5 返回5个带时间戳样本 检查仿真、主题名称和发布者
退出 shutdown 进程正常退出 记录卡死位置

make tests验证主机测试集合,不能代替SITL;SITL使用主机调度,不能据此声明目标微控制器满足实时期限。

构建或SITL异常时的固定检查

先把证据放在源码目录之外,避免污染git status

EVIDENCE_DIR="../px4-evidence/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$EVIDENCE_DIR"
pwd | tee "$EVIDENCE_DIR/pwd.txt"
git rev-parse --show-toplevel | tee "$EVIDENCE_DIR/root.txt"
git rev-parse HEAD | tee "$EVIDENCE_DIR/head.txt"
git status --short | tee "$EVIDENCE_DIR/status.txt"
git submodule status --recursive | \
  tee "$EVIDENCE_DIR/submodules.txt"

捕获测试输出和真实退出码:

set -o pipefail
make tests 2>&1 | tee "$EVIDENCE_DIR/make-tests.log"
TEST_STATUS=${PIPESTATUS[0]}
printf 'tests_exit=%s\n' "$TEST_STATUS" | \
  tee "$EVIDENCE_DIR/make-tests.exit"

先查看第一条失败,而不是只看最后一屏:

rg -ni -m 20 \
  "error|failed|failure|traceback|ninja: build stopped|no such file" \
  "$EVIDENCE_DIR/make-tests.log"

如果没有匹配结果,直接查看日志开头和结尾:

sed -n '1,80p' "$EVIDENCE_DIR/make-tests.log"
tail -n 80 "$EVIDENCE_DIR/make-tests.log"

如果修改后的SITL仍显示旧文字,依次确认:

pwd
git rev-parse HEAD
git status --short
rg -n "learning-build: read-only diagnostic v1" \
  src/examples/hello/hello_main.cpp

只有在保存日志、确认源码差异后,才隔离明确的SITL构建目录:

BUILD_DIR="build/px4_sitl_default"
test -f "$BUILD_DIR/CMakeCache.txt" || exit 1
mv "$BUILD_DIR" \
  "$EVIDENCE_DIR/px4_sitl_default.failed"
git submodule update --init --recursive
make px4_sitl sihsim_quadx

这样既强制重新生成该目标,又保留旧构建供比较。PX4的distclean会反初始化子模块并清理部分忽略文件,不应在包含开发数据的工作副本中作为普通排障步骤;也不得使用git clean -fdx或手工删除不明目录替代。重新构建后问题仍存在时,回到日志中的第一条错误,不继续叠加修改。

故障注入怎么开始

在SITL控制台先执行:

failure help

只使用该固定版本帮助中实际列出的命令和组件。每个故障场景先写出:

注入对象:
注入类型:
预期检测时间:
预期状态变化:
预期执行器动作:
恢复条件:
需要保存的日志:

若帮助中没有对应注入能力,应编写测试替身或使用更高一层测试环境,不要把“没有观察到故障”解释为测试通过。

故障注入

至少考虑:

  • 传感器停止更新;
  • 时间戳跳变或样本延迟;
  • 总线超时和错误;
  • GNSS丢失或跳点;
  • 磁力计不一致;
  • 遥控链路丢失;
  • 数据链中断;
  • 电池低电压;
  • 参数损坏;
  • 存储写入失败;
  • CPU过载;
  • 执行器饱和或失效;
  • 系统重启。

故障注入必须定义预期检测时间、状态转换、输出动作、日志证据和恢复条件。

调试证据的优先级

推荐顺序:

  1. 可重复步骤;
  2. 版本和配置;
  3. 状态与错误码;
  4. 时间戳日志;
  5. 任务和资源统计;
  6. 断言与崩溃转储;
  7. 调试器断点和内存检查;
  8. 示波器或逻辑分析仪;
  9. 受控故障注入。

大量打印不是可靠的第一选择。它可能改变时序、填满缓冲区并掩盖原问题。

使用调试器

GNU调试器(GDB,GNU Debugger)配合SWD或联合测试行动小组接口(JTAG,Joint Test Action Group)可用于:

  • 停止在异常位置;
  • 查看调用栈;
  • 检查寄存器和内存;
  • 设置断点和观察点;
  • 解析硬故障;
  • 下载或恢复固件。

在实时控制任务中暂停处理器会冻结输出和看门狗状态。连接真实动力系统时不得随意断点调试。

建立恢复路径

通用恢复步骤无法替代具体板卡文档,因为恢复按键、USB标识、引导加载程序、闪存地址和调试接头都可能不同。刷写前必须把下表填写为可执行值:

项目 必须记录
正常上传 完整命令、端口、成功输出
进入引导模式 按键、跳线、上电顺序或命令
设备识别 USB标识、串口名称或调试探针
应用镜像 文件、目标、提交和SHA-256
引导镜像 官方文件、版本和适用板卡
SWD/JTAG 接头针脚、电压、工具和配置
擦写地址 仅使用目标板官方内存布局
参数恢复 备份文件、版本和导入验证
成功标志 启动信息、版本、传感器和通信
停止条件 身份不符、供电异常或校验失败

例如,只有在真实硬件已确认属于px4_fmu-v5_default目标时,正常上传命令才可以写为:

make px4_fmu-v5_default upload

官方示例的成功输出包括EraseProgramVerify达到100%,随后Rebooting。若设备不能进入现有引导加载程序,就必须改用该板卡官方恢复说明和正确SWD接线;不能猜测闪存地址,也不能把FMUv5命令套到相似板卡。

恢复流程必须实际演练。只保存一个文件名而没有对应版本、地址和操作步骤,不算恢复方案。

测试卡模板

字段 内容
目标 本次只验证什么
基线 固件、提交、参数和硬件
改动 补丁或配置差异
环境 仿真模型、台架或场地
前置条件 拆桨、限流、区域和人员
步骤 可重复操作
期望结果 数值范围、状态和时限
中止条件 何时立即停止
证据 日志、波形、录像和校验值
恢复 回到已验证基线的方法

发布门禁

  • 所有新增代码经过评审;
  • 基线和修改版测试使用相同场景;
  • 自动测试可重复运行;
  • 时序、闪存、内存和日志开销在预算内;
  • 参数和消息兼容性已验证;
  • 失效与恢复路径有证据;
  • 板级目标和硬件版本明确;
  • 没有跳过的高风险未知项;
  • 受控飞行没有超出预先批准的包线;
  • 发布产物、源码和测试记录能够对应。

检查理解

  1. 软件在环为什么不能证明真实总线和电源正确?
  2. 硬件在环的覆盖范围为什么取决于注入边界?
  3. 大量打印为什么可能改变原始故障?
  4. 调试器断点为什么不能在带真实动力的系统中随意使用?
  5. 什么条件满足后才算具有可执行的恢复路径?

主要参考