
1. 项目概述与核心价值如果你正在研究无人机算法无论是视觉导航、路径规划还是集群协同那么一个高保真、可定制的仿真环境就是你绕不开的“第一块试验田”。在真实世界摔坏一架无人机成本高昂调试代码更是困难重重。而基于AirSim和Unreal Engine 4UE4搭建的仿真平台恰恰能让你在Ubuntu系统上以极低的成本和极高的自由度创建出从城市街道到复杂山地的任意场景让算法在逼近真实的虚拟世界里先跑起来。我最初接触这个组合也是为了做视觉SLAM研究。当时被真实数据采集的繁琐和不确定性折磨得不轻转而寻求仿真方案。AirSim作为微软开源的仿真平台提供了极其丰富的API能让你用Python或C像控制真机一样控制虚拟无人机并获取带精确真值的相机图像、深度图、姿态信息。而UE4则是构建那个逼真世界的画笔。很多人可能觉得在Linux上玩UE4是自找麻烦毕竟它更“亲”Windows。但当你需要将仿真环境部署到没有图形界面的服务器进行大规模强化学习训练或者希望整个开发流水线都基于Linux时在Ubuntu上打通这条链路就变得至关重要。这个过程确实有不少坑但一旦搭建完成其灵活性和自动化潜力是巨大的。本文将带你从零开始在Ubuntu 20.04 LTS系统上完成AirSim与UE4的编译、集成并最终创建属于你自己的无人机仿真场景。我会详细拆解每一个步骤背后的原理分享我踩过的坑和总结的优化技巧目标是让你不仅能复现更能理解为什么这么做从而具备自定义和排错的能力。2. 环境准备与核心组件解析在动手之前我们必须理清整个技术栈的构成和它们之间的关系。这绝不是简单的“安装-运行”而是一个涉及游戏引擎、仿真插件和系统兼容性的深度集成过程。2.1 系统与硬件要求一个稳定的基础系统是成功的首要条件。我强烈推荐使用Ubuntu 20.04 LTS作为你的操作系统。LTS长期支持版本拥有更完善的库支持和社区资源能避免许多因系统版本过新或过旧导致的依赖冲突。虽然Ubuntu 22.04也已发布但一些图形驱动和UE4的兼容性可能仍需时间沉淀20.04是目前最稳妥的选择。硬件方面你的电脑需要一块性能不错的独立显卡。UE4是一个实时渲染引擎需要强大的GPU来绘制复杂的场景。AirSim的传感器模拟尤其是激光雷达和多个相机也会加重渲染负担。我个人建议至少是NVIDIA GTX 1060或同等性能以上的显卡并确保拥有至少6GB的显存。内存推荐16GB以上因为UE4编辑器本身就是一个内存消耗大户。注意务必在系统安装完成后首先安装对应显卡的官方驱动。使用Ubuntu自带的“软件和更新”中的“附加驱动”选项卡来安装推荐版本的NVIDIA驱动这是最不容易出问题的方法。安装后重启并通过nvidia-smi命令验证驱动是否正常加载。2.2 理解AirSim与UE4的协作模式很多人会混淆AirSim和UE4的角色。你可以这样理解Unreal Engine 4 (UE4)它是一个功能强大的“世界创造器”和“渲染引擎”。负责构建三维场景、管理光影材质、进行物理碰撞计算通过其内部的PhysX或Chaos物理引擎并最终将画面渲染出来。它提供了编辑器Unreal Editor让你可以通过可视化操作来摆放房屋、树木、道路。AirSim它是一个高度专业化的“无人机/汽车模拟器插件”和“通信中间件”。它以UE4插件或Unity插件的形式存在注入到UE4项目中。AirSim的核心作用是物理模拟实现了比UE4默认更贴近真实的飞行器动力学模型。当你通过API发送油门和舵量指令时是AirSim的代码在计算无人机下一刻的姿态和位置。传感器模拟生成逼真的相机图像包含镜头畸变、运动模糊、激光雷达点云、IMU数据、GPS信号等这些都是算法研发的“粮食”。API服务启动一个本地服务器默认是41451端口监听来自你Python脚本的控制指令如takeoffAsync()并返回传感器数据。所以我们的工作流是在Ubuntu上编译UE4引擎源码-编译AirSim插件源码- 将AirSim插件放入一个UE4空白或自定义项目中 - 在UE4编辑器中搭建或导入一个三维场景- 通过Python脚本连接并控制场景中的无人机。2.3 安装必要的系统依赖在编译任何源码之前需要为系统安装一系列基础开发工具和库。打开终端执行以下命令组。这些命令主要安装了编译器、Python环境、图形库和必要的工具。# 更新软件包列表 sudo apt-get update # 安装基础编译工具和依赖 sudo apt-get install build-essential software-properties-common curl git cmake ninja-build clang lld -y # 安装Python3及pipUbuntu 20.04默认已安装Python3但需确保pip sudo apt-get install python3 python3-pip python3-dev -y # 安装AirSim所需的特定Python包 pip3 install msgpack-rpc-python numpy pandas airsim # 安装图形和多媒体库UE4编译所需 sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libx11-dev libxt-dev libudev-dev -y # 安装其他工具 sudo apt-get install clang-12 clang-12 lld-12 -y关键点解析ninja-build和cmake这是现代C项目的主流构建工具组合比传统的make更快AirSim和UE4都支持。clang和lldUE4推荐使用Clang编译器套件和LLD链接器在Linux上进行编译相比GCC它们与UE4的兼容性更好编译速度也可能更快。msgpack-rpc-python这是AirSim的Python API底层使用的通信库实现了高效的数据序列化和远程过程调用。3. 编译Unreal Engine 4源码这是整个流程中最为耗时和容易出错的环节。Epic Games官方并不提供预编译的Linux版UE4编辑器我们必须自己从GitHub拉取源码进行编译。请注意你需要一个Epic Games账户并将其与GitHub账户关联才能克隆UE4的仓库。3.1 获取UE4源代码访问 GitHub上的UnrealEngine仓库 。点击页面上的“Connect to GitHub”或类似按钮按照指引将你的Epic账户与GitHub关联。这是Epic为保护其知识产权设置的必要步骤。关联成功后页面会刷新此时你就可以使用git clone命令了。在终端中选择一个空间充足的磁盘位置整个源码需要约80GB空间执行# 克隆UE4源码使用 --depth 1 只克隆最新提交以节省时间和空间 git clone --depth 1 https://github.com/EpicGames/UnrealEngine.git cd UnrealEngine3.2 执行编译脚本UE4提供了一个自动化编译的Shell脚本。运行它然后就是漫长的等待根据CPU性能可能需要2-6小时。./Setup.sh ./GenerateProjectFiles.sh make实操心得与避坑指南内存不足问题编译UE4是内存消耗极大的过程尤其是链接Linking阶段。如果内存不足例如小于16GB可能会在编译过程中卡死或报错。一个有效的解决方案是创建足够大的交换空间Swap。如果你使用的是物理机可以尝试增加Swap分区如果在虚拟机中确保为其分配了足够的内存和交换文件。# 检查现有交换空间 sudo swapon --show # 如果不足可以临时创建一个8GB的交换文件根据你的磁盘空间调整 sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile # 可以将其添加到 /etc/fstab 使其永久生效编译中途失败如果编译因错误中断不要慌张。首先仔细阅读错误信息。常见的失败原因包括依赖缺失错误信息通常会提示缺少某个.so库文件。根据提示使用apt-get install安装对应的开发包通常是libxxx-dev格式。磁盘空间不足确保目标磁盘有超过100GB的可用空间。网络问题Setup.sh脚本会下载一些二进制依赖确保网络通畅。验证编译成功编译完成后在UnrealEngine/Engine/Binaries/Linux/目录下应该能找到UnrealEditor这个可执行文件。尝试运行它cd Engine/Binaries/Linux ./UnrealEditor如果UE4编辑器能够正常启动显示项目浏览器界面那么恭喜你最艰难的一步已经完成了。4. 编译与集成AirSim插件有了UE4引擎接下来我们需要准备AirSim这个“大脑”。4.1 编译AirSimAirSim的编译相对简单。我们将其编译成一个UE4插件模块。# 切换到你的工作目录克隆AirSim源码 cd ~ git clone https://github.com/microsoft/AirSim.git cd AirSim # 使用AirSim提供的脚本搭建编译环境它会自动识别并设置UE4路径 ./setup.sh # 如果自动识别失败你可能需要手动指定UE4路径 # ./setup.sh --ue4path /path/to/your/UnrealEngine # 进入构建目录使用CMake生成构建文件 mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease # 开始编译-j 参数指定并行编译的线程数可以加快速度 make -j$(nproc)编译完成后在build目录下的output子文件夹里具体路径可能因版本略有不同请查看CMake输出你会找到编译好的AirSim.so等插件文件。4.2 创建UE4项目并集成插件现在我们需要创建一个UE4项目并把AirSim插件放进去。启动UE4编辑器通过之前验证的路径启动UE4编辑器。创建新项目在项目浏览器中选择“游戏” - “空白”选择一个纯C项目例如命名为MyDroneSim并选择一个保存位置。务必选择“C项目”因为AirSim插件需要C代码支持才能完全激活。关闭编辑器项目创建成功后先关闭UE4编辑器。集成插件将编译好的AirSim插件文件复制到你的UE4项目中。关键步骤是找到你编译AirSim生成的插件文件夹通常在AirSim/build/output/AirSim/下包含Binaries,Content,Source等子目录。在你的UE4项目目录例如~/MyDroneSim/下创建一个名为Plugins的文件夹。将整个AirSim插件文件夹复制到~/MyDroneSim/Plugins/下。最终结构应类似于~/MyDroneSim/Plugins/AirSim/...。生成项目文件并编译由于我们添加了C插件需要重新生成项目文件并编译。cd ~/MyDroneSim # 使用UE4附带的生成脚本它会自动识别Plugins下的AirSim /path/to/your/UnrealEngine/Engine/Build/BatchFiles/Linux/GenerateProjectFiles.sh -projectpwd/MyDroneSim.uproject -game # 编译项目 make重新打开项目再次通过UE4编辑器打开MyDroneSim.uproject文件。此时编辑器可能会提示“编译C代码”点击确认。完成后你可以在编辑器的“设置”-“插件”中搜索“AirSim”应该能看到它已被启用。5. 构建自定义无人机仿真场景环境搭建完毕现在进入创造环节——构建你的专属仿真世界。5.1 利用市场资源快速搭建场景对于初学者最快的方式是使用UE4商城Marketplace中的免费资源。虽然UE4编辑器内嵌的商城在Linux版中可能无法直接使用但你可以在Windows系统的Epic客户端上下载资源然后拷贝到Linux项目中。寻找场景在Windows上登录Epic Games Launcher在商城中搜索“Landscape”、“City”、“Modular Building”等关键词可以找到大量免费的高质量场景素材包例如 “Infinity Blade: Grass Lands” 就是一个经典的户外测试场景。迁移资产将下载的素材包通常位于Windows的Epic Games/UE_4.27/Content之类路径下整个文件夹复制到你的Linux项目中的Content目录下。在UE4编辑器中整合在Linux上重新打开项目在内容浏览器中你就能看到导入的资产。你可以直接打开迁移过来的地图文件.umap或者将资产拖拽到新建的空白地图中自由组合搭建。5.2 从零开始创建基础地形如果你想完全自定义可以从UE4强大的地形编辑工具开始。在编辑器中选择“模式”面板下的“地形”工具。点击“创建新地形”设置合适的分辨率和尺寸。对于无人机仿真一个1025x1025分辨率、每格代表1米的地形可以创建一个约1平方公里的可飞行区域是个不错的起点。使用雕刻工具Sculpt可以拉高山脉、挖出河谷。使用绘制工具Paint可以为地形赋予不同的材质层如草地、岩石、沙地。关键技巧添加碰撞体。UE4中默认的地形是有碰撞的无人机不会穿模。但对于你自己从外部导入的3D模型如.obj, .fbx文件务必在导入设置或模型细节面板中生成碰撞体Generate Collision。否则无人机将直接穿过这些物体失去仿真意义。5.3 配置AirSim仿真参数场景建好后需要告诉AirSim在这个场景里如何运行。这通过一个名为settings.json的配置文件完成。该文件应放置在你的项目可执行文件同级目录或项目Content目录下。一个基础的无人机配置示例如下{ SeeDocsAt: https://github.com/Microsoft/AirSim/blob/master/docs/settings.md, SettingsVersion: 1.2, SimMode: Multirotor, // 仿真模式多旋翼无人机 Vehicles: { Drone1: { // 你的无人机名称 VehicleType: SimpleFlight, // 使用内置的简单飞行模型 X: 0, Y: 0, Z: -2, // 初始位置UE4中Z轴向上-2表示放在地面以下2米这里通常用负值表示低于地面但建议设为-0.1或0.5 Yaw: 0, // 初始偏航角 Cameras: { front_center: { CaptureSettings: [ { ImageType: 0, // 0Scene场景图, 1Depth深度图, 2Segmentation语义分割图 Width: 640, Height: 480 } ], X: 0.3, Y: 0, Z: -0.1, // 相机相对于无人机机体的位置 Pitch: 0, Roll: 0, Yaw: 0 // 相机相对于无人机机体的朝向 } } } }, CameraDefaults: { CaptureSettings: [ { ImageType: 0, Width: 960, Height: 540 } ] } }重要参数解析Z: -2在UE4中世界坐标系是Z轴向上。这个值代表无人机初始位置的高度。通常我们将地面高度设为0。Z -2意味着将无人机生成在地面以下2米这会导致它一开始就“陷”进地里。正确的做法是设置为一个略低于0的值如-0.1让无人机刚好“落”在地面上或者设置为一个正数如5.0让无人机在空中生成。我建议设为-0.1。VehicleType: SimpleFlight这是一个易于上手的简化动力学模型适合算法初步测试。对于更逼真的仿真可以配置为PhysXCar车或使用更复杂的模型但需要额外的配置。ImageType你可以同时请求多种图像类型。0是普通的RGB图像1是深度图每个像素值代表到相机的距离2是语义分割图每个物体被赋予唯一的颜色ID这对于计算机视觉训练极其有用。6. 运行仿真与Python API控制一切就绪让我们启动仿真并用代码控制无人机。6.1 启动仿真场景在UE4编辑器中打开你精心布置好的场景地图。点击工具栏上的“播放”按钮。此时UE4会以“独立游戏”模式运行你的场景。如果settings.json配置正确AirSim插件会自动加载并在场景中生成你定义的无人机。你会在终端如果你是从终端启动的编辑器或编辑器的“输出日志”窗口中看到类似“UAirSimHost::StartListening”的日志表明AirSim的RPC服务器已启动正在监听41451端口。6.2 使用Python API进行基础控制在同一台机器或网络可达的另一台机器上你可以编写Python脚本来控制无人机。首先确保已安装airsimPython包我们在环境准备时已安装。创建一个名为drone_control.py的脚本import airsim import time # 连接到AirSim仿真服务器 client airsim.MultirotorClient() client.confirmConnection() # 确认连接成功 # 获取控制权并解锁Arm无人机 client.enableApiControl(True) client.armDisarm(True) print(准备起飞...) # 异步起飞到5米高度 client.takeoffAsync().join() # 悬停2秒 time.sleep(2) print(向前飞行10米...) # 以1米/秒的速度向前X轴方向飞行10米 client.moveByVelocityBodyFrameAsync(vx1, vy0, vz0, duration10).join() print(返航并降落...) # 返回到起始点0,0,-5并降落 client.goHomeAsync().join() client.landAsync().join() # 上锁并释放控制权 client.armDisarm(False) client.enableApiControl(False) print(任务完成。)代码要点解析airsim.MultirotorClient()创建与多旋翼无人机仿真的连接客户端。client.confirmConnection()这是一个重要的检查步骤确保网络通信正常。enableApiControl和armDisarm模拟真实飞控的“API控制使能”和“解锁”步骤必须依次执行才能获得控制权。Async方法AirSim的许多控制方法都有同步join()和异步版本。使用Async后缀的方法会立即返回一个“未来”Future对象你可以调用.join()来等待该动作完成或者不等待以便执行其他操作如并发执行多个指令或同时进行数据采集。6.3 获取传感器数据控制无人机飞行只是第一步获取传感器数据用于算法开发才是仿真的核心价值。以下示例展示如何获取相机图像和IMU数据import airsim import cv2 import numpy as np client airsim.MultirotorClient() client.confirmConnection() # 1. 获取场景RGB图像 responses client.simGetImages([ airsim.ImageRequest(front_center, airsim.ImageType.Scene, pixels_as_floatFalse, compressFalse) ]) if responses: img1d np.frombuffer(responses[0].image_data_uint8, dtypenp.uint8) img_rgb img1d.reshape(responses[0].height, responses[0].width, 3) # 使用OpenCV显示图像 cv2.imshow(Scene, img_rgb) cv2.waitKey(0) cv2.destroyAllWindows() # 2. 获取IMU数据 imu_data client.getImuData() print(fIMU加速度: {imu_data.linear_acceleration}) print(fIMU角速度: {imu_data.angular_velocity}) print(fIMU朝向: {imu_data.orientation}) # 3. 获取状态信息位置、姿态、速度等 state client.getMultirotorState() kinematics_estimated state.kinematics_estimated print(f位置: {kinematics_estimated.position}) print(f姿态(四元数): {kinematics_estimated.orientation}) print(f线速度: {kinematics_estimated.linear_velocity}) print(f角速度: {kinematics_estimated.angular_velocity})7. 常见问题排查与性能优化在实际操作中你几乎一定会遇到各种问题。这里记录了一些典型问题及其解决方案。7.1 编译与启动问题问题现象可能原因解决方案./Setup.sh失败提示Git仓库问题UE4源码克隆不完整或权限问题删除UnrealEngine目录重新完整克隆。确保Git已正确配置。make编译UE4时内存不足OOM Killer系统物理内存和交换空间不足如前所述增加交换空间。关闭不必要的程序。在虚拟机中增加分配给虚拟机的内存。运行./UnrealEditor报错提示缺少libxxx.so系统动态链接库缺失根据错误信息使用apt-file search libxxx.so查找对应的包然后sudo apt install安装。UE4编辑器能打开但打开项目时崩溃项目文件损坏或插件冲突尝试新建一个空白C项目测试。检查Plugins文件夹确保AirSim插件编译版本与UE4引擎版本匹配。AirSim插件编译失败CMake找不到UE4setup.sh未能自动检测UE4路径手动指定路径cmake .. -DCMAKE_BUILD_TYPERelease -DUE4_ROOT/path/to/UnrealEngine7.2 仿真运行问题问题现象可能原因解决方案Python脚本连接超时 (airsim.exceptions.TimeoutError)AirSim RPC服务器未启动防火墙阻止端口被占用1. 确认UE4场景已处于“播放”模式。2. 检查settings.json是否在正确位置且格式无误。3. 尝试telnet 127.0.0.1 41451测试端口是否开放。4. 重启UE4编辑器。无人机生成后直接坠毁或穿模初始位置Z值设置不当场景物体无碰撞1. 检查settings.json中Z值确保无人机生成在空中或轻微接触地面。2. 在UE4编辑器中检查关键静态网格体Static Mesh的碰撞设置确保已生成或导入了碰撞体。获取的图像全黑或扭曲相机位置/朝向配置错误渲染问题1. 检查settings.json中相机相对于机体的位置 (X, Y, Z) 和朝向 (Pitch, Roll, Yaw)。2. 尝试在UE4编辑器中在“播放”模式下按反引号键打开控制台输入show flight命令可以显示AirSim的调试信息查看相机是否正常渲染。仿真帧率FPS过低场景过于复杂图形设置过高硬件瓶颈1. 在UE4编辑器的“播放”选项里启用“游戏模式”并设置较低的屏幕分辨率。2. 简化场景减少面数过高的模型使用LOD细节层次。3. 关闭UE4编辑器中的一些可视化调试工具。7.3 性能优化与高级技巧无头模式Headless Mode运行对于不需要查看画面的自动化测试或强化学习训练可以以无头模式运行UE4大幅节省资源。# 在项目目录下 /path/to/UnrealEngine/Engine/Binaries/Linux/UnrealEditor /path/to/yourproject.uproject -game -RenderOffscreen -ResX640 -ResY480参数-RenderOffscreen表示离屏渲染-ResX和-ResY设置渲染分辨率。此时不会有编辑器窗口弹出但AirSim服务器仍在运行。多无人机仿真在settings.json的Vehicles部分可以定义多个不同名称和初始位置的无人机。在Python代码中使用client airsim.MultirotorClient(vehicle_nameDrone2)来创建连接到特定无人机的客户端从而实现多机控制。记录与回放数据AirSim支持记录整个仿真过程的数据姿态、图像、控制指令等。在settings.json中添加RecordUIVisible: true在仿真运行时按R键开始/停止录制。数据会以.mcap或.txt格式保存便于后续分析。自定义无人机模型如果你有特定的无人机3D模型.fbx格式可以替换AirSim默认的无人机模型。这需要一些UE4资产导入和蓝图调整的知识。基本步骤是将模型导入项目Content创建一个基于Pawn的蓝图将模型指定为网格体并添加AirSim提供的VehicleMovementComponent等组件。这个过程相对复杂但AirSim文档和社区有相关指南。搭建这个环境的过程就像在虚拟世界里建立一个属于自己的无人机实验室。从系统配置到源码编译从场景搭建到代码控制每一步都需要耐心和细致。我最深的体会是日志是你的朋友。无论是编译错误还是运行时异常仔细阅读终端和UE4输出日志里的信息十有八九能找到线索。另外善用AirSim的官方文档和GitHub Issues页面你遇到的绝大多数问题很可能已经有人提出并解决了。当你的Python脚本成功让虚拟无人机在自定义的峡谷中自主穿行时那种成就感会告诉你这一切的折腾都是值得的。这个平台将成为你探索更复杂算法如视觉导航、集群协同和对抗策略的强大基石。