ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Ubuntu 20.04无人机开发环境搭建:ROS+PX4仿真避坑指南

Ubuntu 20.04无人机开发环境搭建:ROS+PX4仿真避坑指南 从入门到能跑仿真Ubuntu 20.04 无人机软件开发环境的搭建与避坑不管你是打算做 PX4/ArduPilot 二次开发还是想在机载电脑上跑 ROS 做视觉避障只要跨进无人机软件开发这扇门第一个绕不开的环境就是Ubuntu 20.04。我见过太多人卡在第一步系统装好了不知道下一步该干嘛、权限报错看不懂、依赖冲突解决一整天最后连一个仿真都没跑起来。这篇内容就是把我自己搭这套环境时做的事、为什么这么做、以及踩过的坑一次性讲清楚给准备入门或正在被环境折磨的你一条可以直接照着走的路径。这篇文章不是什么高深原理而是实打实的工程基础课。我会先解释为什么无人机软件生态普遍绑定 Ubuntu 20.04 而不是更新的版本然后从零开始做系统配置再把 Linux 工程基础里真正影响开发效率的部分拎出来讲最后完整走一遍 ROS 和 PX4 仿真的搭建流程。适合 Ubuntu 接触不多、想搞无人机开发的新手也适合已经在用但始终没理清环境逻辑的开发者。1. 无人机软件栈为什么绕不开 Ubuntu 20.041.1 无人机软件不是“一个程序”而是一条工具链很多人以为无人机软件开发就是写飞控里的 C/C 代码其实远不止如此。一套完整的无人机软件栈至少包含四层飞控层运行在 STM32 等 MCU 上的实时控制固件比如 PX4、ArduPilot。机载电脑层运行在 Linux 系统里的高算力程序比如 ROS 节点、SLAM、目标检测。地面站层QGroundControl、Mission Planner 这类地面控制软件。仿真层Gazebo、jMAVSim 这类用来在电脑上模拟无人机飞行的环境。这四层在开发阶段几乎都要在一台 Linux 电脑上完成编译、运行和联调。飞控固件要交叉编译后刷进硬件机载电脑代码要直接编译运行仿真更是要把整套软件栈拉起来跑。所以你的开发机系统选得好不好直接影响后面每个环节的顺畅程度。1.2 版本选型不是拍脑袋20.04 的生态位置先给一个直接结论如果你用的是 PX4 ROS 这套主流开源组合Ubuntu 20.04 是当前兼容性最省心的版本。原因有几个方面ROS 1 的最后一个版本 Noetic 只官方支持 Ubuntu 20.04。ROS 2 的 Foxy 同样绑定 20.04。虽然 ROS 2 的新版本已经开始支持 22.04/24.04但很多项目积攒下来的代码、文档、依赖库还是围绕 Noetic 写的你随手查的一个功能包可能都基于 Noetic。PX4 官方文档的默认开发环境就是 Ubuntu 20.04。PX4 的编译脚本、工具链版本、Gazebo 仿真搭配在 20.04 上经过的测试最充分。第三方依赖的兼容性。比如一些相机驱动、激光雷达 SDK、CUDA 版本厂商给的安装包往往优先适配 LTS长期支持版本。20.04 作为 2020 年的 LTS在 2025 年之前一直是“够新且稳定”的平衡点。不是说你不能用 22.04 或者更新版本而是如果你刚入门选择一个资料最多、踩坑代价最低的环境能省下大量查错时间。等你把整套流程跑通再考虑迁移也不迟。1.3 安装方式双系统、虚拟机还是 WSL 2确定了 Ubuntu 20.04 之后下一个问题是怎么装。三种主流方式各有取舍直接说我的建议安装方式优点缺点适用场景双系统性能最好硬件直通USB 设备识别最稳装系统有风险切换系统要重启长期开发、跑仿真、接飞控硬件虚拟机VMware/VirtualBox安装简单不影响原系统图形性能弱USB 透传偶尔抽风先体验、纯学习、临时用WSL 2启动快文件互通方便对 USB/串口设备支持麻烦GUI 配置复杂熟悉 Linux 命令、编译纯服务器程序我的建议很明确如果你准备认真做无人机开发直接上双系统。因为后面很可能会遇到连接 Pixhawk 飞控、接传感器、跑 Gazebo 3D 仿真这些场景双系统下这些事情的体验远好于虚拟机和 WSL 2。虚拟机适合你只是想先看看 Linux 长什么样WSL 2 适合只做算法模块的编码调试但一遇到硬件设备就容易卡壳。2. 新装系统后的第一轮“工程化装修”2.1 换源、更新、安装基础软件包不管你是刚装好系统还是拿到一台干净环境第一步永远是换软件源。Ubuntu 默认源在国外下载速度会让你怀疑人生。国内推荐换阿里云、清华或中科大的镜像源。打开终端先备份原始源文件这是个好习惯sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后编辑/etc/apt/sources.list把archive.ubuntu.com和security.ubuntu.com替换成镜像源地址。用 sed 可以一键完成sudo sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list sudo sed -i s/security.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list执行更新并顺手装上一批开发必备软件sudo apt update sudo apt upgrade -y sudo apt install -y vim git curl wget net-tools htop tmux \ terminator build-essential cmake python3 python3-pip \ openssh-server can-utils这里逐个说下为什么装这些build-essential提供 gcc/g/make任何 C/C 项目编译都绕不开cmake是绝大多数现代项目的构建工具git不用解释代码版本管理全靠它net-tools提供 ifconfig 等老牌网络命令排查 IP 时方便terminator是一个支持分屏的终端跑多个 ROS 节点时非常实用openssh-server让你可以用 SSH 从另一台电脑远程操作这台机器机载电脑开发尤其需要。2.2 把终端和 Shell 调教成“称手工具”环境装好后第一步就该配置好终端。不要小看这一步日常开发绝大部分时间在终端里度过终端顺不顺手直接影响效率。我会在~/.bashrc里加上几个最常用的 aliasecho alias llls -alF ~/.bashrc echo alias lals -A ~/.bashrc echo alias gsgit status ~/.bashrc echo alias gpgit pull ~/.bashrc source ~/.bashrcPython 方面Ubuntu 20.04 自带 Python 3.8建议用python3 -m pip而不是直接敲pip避免系统 Python 环境被搞乱。后续做 Python 开发强烈建议使用venv或 conda 隔离环境不要让 pip 的包直接装在系统 Python 里。我见过太多人因为直接在系统环境里pip install一些库把系统自带的包搞坏最后被迫重装系统。另外建议把中文输入法搞定。Ubuntu 20.04 上我推荐安装 fcitx5 中文拼音sudo apt install -y fcitx5 fcitx5-chinese-addons安装后在“设置—区域与语言—输入法”里添加拼音即可。终端里输代码时不需要中文输入法但写文档、查资料时没有它就很难受。2.3 用户、权限和软件安装的本质很多新手在 Ubuntu 里遇到的第一道坎是“Permission denied”。这背后是 Linux 的权限模型理解它才能彻底根治问题。Linux 下每个文件都有所有者、所属组和其他用户的读/写/执行权限。sudo只是让你临时以 root 身份执行命令不是说你以后所有操作都要加 sudo。如果你发现自己频繁需要 sudo 才能操作自己目录下的文件大概率是目录权限或所有者有问题。常用的用户和权限命令在这里做个小结sudo adduser newuser # 新建用户并创建用户目录 sudo usermod -aG sudo newuser # 把用户加到 sudo 组 sudo chown -R user:user dir # 修改文件所有者为 user sudo chmod 755 script.sh # 设置权限 rwxr-xr-x很多人喜欢sudo chmod 777解决问题这是个大忌。777 意味着所有用户都能读写执行在开发机上会埋下严重的安全隐患也会让文件所有者变得混乱。正确做法是管理好用户和组把当前用户加到合适的组里。比如无人机开发中经常要访问串口设备就要把用户加到 dialout 组sudo usermod -aG dialout $USER否则后面连飞控、接传感器时会一直提示没有权限打开设备节点。3. Linux 工程基础真正拉开差距的是系统思维3.1 文件系统理解“一切皆文件”很多新手觉得 Linux 命令背不完其实问题不在于背而在于没有理解 Linux 的底层设计哲学——一切皆文件。普通文件、目录、设备、甚至进程信息都可以用文件的方式去访问和操作。Linux 目录结构FHS是有固定规范的我用自己的理解快速梳理一遍/bin、/usr/bin系统命令和用户程序的存放位置。/etc配置文件所在地几乎所有软件的配置都在这。/home用户目录你自己的代码和文件都在这。/var日志、缓存等经常变化的文件比如/var/log/syslog。/opt第三方软件安装目录很多厂商 SDK 默认装这里。/tmp临时文件重启后会被清掉。这就是为什么我们常说要“把软件装到对的位置”。用 apt 安装的软件会把可执行文件放到/usr/bin配置文件放到/etc库文件放到/usr/lib这是 Debian 系的标准布局。而源码编译安装的软件默认装到/usr/local两者互不干扰。理解了目录规范再去看那些“找不到命令”“找不到库文件”的报错心里就有数了——大概率是 PATH 环境变量没包含对应目录或者动态链接库搜索路径不对。3.2 软件安装的三种方式不要混着用Ubuntu 里装软件有三种主要方式很多人经常混用导致依赖错乱apt 安装从软件仓库下载预编译好的 deb 包自动解决依赖。这是首选方式干净、可控。命令是sudo apt install 包名。pip 安装Python 包的安装方式只影响 Python 环境。要注意别用 sudo pip 装到系统解释器里除非你确定自己在干什么。源码编译安装从 GitHub 或官网拉源码自己./configure make sudo make install。这种方式灵活性最高但升级卸载全靠手动依赖问题也最多。很多无人机项目比如 PX4就是源码编译方式因为厂商没提供现成的 deb 包必须自己构建。我的原则是能用 apt 绝不用源码编译除非官方明确要求。PX4 这种项目之所以源码编译是因为它本身就是一个大型 monorepo需要自己拉子模块、管理工具链版本这也是为什么环境搭建对新手来说是道坎。3.3 进程、服务与日志定位开发中经常遇到“程序启动了但莫名其妙退出了”这类问题。在 Windows 上你可能习惯去任务管理器看但在 Linux 上最重要的三个命令是ps aux # 查看当前进程 top / htop # 实时看系统资源占用 systemctl status 服务名 # 查看系统服务状态Ubuntu 20.04 使用 systemd 管理服务和开机启动。比如你想让 SSH 服务开机自启sudo systemctl enable ssh sudo systemctl start ssh sudo systemctl status ssh排查问题时日志比进程状态更关键。系统日志集中在/var/log/而 systemd 管理服务的日志用journalctl查看journalctl -u ssh -f # 实时查看 SSH 服务的日志 journalctl -xe # 查看最近的系统错误日志我遇到过一个典型场景ROS 节点启动就崩终端只提示“段错误”看不出原因。后来用journalctl看到底层库的报错才发现是显卡驱动和某依赖库版本不匹配。这个思路可以复制到任何 Linux 问题排查上——先看日志再猜原因永远别瞎试。3.4 脚本化思维把重复劳动交给电脑一套环境搭建流程里有大量固定操作source 环境变量、编译、启动仿真。手动一条条敲不仅慢还容易漏。这时候就该写脚本。我给自己的环境准备了一个一键编译脚本结构大致这样#!/bin/bash set -e # 出错立即停止 echo [1/3] 初始化环境变量... source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash echo [2/3] 编译工作空间... cd ~/catkin_ws catkin_make echo [3/3] 设置环境... source ~/catkin_ws/devel/setup.bash echo 编译完成set -e是重点它让脚本在第一条失败的命令处停下来避免在错误基础上继续执行产生更多问题。写脚本时还有一个习惯值得养成把 ASCII 码转成大段界面的脚本兼容性问题处理好终端宽度不够时容易乱。4. 动手搭建无人机开发验证环境ROS PX4 仿真4.1 ROS Noetic 安装与 source 机制前面铺垫了这么多现在到核心环节。先装 ROS Noetic 桌面完整版sudo sh -c echo deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main /etc/apt/sources.list.d/ros-latest.list sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 sudo apt update sudo apt install -y ros-noetic-desktop-full安装完成后一定要执行这行把 ROS 环境变量写入 shell 配置echo source /opt/ros/noetic/setup.bash ~/.bashrc source ~/.bashrc这步极其关键。ROS 是一个庞大的软件集合所有 ROS 命令、功能包的位置都靠环境变量来指定。很多人安装完 ROS 后马上敲roscore结果提示找不到命令原因就是没 source。source 一次只在当前终端生效写进~/.bashrc才能真正一劳永逸。然后初始化 rosdep这是 ROS 管理功能包依赖的工具sudo rosdep init rosdep update国内网络环境下rosdep update经常卡住这是 ROS 新手最常遇到的第一个大坑我待会儿在最后一章专门讲解决办法。4.2 PX4 固件编译与 Gazebo 仿真ROS 装好只是第一步真正跑无人机仿真还需要 PX4 固件。从源码编译 PX4 的过程如下git clone --recursive https://github.com/PX4/PX4-Autopilot.git cd PX4-Autopilot make px4_sitl gazebositl是 Software In The Loop 的意思即软件在环仿真。这套机制把飞控固件当作一个普通 Linux 进程跑起来与 Gazebo 模拟器通信实现“无人机在电脑里飞行”的效果。首次编译会下载大量依赖耗时取决于网络状况20 到 40 分钟都算正常。如果编译过程中提示缺少依赖PX4 官方提供了一个自动化脚本bash ./PX4-Autopilot/Tools/setup/ubuntu.sh这个脚本会把需要的工具链、Python 库、交叉编译器都装好。但是要注意它会修改你系统里的 Python 环境所以更稳妥的做法是先创建一个 conda 环境或者 venv 环境再跑这个脚本。跑仿真前还要注意一个细节Gazebo 首次启动时会从网上拉取无人机模型文件国内访问模型库特别慢甚至直接卡在加载界面。常见的解决办法是提前把模型库下载好放到~/.gazebo/models目录下或者在启动环境里设置export GAZEBO_MODEL_PATH模型目录:$GAZEBO_MODEL_PATH把这些写入~/.bashrc就再也不会卡在加载界面了。4.3 机载电脑与交叉编译的工程思路无人机开发不仅有机载电脑的 Linux 程序还有飞控 MCU 上的固件。飞控固件编译和普通程序不一样它在性能强大的电脑上编译生成的是另一套 CPU 架构ARM可执行文件这个过程叫交叉编译。PX4 官方对 Pixhawk 系列飞控的固件编译方式是cd PX4-Autopilot make px4_fmu-v5_default它会自动调用预先配置好的交叉编译工具链把我们熟悉的gcc替换成了arm-none-eabi-gcc这类针对 ARM 的编译器。理解这一点很重要因为嵌入式平台比如 Zynq-7000 系列的软件开发也有类似流程先装对应平台厂商提供的交叉编译工具链然后设置CC、CXX等环境变量指向工具链再编译源码。这套思路在无人机、自动驾驶、机器人领域通用。以后你拿到一块新板子不用慌核心就是三步找工具链、配环境变量、编译测试程序验证。建议自己试着给一个最低限度的 hello world 写交叉编译脚本跑通一次后面上手会快很多。5. 实际开发中绕不开的坑与排查思路5.1 一套通用的 Linux 问题排查链路在经历了若干次“配置两天、运行三秒”之后我总结了一套自己的排查思路分享出来供参考复现场景什么命令、什么操作触发了问题尽量最小化复现。看报错信息报错信息里往往直接写明了原因不要跳过第一行红字。看日志journalctl -xe、/var/log/下的系统日志或者程序自己的 log 文件。确认环境变量command not found、库找不到八成是 PATH 或LD_LIBRARY_PATH没设对。确认权限Permission denied要么用 sudo要么改用户组和文件权限。二分定位如果是刚装完的软件回退到“装之前能用吗”来缩小范围。网上搜索把完整报错粘贴到搜索引擎注意看发布时间和系统版本是否匹配。这套链路看着简单但真遇到问题时能帮你少走弯路。我见过很多人遇到报错就开始盲目卸载重装折腾一整天发现是路径少了个斜杠非常浪费时间。5.2 高频坑一rosdep update 卡住前面提过rosdep update慢的问题。这个工具要访问 GitHub 上的资源列表在国内网络环境下经常超时。我用的解决方法是配置代理镜像思路是把 rosdep 的资源下载地址从 GitHub 换成国内可达的镜像地址sudo apt install -y python3-rosdep2 sudo sed -i s/raw.githubusercontent.com/raw.gitmirror.com/g /usr/lib/python3/dist-packages/rosdep2/sources_list.py sudo sed -i s/api.github.com/镜像地址/g /usr/lib/python3/dist-packages/rosdep2/gbpdistro_support.py关键点是找到你环境里 rosdep 的安装路径然后修改对应的 URL 前缀。如果你网络环境通畅此坑可以绕过但如果卡住超过 10 分钟建议直接动手换镜像。这个问题的本质是 rosdep 要下载一份“包名到依赖”的映射数据库文件不大但对网络要求高。理解了这一点后续遇到类似“下载慢”问题也就能举一反三了。5.3 高频坑二USB 设备权限与 dialout 组连接 Pixhawk 等飞控硬件时最典型的问题是ls /dev/ttyACM0 # 提示Permission denied原因就是当前用户对串口设备节点没有访问权限。前面已经提到解决办法把用户加入 dialout 组并重新登录sudo usermod -aG dialout $USER # 重新登录后生效之所以这么麻烦是因为 Linux 对设备的访问权限继承自“组”的概念。设备节点的默认组是 dialout所以正确做法是把用户加进这个组而不是用chmod 777改设备权限。用后者你每次插拔设备后权限又变回默认还是要重新改非常不优雅。顺带提一句连接飞控后在 QGroundControl 里看不到设备也经常是同样的问题。别急着换数据线先查权限。5.4 高频坑三Python 包冲突与 pip 乱装无人机项目通常依赖大量 Python 包比如 MAVSDK-Python、numpy、opencv-python。很多新手图省事直接sudo pip3 install xxx结果可能把系统 Python 环境弄坏甚至导致apt都无法正常工作。我自己的方案是所有 Python 开发需求一律使用虚拟环境。可以以venv为例cd ~/project python3 -m venv .venv source .venv/bin/activate pip install numpy opencv-python这样每个项目的依赖互相隔离某个项目依赖版本升级不影响其他项目也不会动到系统 Python。如果遇到某些需要 Python 版本比较固定的项目比如 ROS 的某些包只支持 Python 3.8可以直接用 conda 创建对应版本环境。20.04 自带的 Python 3.8 对 ROS 生态而言其实是优势别轻易升级系统默认 Python。5.5 高频坑四Gazebo 加载慢或黑屏Gazebo 首次启动你会看到一个无限转圈的黑界面大概率是在下载模型库。除了前面提到的提前下载模型库并设置GAZEBO_MODEL_PATH外还有一个常见的性能问题你的电脑显卡不支持 OpenGL 硬件加速Gazebo 会回退到软件渲染画面极其卡顿。解决办法是安装显卡驱动或者调整 Gazebo 的环境变量export LIBGL_ALWAYS_SOFTWARE1但注意这是无奈之举软件渲染会严重影响仿真性能只能作为临时兜底。如果你计划长期做视觉仿真还是建议用一台带独立显卡、驱动正常的电脑或者直接清掉双系统用真实 Linux 系统性能比虚拟机里跑 Gazebo 好太多。我知道这一节列的坑不算全面但都是实际开发中最容易卡住新人的地方。环境搭建本身就是一次“练手”经历过这些问题以后再看到类似的报错信息你的第一反应就不再是慌张而是按套路定位、解决。这就是工程经验和纯粹看教程之间的最大区别。最后分享一点个人体会搭建环境的过程确实煎熬但当你第一次在 Gazebo 里看到无人机起飞第一次通过 ROS 拿到仿真传感器数据时那种成就感会告诉你这一切都值得。别怕折腾环境本身就是你对 Linux 的第一堂实战课。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进