Ubuntu 20.04 部署 MAVROS:从基础安装到实战环境配置
1. 环境准备为什么选择 Ubuntu 20.04 和 ROS Noetic如果你刚接触无人机和ROS开发可能会有点懵为什么大家总在说 Ubuntu 20.04 和 ROS Noetic这俩组合到底有什么魔力我刚开始玩无人机的时候也问过同样的问题。简单来说这就像玩游戏选“标准版”一样不是因为它最强而是因为它最稳、社区支持最好、踩坑最少。Ubuntu 20.04 是一个长期支持版本官方维护到2025年这意味着系统底层非常稳定不会三天两头出更新把你正在跑的代码搞崩。而 ROS Noetic 是 ROS 1 的最后一个版本专门为 Ubuntu 20.04 量身打造生态成熟几乎你遇到的所有问题都能在社区里找到现成的解决方案。对于 MAVROS 来说它本质上是一个“翻译官”。想象一下你的无人机飞控比如 Pixhawk说一种叫 MAVLink 的“方言”而你的电脑上运行的 ROS 程序说的是另一种“语言”。没有 MAVROS它们俩谁也听不懂谁。MAVROS 的核心工作就是把 MAVLink 消息转换成 ROS 能理解的话题和服务同时也能把 ROS 的命令翻译成 MAVLink 消息发给飞控。所以部署 MAVROS就是在你的 Ubuntu 电脑上搭建起这个关键的通信桥梁。在开始动手之前我强烈建议你先检查一下自己的系统环境。打开终端输入lsb_release -a确认你的 Ubuntu 版本是 20.04。然后输入roscore试试如果 ROS Noetic 已经正确安装这个命令会启动 ROS 的核心节点。如果还没装 ROS那得先解决这个前提条件。网上有很多 ROS Noetic 的安装教程但核心就是跟着 ROS 官网的步骤走别用乱七八糟的第三方脚本最稳妥。装好之后记得把source /opt/ros/noetic/setup.bash这行命令加到你的~/.bashrc文件末尾这样每次打开终端ROS 环境就自动准备好了。2. 安装路径选择二进制安装 vs 源码安装好了系统环境就绪ROS 也在跑了现在到了第一个关键决策点怎么装 MAVROS这里通常有两条路二进制安装和源码安装。这可不是随便选选它直接关系到你后续开发的灵活性和可能遇到的麻烦。我两种方式都折腾过可以跟你分享一下我的体会。2.1 省心之选二进制安装如果你只是想快速把 MAVROS 跑起来用于学习、测试或者进行一些高层的应用开发比如用 ROS 发送指令控制无人机飞行那么二进制安装是你的首选。它的优点就一个字快。Ubuntu 的 apt 包管理器会帮你处理好所有依赖一键安装几乎不需要你操心。具体操作起来非常简单。打开终端依次执行下面几条命令就行sudo apt-get update sudo apt-get install ros-noetic-mavros ros-noetic-mavros-extras第一条命令是更新软件源列表确保你能找到最新的包。第二条就是安装 MAVROS 的核心包和扩展包。这个过程通常很顺利几分钟就搞定了。但是这里有一个几乎所有新手都会遇到的“坑”也是二进制安装最麻烦的一步安装地理数据库。MAVROS 需要一些地理信息数据比如地球重力场、地磁场模型来进行高精度的导航计算。安装完上述包后你需要运行一个脚本来下载这些数据roscd mavros sudo ./install_geographiclib_datasets.sh问题就出在这里。这个脚本会从国外的服务器下载数据由于网络原因十有八九会失败或者速度慢到令人绝望。我当初就在这里卡了半天。别慌我们有解决办法。手动安装地理数据库是最靠谱的。你需要下载三个压缩包egm96-5.tar.bz2 大地水准面模型egm96.zip 地球重力模型emm2015.zip 地球磁场模型你可以按照原始文章里给的链接去 GeographicLib 的 SourceForge 页面找也可以用其他方式获取。下载完成后执行以下操作# 创建目标目录 sudo mkdir -p /usr/share/GeographicLib # 假设你的下载文件在 ~/Downloads 目录下 cd ~/Downloads # 解压并移动到系统目录 sudo tar -xjf egm96-5.tar.bz2 -C /usr/share/GeographicLib sudo unzip egm96.zip -d /usr/share/GeographicLib sudo unzip emm2015.zip -d /usr/share/GeographicLib完成这一步二进制安装才算真正结束。这种方式安装的 MAVROS 版本是 ROS 官方仓库维护的稳定版兼容性最好但版本可能不是最新的。2.2 折腾之选源码安装那什么情况下要选源码安装呢主要在这几种场景第一你需要 MAVROS 的最新功能或特定分支的代码第二你打算修改 MAVROS 的源码比如添加自定义的消息类型或修改某些通信逻辑第三你是个喜欢折腾、想彻底弄明白编译过程的开发者。源码安装给了你最大的控制权但代价就是过程繁琐更容易出错。源码安装的核心是创建一个 ROS 工作空间然后用wstool和catkin工具来管理源码和编译。我们一步步来。首先安装必要的工具链sudo apt install python3-catkin-tools python3-rosinstall-generator python3-osrf-pycommon -ycatkin-tools是比老式catkin_make更现代的编译工具更好用。接着创建并初始化工作空间mkdir -p ~/mavros_ws/src cd ~/mavros_ws catkin init wstool init src这时src目录下会生成一个隐藏的.rosinstall文件用来记录要下载的软件包信息。然后生成 MAVLink 和 MAVROS 的源码描述文件rosinstall_generator --rosdistro noetic mavlink | tee ~/mavros_ws/mavros.rosinstall rosinstall_generator --upstream mavros | tee -a ~/mavros_ws/mavros.rosinstall--upstream参数意味着我们直接从 MAVROS 的 GitHub 主仓库获取而不是 ROS 的发行版仓库。你可以用cat ~/mavros_ws/mavros.rosinstall看看里面定义了要克隆哪个仓库的哪个版本。接下来让wstool根据这个文件去拉取源码wstool merge -t src ~/mavros_ws/mavros.rosinstall wstool update -t srcwstool update这步就是实际的git clone操作会从 GitHub 下载代码网络不好也可能需要耐心等待或者配置代理。下载完源码就要安装依赖。这里有个大坑点ROS Noetic 使用的依赖工具是rosdep2而且国内直接用rosdep install基本百分之百失败。我强烈推荐使用“鱼香ROS”大佬制作的rosdepc它是rosdep的国内镜像版速度飞快。 安装rosdepc后使用它来安装所有依赖rosdepc install --from-paths src --ignore-src -y看到它哗啦啦地自动安装一堆系统依赖包心里就踏实了一大半。依赖装好同样需要手动安装地理数据库步骤同二进制安装部分或者运行 MAVROS 自带的脚本如果网络好sudo ./src/mavros/mavros/scripts/install_geographiclib_datasets.sh最后进行编译catkin build如果一切顺利你会看到编译成功的输出。编译完成后别忘了把工作空间的setup.bash文件 source 到你的终端环境里echo source ~/mavros_ws/devel/setup.bash ~/.bashrc source ~/.bashrc这样你的系统就会优先使用你刚刚编译的这份 MAVROS 了。3. 安装验证与基础环境测试MAVROS 装好了但它到底能不能用和飞控能不能通上信这一步的验证至关重要能帮你提前发现安装过程中隐藏的问题。我们分几个层次来测试。3.1 基础功能检查首先我们来检查 MAVROS 的核心节点mavros_node能不能正常启动。这个节点是 MAVROS 与飞控通信的枢纽。打开一个终端输入roslaunch mavros apm.launch这里用的是 ArduPilotAPM的启动文件。如果你用的是 PX4 飞控可以尝试px4.launch。不过在还没连接真实飞控的时候这个命令很可能会启动失败因为它会尝试连接/dev/ttyACM0这样的串口设备而你的电脑可能没有。这没关系我们主要看 MAVROS 的包能不能被 ROS 找到。一个更简单的检查方法是roscd mavros ls如果能成功进入mavros这个包的目录并且看到里面有很多.launch文件和scripts等文件夹那就说明安装基本成功了ROS 系统已经识别到了 MAVROS 功能包。3.2 核心话题与服务验证MAVROS 安装成功后会向 ROS 系统提供一系列标准的话题和服务。我们可以通过rostopic list和rosservice list命令来窥探一下。在一个新的终端里确保没有运行任何roslaunch先启动 ROS 核心roscore然后在另一个终端运行rosrun mavros mavros_node同样这个节点会因为连不上飞控而报错但没关系我们关注的是它启动后提供了哪些接口。再开第三个终端输入rostopic list | grep mavros你应该能看到一长串列表比如/mavros/global_position/global、/mavros/imu/data、/mavros/setpoint_position/local等等。这些就是 MAVROS 将要发布或订阅的话题。同样运行rosservice list | grep mavros你会看到诸如/mavros/cmd/arming、/mavros/set_mode这样的服务。这些接口的存在是 MAVROS 功能正常的标志。3.3 连接模拟器进行集成测试只检查自身还不够我们需要一个“假飞控”来模拟真实通信环境。这里隆重推荐QGroundControl (QGC)和它的模拟器功能。QGC 不仅是一个强大的地面站软件它还内置了 PX4 或 ArduPilot 的软件在环仿真。测试流程是这样的启动模拟器打开 QGroundControl进入“设置”-“模拟器”选择一个机型例如多旋翼和飞控固件例如PX4然后点击“开始模拟”。QGC 会在后台启动一个完整的飞控仿真程序并通过 UDP 端口监听连接。配置 MAVROS 连接我们需要修改 MAVROS 的启动文件让它去连接 QGC 模拟器。找到你的 MAVROS 启动文件如果是二进制安装通常在/opt/ros/noetic/share/mavros/launch/如果是源码安装在~/mavros_ws/src/mavros/mavros/launch/。我们可以复制一个px4.launch出来修改。 更简单的方法是创建一个自定义的启动文件比如叫test_sitl.launchlaunch arg namefcu_url defaultudp://:14540127.0.0.1:14557 / arg namegcs_url default / arg nametgt_system default1 / arg nametgt_component default1 / arg namelog_output defaultscreen / include file$(find mavros)/launch/node.launch arg namepluginlists_yaml value$(find mavros)/launch/px4_pluginlists.yaml / arg nameconfig_yaml value$(find mavros)/launch/px4_config.yaml / arg namefcu_url value$(arg fcu_url) / arg namegcs_url value$(arg gcs_url) / arg nametgt_system value$(arg tgt_system) / arg nametgt_component value$(arg tgt_component) / arg namelog_output value$(arg log_output) / /include /launch关键参数是fcu_url这里设置为udp://:14540127.0.0.1:14557。意思是 MAVROS 在本机127.0.0.1的 14557 端口监听并连接到 14540 端口。这个端口需要和 QGC 模拟器的输出端口匹配。启动并验证先启动 QGC 模拟器然后运行你的自定义启动文件roslaunch mavros test_sitl.launch如果终端里出现一连串的[INFO]日志显示 “CON: Got HEARTBEAT” 等内容并且没有红色的错误信息那么恭喜你MAVROS 已经成功连接上了模拟飞控。数据流检查此时再运行rostopic echo /mavros/imu/data你应该能看到源源不断的 IMU 数据流出来。运行rosservice call /mavros/set_mode base_mode: 0 custom_mode: OFFBOARD可以尝试切换飞行模式虽然模拟器不一定响应。看到这些动态数据才证明整个链路——从模拟飞控、MAVLink 通信到 MAVROS 转换、再到 ROS 话题——是完全畅通的。4. 实战环境配置与避坑指南环境验证通过算是拿到了入场券。但要真正开始开发还得把“战场”布置好。这里分享几个我踩过坑后才明白的实战配置要点。4.1 串口权限与稳定连接当你准备连接真实飞控时第一个拦路虎就是串口权限。在 Linux 下普通的 USB 转串口设备如 FTDI、CP2102通常挂载为/dev/ttyUSB0或/dev/ttyACM0默认只有 root 用户有读写权限。直接用sudo来启动 ROS 节点是下策会带来环境变量等一系列问题。正确的做法是将当前用户加入到dialout用户组sudo usermod -a -G dialout $USER执行这条命令后必须注销当前用户并重新登录或者重启电脑这个组权限变更才会生效。之后你就能以普通用户身份访问串口了。连接稳定性也是个常见问题。有时串口设备会莫名断开重连设备名可能在/dev/ttyUSB0和/dev/ttyUSB1之间跳跃。为了解决这个问题我们可以使用udev 规则为特定设备创建固定的、有意义的符号链接。比如根据飞控的供应商 ID 和产品 ID 来绑定。首先用lsusb命令找到你的飞控或数传电台的 USB 信息Bus 003 Device 004: ID 26ac:0011这里26ac:0011就是 VID:PID。然后创建一个新的 udev 规则文件sudo nano /etc/udev/rules.d/99-pixhawk.rules写入以下内容替换成你的 VID 和 PIDSUBSYSTEMtty, ATTRS{idVendor}26ac, ATTRS{idProduct}0011, MODE:0666, GROUP:dialout, SYMLINKpixhawk保存退出后重新加载 udev 规则并重启服务sudo udevadm control --reload-rules sudo service udev restart拔插一下设备现在你会发现除了/dev/ttyUSB0还多了一个固定的/dev/pixhawk链接指向它。在 MAVROS 的启动参数中你就可以使用这个固定的名字fcu_url:/dev/pixhawk:921600再也不用担心设备号变化了。4.2 参数配置与消息频率优化默认的 MAVROS 配置可能不适合所有场景。比如有些数据流像HIGHRES_IMU的发布频率太高会占用大量带宽而有些你需要的数据比如GPS_RAW_INT可能默认没开启。这些都需要通过参数来调整。MAVROS 的参数配置主要在两个 YAML 文件中px4_config.yaml或apm_config.yaml。你可以在 MAVROS 的launch目录下找到它们。我建议不要直接修改系统里的文件而是将其复制到你的项目或工作空间下进行修改。例如创建一个my_custom_config.yaml# 调整IMU数据频率 imu: frame_id: base_link # 将原始IMU话题频率从默认的200Hz降到100Hz # 注意这里修改的是MAVROS内部处理频率飞控端的数据流仍需通过MAVLink命令设置 # rate: 100.0 # 确保GPS数据流被正确请求 gps: # 启用GPS数据 enabled: true # 使用GPS_RAW_INT消息 type: 1 # 0禁用1GPS_RAW_INT2GPS_STATUS # 配置RC通道输入如果使用遥控器 rc: enabled: true然后在你的启动文件中用config_yaml参数指向这个自定义文件arg nameconfig_yaml value$(find your_package)/config/my_custom_config.yaml /更高级的频率控制需要在 MAVROS 启动后通过 ROS 服务调用 MAVLink 命令来设置飞控端的数据流速率。例如设置 HIGHRES_IMU 的流频率为 100Hzrosservice call /mavros/set_stream_rate 0 100 1这个命令的参数含义是stream_id(0 表示请求所有流),message_rate(100 Hz),on_off(1 开启)。具体的stream_id需要查阅 MAVLink 协议文档。4.3 与仿真环境的协同工作很多时候我们的开发是在仿真环境中进行的比如Gazebo或AirSim。这时 MAVROS 的角色略有变化它不再连接真实的飞控硬件而是连接仿真器里的“软件飞控”。以PX4 SITL (Software In The Loop) Gazebo为例典型的启动流程是这样的启动 PX4 SITL 和 Gazebo 世界cd ~/PX4-Autopilot make px4_sitl gazebo_iris这会启动一个 Iris 无人机模型在默认的 Gazebo 空世界中并且 PX4 飞控程序以 SITL 模式运行通过 UDP 端口通常是 14540对外通信。启动 MAVROS连接这个 SITL 实例roslaunch mavros px4.launch fcu_url:udp://:14540127.0.0.1:14540注意这里的fcu_url和连接真实硬件时不同使用的是 UDP 协议和特定的端口。此时你的 ROS 系统里就有了一个完整的仿真无人机。Gazebo 提供物理引擎和传感器模拟PX4 SITL 提供飞控算法MAVROS 提供 ROS 接口。你可以用rqt工具查看所有话题或者编写一个简单的 ROS 节点向/mavros/setpoint_position/local发布目标位置看看无人机是否能飞过去。在这个过程中最容易出问题的是端口冲突和坐标系不一致。确保 SITL、MAVROS 和地面站如果同时运行使用的 UDP/TCP 端口不重复。坐标系方面PX4 通常使用 NED北东地坐标系而 ROS 和 Gazebo 默认使用 ENU东北天坐标系。MAVROS 的某些启动文件如px4_config.yaml里已经包含了坐标系转换的参数target_frame_id: local_enu这很重要能帮你自动处理大部分转换但在自己写控制代码时心里一定要清楚当前数据是在哪个坐标系下表达的。5. 进阶调试与性能监控当你的无人机项目越来越复杂可能会遇到消息延迟、丢包或者节点崩溃的问题。这时候光看日志就不够了需要一些更专业的工具和方法来诊断。5.1 使用 rqt 图形化工具ROS 自带的rqt是一个神器它像是一个插件化的仪表盘。运行rqt命令打开主界面你可以添加各种有用的插件rqt_graph查看节点和话题之间的连接图。一眼就能看出mavros_node订阅和发布了哪些话题有没有其他节点在正常通信。如果图断了问题一目了然。rqt_plot绘制数值话题的数据曲线。比如你可以同时绘制/mavros/local_position/pose中的pose.position.x和pose.position.y实时观察无人机的二维轨迹。这对于调试控制环路的稳定性非常直观。rqt_console集中查看和管理所有 ROS 节点的日志输出。你可以过滤不同严重级别INFO, WARN, ERROR的日志比在终端里翻看滚动屏高效得多。Topic Monitor和Message Publisher可以实时查看任意话题的内容或者手动向某个话题发布消息用于测试。我习惯在开发时把rqt_graph和rqt_plot常开着。前者帮我理清通信脉络后者帮我监控关键状态量的变化趋势。5.2 网络与通信延迟分析MAVROS 的性能瓶颈常常出现在 MAVLink 通信链路上。无论是串口还是 UDP带宽都是有限的。你可以通过 MAVROS 提供的/mavros/connection_status这个话题来监控连接质量。用rostopic echo /mavros/connection_status可以看到类似下面的信息header: seq: 12345 stamp: {...} frame_id: connected: True heartbeat_rate: 1.023 ...关注connected状态和heartbeat_rate。如果connected频繁在 True/False 间切换说明连接极不稳定。heartbeat_rate理论上应该是 1.0 Hz如果波动很大也说明通信不畅。对于更底层的分析可以借助Wireshark或tcpdump来抓取 MAVLink 网络包如果使用 UDP 连接。但这需要你对 MAVLink 协议有一定了解。一个更简单的方法是启用 MAVROS 的调试日志。在启动 MAVROS 时设置日志输出级别roslaunch mavros px4.launch fcu_url:/dev/ttyUSB0:921600 log_output:screen debug:true或者在节点运行后使用rosrun rqt_logger_level rqt_logger_level工具将mavros相关的 logger 级别从INFO调整为DEBUG。这样你会在终端看到非常详细的收发消息的字节流虽然信息量大但对于诊断诡异的通信问题很有帮助。5.3 编写一个简单的测试节点最终检验 MAVROS 环境是否“好用”的最好方法就是写一小段代码来实际调用它。这里给一个最简单的 Python 测试脚本它订阅无人机的位置信息并尝试发送解锁指令#!/usr/bin/env python3 import rospy from mavros_msgs.msg import State from mavros_msgs.srv import CommandBool def state_callback(msg): # 回调函数打印当前连接状态和飞控模式 rospy.loginfo(Connected: %s, Armed: %s, Mode: %s, msg.connected, msg.armed, msg.mode) def test_mavros(): rospy.init_node(mavros_test_node, anonymousTrue) # 订阅状态话题 rospy.Subscriber(/mavros/state, State, state_callback) # 等待MAVROS服务就绪 rospy.wait_for_service(/mavros/cmd/arming) arming_client rospy.ServiceProxy(/mavros/cmd/arming, CommandBool) rospy.loginfo(Press Enter to attempt ARM...) input() # 等待用户按回车 try: resp arming_client(True) # 发送解锁请求 rospy.loginfo(Arming success: %s, resp.success) except rospy.ServiceException as e: rospy.logerr(Arming failed: %s, e) rospy.spin() if __name__ __main__: try: test_mavros() except rospy.ROSInterruptException: pass把这个脚本保存为test_mavros.py放在你的 ROS 包目录下并赋予执行权限 (chmod x test_mavros.py)。在确保 MAVROS 已连接飞控或模拟器后运行它。你会看到它打印出当前的连接和锁定状态按下回车后它会尝试解锁无人机。注意在真实无人机上运行此脚本前请务必确保安全这个脚本虽然简单但它验证了从话题订阅到服务调用的完整 ROS-MAVROS 链路是否工作正常。在实际项目中你可以基于这个框架扩展出更复杂的航点飞行、视觉跟随等功能。