新增吊舱串口监听诊断脚本listen_pod.py
台架工具: 统计表2-2/表4帧数、打印首帧关键状态、按60Hz标称80%判读链路, --center可下发归中验证下行; 打桩冒烟测试通过(帧解析/统计/判读/退出码)。 部署文档§7第3步改为引用该脚本
This commit is contained in:
+4
-2
@@ -109,8 +109,10 @@ pytest # 仅上机自测需要,部署运行可省
|
|||||||
`cd utils && ~/venv-pod/bin/python -m pytest tests/pod_bridge -q` → 应 92 全绿
|
`cd utils && ~/venv-pod/bin/python -m pytest tests/pod_bridge -q` → 应 92 全绿
|
||||||
(单测已打桩 mavsdk 设定点类型,与 libcmavsdk 原生库健康状态无关)。
|
(单测已打桩 mavsdk 设定点类型,与 libcmavsdk 原生库健康状态无关)。
|
||||||
2. **串口回环**:USB 转串口模块 TX/RX 短接,跑一个 feed/echo 小脚本验证字节收发。
|
2. **串口回环**:USB 转串口模块 TX/RX 短接,跑一个 feed/echo 小脚本验证字节收发。
|
||||||
3. **只接吊舱**:观察能否解析出 表2-2(60Hz EE 16)帧;用 `send_control(归中 0x2B)`
|
3. **只接吊舱**:用仓库自带诊断脚本
|
||||||
验证下行。
|
`python utils/pod_bridge/listen_pod.py /dev/ttyUSB0 --seconds 5`
|
||||||
|
(加 `--center` 可同时下发归中 0x2B 验证下行);脚本自动统计帧数并判读,
|
||||||
|
遥测帧率 ≥48Hz(标称 60Hz 的 80%)退出码为 0 即链路正常。
|
||||||
4. **只接飞控**:`Px4Gateway.connect` 后确认 `own_state().position_valid` 为 True。
|
4. **只接飞控**:`Px4Gateway.connect` 后确认 `own_state().position_valid` 为 True。
|
||||||
5. **全链路地面联试**:电机不装桨,观察 offboard 心跳与引导输出。
|
5. **全链路地面联试**:电机不装桨,观察 offboard 心跳与引导输出。
|
||||||
6. 最后才考虑带动力测试。
|
6. 最后才考虑带动力测试。
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
"""listen_pod.py —— 吊舱串口监听诊断(台架工具,非飞行组件)。
|
||||||
|
|
||||||
|
用途(对应 docs/树莓派4B部署注意事项.md §7 第 3 步「只接吊舱」):
|
||||||
|
* 打开吊舱串口,静默监听 N 秒,统计 表2-2 遥测(EE 16)/ 表4 目标(EE 18)帧数;
|
||||||
|
* 打印首帧遥测的关键状态(锁定位/激光/脱靶量)与最终判读;
|
||||||
|
* --center 选项可在监听开始时下发一帧 归中(0x2B) 验证下行链路。
|
||||||
|
|
||||||
|
用法:
|
||||||
|
python utils/pod_bridge/listen_pod.py [/dev/ttyUSB0] [--baud 115200]
|
||||||
|
[--seconds 5] [--center]
|
||||||
|
|
||||||
|
退出码:0 = 遥测帧率达到预期(≥80% 标称 60Hz);1 = 异常(接线/电平/波特率排查)。
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1])) # utils/ 入 sys.path
|
||||||
|
|
||||||
|
from pod_bridge.pod_serial import PodSerial # noqa: E402
|
||||||
|
from pod_bridge.protocol import (ControlCode, ControlCommand, # noqa: E402
|
||||||
|
TargetGeo, Telemetry, encode_control)
|
||||||
|
|
||||||
|
_TELEMETRY_NOMINAL_HZ = 60.0 # 规格 §2.1:周期 16.7ms
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
ap = argparse.ArgumentParser(description="吊舱串口监听诊断")
|
||||||
|
ap.add_argument("port", nargs="?", default="/dev/ttyUSB0",
|
||||||
|
help="串口设备号(默认 /dev/ttyUSB0,Windows 如 COM3)")
|
||||||
|
ap.add_argument("--baud", type=int, default=115200, help="波特率(默认 115200)")
|
||||||
|
ap.add_argument("--seconds", type=float, default=5.0, help="监听时长(默认 5s)")
|
||||||
|
ap.add_argument("--center", action="store_true",
|
||||||
|
help="监听开始时下发一帧 归中(0x2B) 验证下行")
|
||||||
|
args = ap.parse_args()
|
||||||
|
|
||||||
|
pod = PodSerial(args.port, args.baud)
|
||||||
|
print(f"[listen] {args.port} @ {args.baud} 8N1,监听 {args.seconds:.0f}s ...")
|
||||||
|
|
||||||
|
if args.center:
|
||||||
|
pod.send(encode_control(ControlCommand(code=ControlCode.CENTER)))
|
||||||
|
print("[listen] 已下发 归中(0x2B),观察云台是否回中")
|
||||||
|
|
||||||
|
t0 = time.monotonic()
|
||||||
|
n_tele, n_tgt, n_other = 0, 0, 0
|
||||||
|
while time.monotonic() - t0 < args.seconds:
|
||||||
|
for frame in pod.poll():
|
||||||
|
if isinstance(frame, Telemetry):
|
||||||
|
n_tele += 1
|
||||||
|
if n_tele == 1:
|
||||||
|
print("[listen] 首帧遥测: 锁定=%s 激光=%s 脱靶=(%+.2f°, %+.2f°) "
|
||||||
|
"框架角 R/P/Y=(%+.2f, %+.2f, %+.2f)"
|
||||||
|
% (frame.is_target_locked, frame.laser_range_m,
|
||||||
|
frame.off_target_x_deg, frame.off_target_y_deg,
|
||||||
|
frame.frame_roll_deg, frame.frame_pitch_deg,
|
||||||
|
frame.frame_yaw_deg))
|
||||||
|
elif isinstance(frame, TargetGeo):
|
||||||
|
n_tgt += 1
|
||||||
|
if n_tgt == 1:
|
||||||
|
print("[listen] 首帧目标: lat=%.7f lon=%.7f rel_alt=%.1fm"
|
||||||
|
% (frame.latitude_deg, frame.longitude_deg,
|
||||||
|
frame.rel_alt_m))
|
||||||
|
else:
|
||||||
|
n_other += 1
|
||||||
|
time.sleep(0.005)
|
||||||
|
pod.close()
|
||||||
|
|
||||||
|
expected = _TELEMETRY_NOMINAL_HZ * args.seconds
|
||||||
|
rate = n_tele / args.seconds if args.seconds > 0 else 0.0
|
||||||
|
print(f"[listen] 统计: 遥测帧={n_tele}(期望~{expected:.0f},{rate:.1f}Hz) "
|
||||||
|
f"目标帧={n_tgt} 其他帧={n_other}")
|
||||||
|
|
||||||
|
if n_tele >= expected * 0.8:
|
||||||
|
print("[listen] 判读: 链路正常 ✅(可进入下一步接飞控)")
|
||||||
|
if n_tgt == 0:
|
||||||
|
print("[listen] 目标帧为 0 属正常:未锁定/未收表3 姿态时吊舱不解算")
|
||||||
|
return 0
|
||||||
|
print("[listen] 判读: 异常 ❌ 遥测帧率不足。排查顺序:共地 → TX/RX 交叉 → "
|
||||||
|
"电平匹配(RS232 需转换) → 波特率 → 设备号")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user