1. 为什么Ego-Planner的环境搭建总在第一步就卡住
Ego-Planner 是近年来在自主导航圈子里讨论度很高的一套轨迹规划方案,它最大的特点是不依赖ESDF地图,直接用梯度信息在障碍物附近做局部优化,因此规划速度快、轨迹平滑,特别适合无人机、小型地面机器人这类算力有限的平台。但很多人在真正跑通它之前,就已经倒在了环境搭建这一步——不是编译报错,就是仿真里飞机不动,或者 Gazebo 界面疯狂闪烁根本没法调试。
我自己前前后后在三台不同配置的机器上装过 Ego-Planner,踩的坑足够写一本小册子。这篇内容就是把这些坑按顺序摊开讲清楚,从系统环境选择、ROS 安装、依赖库编译,一直到 Gazebo 仿真跑起来看到轨迹,每一步都告诉你为什么这么做、哪里最容易出错、出错了怎么排查。适合已经有一点 ROS 基础、想上手 Ego-Planner 但被环境折磨过的同学,也适合完全没接触过 WSL 但想在 Windows 上做仿真的朋友。
先说一个反直觉的结论:Ego-Planner 跑不起来,八成不是代码问题,而是环境版本和依赖顺序的问题。它依赖 Ceres Solver 做非线性优化,依赖 ROS 做通信,依赖 Gazebo 做仿真,这三者之间版本咬合非常紧。你随便挑一个"最新版"组合,大概率编译不过。所以下面我会先讲清楚版本怎么选,再讲怎么装。
1.1 系统与ROS版本的选择逻辑
Ego-Planner 官方主要在 Ubuntu 18.04 + ROS Melodic 和 Ubuntu 20.04 + ROS Noetic 上验证过。这两个组合是经过大量用户实测的稳定搭配。如果你用 Ubuntu 22.04 + ROS2 Humble,理论上也能跑,但需要改不少 launch 文件和消息类型,对新手不友好。
我的建议很直接:想省事就用 Ubuntu 20.04 + ROS Noetic。原因有三点。第一,Noetic 是 ROS1 的最后一个长期支持版本,Python3 支持完善,很多老包不用改就能用。第二,Ego-Planner 的很多依赖包(比如uav_utils、pose_utils)在 Noetic 下编译最顺。第三,网上现成的教程和 issue 解答大多基于这个组合,遇到问题好搜。
如果你只有 Windows 电脑,那就用 WSL2 装 Ubuntu 20.04。WSL2 的好处是文件系统性能比 WSL1 好很多,编译大型项目不会慢到怀疑人生。但要注意,WSL2 跑 Gazebo 需要额外配置图形界面,否则你会看到一个黑屏或者直接报错退出。
1.2 WSL2下Ubuntu的安装与常见卡点
在 Windows 上装 WSL2,最标准的命令是wsl --install。但实测下来,这个命令在国内网络环境下经常卡在下载环节,甚至直接超时。我的做法是手动分步来:
- 先在"启用或关闭 Windows 功能"里勾选"适用于 Linux 的 Windows 子系统"和"虚拟机平台",然后重启。
- 去 Microsoft Store 搜索 Ubuntu 20.04 LTS 直接安装。Store 的下载速度通常比命令行稳定。
- 安装完成后首次启动,设置用户名和密码。密码输入时屏幕不显示是正常的,别以为键盘坏了。
装完之后第一件事是换源。默认的源在国内访问很慢,换成国内镜像源能省下大量等待时间。换源命令网上很多,核心就是修改/etc/apt/sources.list,把archive.ubuntu.com替换成国内镜像地址。换完执行sudo apt update && sudo apt upgrade,这一步可能要跑十几分钟,耐心等。
注意:WSL2 的 Ubuntu 默认没有图形界面。如果你直接敲
gazebo,会提示找不到显示。需要配置 X Server 转发,或者用 WSLg(Windows 11 自带)。Windows 10 用户建议装 VcXsrv 做 X11 转发,Windows 11 用户直接用 WSLg 就行,省事很多。
1.3 ROS Noetic的安装:为什么推荐一键脚本
ROS Noetic 的官方安装步骤涉及添加源、添加密钥、安装一堆包,中间任何一步网络抖动都可能失败。对于新手,我推荐用"鱼香ROS"的一键安装脚本。这个脚本会自动处理源、密钥、依赖,还会帮你选版本。虽然有人觉得用脚本不够"硬核",但说实话,环境搭建阶段的目标是快速得到一个能用的系统,不是练习敲命令。
一键脚本跑完之后,验证是否成功的方法很简单:新开一个终端,输入roscore。如果看到started core service就说明 ROS 核心没问题。再开一个终端输入rosrun turtlesim turtlesim_node,能看到小乌龟窗口就说明图形界面也通了。
这里有个高频坑:WSL2 下roscore报错说无法绑定端口。这通常是因为 Windows 的防火墙或者 WSL 的网络模式问题。解决办法是在 WSL 里执行sudo apt install net-tools,然后用ifconfig确认 IP,再检查/etc/hosts里有没有正确的主机名映射。另一个办法是把 WSL 的网络模式改成 mirrored(Windows 11 22H2 以上支持),能省掉很多网络配置的麻烦。
2. Ego-Planner依赖链的编译顺序与Ceres Solver的坑
环境通了之后,下一步是编译 Ego-Planner 本身。但别急着 clone 代码,因为它依赖好几个第三方库,顺序错了就会连环报错。我见过太多人一上来就catkin_make,然后被满屏的红色错误吓退。
2.1 依赖库清单与安装优先级
Ego-Planner 的核心依赖包括:Eigen3、Ceres Solver、PCL(点云库)、以及一些 ROS 功能包。其中Ceres Solver 是最容易出问题的,因为它的版本和 Eigen 版本强相关。
我的安装顺序是这样的:
| 顺序 | 依赖项 | 安装方式 | 备注 |
|---|---|---|---|
| 1 | Eigen3 | sudo apt install libeigen3-dev | 系统源自带,版本够用 |
| 2 | Ceres Solver | 源码编译 | 必须指定 Eigen 路径 |
| 3 | PCL | sudo apt install libpcl-dev | 注意版本兼容 |
| 4 | ROS 功能包 | sudo apt install ros-noetic-* | 按需安装 |
| 5 | Ego-Planner | catkin 编译 | 最后一步 |
为什么 Ceres 要源码编译?因为 apt 源里的 Ceres 版本可能和 Ego-Planner 要求的 API 不一致。Ego-Planner 用到了 Ceres 的AutoDiffCostFunction和Problem::AddResidualBlock,这些接口在不同版本间有细微差异。源码编译能确保你拿到的是兼容版本。
2.2 Ceres Solver编译时的Eigen路径陷阱
编译 Ceres 的标准流程是:
git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver mkdir build && cd build cmake .. make -j4 sudo make install但这里有个大坑:cmake 默认可能找不到 Eigen。如果 Eigen 装在非标准路径,或者系统里有多个 Eigen 版本,cmake 就会报Eigen not found。解决办法是在 cmake 时显式指定:
cmake -DEIGEN_INCLUDE_DIR=/usr/include/eigen3 ..另一个坑是Ceres 编译到一半内存爆掉。Ceres 的模板实例化非常吃内存,make -j4在小内存机器上可能直接 OOM。如果你机器只有 8G 内存,建议用make -j2甚至make单线程。慢是慢点,但不会崩。
编译完成后,验证 Ceres 是否装好的方法是写一个最小的测试程序,链接-lceres,看能不能编译通过。这一步别省,因为后面 Ego-Planner 编译失败时,你至少能确定不是 Ceres 的问题。
2.3 Ego-Planner源码编译的报错排查链路
到了编译 Ego-Planner 这一步,最常见的报错有三类:
第一类:找不到头文件。比如fatal error: uav_utils/...。这说明依赖的 ROS 包没装全。Ego-Planner 依赖uav_utils、pose_utils、quadrotor_msgs等包,这些通常需要从源码编译。把它们 clone 到工作空间的src目录下,一起catkin_make。
第二类:Ceres 链接错误。比如undefined reference to ceres::...。这通常是 CMakeLists.txt 里没正确链接 Ceres。检查find_package(Ceres REQUIRED)和target_link_libraries是否写对。
第三类:Eigen 对齐错误。运行时报invalid pointer或者段错误,很可能是 Eigen 的aligned_allocator问题。Ego-Planner 里用了大量固定大小的 Eigen 类型,如果容器没指定对齐分配器,就会崩。解决办法是在定义std::vector时加上Eigen::aligned_allocator。
排查顺序建议是:先确认所有依赖包都编译通过,再单独编译 Ego-Planner,最后跑仿真。不要一次性把所有包扔进去编译,那样报错信息会混在一起,根本分不清是谁的问题。
3. Gazebo仿真跑通的关键配置与界面闪烁处理
编译通过只是第一步,真正跑仿真时还有一堆坑等着。最典型的就是 Gazebo 界面闪烁、模型加载不出来、飞机悬停不动。
3.1 Gazebo界面闪烁的根本原因
"为什么 Gazebo 界面一直在闪"是搜索量极高的问题。这个现象在 WSL2 + X11 转发环境下特别常见。根本原因是图形渲染的垂直同步和转发延迟不匹配。Gazebo 默认用 OpenGL 渲染,而 X11 转发对 OpenGL 的支持有限,导致画面撕裂和闪烁。
解决办法有几个层次:
- 最简单:在 Gazebo 启动参数里加
--render-engine ogre,强制用 Ogre 渲染引擎,兼容性更好。 - 进阶:配置 WSLg(Windows 11),它原生支持 GPU 加速,闪烁问题基本消失。
- 终极:直接用双系统或者物理机装 Ubuntu,彻底避开转发问题。
如果只是偶尔闪,不影响操作,也可以忍。但如果闪到没法点菜单,那就必须处理。
3.2 仿真启动文件的参数解读
Ego-Planner 的仿真通常通过一个 launch 文件启动,里面会同时拉起 Gazebo、RViz、规划器节点。以常见的simulator.launch为例,关键参数包括:
map_size:地图尺寸,决定了仿真世界的边界。obstacle_num:障碍物数量,太少测不出避障效果,太多会拖慢规划。flight_type:飞行模式,1 是手动点选目标点,2 是预设轨迹。use_gazebo:是否用 Gazebo 做物理仿真,设 false 就只跑 RViz 可视化。
我建议第一次跑的时候把obstacle_num设小一点,比如 5 到 10 个,先确认规划器能出轨迹。等跑通了再增加障碍物密度,测试极限性能。
3.3 飞机不动或轨迹不显示的排查步骤
仿真启动后,如果 RViz 里看不到轨迹,或者飞机悬停不动,按这个顺序查:
- 检查话题是否发布。
rostopic list看有没有/planning/trajectory和/odom。没有的话说明规划器节点没起来。 - 检查坐标系。RViz 的 Fixed Frame 要设成
world或map,设错了什么都看不到。 - 检查目标点是否发布。手动模式下需要你在 RViz 里用
2D Nav Goal点一个目标,飞机才会动。 - 检查 Gazebo 是否暂停。Gazebo 左下角有个播放按钮,有时候启动后默认是暂停状态,点一下才动。
还有一个隐蔽的坑:WSL2 下时间同步问题。WSL2 的时钟可能和 Windows 主机不同步,导致 ROS 的use_sim_time参数混乱,表现为轨迹时间戳跳变。解决办法是在 WSL 里执行sudo hwclock -s同步硬件时钟,或者在 launch 文件里关掉use_sim_time。
4. 从仿真到实机的经验迁移与性能调优
仿真跑通之后,很多人会想直接上实机。但仿真和实机的差距,在 Ego-Planner 上体现得特别明显。
4.1 仿真参数与实机参数的差异
仿真里飞机是理想模型,没有风阻、没有电机延迟、没有传感器噪声。实机上这些全都有。所以直接把仿真参数搬到实机,大概率会炸机。
需要调整的核心参数包括:
- 最大速度:仿真里可以设 5m/s,实机建议先设 1m/s,跑稳了再往上加。
- 最大加速度:仿真里设 10m/s²,实机建议 2m/s² 起步。
- 规划频率:仿真里 100Hz 没问题,实机上受限于机载计算机算力,可能只能跑 30Hz。
- 安全距离:仿真里可以贴着障碍物飞,实机上要留至少 0.5m 余量,因为定位有漂移。
我的经验是,实机调试时先把规划器的保守程度拉满,也就是速度慢、加速度小、安全距离大。等飞稳了,再一项一项往激进调。每次只调一个参数,调完飞一次,记录表现。这样出了问题能快速定位是哪个参数导致的。
4.2 机载算力不足时的降级策略
Ego-Planner 虽然比基于 ESDF 的方法轻量,但在低算力平台(比如树莓派、Jetson Nano)上跑,还是可能吃力。降级策略有几个方向:
- 降低地图分辨率:把体素地图的分辨率从 0.1m 调到 0.2m,内存和计算量都减半。
- 减少优化迭代次数:Ceres 的最大迭代次数从 50 降到 20,规划时间能缩短一半,轨迹质量略降但通常够用。
- 限制规划范围:只对飞机前方一定范围内的障碍物做优化,远处的忽略。
这些降级会牺牲一些轨迹最优性,但在算力受限时是必要的取舍。关键是要在仿真里先验证降级后的参数还能不能安全避障,别直接上实机试。
4.3 定位漂移对规划器的影响
Ego-Planner 依赖定位系统提供的位置和速度。如果定位漂移大,规划器会以为自己在 A 点,实际在 B 点,规划的轨迹就会撞墙。
常见的定位方案有 VINS、LOAM、动捕系统等。动捕最准但贵,VINS 便宜但漂移大。用 VINS 跑 Ego-Planner 时,一定要把规划器的安全距离调大,抵消漂移带来的误差。另外可以在规划器里加一个"定位置信度"检查,置信度低时自动减速或悬停。
我在实际项目里遇到过 VINS 在快速旋转时跟丢的情况,飞机直接朝墙飞。后来加了一个简单的保护逻辑:如果连续几帧定位跳变超过阈值,就触发紧急悬停。这个逻辑救过好几次飞机。
5. 几个让我印象深刻的踩坑实录
5.1 WSL离线安装Ubuntu的曲折过程
有一次在客户现场,网络受限,没法从 Store 下载 Ubuntu。只能走离线安装。离线包需要提前下载好.appx文件,然后用 PowerShell 的Add-AppxPackage命令安装。但这里有个坑:离线包安装后,WSL 的默认版本可能是 1 而不是 2。需要用wsl --set-version Ubuntu-20.04 2手动切换。切换过程要几分钟,期间没有任何进度提示,容易以为卡死了。
还有一次,离线包安装后启动报错your version of windows subsystem for linux is too old。这是因为 Windows 的 WSL 内核组件没更新。解决办法是单独下载 WSL2 内核更新包安装,或者直接升级 Windows 版本。
5.2 Gazebo模型加载失败的隐藏原因
Gazebo 启动后如果一直显示空世界,或者模型是白模,通常是模型库没下载全。Gazebo 的模型默认从在线库拉取,网络不好就会失败。解决办法是提前把模型库下载到本地~/.gazebo/models目录,然后在启动参数里设GAZEBO_MODEL_PATH指向本地目录。
另一个隐蔽原因是模型文件的权限问题。如果模型是从别的机器拷贝过来的,文件权限可能不对,Gazebo 读不了。用chmod -R 755改一下权限就好。
5.3 Ceres版本冲突导致的诡异崩溃
最诡异的一次崩溃是:仿真跑了几秒钟后,规划器节点突然退出,没有任何错误信息。查了半天才发现是系统里有两个 Ceres 版本,一个在/usr/local/lib,一个在/usr/lib。运行时链接到了旧版本,和新版本的 API 不兼容,导致内存越界。
解决办法是编译时用ldd检查可执行文件链接的 Ceres 路径,确保指向你编译的那个版本。如果系统里有多个版本,可以在 CMakeLists.txt 里显式指定Ceres_DIR。
6. 给准备上手Ego-Planner的朋友几句实在话
Ego-Planner 是一套很优秀的规划方案,但它的环境搭建确实有门槛。我的建议是:别追求一次装好,做好折腾半天的心理准备。遇到报错先看错误信息的第一行,那通常是最根本的原因。后面的错误往往是连锁反应。
另外,仿真跑通不等于实机能飞。仿真里调好的参数,实机上要重新调。实机调试时,安全永远第一,宁可飞得慢一点、保守一点,也别为了追求效果冒险。
最后分享一个小技巧:把整个环境搭建过程写成一个脚本,包括换源、装依赖、编译。这样下次换机器或者重装系统,一条命令就能恢复环境,省下大量重复劳动。我自己的脚本已经迭代了七八个版本,现在装一台新机器从零到跑通仿真,半小时搞定。这个投入绝对值得。