1. 项目概述与环境准备
在机器人、无人机和自动驾驶的研发领域,一个高保真、可编程的仿真环境是算法迭代和验证的“加速器”。AirSim作为微软开源的仿真平台,凭借其基于物理的传感器模型和与Unreal Engine(UE4)的深度集成,成为了许多研究者和工程师的首选。然而,将AirSim、UE4以及自定义场景在Ubuntu 20.04 LTS这个稳定的生产环境中成功搭建起来,却是一个充满“坑点”的系统工程。这不仅仅是运行几条命令那么简单,它涉及到系统依赖、图形驱动、引擎编译、插件配置等一系列环环相扣的步骤。今天,我就基于自己多次在Ubuntu 20.04上从零搭建环境的实战经验,为你拆解每一步的核心逻辑和避坑要点,特别是最后一步——导入自定义场景时那些官方文档不会告诉你的细节。
为什么选择Ubuntu 20.04 LTS?对于仿真和开发而言,系统的长期稳定性和广泛的社区支持至关重要。20.04作为长期支持版本,其软件库和内核版本在AirSim和UE4所需的依赖兼容性上达到了一个较好的平衡点。而AirSim+UE4的组合,则为我们提供了从简单的API控制到复杂物理渲染的全栈仿真能力。整个流程可以概括为三个核心阶段:首先是打好地基,即准备一个“干净”且驱动完备的Ubuntu系统;其次是构建核心,即编译和配置Unreal Engine 4.27(这是一个与AirSim兼容性经过验证的版本);最后是集成与扩展,即编译AirSim插件并成功导入你自己的3D场景。下面,我们就从最基础的系统环境开始。
1.1 系统基础与显卡驱动:一切的前提
在Ubuntu上玩转UE4这类重型图形应用,一个正确安装且性能释放充分的NVIDIA显卡驱动是绝对的前提。很多新手卡在第一步,就是因为用了系统自带的 nouveau 开源驱动,或者安装了版本不匹配的驱动。
1.1.1 彻底禁用 Nouveau 驱动
Ubuntu默认使用开源Nouveau驱动,它与NVIDIA官方闭源驱动冲突,必须在安装前禁用。
# 打开黑名单配置文件
sudo nano /etc/modprobe.d/blacklist-nouveau.conf
在文件中添加以下两行:
blacklist nouveau
options nouveau modeset=0
保存后,更新initramfs并重启:
sudo update-initramfs -u
sudo reboot
重启后,验证是否禁用成功:
lsmod | grep nouveau
如果没有任何输出,则表示禁用成功。
1.1.2 安装合适的NVIDIA驱动
不要直接使用 ubuntu-drivers autoinstall ,对于开发环境,我们更需要一个特定版本。访问 NVIDIA官网 根据你的显卡型号查找推荐驱动。例如,对于RTX 30系列,470或更高版本的驱动是必须的。这里以安装470版本为例:
# 添加官方PPA仓库(可选,但通常版本更新)
sudo add-apt-repository ppa:graphics-drivers/ppa
sudo apt update
# 查看可用的驱动版本
ubuntu-drivers devices
# 安装指定版本驱动,例如 nvidia-driver-470
sudo apt install nvidia-driver-470
安装完成后, 必须重启系统 。重启后,使用 nvidia-smi 命令验证驱动和GPU是否被正确识别。你应该能看到显卡型号、驱动版本以及GPU的进程占用情况。
注意: 如果你使用笔记本电脑并且是双显卡(NVIDIA独显 + Intel/AMD核显),情况会复杂一些。你需要确保在运行UE4编辑器时,使用的是高性能的NVIDIA显卡。除了在NVIDIA控制面板(
nvidia-settings)中设置外,在终端启动UE4时,可以显式指定:__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia ./UE4Editor
1.1.3 安装核心系统依赖
UE4编译需要一整套开发工具和库。以下命令一次性安装所需的基础包:
sudo apt update
sudo apt install build-essential software-properties-common cmake git wget zip unzip \
libc6-dev libx11-dev libglu1-mesa-dev libgl1-mesa-dev \
libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev \
libz-dev libssl-dev libudev-dev libpng-dev libsdl2-dev \
g++-8 gcc-8 clang-8 lld-8 python3-dev python3-pip \
libvulkan1 libvulkan-dev
这里特别强调 g++-8 和 clang-8 ,因为UE4.27的源码编译对编译器版本有明确要求,使用系统默认的更高版本(如g++-11)极有可能导致编译失败。安装后,我们可以将gcc-8和g++-8设置为默认版本:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8
2. Unreal Engine 4.27 源码编译详解
直接从Epic Games Launcher安装UE4对于Windows用户很方便,但在Linux上,为了获得最好的兼容性和对AirSim插件的支持,从源码编译是推荐且几乎必须的路径。这个过程耗时较长(取决于CPU核心数和磁盘IO,通常1-4小时),但每一步都至关重要。
2.1 获取UE4源码与依赖项
首先,你需要访问 Epic Games的GitHub页面 ,并按照其指引关联你的Epic账户以获得克隆权限。这步是法律授权所需,无法绕过。
# 在一个空间充足的磁盘分区(建议至少预留150GB)克隆代码
git clone https://github.com/EpicGames/UnrealEngine.git -b 4.27
cd UnrealEngine
克隆完成后,不要急于运行编译脚本。我们需要先确保所有子模块都被正确拉取,并且下载所需的二进制依赖。
2.1.1 运行依赖设置脚本
在 UnrealEngine 目录下,执行:
./Setup.sh
这个脚本会自动下载并配置编译所需的工具链(如特定版本的Clang)和大量的第三方库文件(如.NET Core、OpenSSL等)。它会检查你的系统环境,并下载约10-20GB的数据到 Engine/Extras 和 Engine/Binaries/ThirdParty 等目录。 请保持网络通畅 ,如果中途失败,可以多次运行此脚本,它会尝试续传。
2.2 编译UE4编辑器
依赖配置完成后,就可以开始编译引擎本体了。
./GenerateProjectFiles.sh
make
./GenerateProjectFiles.sh 会生成用于编译的Makefile。 make 命令则开始真正的编译过程。
2.2.1 编译过程中的关键观察点与问题排查
- 内存与交换空间 :编译UE4是内存消耗大户。如果物理内存不足(例如小于16GB),会大量使用交换分区,导致编译速度极慢甚至卡死。建议确保有32GB以上物理内存,或者设置一个足够大的交换文件(如32GB):
sudo fallocate -l 32G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 永久生效需写入 /etc/fstab - CPU核心数利用 :
make默认会使用所有可用的CPU核心。你可以通过make -j N来指定并行编译任务数,N通常设置为你的CPU物理核心数或略多(如8核CPU用-j 10)。但过多的任务可能导致内存不足。 - 常见编译错误 :
- “fatal error: ‘stddef.h’ file not found” :这通常是Clang工具链路径问题。确保
Setup.sh成功运行,并检查Engine/Extras/ThirdPartyNotUE/SDKs/HostLinux/Linux_x64下是否存在完整的工具链。 - 链接器内存耗尽 :同样是内存不足的表现,增加交换文件大小或减少
-j参数。 - 特定模块编译失败 :有时是网络问题导致依赖下载不完整。可以尝试删除
Engine/Binaries和Engine/Intermediate目录,重新运行./Setup.sh和make。
- “fatal error: ‘stddef.h’ file not found” :这通常是Clang工具链路径问题。确保
编译成功完成后,你会在 UnrealEngine 目录下看到 Engine/Binaries/Linux/UE4Editor 可执行文件。运行它来验证:
cd Engine/Binaries/Linux
./UE4Editor
首次启动会进行着色器编译等初始化工作,稍等片刻后,你应该能看到Unreal Engine 4.27的编辑器界面。恭喜,最耗时、最复杂的一步已经完成。
3. AirSim插件编译与集成
有了可运行的UE4编辑器,接下来就是将AirSim这个“大脑”集成进去。AirSim以UE4插件的形式存在,我们需要先编译插件,然后将其放入一个UE4项目中。
3.1 编译AirSim插件
AirSim的编译相对独立,它会产生一个 .so 动态库文件供UE4调用。
# 克隆AirSim源码(建议放在独立目录,不要放在UE4目录内)
git clone https://github.com/microsoft/AirSim.git
cd AirSim
# 使用项目提供的脚本搭建编译环境
./setup.sh
./build.sh
setup.sh 会安装AirSim所需的额外Python依赖(如msgpack-rpc-python)和构建工具。 build.sh 则会调用CMake和make进行编译。
3.1.1 编译输出与结构
编译成功后,关键产出在 AirSim/Unreal/Plugins 目录下。你会看到一个名为 AirSim 的插件文件夹。这个文件夹的结构是标准的UE4插件格式,其中 Binaries/Linux/ 下存放着编译好的 libUE4Editor-AirSim.so 等库文件。
3.2 创建UE4项目并集成插件
你不能直接把插件扔进UE4引擎目录。标准的做法是创建一个空项目,然后将插件复制到项目的插件目录。
3.2.1 创建空项目
- 启动我们刚才编译好的UE4编辑器 (
./UE4Editor)。 - 在项目浏览器中,选择“Games” -> “Blank”(空白项目)。
- 选择“C++”项目( 必须选择C++ ,否则后续无法正确加载插件),设置好项目名称(例如
MyAirSimProject)和存储路径,然后点击“Create”。 - UE4会为你生成一个C++项目并自动打开Visual Studio Code或你设置的默认IDE进行初始编译。等待其完成。
3.2.2 集成插件
关闭UE4编辑器。将刚才编译好的整个 AirSim 插件文件夹(即 AirSim/Unreal/Plugins/AirSim ), 完整地复制 到你刚创建的项目目录下的 Plugins 文件夹中。如果项目下没有 Plugins 文件夹,就自己创建一个。
MyAirSimProject/
├── Config/
├── Content/
├── Plugins/ <-- 创建这个文件夹
│ └── AirSim/ <-- 复制整个插件文件夹到这里
├── Source/
└── MyAirSimProject.uproject
3.2.3 重新生成项目文件并编译
由于添加了C++插件,需要重新生成项目文件。
# 进入你的项目目录
cd ~/Documents/Unreal\ Projects/MyAirSimProject
# 使用UE4附带的生成脚本,指定你的UE4引擎根目录
/path/to/your/UnrealEngine/Engine/Build/BatchFiles/Linux/GenerateProjectFiles.sh -project="/path/to/your/MyAirSimProject/MyAirSimProject.uproject" -game
# 然后编译项目
cd /path/to/your/UnrealEngine
make MyAirSimProjectEditor
或者,更简单的方法是:直接双击项目目录下的 MyAirSimProject.uproject 文件。系统会提示你“模块缺失,需要重新编译”,点击确认,它会自动调用UE4的编译系统。
编译成功后再次打开项目,你可以在UE4编辑器的“设置” -> “插件”中,看到“AirSim”插件已被启用。至此,AirSim仿真平台的核心环境就搭建完成了。你可以运行UE4内置的“Blocks”环境来测试:在编辑器中选择“播放”(Play),然后在终端中使用AirSim的Python API示例脚本来控制车辆或无人机。
4. 自定义场景导入:核心流程与深度避坑
使用官方提供的“Blocks”或“Landscape”环境入门后,你一定会想导入自己的3D场景,比如一个用Blender或3ds Max创建的园区、城市模型。这是将AirSim应用于具体研究(如视觉SLAM、路径规划)的关键一步,也是“坑”最多的地方。
4.1 场景资产准备与格式处理
UE4支持多种3D格式,但最通用、问题最少的是 FBX 格式。在从其他软件导出FBX时,设置至关重要。
4.1.1 建模软件导出设置(以Blender为例)
- 比例与轴向 :UE4使用厘米(cm)为单位,Y轴向前,Z轴向上。在Blender导出FBX时,务必在“变换”选项中勾选“应用变换”,并设置“前向”为Y Forward,“向上”为Z Up。比例缩放设置为1.0。
- 平滑组与法线 :这是导致模型在UE4中显示为“全黑”或“全光滑”的常见原因。在Blender的“几何数据”导出选项中,务必勾选“平滑组”(Smoothing Groups)。如果模型有自定义法线,也可以勾选“导出法线”。
- 材质与纹理 :尽量使用简单的原理化BSDF(Principled BSDF)材质。导出时勾选“嵌入纹理”(Embed Textures)可以将贴图打包进FBX,避免路径丢失问题。但更推荐的做法是将纹理图片单独存放,并在UE4中重新指定。
4.1.2 在UE4中导入FBX
在UE4编辑器的Content Browser中右键 -> “导入到 /Game...”,选择你的FBX文件。会弹出导入选项窗口:
- 材质导入方法 :对于首次导入,选择“不创建材质”(Do Not Create Material)。我们稍后在UE4中创建更可控的材质实例。
- 自动生成碰撞 :如果你的模型没有碰撞体,可以勾选“自动生成碰撞”(Generate Collision)。但对于复杂模型,自动生成的碰撞体可能效率低下,最好在建模软件中创建简单的碰撞体(命名为
UCX_开头)并一并导出。 - 转换场景 :保持默认。点击“导入”后,你会在内容浏览器中看到新导入的静态网格体(Static Mesh)和可能的材质球。
4.2 构建场景与光照
导入的网格体只是“零件”,需要将其拖放到关卡中组装成“场景”。
4.2.1 创建关卡与放置资产
- 新建一个空关卡(File -> New Level -> Empty Level)。
- 从内容浏览器将导入的静态网格体拖入视口。使用移动(W)、旋转(E)、缩放(R)工具进行布局。
- 重要:将地面重命名为“Ground” 。AirSim的默认设置会寻找名为“Ground”的Actor作为地面参考系。右键点击你的地面网格体Actor -> “重命名”(Rename)。
4.2.2 构建光照与导航网格
- 光照 :从模式面板(Modes Panel)拖拽一个“定向光源”(Directional Light)和“天光”(Sky Light)到场景中。选中“天光”,在细节面板中勾选“实时捕获”(Real Time Capture)。然后点击工具栏上的“构建”(Build)按钮(或按
Ctrl+Shift+;)来构建光照。没有构建光照的场景会非常暗。 - 导航网格(仅对车辆重要) :从模式面板拖拽“导航网格体边界体积”(Nav Mesh Bounds Volume)到场景,缩放其覆盖整个可行驶区域。然后需要构建AI路径:点击工具栏上的“构建”按钮旁的小箭头,选择“构建AI路径”(Build AI Paths)。对于无人机仿真,这一步不是必须的。
4.3 AirSim设置与场景关联
现在需要告诉AirSim:“这个新场景就是你的仿真世界了。”
4.3.1 配置 settings.json
在你的项目目录下(或用户目录的 ~/Documents/AirSim ),创建或修改 settings.json 文件。一个连接自定义场景的最小配置如下:
{
"SettingsVersion": 1.2,
"SimMode": "Car", // 或 "Multirotor" 对应无人机
"Vehicles": {
"MyCar": {
"VehicleType": "PhysXCar",
"X": 0, "Y": 0, "Z": 0 // 生成初始位置
}
},
"OriginGeopoint": {
"Latitude": 47.641468,
"Longitude": -122.140165,
"Altitude": 122
}
}
关键点在于,我们不需要像使用“Blocks”环境那样指定 "UdpPort" 和 "ApiServerPort" ,因为现在AirSim插件直接运行在我们的自定义项目进程中。
4.3.2 设置默认关卡并打包
- 在UE4编辑器中,打开“项目设置”(Project Settings)-> “项目”(Project)-> “地图和模式”(Maps & Modes)。将“编辑器启动地图”(Editor Startup Map)和“游戏默认地图”(Game Default Map)都设置为你刚创建并布置好的关卡。
- (可选但推荐)项目打包 :为了便于分发和稳定运行,可以将项目打包成独立的可执行文件。在编辑器菜单栏选择“文件”(File)-> “打包项目”(Package Project)-> “Linux”。选择一个输出目录,UE4会开始打包过程。打包完成后,你可以在输出目录的
LinuxNoEditor文件夹下找到可执行文件,它包含了所有依赖,可以在没有安装UE4编辑器的机器上运行。
5. 实战问题排查与性能优化指南
即使严格按照步骤操作,在实际搭建和运行中仍会遇到各种问题。这里我总结了一份“避坑速查表”,涵盖了从环境搭建到场景运行的全链条。
5.1 环境搭建与编译问题
| 问题现象 | 可能原因 | 排查与解决步骤 |
|---|---|---|
./Setup.sh 下载极慢或失败 | 网络连接Epic Games服务器不畅 | 1. 使用稳定的网络环境,可尝试手机热点。 2. 手动下载依赖:脚本运行时会输出下载链接,可尝试用下载工具获取后放入对应目录。 |
make 编译UE4时内存不足(OOM Killer) | 物理内存和交换空间不足 | 1. 使用 free -h 查看内存和交换空间。 2. 如前所述,创建足够大的交换文件(32GB+)。 3. 减少并行编译任务: make -j 2 。 |
| 编译AirSim时CMake报错,找不到UE4目录 | 环境变量 UE4_ROOT 未设置 | 在运行 ./build.sh 前,先设置环境变量: export UE4_ROOT=/path/to/your/UnrealEngine 。 |
| UE4编辑器能打开,但启动自带项目(如Blocks)崩溃 | 显卡驱动问题或Vulkan兼容性问题 | 1. 确认驱动安装正确 ( nvidia-smi )。 2. 尝试在编辑器启动命令后加 -vulkan 或 -opengl4 切换图形API: ./UE4Editor -vulkan 。 |
| 插件编译成功,但项目中不显示AirSim插件 | 插件复制路径错误或项目未重新编译 | 1. 确认插件在 YourProject/Plugins/AirSim/ 下。 2. 删除项目目录下的 Binaries 和 Intermediate 文件夹,重新生成项目文件并编译。 |
5.2 自定义场景导入与运行问题
| 问题现象 | 可能原因 | 排查与解决步骤 |
|---|---|---|
| FBX模型导入后全黑 | 1. 法线问题。 2. 光照未构建。 3. 材质问题。 | 1. 检查FBX导出时是否勾选“平滑组”。 2. 在UE4中为静态网格体双击打开,在预览窗口检查法线(显示 -> 法线)。 3. 确保场景中有光源并已构建光照(点击构建按钮)。 4. 检查导入的材质,尝试创建一个新的简单材质球赋予模型。 |
| 模型在视口中闪烁(Z-fighting) | 模型面片距离过近或有重叠 | 1. 在建模软件中检查并修正模型几何错误。 2. 在UE4的静态网格体编辑器中,略微调整重叠部分的顶点位置。 |
| AirSim API无法连接 | 1. settings.json 路径错误。 2. 项目默认关卡未设置。 3. 端口冲突。 | 1. 确认 settings.json 放在 项目根目录 或 ~/Documents/AirSim 。 2. 确认项目设置中的“游戏默认地图”是你的自定义关卡。 3. 检查是否有其他程序占用41451端口(AirSim默认API端口)。 |
| 车辆/无人机生成后掉入无限深渊 | 1. 没有名为“Ground”的地面。 2. 生成坐标(Z)设置错误。 3. 地面没有碰撞体。 | 1. 确认场景中有一个Actor被命名为“Ground”。 2. 在 settings.json 中调整车辆生成点的Z坐标,确保高于地面。 3. 为地面网格体添加碰撞(在静态网格体编辑器中:碰撞 -> 添加简单碰撞或复杂碰撞)。 |
| 仿真帧率极低 | 1. 场景过于复杂,渲染开销大。 2. 光照构建质量过高。 3. AirSim传感器配置过多。 | 1. 使用UE4的“统计”窗口(Stat FPS)查看性能瓶颈。 2. 降低阴影分辨率、后处理效果等(项目设置 -> 渲染)。 3. 简化场景模型,使用LOD(层次细节)。 4. 在 settings.json 中减少不必要的传感器或降低其分辨率/频率。 |
5.3 性能优化与工作流建议
- 开发阶段使用“开发构建” :在打包项目前,在编辑器内运行和测试。UE4编辑器的“独立进程游戏”(Standalone Game)模式比打包后的版本启动更快,便于快速迭代。
- 善用“子关卡”(Sublevels) :对于大型场景,不要把所有资产都放在一个主关卡里。将场景按功能或区域划分成多个子关卡,在编辑器中动态加载和卸载,可以大幅提升编辑效率和运行时性能。
- 优化材质和纹理 :避免使用4K以上不必要的超大纹理。使用材质实例(Material Instance)而不是动态材质参数,以减少Draw Call。
- AirSim API使用技巧 :在Python脚本中,批量获取传感器数据(如使用
simGetImages一次获取多个相机图像)比多次调用单次获取API效率高得多。对于不需要每帧都处理的数据,可以降低查询频率。 - 版本控制 :将你的UE4项目(
Content,Source,Config,.uproject文件)和AirSim插件目录纳入Git管理。但切记忽略Binaries,Intermediate,DerivedDataCache,.vs等由编译和编辑器生成的中间文件和目录。这能让你在环境出错时快速回滚。
整个搭建过程就像搭积木,底层是稳固的Ubuntu系统和显卡驱动,中间是庞大但必须自己构建的UE4引擎,顶层是灵活但需要精细配置的AirSim插件和你的自定义场景。每一步的失败都可能由前一步的疏漏导致,因此耐心和按部就班是关键。当你第一次用自己的场景驱动无人机飞起来,或者让自动驾驶小车循迹时,你会觉得这一切的折腾都是值得的。这个环境将成为你算法研发的强力沙盒,让你在安全的虚拟世界中,无限次地测试、碰撞和优化你的代码。



286

被折叠的 条评论
为什么被折叠?



