使用树莓派4B+pymavlink进行Ardupilot的二次开发
一、前言 入门Ardupilot 二次开发,必须得啃飞控源码? 下图为Ardupilot官方学习资料中提到的内容! 70多万行的代码,很容易从入门到放弃,建议大家先从Pymavlink轻松入门! 这篇文章用 【物唯 WFG120A 飞控】 ...
一、前言
入门Ardupilot 二次开发,必须得啃飞控源码?
下图为Ardupilot官方学习资料中提到的内容!

70多万行的代码,很容易从入门到放弃,建议大家先从Pymavlink轻松入门!
这篇文章用【物唯 WFG120A 飞控】做个简单教学:不动飞控核心代码,通过飞控的串口外挂一台树莓派(机载计算板),然后在树莓派上用python语言直接做业务开发,最后用 pymavlink 搞定树莓派与飞控的通讯,照样能做 AI 识别、自主导引这些"默认固件没有"的活儿;同时也不用担心改错代
码而导致污染飞控的核心代码!

边缘计算板通常是搭载 Linux 系统的各种算力板,如树莓派、香橙派或 RK 系列的算力板!其用法基本上都差不多。【树莓派 4B】是最常见的入门级机载算力板,ArduPilot 官方源码中也对它做了适配,此外它的入门教程非常齐全,系统安装也非常简单,本人手上刚好有 1 块闲置的树莓派 4B,其外形如下图所示:

飞控上,我将采用物唯WFG120A飞控来做演示!

二、飞控的AP固件串口映射表
串口连线与配置,这是很多新手最容易踩坑的一步。每个飞控厂商的飞控都会直接引出串口接口,需要搞清楚Ardupilot的Serila逻辑串口与单片机的物理串口USART的映射关系以及默认配置功能,通常厂家会提供一个AP串口映射表:
如下表所示,为物唯 WFG120A 飞控的AP固件串口映射表:

那接树莓派,飞控该选哪个串口?
- Serial4(UART4):默认就配成了 Mavlink2,是给无线数传电台用的。
- Serial6(USART6):默认是 RC_IN,接遥控接收机,别动它。
- Serial3 (USART3):默认 GPS,也别占。
需要选择一个串口与树莓派连接,除了上述的3个串口不选,其余的串口都可以按照自己的喜好来修改定义。此处我就用的WFG120A的Serial7(UART7) 来连接树莓派!

三、WFG120A飞控与树莓派4B的接线
把 WFG120A 的 Serial7(UART7) 接到 树莓派 4B 的硬件 UART(GPIO8与GPIO10)。记住 UART 是交叉接,GND需要共地,然后树莓派需要单独的5V供电!

四、配置WFG120A飞控的串口功能与波特率
以ArdupCopter4.6.3固件为例,MP地面站采用MissionPlanner1.3.83版本。
接完线,默认是连不上的——因为 飞控固件中的Serial7 默认是不是Mavlink V2,需要在用USB线将WFG120A飞控与电脑连接,打开 Mission Planner → 初始配置→必要硬件→Serial Ports,按照如下图所示进行设置:

串口波特率配置为:921600
串口功能配置为:Mavlink2
五、安装树莓派系统
从官网下载 Raspberry Pi OS(Legacy, 64-bit),用 Raspberry Pi Imager工具 刷进 SD 卡(最好32GB或以上;刷系统前需要格式化FAT32),然后就是系统的安装,账号密码的设置等等!树莓派系统的文档教程和视频教程都非常多,也非常简单,就不再去赘述了!

另外,在树莓派系统的官方下载页面中,能够看到有Raspberry Pi OS 和Raspberry Pi OS Full 两个系统。
其中Full的系统是预装了所有推荐的软件。这包括大量的编程工具(如 Thonny, Mu, Geany)、数学软件、甚至是一些复古游戏模拟器等。普通用户不需要这么大的系统,因为很多预装软件你可能永远用不到。我建议是安装标准版的系统即可!

六、树莓派的串口配置
树莓派的系统安装完毕后,将树莓派的HDMI口连接显示器,USB口分别连接鼠标与键盘,开启后就可以类似电脑一样进行操作!开机后,首先要做的就是配置串口,具体操作如下:
打开树莓派的命令行终端,然后输入以下命令,并回车!
sudo raspi-config
然后依次按照如下操作即可!

然后选中,并按下回车



七、pymavlink 是什么?怎么装?
至此,树莓派与飞控的安装连线、飞控端上的串口配置、树莓派端口的串口配置都完成了。接下来就是软件通讯层面的处理,Ardupiloit固件的飞控与树莓派之间,采用标准MavlinkV2协议进行通讯!飞控端上的Mavlink代码不用我们手写,已经写好集成在飞控的官方固件中了,同样树莓派上的Mavlink通讯代码也不需要写,安装一个pymavlink的库,就可以实现飞控与树莓派之间的数据通讯!
pymavlink 是 用Python语言以及相关的依赖,来访问 MAVLink 的官方库。它把飞控发来的一堆二进制消息(姿态、位置、电池、遥控器等)解析成 Python 对象,也能同树莓派向飞控去发送指令。读数据、发指令、全通过它。
在安装pymavlink之前,先分别执行以下命令,确认这两个依赖是否已安装,如下:
python3 --version
python3 -m pip --version如下图所示,安装完成的就会如下显示,如果提示未安装的话,那么需先安装!

然后,再执行安装pymavlink的步骤,因本人安装的树莓派的系统比较新,所以需要通过venv 环境的方式去安装pymavlink!如果是旧版的树莓派系统,则不通过虚拟环境进行安装!新旧版系统的安装Pymavlink的具体差异,大家可自行查阅,此处不作为重点去阐述!
venv 虚拟环境的安装命令如下:
py
cd ~
sudo apt install -y python3-venv
python3 -m venv ~/venv
source ~/venv/bin/activate然后再执行激活虚拟环境的指令:
source ~/venv/bin/activate此时会看到,终端命令前面有(venv开头),代表进入了虚拟环境,如下图所示:

此时我们便可以进入虚拟环境中安装pymavlink,执行如下命令即可进行安装:
pip install pymavlink安装成功后,终端打印如下:

安装pymavlink成功后,如果把命令行窗口关闭掉,就会退出虚拟环境(命令行前面的括号就会消失),后面就无法运行顺利联调pymavlink的程序!
所以当我们重新打开命令行的时候,需要先激活虚拟环境,输入命令:
source ~/venv/bin/activate然后命令行中就又能看到开头带有(venv),此时我们就可以直接执行py程序。输入ls命令可以查看到文件目录下有一个 test.py的程序,如下图所示:

这个测试程序的功能非常简单,执行后,如果树莓派收到飞控发来的心跳包,就打印:ss!

在执行这个test.py的程序的时候,可能会报一个错误!
我们只需安装一个pyserial插件即可解决,执行以下命令:
pip install pyserial然后再执行这个test.py这个python程序,执行指令:
python3 test.py就会看到命令行成功打印 “ss”,那么代表飞控与树莓派的mavlink通讯正常,如下图所示:

八、实例1 :通过 pymavlink 连接,读到飞控姿态角
通过前面的pymavlink设置,我们成功打通了飞控和树莓派的通讯!
接下来通过写一个简单的程序,来进一步体会树莓派接入飞控,如何将飞控的姿态角度读取到树莓派上?首先新建一个test2.py的文件,然后写入以下代码:
# 函数功能:实时打印飞控偏航与俯仰角度
from pymavlink import mavutil
import math
# 连接飞控(使用uart)
master = mavutil.mavlink_connection('/dev/serial0', baud=921600)
# 等待读取心跳包的反馈!
master.wait_heartbeat()
print("已成功连接飞控!")
# ================= 添加这一段核心代码 =================
# 请求飞控以 10Hz 的频率发送 EXTRA1 数据流(包含姿态ATTITUDE)
master.mav.request_data_stream_send(
master.target_system,
master.target_component,
mavutil.mavlink.MAV_DATA_STREAM_EXTRA1, # 包含俯仰、偏航、滚转等姿态信息
10, # 频率10Hz
1 # 1为开启
)
# ====================================================
print("\n实时读取角度程序运行中!可按Ctrl+C结束程序!...")
try:
while True:
# 读取ATTITUDE消息
msg = master.recv_match(type='ATTITUDE', blocking=True, timeout=1)
if msg:
pitch = round(math.degrees(msg.pitch), 2)
yaw = round(math.degrees(msg.yaw) % 360, 2)
# Data
print(f"\r当前飞控俯仰角度为:{pitch}度 当前飞控偏航角度为:{yaw}度", end="", flush=True)
except KeyboardInterrupt:
print("\n程序退出!")
master.close()然后运行上述程序。
python3 test2.py最后就能在树莓派的终端上看到,姿态角度被实时打印出来,如下图所示:

那么走到这里,大家基本上就掌握了树莓派与Ardupilot之间的pymavlink通讯开发模式!
九、实例2:3挡开关的条件判断示范
下面再举一个条件判断的代码示例!
比如很多人想用遥控器挡位开关,来控制某种自定义的功能!比如我们设置一个3挡开关(用遥控器上6通道),当我们开关处于低位的时候,控制飞机干某个逻辑或舵机执行什么操作,再或者某个PWM通道,输出某个特定的PWM值等等!
在这里,我就举一个最简单的例子,飞控实时读取遥控器6通道的PWM值,同时做一个信息打印。如果遥控器在低挡/中挡/高挡,就打印输出:“我是低挡/中挡/高挡”。
然后大家只要把这里的业务逻辑改掉,替换成自己的业务代码,就能实现挡位开关实现条件判断,并执行自定义功能的效果,代码如下:
#!/usr/bin/env python3
# 读取飞控 RC_CHANNELS 消息,按 6 通道(三档开关)PWM 判断挡位并打印
from pymavlink import mavutil
import time
# ===== 1) 连接飞控(串口和波特率) =====
master = mavutil.mavlink_connection('/dev/serial0', baud=921600)
master.wait_heartbeat()
print("连接成功,开始读取遥控器 6 通道(三档开关)...")
# ===== 2) 请求飞控发送遥控器数据流(关键!) =====
master.mav.request_data_stream_send(
master.target_system,
master.target_component,
mavutil.mavlink.MAV_DATA_STREAM_RC_CHANNELS,
10, 1
)
# ===== 3) 挡位阈值(放宽了死区,保证中间档能识别) =====
PWM_LOW_MAX = 1250 # 低于1250为低挡
PWM_MID_MIN = 1250 # 1250 ~ 1750之间为中挡
PWM_MID_MAX = 1750
PWM_HIGH_MIN = 1750 # 高于1750为高挡
# ===== 4) 业务函数:在这里替换你的功能 =====
def on_switch(position):
if position == 'LOW':
print("6 通道低挡(PWM < 1250)→ 我是低挡")
elif position == 'MID':
print("6 通道中挡(PWM 1250~1750)→ 我是中挡")
elif position == 'HIGH':
print("6 通道高挡(PWM > 1750)→ 我是高挡")
# ===== 5) 主循环:持续读取遥控器状态 =====
last_pos = None # 记录上一次挡位,避免重复打印
print("等待RC数据中,请来回拨动6通道开关...")
try:
while True:
# 读取RC_CHANNELS消息
msg = master.recv_match(type='RC_CHANNELS', blocking=True, timeout=1)
if not msg:
continue
# 正确获取第6通道的数值!(注意是chan6_raw,不是channels[5])
ch6 = msg.chan6_raw
# [调试] 实时打印当前的PWM数值,方便你确认真实值
print(f"当前6通道实时PWM: {ch6} ", end="\r", flush=True)
# 判断挡位(三段式直接判断,彻底避开死区)
if ch6 < PWM_LOW_MAX:
pos = 'LOW'
elif PWM_MID_MIN <= ch6 <= PWM_MID_MAX:
pos = 'MID'
elif ch6 > PWM_HIGH_MIN:
pos = 'HIGH'
else:
pos = last_pos # 兜底,保持上一次状态
# 只有挡位真正变化时才执行功能
if pos is not None and pos != last_pos:
on_switch(pos)
last_pos = pos
time.sleep(0.05)
except KeyboardInterrupt:
print("\n程序退出!")
master.close()最终如下图所示:运行程序后,打印效果如下:

把中间的业务代码替换掉,就是你所需要的业务场景:比如读到气压计的数据达到什么条件,触发避让、判断传感器达到什么状态,决定是否抛投、读 AI 模型的置信度达到什么状态,决定是否进入导引……等等!这就是"用树莓派给飞控加智能"的起点。
实例1与实例2,小结:
掌握这个基础的思想后,要实现判断某种状态,从而实现某种功能就变得非常简单了!哪怕不懂飞控的业务代码,也能完成很多简单的逻辑开发任务!
十、留个作业:如何让python程序,开机自启?
你可能会问:为什么非得做自启?我手动跑不就行了?
设想一下真实场景:你的飞机(或地面站)一通电,树莓派上的程序应该自己就起来了,比如识别目标、框选、导引,全程不需要有人先 ssh 进去敲一行命令。这才是"机载 AI"该有的样子:上电即运行。如果靠人手动跑去启动,就失去了"自主"的意义。
所以需要一种机制,让树莓派开机后自动运行你的 py 程序。最规范的做法是 systemd 服务:当然,还有 rc.local、crontab @reboot、桌面自启动等更"轻量"的做法,各有取舍。
这道作业就留给大家:不懂完全没有关系,借助AI力量去探索吧!让一段 pymavlink 程序在树莓派开机后自动运行、崩了还能自动重启,并在后台把关键日志打出来!

不要怕,在这个 AI 时代,这个问题异常容易解决:把你的需求(比如"帮我在树莓派上建一个 systemd 服务,开机自动运行我的 py 脚本,崩溃自动重启,输出到日志")直接描述清楚,丢给任意 AI 助手,它会给你完整可用的配置。你唯一要做的,是把这段配置**真正理解、并去执行调试!
十一、再下一步,怎么学习?
拿到 MAVLink,能做的事非常多:读姿态/位置/任务、自己写地面站、开机自检、数据打点、多机集群、自主任务调度。这也是"飞控二次开发 / 地面站开发 / 集群"的分水岭。 你会发现,真正复杂的不是连上,而是怎么用。
遇到具体问题,除了问AI还有就是可以查阅pymavlink的官方文档!
pymavlink GitHub:官方库,消息定义和示例都在里面。
另外,你可以直接把业务需求描述清楚,丢给 AI,让它帮你把"我想让飞机自己X"翻译成 pymavlink 的 set_mode/mission/command 代码。 边界熟练之后,上手非常快。
