UE4.27集成AirSim插件:无人机仿真项目C++配置全攻略

📅 2026/8/3 4:02:30
UE4.27集成AirSim插件:无人机仿真项目C++配置全攻略
1. 项目概述与核心挑战最近在做一个无人机仿真相关的项目核心需求是在UE4.27引擎里通过C代码驱动一个高保真的飞行器模型并接入真实的飞控算法进行闭环测试。AirSim这个由微软开源的仿真平台自然就成了首选它原生支持PX4和ArduPilot物理和传感器模型都比较靠谱。但说实话把AirSim插件集成到一个已有的、或者新建的UE4.27 C项目里这个过程远没有官方文档描述的那么“开箱即用”。我前后折腾了快一周踩遍了从环境变量、编译选项到uproject配置的几乎所有坑才终于让插件在编辑器里正常加载并且能用自己的C代码去调用它的API。这篇指南就是把我趟过的这些雷区以及最终成功的配置细节完整地记录下来。如果你也正在做类似的事情无论是做无人机算法验证、自动驾驶仿真还是任何需要将AirSim作为仿真后端集成到自定义UE4项目中的工作这篇内容应该能帮你节省大量时间避免在环境配置上无谓地消耗精力。2. 前期环境准备与关键依赖梳理在动手修改任何代码或配置文件之前一个干净、正确的基础环境是成功的基石。很多人集成失败第一步就栽在了这里。2.1 编译环境与工具链锁定首先必须明确一个版本对应关系AirSim v1.8.1是最后一个官方明确支持UE 4.27的稳定版本。后续的版本如v1.9主要面向UE5在UE4.27上编译会遇到大量API不兼容的问题。所以请务必从AirSim的GitHub Release页面下载v1.8.1的源代码。其次编译工具链必须匹配。UE4.27默认使用Visual Studio 2019和Windows 10 SDK (10.0.18362.0 或更高)。我强烈建议你通过Visual Studio Installer确认并安装以下工作负载“使用C的桌面开发”这是基础。“使用C的游戏开发”这个工作负载会包含编译UE4所需的所有Windows SDK、.NET Framework等组件避免后续出现找不到头文件的错误。注意即使你电脑上已经安装了VS2022也请务必安装VS2019并作为编译UE4的主要工具。UE4对编译器版本非常敏感混用会导致难以排查的链接错误。2.2 AirSim源码的预处理与编译下载的AirSim源码并不能直接作为插件使用它需要先被编译成一个UE4能识别的插件模块。这个过程官方提供了一个build.cmd脚本但直接运行常常会出问题。源码放置不要将AirSim源码放在路径包含中文或特殊字符的目录下。我建议在某个盘的根目录创建一个简单的工作区例如D:\AirSimProject。运行编译脚本以管理员身份打开“VS2019的开发者命令提示符”导航到AirSim源码目录下的Unreal\Plugins文件夹。直接运行build.cmd。这个脚本会自动下载UE4.27的源码如果本地没有并编译AirSim插件。关键一步复制产物编译成功后你会在AirSim\Unreal\Environments\Blocks\Plugins目录下看到一个名为AirSim的文件夹。这个才是我们最终需要集成到项目中的插件。将其完整复制到你的剪贴板备用。不要使用源码根目录下的那个AirSim文件夹。2.3 目标UE4 C项目的创建创建一个纯净的UE4 C项目作为起点至关重要。打开Epic Games Launcher启动UE4.27选择“游戏” - “空白” - “C”项目取名如MyAirSimProject选择带初学者内容创建一个。创建成功后关闭UE编辑器。找到项目目录其结构应类似于MyAirSimProject/ ├── MyAirSimProject.uproject ├── Source/ │ ├── MyAirSimProject/ │ ├── MyAirSimProject.Target.cs │ └── MyAirSimProjectEditor.Target.cs └── Content/3. 插件集成与uproject配置详解这是整个流程的核心也是最容易出错的部分。我们将把编译好的AirSim插件放入项目并深度配置.uproject文件。3.1 插件目录的放置在你的MyAirSimProject根目录下创建一个名为Plugins的文件夹如果不存在。将之前复制的AirSim插件文件夹粘贴到MyAirSimProject/Plugins/目录下。此时结构应为MyAirSimProject/ ├── Plugins/ │ └── AirSim/ (包含 Binaries, Content, Resources, Source, AirSim.uplugin等) ├── MyAirSimProject.uproject ├── Source/ └── Content/3.2 深度解析.uproject文件配置右键点击MyAirSimProject.uproject选择“Generate Visual Studio project files”。然后用Visual Studio 2019打开生成的MyAirSimProject.sln。先不要编译我们需要先手动编辑MyAirSimProject.uproject文件。用文本编辑器如VSCode打开.uproject文件。初始内容大概是这样{ FileVersion: 3, EngineAssociation: 4.27, Category: , Description: , Modules: [ { Name: MyAirSimProject, Type: Runtime, LoadingPhase: Default } ] }为了让项目正确加载并编译AirSim插件我们需要进行以下几处关键修改修改1添加插件依赖在Modules数组的后面添加一个Plugins数组。这告诉UE4本项目必须加载以下插件。{ FileVersion: 3, EngineAssociation: 4.27, Category: , Description: , Modules: [ { Name: MyAirSimProject, Type: Runtime, LoadingPhase: Default } ], Plugins: [ { Name: AirSim, Enabled: true } ] }修改2调整模块加载顺序关键避坑点AirSim插件内部有自己的模块如AirSimRPCLib等。如果你的游戏模块MyAirSimProject需要在代码中直接#include AirSim.h并使用其API那么你的游戏模块必须在AirSim插件模块之后加载否则编译时会报“未识别的标识符”错误。 这是通过LoadingPhase参数控制的。将游戏模块的LoadingPhase从Default改为PostConfigInit。这个阶段在引擎核心系统和大多数插件初始化之后确保AirSim的头文件已经可用。Modules: [ { Name: MyAirSimProject, Type: Runtime, LoadingPhase: PostConfigInit } ],修改3启用必要的引擎插件AirSim依赖一些引擎自带的插件例如Json、JsonUtilities用于RPC通信以及ShaderConductor可能用于某些渲染特性。为了确保万无一失最好也在Plugins数组中显式启用它们。Plugins: [ { Name: AirSim, Enabled: true }, { Name: Json, Enabled: true }, { Name: JsonUtilities, Enabled: true }, { Name: ShaderConductor, Enabled: true } ]修改4解决潜在编译冲突Windows平台AirSim使用了Windows.h头文件这可能会与UE4本身的一些定义如TEXT()宏产生冲突。一个常见的解决方案是告诉UE4在编译我们的游戏模块时不要使用预编译头PCH中的某些Windows定义。这需要在项目的Build.cs文件中配置但先在.uproject中我们可以为插件设置一些参数。不过更常见的做法是在Build.cs中处理。我们稍后会在C配置部分详细说明。保存修改后的.uproject文件。4. 项目C配置与代码集成现在配置项目的C端使其能够与AirSim插件协同工作。4.1 编辑项目构建文件.Build.cs导航到MyAirSimProject/Source/MyAirSimProject/目录打开MyAirSimProject.Build.cs文件。我们需要在这里添加对AirSim插件模块的依赖并处理Windows头文件冲突。using UnrealBuildTool; public class MyAirSimProject : ModuleRules { public MyAirSimProject(ReadOnlyTargetRules Target) : base(Target) { PCHUsage PCHUsageMode.UseExplicitOrSharedPCHs; // 1. 添加公共依赖模块 PublicDependencyModuleNames.AddRange(new string[] { Core, CoreUObject, Engine, InputCore, // 添加对Json模块的依赖因为AirSim的RPC会用到 Json, JsonUtilities }); // 2. 添加私有依赖模块插件模块通常在这里添加 PrivateDependencyModuleNames.AddRange(new string[] { // 依赖AirSim插件模块 AirSim }); // 3. 解决Windows.h冲突 (关键) // 定义这个宏可以避免Windows.h中的min和max宏与C标准库冲突 PublicDefinitions.Add(NOMINMAX); // 定义这个宏可以避免TEXT()宏的重复定义问题 PublicDefinitions.Add(WIN32_LEAN_AND_MEAN); // 4. 如果你需要用到AirSim的RPC客户端功能可能需要添加额外的库路径 // 但通常AirSim插件会自己处理好除非你遇到链接错误。 // 如果遇到无法解析的外部符号错误可以在这里添加 // if (Target.Platform UnrealTargetPlatform.Win64) // { // PublicAdditionalLibraries.Add(Path/To/Your/rpclib.lib); // } } }4.2 编写测试代码调用AirSim API为了验证集成是否成功我们在游戏模块中写一段简单的代码来调用AirSim。首先在MyAirSimProject/Source/MyAirSimProject/目录下修改MyAirSimProject.h和MyAirSimProject.cpp。这里我们创建一个简单的Actor在游戏开始时打印出AirSim的API版本。MyAirSimProject.h#pragma once #include CoreMinimal.h #include GameFramework/Actor.h // 包含AirSim的主要头文件 #include AirSim.h #include MyAirSimProject.generated.h UCLASS() class MYAIRSIMPROJECT_API AMyAirSimProject : public AActor { GENERATED_BODY() public: AMyAirSimProject(); protected: virtual void BeginPlay() override; public: virtual void Tick(float DeltaTime) override; };MyAirSimProject.cpp#include MyAirSimProject.h #include Misc/DateTime.h AMyAirSimProject::AMySimProject() { PrimaryActorTick.bCanEverTick true; } void AMyAirSimProject::BeginPlay() { Super::BeginPlay(); // 尝试获取AirSim的API客户端 msr::airlib::RpcLibClient* client nullptr; try { // 连接到本地默认的AirSim服务器端口41451 client new msr::airlib::RpcLibClient(127.0.0.1, 41451); client-confirmConnection(); // 确认连接 // 获取API版本信息 std::string serverVersion client-getServerVersion(); FString msg FString::Printf(TEXT([AirSim] Connected! Server Version: %s), *FString(serverVersion.c_str())); GEngine-AddOnScreenDebugMessage(-1, 10.0f, FColor::Green, msg); UE_LOG(LogTemp, Log, TEXT(%s), *msg); delete client; } catch (const std::exception e) { FString errMsg FString::Printf(TEXT([AirSim] Connection Failed: %s), *FString(e.what())); GEngine-AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, errMsg); UE_LOG(LogTemp, Error, TEXT(%s), *errMsg); if (client) delete client; } } void AMyAirSimProject::Tick(float DeltaTime) { Super::Tick(DeltaTime); }这段代码在游戏开始时会尝试连接到本机运行的AirSim仿真需要通过AirSim提供的可执行文件或自己启动一个仿真环境并打印出版本号。这是一个最基本的连通性测试。4.3 首次编译与生成回到Visual Studio 2019右键点击解决方案资源管理器中的MyAirSimProject项目选择“重新生成”。这个过程会比较久因为这是第一次编译需要编译整个项目以及我们集成的AirSim插件。确保你的磁盘空间充足可能需要几十GB的临时空间。编译成功后你可以在VS中按F5启动调试或者直接关闭VS双击MyAirSimProject.uproject文件启动UE4编辑器。启动编辑器时的关键观察点在UE4编辑器启动的加载阶段你应该在输出日志中看到类似“LogAirSim: AirSim: Starting AirSim plugin...”的信息。这表明插件已被成功加载。进入编辑器后在菜单栏中应该能看到“Play - AirSim”的选项里面有各种仿真设置。这是插件加载成功的另一个标志。5. 常见编译与运行时问题排查即使按照上述步骤操作你也可能会遇到一些问题。下面是我遇到过的典型错误及其解决方案。5.1 编译错误排查表错误信息可能原因解决方案fatal error C1083: 无法打开包括文件: “Windows.h”: No such file or directoryWindows SDK未安装或路径不对。通过VS Installer确保安装了正确版本的Windows 10 SDK (10.0.18362.0或更高)。error LNK2019: 无法解析的外部符号 “...AirSim...”项目没有正确链接AirSim插件模块。1. 检查.uproject中Plugins数组是否正确添加并启用。2. 检查Build.cs文件的PrivateDependencyModuleNames是否添加了AirSim。3. 确保插件目录Plugins/AirSim/下的Binaries文件夹存在且包含.dll和.lib文件。如果不存在说明插件编译步骤可能失败了需要回到第2步重新编译AirSim插件。error C2065: ‘msr’: 未声明的标识符游戏模块在AirSim插件模块之前加载导致头文件不可见。检查并修改.uproject文件中游戏模块的“LoadingPhase”为“PostConfigInit”。error C2589: “(”:“::”右边的非法标记或error C2059: 语法错误:“::”Windows.h中的min/max宏与C标准库冲突。在项目的Build.cs文件中添加PublicDefinitions.Add(“NOMINMAX”);。Compilation failed: UnrealHeaderTool.uproject文件格式错误或插件.uplugin文件损坏。仔细检查.uproject文件的JSON语法确保没有多余的逗号或括号不匹配。可以尝试用JSON验证工具检查。编辑器启动崩溃提示AirSim插件加载失败插件二进制文件与当前UE4.27版本不兼容或缺失依赖的DLL。1. 确认你使用的AirSim插件是v1.8.1为UE4.27编译的版本。2. 检查Plugins/AirSim/Binaries/Win64/下是否有.dll文件。尝试以管理员身份运行编辑器。3. 查看Windows事件查看器或编辑器崩溃日志获取更详细的错误信息。5.2 运行时连接问题当你运行我们写的测试代码时可能会连接失败。错误Connection refused或超时这表示没有AirSim仿真环境在运行。你需要先启动一个AirSim环境。最简单的方法是使用AirSim自带的Blocks环境。导航到AirSim\Unreal\Environments\Blocks目录双击Blocks.uproject。首次打开会编译Shader稍等片刻。在Blocks编辑器中点击“播放”按钮。这时一个AirSim仿真服务器就在本地启动了默认端口41451。然后再运行你自己的MyAirSimProject。此时测试代码就应该能连接成功了。错误Vehicle not available这表示连接成功但默认的车辆或无人机没有初始化。在Blocks环境中确保你是在“车辆模式”下运行。你可以在你的项目代码中通过client-enableApiControl(true)和client-armDisarm(true)来尝试获取控制权但这需要更复杂的设置匹配仿真环境中的车辆名称。5.3 性能与稳定性建议独立进程模式对于严肃的仿真应用建议将AirSim运行在独立进程例如Blocks环境你的UE4项目作为另一个客户端进程。这样即使你的客户端崩溃仿真服务器也不会受影响。可以通过RPC默认端口41451或ROS/ROS2进行通信。蓝图与CAirSim暴露了丰富的蓝图节点对于快速原型设计非常方便。但对于需要高性能、复杂逻辑或与外部代码如PX4深度集成的部分坚持使用C API是更可靠的选择。资源管理AirSim的传感器渲染尤其是激光雷达、深度相机非常消耗资源。在项目设置中合理调整渲染分辨率和帧率在代码中控制传感器数据的更新频率对于维持实时性至关重要。6. 高级配置自定义设置与多车辆控制当基础集成跑通后你通常会需要进行更复杂的配置。6.1 理解与修改settings.jsonAirSim的行为由一个settings.json文件控制。当你的项目运行时AirSim插件会在以下位置寻找这个文件按优先级你的项目可执行文件.exe所在的目录。你的项目Saved目录下的Config文件夹。你的用户文档目录%USERPROFILE%\Documents\AirSim。我建议在你的项目根目录下创建一个settings.json文件这样最容易管理。一个最简单的多旋翼无人机配置如下{ SettingsVersion: 1.2, SimMode: Multirotor, // 仿真模式Multirotor多旋翼, Car, ComputerVision Vehicles: { Drone1: { // 车辆名称在代码中会用到 VehicleType: SimpleFlight, // 物理模型类型 X: 0, Y: 0, Z: 0, // 初始位置 (米) Yaw: 0 // 初始偏航角 (度) } }, CameraDefaults: { CaptureSettings: [ { ImageType: 0, // 0Scene, 1Depth, 2Segmentation... Width: 256, Height: 144, FOV_Degrees: 90 } ] } }在你的C代码中你可以通过车辆名称来获取特定车辆的客户端// 连接到特定的车辆 msr::airlib::MultirotorRpcLibClient client(“127.0.0.1”, 41451, “Drone1”); client.confirmConnection(); client.enableApiControl(true); client.armDisarm(true); // 现在可以控制 Drone1 了 client.takeoffAsync(5)-waitOnLastTask(); // 起飞到5米高6.2 与外部飞控如PX4的集成这是AirSim最强大的功能之一。你需要将AirSim配置为使用PX4的“Software In The Loop (SITL)”模式。修改settings.json:{ SettingsVersion: 1.2, SimMode: Multirotor, Vehicles: { PX4Drone: { VehicleType: PX4Multirotor, // 关键使用PX4物理模型 UseSerial: false, // 使用UDP通信 UseTcp: true, TcpPort: 4560, // PX4 SITL默认端口 ControlPort: 14580, LocalHostIp: 127.0.0.1, OffboardUpdateFrequency: 50 // Hz } } }启动PX4 SITL你需要按照PX4开发指南搭建SITL环境通常使用jmavsim或gazebo。启动后PX4会在本地4560端口等待连接。启动你的UE4项目当你的项目运行时AirSim插件会自动尝试连接到127.0.0.1:4560的PX4实例。连接成功后你可以在QGroundControl中看到飞机状态并通过MAVLink指令或PX4的Offboard模式来控制它。这个过程环境配置比较复杂涉及到PX4固件编译、jmavsim启动等多个步骤但一旦打通你就拥有了一个硬件在环HITL或软件在环SITL的高保真仿真平台。集成AirSim到自定义UE4 C项目与其说是一个技术活不如说是一个“配置管理”的精细活。核心在于理解UE4的模块加载顺序、插件依赖关系以及编译工具链的版本锁死。最深刻的教训就是严格遵循版本对应AirSim v1.8.1 for UE4.27, VS2019并耐心检查每一个配置文件的语法和路径。当编辑器成功加载插件你的第一行C代码成功调用到AirSim API的那一刻之前所有的折腾都是值得的。这个环境搭建好后你就可以专注于最核心的仿真逻辑和算法开发了。如果在集成后还需要添加新的传感器模型或者修改物理参数直接去修改Plugins/AirSim/Source下的代码并重新编译插件即可这又是另一个层次的工作流了。