ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

WSL+ROS环境下Ego-Planner部署与仿真避坑指南

WSL+ROS环境下Ego-Planner部署与仿真避坑指南 1. 环境搭建前的整体思路与方案选型1.1 为什么选择WSL加ROS这套组合Ego-Planner是浙大FAST实验室开源的一套基于梯度的局部轨迹规划算法在无人机自主导航领域被广泛引用。它的核心优势在于不需要ESDF地图直接用稀疏的AABB障碍物信息做梯度优化计算效率比Fast-Planner那一代高出一大截。但很多人卡在第一步——环境搭不起来。我前后在三台不同配置的机器上部署过Ego-Planner踩过的坑基本覆盖了从系统层到编译层的所有环节。先说方案选型为什么用WSL而不是纯Ubuntu双系统或者虚拟机原因很直接——日常办公还得用Windows双系统切换成本太高虚拟机跑Gazebo这种3D仿真显卡直通麻烦帧率低到没法看。WSL2支持GPU加速需要WSLg和对应的驱动Gazebo能跑到接近原生的性能同时Windows和Linux的文件系统可以互通改代码用VSCode远程连接WSL体验比纯Linux桌面还顺手。ROS版本的选择上Ego-Planner官方推荐Ubuntu 20.04加ROS Noetic。这个组合是经过验证最稳的因为Ego-Planner依赖的Ceres Solver、PCL、Eigen这些库在Noetic下版本匹配度最好。有人尝试在Ubuntu 22.04加ROS2 Humble上跑理论上可行但需要改不少CMake配置和消息类型对于第一次接触这个项目的人来说没必要给自己增加难度。先把Noetic跑通理解整个数据流之后再考虑迁移ROS2。1.2 WSL版本选择与安装方式对比WSL现在有两个主要版本WSL1和WSL2。Ego-Planner必须用WSL2因为WSL1不支持完整的系统调用Gazebo的图形渲染和Ceres的某些底层计算会出问题。检查当前WSL版本很简单在PowerShell里执行wsl -l -v就能看到每个发行版对应的版本号。安装方式有两种微软商店一键安装和命令行离线安装。商店安装最省事但下载速度看网络脸色有时候一个Ubuntu镜像能下半小时。命令行安装用wsl --install -d Ubuntu-20.04同样受网络影响。如果你遇到wsl --install 太慢的情况我的建议是直接去下载Ubuntu 20.04的WSL离线包rootfs.tar.gz格式然后用wsl --import命令导入。这个离线包大概几百MB用下载工具拉比商店快得多。导入命令是这样的wsl --import Ubuntu-20.04 D:\wsl\Ubuntu2004 D:\wsl\ubuntu2004.rootfs.tar.gz --version 2第一个参数是发行版名称第二个是安装目标路径第三个是离线包路径。导入完成后用wsl -d Ubuntu-20.04进入系统。这种方式的好处是安装位置可控不会默认塞到C盘用户目录下后期磁盘空间管理方便很多。注意导入的离线包如果是老版本进去之后先执行sudo apt update sudo apt upgrade把基础包更新一遍不然后面装ROS可能会遇到依赖版本冲突。1.3 显卡驱动与GUI支持的准备WSL2跑Gazebo需要图形界面支持。Windows 11自带WSLg装好WSL2之后GUI应用可以直接显示。Windows 10的话需要额外配置X Server比如VcXsrv或者Xming。我实测下来Windows 11加WSLg的体验明显更好窗口缩放、剪贴板共享、音频都正常Gazebo的界面不会闪。显卡驱动方面NVIDIA显卡需要安装Windows端的Game Ready驱动版本号470以上WSL里面不需要单独装显卡驱动系统会自动挂载/usr/lib/wsl/lib下的库。验证方法是在WSL里执行nvidia-smi如果能正常输出显卡信息就说明GPU直通成功了。AMD显卡的支持相对麻烦一些需要安装对应的ROCm驱动而且不是所有型号都支持这一点要提前确认。如果nvidia-smi报错或者Gazebo界面一直在闪大概率是驱动版本不匹配或者WSLg的渲染后端有问题。可以尝试在WSL里设置环境变量export LIBGL_ALWAYS_SOFTWARE1强制软件渲染虽然性能差一些但至少能跑起来排查问题。2. ROS与依赖库的安装细节2.1 用鱼香ROS一键安装还是手动配置ROS Noetic的安装方式有两种主流选择手动添加源然后apt安装或者用鱼香ROS一键安装脚本。手动安装的步骤是设置sources.list、添加密钥、apt update、apt install ros-noetic-desktop-full。这个过程本身不复杂但国内网络环境下下载速度是个大问题ros-noetic-desktop-full这个包加起来有好几个GB中途断线就得重来。鱼香ROS一键安装脚本wget http://fishros.com/install -O fishros bash fishros的优势在于自动换源它会根据你的系统版本选择最快的镜像源而且把ROS、Gazebo、常用工具链都串起来装。我试过在全新WSL环境里用这个脚本从零到能跑roscore大概十五分钟比手动配置快不少。但要注意这个脚本安装的Gazebo版本可能和Ego-Planner要求的版本有差异装完之后需要确认一下Gazebo的版本号。手动安装的话关键命令是这些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 ros-noetic-desktop-full装完之后别忘了echo source /opt/ros/noetic/setup.bash ~/.bashrc不然每次开终端都要手动source。2.2 Ceres Solver的编译与版本匹配Ego-Planner依赖Ceres Solver做非线性优化。ROS Noetic自带的Ceres版本是1.14但Ego-Planner的某些分支需要Ceres 2.0以上。如果你直接用apt安装的libceres-dev编译Ego-Planner时可能会报找不到ceres::Manifold或者LocalParameterization相关的错误这就是版本不匹配的典型症状。我的建议是源码编译Ceres 2.1.0。步骤不复杂但依赖项要装齐sudo apt install cmake libgoogle-glog-dev libgflags-dev libatlas-base-dev libsuitesparse-dev git clone https://ceres-solver.googlesource.com/ceres-solver cd ceres-solver git checkout 2.1.0 mkdir build cd build cmake .. make -j4 sudo make install编译过程中如果报Eigen版本太低的错误需要升级Eigen到3.3以上。Ubuntu 20.04自带的Eigen是3.3.7一般够用但如果遇到问题就去Eigen官网下载3.4.0源码编译安装。实操心得Ceres编译很吃内存WSL默认分配的内存可能不够。建议在Windows用户目录下创建.wslconfig文件写入memory8GB和processors4然后wsl --shutdown重启WSL这样编译时不会因为OOM被kill。2.3 PCL与Eigen的常见冲突处理PCL点云库在Ego-Planner里主要用于地图可视化和点云处理。ROS Noetic自带的PCL是1.10这个版本和Eigen 3.3.7配合没问题。但如果你手动升级了Eigen到3.4PCL编译时可能会报alignment相关的运行时错误这是因为Eigen 3.4对内存对齐的要求更严格而老版本PCL的某些结构体没有加EIGEN_MAKE_ALIGNED_OPERATOR_NEW宏。解决办法有两个一是降级Eigen回3.3.7二是给PCL打补丁重新编译。我推荐第一个方案因为Ego-Planner对Eigen版本没有硬性要求3.3.7完全够用。降级的方法是sudo apt install libeigen3-dev3.3.7-2如果apt里没有这个版本就去Eigen的GitLab仓库下载3.3.7的源码编译安装。另一个常见问题是PCL和ROS的pcl_ros包版本冲突。如果你在CMakeLists里同时find_package了PCL和pcl_ros可能会遇到符号重复定义的链接错误。这时候需要确保find_package(PCL REQUIRED)在find_package(catkin REQUIRED COMPONENTS pcl_ros)之前让CMake优先使用系统PCL。3. Ego-Planner源码编译与仿真环境配置3.1 源码下载与工作空间结构Ego-Planner的源码在GitHub上直接clone速度慢的话可以用gitee的镜像。整个仓库包含几个子模块ego-planner核心算法、uav_simulator仿真环境、map_generator地图生成。clone的时候记得加--recursive把子模块一起拉下来。mkdir -p ~/ego_ws/src cd ~/ego_ws/src git clone --recursive https://github.com/ZJU-FAST-Lab/ego-planner.git工作空间的目录结构建议保持默认不要随意改动包名和路径因为Ego-Planner的launch文件里有很多相对路径引用。如果你需要同时跑多个版本的Ego-Planner可以用不同的工作空间隔离比如~/ego_ws_v1和~/ego_ws_v2每次编译前source对应的setup.bash。编译之前先装依赖sudo apt install libarmadillo-dev libdw-devlibarmadillo-dev是线性代数库libdw-dev用于堆栈回溯。这两个包不装的话编译会报错。3.2 catkin_make编译参数调优Ego-Planner的编译时间比较长尤其是uav_simulator里的local_sensing包包含大量模板代码。默认的catkin_make是单线程编译在WSL里可能要跑十几分钟。可以用catkin_make -j4开四线程但要注意内存占用如果WSL只分配了4GB内存开四线程可能会卡死。编译命令cd ~/ego_ws catkin_make -j4 -DCMAKE_BUILD_TYPERelease-DCMAKE_BUILD_TYPERelease很重要Debug模式下Ego-Planner的优化求解会慢到没法用。Release模式开启-O3优化轨迹规划能跑到实时。如果编译过程中报undefined reference to ceres::...说明Ceres的链接有问题。检查CMakeLists.txt里有没有find_package(Ceres REQUIRED)以及target_link_libraries里有没有加${CERES_LIBRARIES}。有时候Ceres装到了/usr/local/lib但链接器找不到需要export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH。注意每次修改CMakeLists或者添加新文件后最好先catkin_make clean再重新编译避免增量编译的缓存问题。我遇到过好几次改了代码但编译结果没变的情况clean之后就好了。3.3 Gazebo仿真环境的启动与调试Ego-Planner的仿真启动文件在uav_simulator/launch目录下常用的有single_run.launch和swarm.launch。单机仿真用single_run.launch就够了roslaunch ego_planner single_run.launch这个launch会启动Gazebo、加载地图、生成无人机模型、启动Ego-Planner节点。如果Gazebo界面一直在闪或者黑屏先检查WSLg是否正常工作。可以在WSL里跑glxgears测试OpenGL渲染如果glxgears也闪那就是WSLg的渲染问题尝试更新Windows端的显卡驱动或者在WSL里设置export LIBGL_ALWAYS_INDIRECT0。Gazebo启动后在RViz里应该能看到无人机模型和点云地图。用2D Nav Goal工具点击目标点无人机就会开始规划轨迹并飞行。如果无人机不动检查/goal话题有没有收到消息以及Ego-Planner节点有没有正常输出规划结果。仿真环境里的地图是map_generator生成的随机障碍物地图如果你想用自己的地图可以把点云文件放到map_generator/resource目录下然后修改launch文件里的map_size和obstacle_num参数。4. 常见问题排查与避坑经验4.1 WSL相关问题的快速定位WSL的问题主要集中在网络、文件系统和GUI三个方面。网络问题表现为apt下载慢、git clone超时解决办法是换国内源把/etc/apt/sources.list里的archive.ubuntu.com换成mirrors.tuna.tsinghua.edu.cn或者mirrors.aliyun.com。文件系统问题表现为编译时IO错误或者文件权限异常这是因为WSL2的ext4虚拟磁盘和Windows的NTFS文件系统之间有转换开销建议把代码放在WSL的~/目录下不要放在/mnt/c/里。GUI问题最常见的就是Gazebo闪屏。我遇到过三种情况一是WSLg版本太老wsl --update更新一下就好二是显卡驱动不匹配去NVIDIA官网下载最新驱动三是Gazebo的渲染引擎和WSLg的Wayland协议不兼容这时候可以试试export GDK_BACKENDx11强制用X11后端。还有一个坑是WSL的时钟漂移。WSL2的虚拟化时钟有时候会和Windows主机不同步导致ROS的TF变换报时间戳错误。解决办法是在WSL里执行sudo hwclock -s同步硬件时钟或者装一个ntpdate定时同步。4.2 编译错误的分类与解决思路Ego-Planner的编译错误大致分四类找不到头文件、链接错误、模板实例化错误、C标准不匹配。找不到头文件通常是依赖没装全根据报错信息里的头文件名去apt搜索对应的dev包安装就行。链接错误一般是库路径问题用ldd命令检查可执行文件依赖的库有没有解析到正确的路径。模板实例化错误比较隐蔽通常表现为一大堆instantiation of...的报错。这种错误往往是Eigen或者PCL的版本问题降级到ROS Noetic自带的版本一般能解决。C标准不匹配的话在CMakeLists里加set(CMAKE_CXX_STANDARD 14)或者set(CMAKE_CXX_STANDARD 17)Ego-Planner用的是C14但某些依赖可能需要C17。下面这个表格整理了我遇到过的典型编译错误和对应的解决方法错误信息关键词可能原因解决方法undefined reference to ceres::Ceres链接路径不对检查LD_LIBRARY_PATH重新编译CeresEigen::internal::plain_arrayEigen版本冲突降级Eigen到3.3.7pcl::PointCloud相关报错PCL版本不匹配用ROS自带的PCL不要手动升级cannot find -larmadillo缺少armadillo库sudo apt install libarmadillo-devC17 required编译器标准太低CMakeLists里设置CXX_STANDARD 174.3 仿真运行时的性能优化Ego-Planner在WSL里跑仿真性能瓶颈主要在Gazebo的物理引擎和Ego-Planner的优化求解。Gazebo默认的物理更新频率是1000Hz对于无人机仿真来说太高了可以降到250Hz减少CPU占用。修改方法是在world文件里把max_step_size从0.001改成0.004。Ego-Planner的优化求解频率默认是100Hz如果CPU跟不上可以降到50Hz。在advanced_param.xml里找到optimization_rate参数改成50就行。另外RViz的点云显示很吃GPU如果帧率低可以把点云的Decay Time调小或者直接关掉点云显示只看轨迹。WSL的内存分配也很关键。默认WSL2最多用主机内存的50%如果主机是16GB内存WSL最多用8GB。跑Gazebo加Ego-Planner8GB勉强够用但编译的时候可能会OOM。建议在.wslconfig里设置memory12GB给WSL多分一点。实操心得如果Gazebo跑起来后无人机抖动厉害或者直接穿模检查一下local_sensing的raycast参数。这个参数控制深度相机的射线投射数量数值太大会导致计算量爆炸太小则障碍物检测不全。我一般设成raycast_num30在精度和性能之间比较平衡。4.4 从仿真到实机的过渡注意事项仿真跑通之后很多人想直接上实机。这里有几个关键差异要注意仿真里的无人机模型是理想化的没有电机延迟、没有传感器噪声、没有风扰。实机上Ego-Planner的轨迹可能会因为定位漂移而撞障碍物。建议先在仿真里加噪声测试把local_sensing的noise_std参数调大模拟真实传感器的噪声水平。实机的状态估计器也很关键。仿真里用的是Gazebo的ground truth位姿实机上需要用VINS或者FAST-LIO做状态估计。Ego-Planner订阅的是/odom话题实机上要确保状态估计器发布的/odom频率稳定在50Hz以上否则规划器会因为位姿跳变而输出抖动轨迹。最后实机的安全策略一定要做好。Ego-Planner本身没有紧急停止功能需要在外部加一个安全节点监测无人机和障碍物的距离小于安全阈值时直接切offboard模式悬停。这个安全节点用简单的距离判断就行不需要太复杂但一定要有。5. 工具链与辅助配置的补充说明5.1 VSCode远程连接WSL的开发环境配置用VSCode连WSL开发Ego-Planner体验比在WSL终端里用vim好太多。装一个Remote - WSL扩展然后在WSL里执行code .就能打开当前目录。VSCode会自动在WSL里装一个server端代码补全、跳转、调试都在WSL环境里运行和本地开发没区别。C的智能提示需要配置c_cpp_properties.json把ROS的头文件路径加进去{ configurations: [ { name: Linux, includePath: [ ${workspaceFolder}/**, /opt/ros/noetic/include/**, /usr/include/eigen3/**, /usr/local/include/** ], cppStandard: c14 } ], version: 4 }调试的话在launch.json里配置gdb可以给Ego-Planner的核心节点打断点单步跟踪轨迹优化的过程。不过Ego-Planner的优化求解在Ceres内部断点打进去容易卡死建议只在规划器的入口和出口打日志不要深入Ceres内部。5.2 常用调试工具与话题监控ROS的调试工具链很成熟rostopic echo看话题数据rosbag record录包回放rqt_graph看节点连接关系。Ego-Planner的关键话题有/goal目标点、/odom位姿、/planning/trajectory规划轨迹、/planning/pos_cmd位置指令。调试的时候先确认/odom有数据再看/goal有没有收到最后看/planning/trajectory有没有输出。如果轨迹规划失败Ego-Planner会在终端打印Failed to generate trajectory之类的日志。常见原因是目标点在障碍物内部或者起点被障碍物包围。这时候可以用rviz的Publish Point工具在障碍物外面点一个目标点看能不能规划成功。rosbag录包的时候注意磁盘空间Gazebo的点云数据量很大录几分钟就好几个GB。可以只录关键话题rosbag record /odom /goal /planning/trajectory /planning/pos_cmd回放的时候用rosbag play --clock注意加--clock参数不然TF的时间戳会乱。5.3 地图生成与自定义场景Ego-Planner自带的map_generator可以生成随机地图但如果你想测试特定场景比如走廊、房间、树林就需要自己建图。最简单的方法是用Gazebo的Building Editor画一个2D平面图然后导出成点云。或者用Blender建一个3D模型导出成.dae格式在Gazebo里加载。点云地图的格式要求是pcl::PointCloudpcl::PointXYZ保存成.pcd文件。在launch文件里把map_generator的map_type改成point_cloud然后指定pcd_file路径就行。注意点云的坐标系要和Gazebo的世界坐标系对齐不然障碍物位置会偏。如果点云地图太大导致加载慢可以用pcl_filter做降采样把点云分辨率降到0.1米左右。Ego-Planner的障碍物膨胀半径默认是0.3米点云太密的话膨胀后会连成一片无人机找不到可通行的缝隙。6. 个人实操体会与后续扩展方向6.1 我踩过的几个印象深刻的坑第一个坑是WSL的磁盘空间。WSL2的虚拟磁盘默认是动态扩展的但不会自动收缩。我编译了几次Ego-Planner之后虚拟磁盘涨到了50GB删了代码也不释放。后来用wsl --manage Ubuntu-20.04 --set-sparse true开启稀疏模式再执行sudo fstrim -av才把空间收回来。第二个坑是Gazebo的模型下载。第一次启动Gazebo的时候它会从在线模型库下载无人机模型和场景模型国内网络环境下经常卡住。解决办法是提前把模型库下载到~/.gazebo/models目录下或者设置GAZEBO_MODEL_DATABASE_URI环境变量指向本地路径。第三个坑是Ceres的线程数。Ceres默认用所有可用的CPU核心做并行优化在WSL里会把CPU占满导致Gazebo卡顿。可以在Ego-Planner的代码里设置ceres::Solver::Options::num_threads 2限制Ceres的线程数给Gazebo留出CPU资源。6.2 后续可以尝试的扩展Ego-Planner跑通之后可以尝试几个扩展方向。一是多机编队swarm.launch支持多架无人机同时仿真可以研究一下机间避障和编队保持的算法。二是动态障碍物在Gazebo里加一些移动的障碍物测试Ego-Planner的在线重规划能力。三是把Ego-Planner和SLAM结合用FAST-LIO或者VINS做状态估计实现无GPS环境下的自主导航。如果想把Ego-Planner迁移到ROS2工作量主要在消息类型和构建系统上。ROS2用ament_cmake替代catkin消息类型从.msg改成.idlTF变换用tf2替代tf。算法核心代码基本不用改主要是接口层的适配。我试过在ROS2 Humble上编译Ego-Planner改了两天能跑起来但性能比Noetic下差一些可能是ROS2的DDS通信开销更大。最后说一个实际部署时的经验Ego-Planner的轨迹优化对初始值很敏感如果起点和终点的直线路径完全被障碍物挡住优化器可能会陷入局部最优规划出一条绕远路的轨迹。这时候可以在advanced_param.xml里调大max_iteration或者换一个更激进的初始路径生成策略。我在实机上遇到过一次无人机在原地转圈的情况就是因为初始路径太差优化器找不到可行解。后来加了一个简单的A*做全局引导问题就解决了。
返回列表