You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MAVLink/MAVProxy检测无人机解锁状态并启停Python脚本?

无人机解锁状态检测问题及解决方案

你遇到的核心问题是解锁状态检测不稳定,明明无人机处于解锁状态,代码却误判为上锁。结合你提供的两段代码,先分析问题根源,再给出修复后的实现方案:

原代码问题分析

CODE 1 问题

  1. 循环内重复调用master.wait_heartbeat():该函数会阻塞直到收到下一个心跳包,再加上time.sleep(2),导致状态检测间隔过长,且内部状态缓存无法及时更新。
  2. 未持续接收MAVLink消息:master.motors_armed()依赖内部缓存的状态数据,若不主动接收消息,缓存会过期,导致判断错误。

CODE 2 问题

  1. 缩进错误:部分代码缩进层级混乱,会导致逻辑执行顺序出错(比如armed = False的位置会覆盖后续判断结果)。
  2. 状态判断不严谨:位与操作后未显式判断结果是否非零,虽然Python中非零值会被视为True,但显式判断能避免潜在的逻辑歧义。
  3. 仅监听HEARTBEAT消息:单一消息源可能错过状态更新,导致判断不准。

关键注意事项(针对MAVProxy场景)

不要让脚本直接连接无人机串口(/dev/ttyACM0),因为MAVProxy已经占用了该串口,同时访问会导致消息冲突。正确做法是:

  1. 启动MAVProxy时指定输出端口:
mavproxy.py --master /dev/ttyACM0 --baud 57600 --out udp:127.0.0.1:14550
  1. 脚本连接MAVProxy的UDP端口,而非直接连串口。

修复后的代码实现

方案一:使用封装好的motors_armed()方法(推荐)

该方法由pymavutil封装,会自动处理MAVLink消息更新状态,代码更简洁可靠:

from pymavlink import mavutil
import time
# 若需要启停外部脚本,导入subprocess
# import subprocess

# 连接MAVProxy的UDP端口,而非直接连串口
master = mavutil.mavlink_connection('udp:127.0.0.1:14550')

# 等待首次心跳,确认连接成功
master.wait_heartbeat()
print(f"已连接到系统 {master.target_system},组件 {master.target_component}")

# 记录当前解锁状态,避免重复执行启停逻辑
current_armed = None
# 用于保存外部脚本进程(如果需要)
# script_process = None

while True:
    # 非阻塞接收所有MAVLink消息,更新内部状态缓存
    msg = master.recv_match(blocking=False)
    if msg:
        pass  # 无需处理具体消息,master会自动更新状态

    # 获取当前解锁状态
    is_armed = master.motors_armed()

    # 仅在状态变化时执行操作
    if is_armed != current_armed:
        current_armed = is_armed
        if is_armed:
            print("无人机已解锁,启动目标脚本")
            # 启动外部脚本示例
            # script_process = subprocess.Popen(["python3", "your_target_script.py"])
        else:
            print("无人机已上锁,停止目标脚本")
            # 停止外部脚本示例
            # if script_process:
            #     script_process.terminate()
            #     script_process.wait()
            #     script_process = None

    time.sleep(0.1)  # 缩短检测间隔,提升响应速度

方案二:直接解析MAVLink消息(底层实现)

如果需要更精细的控制,可以直接监听HEARTBEAT消息并解析状态:

from pymavlink import mavutil
import time
# import subprocess

master = mavutil.mavlink_connection('udp:127.0.0.1:14550')
master.wait_heartbeat()
print(f"已连接到系统 {master.target_system},组件 {master.target_component}")

current_armed = None
# script_process = None

while True:
    # 阻塞接收HEARTBEAT消息,确保实时获取状态
    msg = master.recv_match(type='HEARTBEAT', blocking=True)
    if not msg:
        continue

    # 解析解锁状态:位与操作后判断是否非零
    is_armed = (msg.base_mode & mavutil.mavlink.MAV_MODE_FLAG_SAFETY_ARMED) != 0

    if is_armed != current_armed:
        current_armed = is_armed
        if is_armed:
            print("无人机已解锁,启动目标脚本")
            # script_process = subprocess.Popen(["python3", "your_target_script.py"])
        else:
            print("无人机已上锁,停止目标脚本")
            # if script_process:
            #     script_process.terminate()
            #     script_process.wait()
            #     script_process = None

内容的提问来源于stack exchange,提问作者SAFIYA ATEEQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 09:35:36