☰
UE5+Cosys-AirSim与ROS2联合仿真跨平台部署与网络配置实战
2026/9/25 1:57:46 网站建设 项目流程

这篇内容很适合作为一篇“环境部署复盘型”的硬核博客来写。用户给的标题很精准——不只是单纯讲安装,而是把“跨平台避坑”和“网络配置”点出来了,这恰恰是整个联合仿真链路里最容易反复折腾人的地方。导向很明确:要实操、要细节、要有真实踩坑记录,不能写成官方文档翻译。我会围绕 UE5 + Cosys-AirSim 的 Windows 端部署、ROS 2 的 Ubuntu 端部署、以及两者之间的通信/网络打通,逐步拆解,重点放在最容易出问题的跨平台节点、IP 配置、话题通信验证这些环节,用比较接地气的方式写,确保有干货、有步骤、有排查思路。

现在直接写正文。 做机器人和自动驾驶仿真的人,多少都遇到过这种尴尬:算法在 Gazebo 里跑得好好的,一旦想换到更逼真的渲染环境,立刻被各种依赖、版本、网络通信问题缠住。我自己在部署 Cosys-AirSim(UE5)和 ROS 2 联合仿真环境时,光是跨平台通信就折腾了将近一周。这篇东西不是官方文档的复述,是我把整个部署过程重新走了一遍之后,把手上的坑、排查思路和最终能跑通的方案沉淀下来的记录。如果你正准备把仿真从简单的刚体环境往高保真视觉环境迁,或者需要在 Windows 的 UE5 和 Linux 的 ROS 2 之间打通数据链路,这篇文章应该能帮你省下不少时间。

先说清楚这套环境是干什么的。Cosys-AirSim 是 AirSim 的一个分支,核心改进是能接入 UE5,同时把传感器仿真、天气、光照这些做得更适合现代机器人算法验证。ROS 2 则负责算法层的节点通信、话题收发和控制闭环。两者结合之后,你可以让视觉感知、路径规划这些模块跑在 ROS 2 侧,而底层的物理仿真、传感器渲染、场景光影交给 UE5 去完成。和传统的 Gazebo + RViz 方案相比,视觉真实度完全是两个层级。当然,代价就是环境部署复杂度上来了,尤其是跨平台的时候。

我最终的部署架构是:Windows 11 跑 UE5 和 Cosys-AirSim 插件,Ubuntu 22.04 跑 ROS 2 Humble,两台机器通过局域网连接。这套方案的好处是渲染和算法互不干扰——UE5 的 GPU 资源不会被 ROS 2 的可视化工具抢占。如果你的显卡够猛,也可以全塞进一台机器里,但网络配置的思路是一样的,我建议还是分开跑,排查问题的时候能少很多干扰。

1. 环境部署前必须想清楚的几件事

1.1 版本组合的选择逻辑

先说版本。Cosys-AirSim 目前对 UE5 的适配比较挑剔,我实测能稳定跑的是 UE5.3.2。ROS 2 这边选了 Humble,原因很朴素:Ubuntu 22.04 原生的 apt 源里直接有预编译包,不用折腾源码编译,这对后面跨平台联调非常重要——你永远不希望算法跑着跑着,底层的通信库出现诡异的内存问题。

另外一个容易被忽视的是 Windows 端的显卡驱动和 CUDA 版本。UE5 本身对驱动有要求,而 AirSim 的视觉传感器在部分场景会调用 CUDA 进行图像处理。我踩过的一个坑是,驱动版本过旧导致 UE5 编辑器一直报 DXGI_ERROR_DEVICE_HUNG,后来更新到 NVIDIA 官方最新驱动才解决。如果你用的是 A 卡,AirSim 的部分 GPU 加速功能可能不生效,这点需要提前知道。

提示:尽量别用 UE5.4 或更新的版本。Cosys-AirSim 的编译脚本对旧版引擎的适配更完善,新版本在编译 AirSim 插件时容易出现 API 变更导致的编译失败。

1.2 网络拓扑与数据流向设计

在动手装任何东西之前,应该先把网络架构画清楚。我的方案里,Windows 端跑 UE5,生成的图像、激光雷达点云、IMU 数据通过 Cosys-AirSim 的 ROS 2 网桥发布;Ubuntu 端跑感知、规划、控制节点,把速度、转向指令发回仿真环境。

这里有一个关键决策:ROS 2 的 DDS 通信是走 Multicast 的(默认情况下)。跨机器通信时,很多问题都是因为 Multicast 被路由器或防火墙挡掉了。比较稳妥的做法是,先用 UDP 单播方式测试连通性,再把 DDS 的通信模式调整成适合局域网部署的配置。这是我整个部署过程中最后悔没提前研究的部分——如果一开始就做好规划,能少走至少两天的弯路。

1.3 静态 IP 与主机名解析

跨平台联合仿真最基础也最容易出问题的就是主机名解析。Windows 和 Linux 的 hostname 默认格式不一样,Windows 常有后缀,而 Ubuntu 的主机名如果没有在 hosts 文件里注册,Windows 端可能根本解析不到。我的建议是:两台机器都设静态 IP,同时在两边的 hosts 文件里把对方的主机名和 IP 对应写上。后面你会发现,这一条能省掉大量“连不上”“超时”的排查时间。

2. 在 Windows 上搭建 UE5 + Cosys-AirSim

2.1 源码获取与编译预处理

首先要拿到 Cosys-AirSim 的源码。它是从 AirSim 拉出来的独立分支,克隆下来之后,需要确保子模块完整更新。这里有个细节:国内网络环境下,GitHub 的 submodule 拉取经常超时,导致后续编译报头文件缺失。我的技巧是——先单独把依赖的 submodule 仓库逐个 clone 到本地,再手动配置.gitmodules指向本地路径。这个方法虽然笨,但可靠。

依赖项上,Windows 端需要装 Visual Studio 2022,记得勾选“使用 C++ 的游戏开发”工作负载,还有 .NET 桌面开发组件。很多人编译失败是因为 VS 组件不全,不是代码本身的问题。此外还要装 Git、CMake,以及 UE5 对应的 Visual Studio 集成组件——这些在安装 UE5 的时候会提示,别跳过。

2.2 UE5 项目创建与插件集成

这里我不建议你从零创建 C++ 工程再费劲配置,直接采用 Cosys-AirSim 仓库里提供的AirSimUnrealPlugin方式会省心很多。思路是:先创建一个纯 C++ 的空白 UE5 项目,然后把 Cosys-AirSim 的插件目录符号链接到项目的Plugins目录下。

实际操作时,我用的是命令行方式:

mklink /J D:\UE5Projects\MySim\Plugins\AirSim D:\Cosys-AirSim\Unreal\Plugins\AirSim

这比复制粘贴文件夹好得多——后续更新 Cosys-AirSim 代码时,不需要重新拷贝整个插件。如果不用符号链接,每次重新编译插件后都要反复复制二进制文件,很容易忘记从而出现“代码更新了但 UE5 跑的还是旧版本”这种极其隐蔽的问题。

2.3 编译过程与 UE5 编辑器设置

打开 UE5 项目后,编辑器会提示是否重新编译缺失的模块。这里必须选择“是”。编译时间取决于 CPU,我第一次编译花了大约四十分钟。编译完成后,需要在 Project Settings 里做几个关键设置:

  • Maps & Modes:把默认地图设置成 AirSim 提供的示例地图,或者你自己导入的地图。
  • 添加 AirSim 的输入映射,否则无法用键盘控制无人机或车辆。
  • 如果做的是无人机仿真,记得在 Settings.json 里指定"SimMode": "Multirotor",车辆则用"Car"。

等 UE5 项目能正常启动、场景里出现 AirSim 的默认载具后,Windows 端的部分就算基本完成了。

2.4 验证 UE5 侧是否正常工作的简单方法

启动 UE5 场景后,按 Play 进入仿真,你应该能在视口里看到载具,并且可以通过键盘控制它移动。这一步往往被很多人忽略——直接跳到 ROS 2 联调,结果发现图像话题一直没数据,排查了半天才发现是 UE5 场景根本没进入仿真状态。所以务必先手动确认:UE5 能够运行,载具能够响应键盘输入,AirSim 的日志窗口里没有报错。

3. Ubuntu 22.04 上的 ROS 2 环境准备

3.1 安装 ROS 2 Humble 与依赖项

Ubuntu 22.04 安装 Humble 相对顺手,跟着官方文档一步步来即可。除了基础包,一定要确认装了ros-humble-desktop和ros-humble-ros-base,这俩虽然名字接近但包内容不同,ros-base是精简版,不含 RViz 这类可视化工具。联调初期,RViz 是你确认雷达点云和图像话题是否正常的关键,所以别省这个安装时间。

还需要装上ros-humble-gazebo-ros-pkgs,即使你不用 Gazebo 做仿真,这个包会带上一堆常用的消息依赖,后续 AirSim 的 ROS 2 网桥可能要引到。

3.2 创建 ROS 2 工作区与依赖管理

工作区的创建用常规方式即可:

mkdir -p ~/ros2_ws/src cd ~/ros2_ws colcon build --symlink-install

这里要提醒一个重要操作:确保source /opt/ros/humble/setup.bash写进了~/.bashrc。跨终端调试时,忘记 source 环境会导致一堆“Package not found”的诡异错误。colcon build 时如果遇到依赖缺失,不要直接去apt install,先用rosdep install --from-paths src --ignore-src -r -y自动解析,能省点时间。

3.3 检查 DDS 通信环境

ROS 2 的通信是走 DDS 的,跨机器联调时,需要确认 UDP 端口没有被防火墙拦截。Ubuntu 默认的 ufw 很多是关闭状态,但如果你开过防火墙,需要在规则里放行 ROS 2 的端口范围和 Multicast 地址。

我先给一个快速验证方法:两台机器上各自开一个终端,一个跑ros2 run demo_nodes_cpp talker,另一个跑ros2 run demo_nodes_cpp listener,如果能看到消息收发,说明 DDS 的基本通信链路是通的。如果这一步都过不了,后面联调 AirSim 网桥必然出问题,所以这个测试值得反复做几轮。

4. Cosys-AirSim 与 ROS 2 的桥接层配置

4.1 选择正确的桥接方式

Cosys-AirSim 官方提供了一套 ROS 2 的 wrapper,本质上就是 AirSim 的 ROS 2 节点,通过 rpc 调用连接 UE5 里的 AirSim 插件,同时对外发布图像、IMU、GPS 这些话题。这套 wrapper 在AirSim/ros2目录下,是一个原生的 ROS 2 功能包。

我强烈建议直接用官方 wrapper,而不是自己去写一套 socket 通信。原因很简单:官方 wrapper 已经处理好了坐标系转换、消息类型定义、图像编码转换(如 RGBA8 转 sensor_msgs/Image)这些繁琐的细节。自己写很容易忽略 Ros 和 AirSim 的坐标系差异——AirSim 用的是 NED 坐标系,和 ROS 的 REP 103 规范(右手定则)在某些轴向上完全相反,这些底层差异不值得你手动去处理。

4.2 wrapper 编译与配置详解

编译官方 wrapper 需要确认一个关键路径。找到AirSim/ros2下的CMakeLists.txt,里面会引用 AirSim 的库路径。因为 AirSim 源码在 Windows 和 Linux 上都要编译一遍(Windows 生成 UE5 插件,Linux 生成 ROS 2 wrapper),所以必须在 Ubuntu 上重新克隆一份 Cosys-AirSim 源码,并编译它的 Linux 版本库:

cd /path/to/Cosys-AirSim ./setup.sh ./build.sh

这一步会花一些时间,因为要编译 AirSim 的核心库。完成后,再回到ros2目录,看看依赖是否正确。编译时比较常见的报错是找不到rclcpp或sensor_msgs,这通常意味着没有 source ROS 2 环境,或者AMENT_PREFIX_PATH没设置好。

4.3 通过命名空间与参数配置多机器人仿真

如果你打算跑多车或多无人机协同,wrapper 支持通过命名空间区分不同机器人的话题。在启动文件里,给每个机器人实例设置不同的namespace参数即可。比如车辆 1 的图像话题是/car1/camera/image_raw,车辆 2 的是/car2/camera/image_raw。

这里要提醒一点:AirSim 的 Settings.json 里需要为每个载具配置不同的 VehicleName,否则 ROS 2 wrapper 连接时会始终指向第一个载具。我第一次跑多车时,所有命名空间都收到同样的图像数据,排查了很久才发现是 Settings.json 里没指定 VehicleName。

4.4 节点连接时序的坑

实际联调时,最容易出现的问题是“先启动 UE5 还是先启动 ROS 2 wrapper”。我的经验是:先启动 UE5 并进入仿真,再启动 wrapper 节点。因为 wrapper 启动时会给 AirSim 发送 reset 指令,如果 UE5 还没加载好,reset 就会失败,然后一直处于等待响应的状态。

如果启动顺序反了,也不用完全关掉重来——wrapper 有自动重连机制,等 UE5 就绪后它会自动连上。只是等待时间有点长,有时候要等十几秒。所以,与其等它自动重连,不如控制好启动顺序。

5. 跨平台网络配置实战

5.1 局域网静态 IP 设置与 hosts 映射

这部分是整个跨平台方案里最繁琐、也最容易出错的地方。先说 IP 规划:Windows 机器用192.168.1.100,Ubuntu 机器用192.168.1.101,网关统一指向路由器。掩码是标准的255.255.255.0,确保两台机器在同一个网段。

然后是 hosts 文件:

  • Windows 的C:\Windows\System32\drivers\etc\hosts里加一行:192.168.1.101 ubuntu-ros
  • Ubuntu 的/etc/hosts里加一行:192.168.1.100 win-ue5

这一步的作用是让 ROS 2 在发现对端节点时,能通过主机名解析到正确的 IP。如果 hosts 文件配置不正确,会出现“偶尔能连通、偶尔超时”的随机性问题——DDS 尝试用主机名去解析对方,解析失败就会直接放弃。

5.2 DDS 的 QoS 与通信模式调优

ROS 2 的中间件默认是 Fast DDS,它在跨机器通信时用的是 Multicast 发现协议。如果局域网交换机禁用了 Multicast 或者网络环境比较复杂,节点会发现不了对方。

解决方法是修改 Fast DDS 的配置文件,把发现机制改成指定对端 IP 的静态发现:

<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles"> <participant profile_name="static_discovery" is_default_profile="true"> <rtps> <builtin> <discovery_config> <discoveryProtocol>SIMPLE</discoveryProtocol> <use_SIMPLE_EndpointDiscoveryProtocol>true</use_SIMPLE_EndpointDiscoveryProtocol> <leaseDuration> <sec>5</sec> </leaseDuration> <leaseAnnouncement> <period> <sec>1</sec> </period> </leaseAnnouncement> </discovery_config> <metatrafficUnicastLocatorList> <locator> <udpv4> <address>192.168.1.101</address> <port>7400</port> </udpv4> </locator> </metatrafficUnicastLocatorList> </builtin> </rtps> </participant> </profiles>

然后通过环境变量指定配置文件:

export FASTRTPS_DEFAULT_PROFILES_FILE=/path/to/fastdds_profile.xml

这个配置需要同时设 Windows 和 Ubuntu 两端。Windows 端可以在系统环境变量里加同样的变量。

5.3 防火墙放行策略与端口确认

这一条单独拎出来说,因为太多人在这里栽跟头。Fast DDS 默认使用的端口范围是7400到7500左右,还有 Multicast 地址239.255.0.1。如果路由器或系统的防火墙不放行这些,节点间可以发现,但数据传输会被阻断——这会导致ros2 topic list能看到话题,但订阅却收不到数据,非常容易让人误判成代码问题。

Ubuntu 端,如果启用了ufw,可以这样放行:

sudo ufw allow 7400:7500/tcp sudo ufw allow 7400:7500/udp sudo ufw allow proto udp from 192.168.1.0/24 to any port 7400:7500

Windows 端更麻烦,需要在“高级安全 Windows Defender 防火墙”里添加入站规则,放行 UE5 进程和 ROS 2 wrapper 进程的所有网络通信。最省事的做法是直接放行 UDP 端口范围7400-7500,然后把 UE5 的可执行文件加入白名单。如果你是默认的 Windows 防火墙设置,大概率会有弹窗让你允许 UE5 通信,务必点允许。

注意:如果你在用公司内网或校园网,这种网络环境通常有 AP 隔离,跨设备通信默认阻断。这种情况下,单纯在系统层面配置防火墙是没有用的,必须联系网络管理员或者在路由器上做端口转发。

5.4 实测网络连通性的完整命令序列

我习惯按从底层到上层的顺序逐级验证:

  1. 两端互 ping IP,确认网络物理层通:
    ping 192.168.1.101
  2. 通过主机名互 ping,确认 hosts 解析正常:
    ping ubuntu-ros
  3. 检查 ROS 2 节点发现,确认 DDS 通信层通:
    ros2 daemon stop && ros2 daemon start ros2 node list
  4. 用 talker/listener 验证话题通信:
    ros2 run demo_nodes_cpp talker # 另一台机器上执行 ros2 run demo_nodes_cpp listener
  5. 最后才是启动 UE5 + wrapper,确认仿真数据话题有数据。

这五步里任何一步失败,都不用急着改代码,先确认网络链路没问题,再做下一步,能省掉大量误判。

6. 联合仿真运行与验证

6.1 启动顺序与完整操作流程

经历了上面所有配置,终于到了启动环节。我最终的启动流程是这样的:

先在 Windows 上启动 UE5:

cd D:\UE5Projects\MySim start UE5Editor.exe MySim.uproject

等编辑器加载完毕,按 Play 进入仿真模式。注意观察视口左下角是否出现 AirSim 的调试信息,如果一直显示“Vehicle not initialized”,说明 Settings.json 里配置有问题,载具没有正确生成。

然后在 Ubuntu 端启动 ROS 2 wrapper:

source /opt/ros/humble/setup.bash source ~/ros2_ws/install/setup.bash ros2 launch airsim_ros2_launch airsim_ros2_single_vehicle.launch.py

看到[INFO] Connected to AirSim的日志后,说明桥接层已经建立通信。这时可以另开终端检查话题:

ros2 topic list

如果看到/airsim_node/.../rgb/camera/image_raw这类话题,说明图像链路已经建立。再用ros2 topic hz检查消息频率,确保数据在持续发布。

6.2 验证图像、雷达点云与控制闭环

用 RViz 订阅图像和点云话题,确认可视化正常:

rviz2

在 RViz 里添加 Image 显示并选择相机话题,添加 PointCloud2 显示并选择雷达话题。如果图像和点云在正常刷新,说明整个视觉链路是通的。

控制闭环的验证也很重要。通过 rqt 或命令行发布速度指令,观察 UE5 里的载具是否移动。例如让车辆前进:

ros2 topic pub --once /airsim_node/vehicle_1/vel_cmd \ airsim_ros2_msgs/msg/VelCmd \ "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"

如果载具动了,说明底层控制链路正常。这一步往往能暴露坐标系方向的问题,比如你发 x 方向速度,车辆却往左跑了,那基本可以确定是坐标变换还需要调整。

6.3 数据频率与系统资源监控

仿真稳定运行后,还应关注数据频率。用ros2 topic hz查看图像话题的频率——通常能达到 20-30 FPS 就算正常,如果低于 10 FPS,可能是分辨率设太高或 GPU 压力大。

我用的是 1920x1080 分辨率,图像话题大约 20 FPS。如果你的显卡性能一般,建议先在 Settings.json 里把分辨率降到 1280x720,等整个系统稳定后再逐步调高。另外,UE5 编辑器本身的帧率和仿真数据的发布频率不是一回事,如果你发现 UE5 的画面很流畅但图像话题频率很低,问题往往出在 wrapper 端的图像编码上,而不是渲染性能。

7. 常见问题排查与避坑指南

7.1 节点发现不了对方

这是跨平台联调里最典型的故障。按照优先级依次检查:

  • 两端是否在同一网段,能否互 ping 通
  • 防火墙是否放行 UDP 7400-7500 端口
  • 是否设置了相同的ROS_DOMAIN_ID。默认都是 0,但如果一端改了而另一端没改,就会互相看不见
  • 路由器是否开启了 AP 隔离

7.2 话题有列表但订阅不到数据

这种情况典型特征是ros2 topic list能列出话题,但ros2 topic echo没反应或超时。大概率是 QoS 不匹配。AirSim wrapper 发布的图像话题默认使用的是 SensorDataQoS,如果你的订阅节点用的是默认 QoS(Reliable),两边其实是不匹配的。虽然 ROS 2 会自动做一定的兼容性协商,但有些组合下结果很微妙。

我建议订阅节点在代码里显式设置 QoS:

from rclpy.qos import QoSProfile, ReliabilityPolicy, HistoryPolicy qos_profile = QoSProfile( reliability=ReliabilityPolicy.BEST_EFFORT, history=HistoryPolicy.KEEP_LAST, depth=1 )

图像、点云这类传感器数据用 BestEffort 就够了,强行用 Reliable 反而会带来延迟和丢帧。

7.3 UE5 崩溃与 GPU 相关问题

用 UE5 时会遇到的崩溃类型不少,最常见的是:场景里有大量动态光源和阴影时,显存占用直接拉满。AirSim 的默认示例地图已经经过优化,但如果导入自己的地图,要留意静态光照烘焙没有做的话,实时光照会消耗大量资源。

建议先在项目设置里把整体画质调到 Medium 级别,等确认功能链路全部通了再调回高画质。另外一个实际经验是,把 UE5 编辑器的“自动曝光”关掉,改成手动曝光,可以避免图像话题的画面亮度不断变化,影响视觉算法的调试。

7.4 Windows 和 Linux 时间不同步导致 DDS 握手失败

这个问题比较隐蔽。Fast DDS 在建立连接时会用到时间戳和 lease duration 机制,如果两台机器时间差太大,节点可能认为对方的租约已经过期,从而反复断连。

解决办法是两端都配置 NTP 时间同步:

sudo timedatectl set-ntp true

Windows 端则在“日期和时间设置”里打开“自动设置时间”。时间同步做完后,联合仿真的稳定性会有肉眼可见的提升。

8. 性能调优与进一步扩展

8.1 图像分辨率与编码器选择

如果在视觉链路 + 稠密点云的场景下,图像话题的数据量非常大。AirSim 支持在 Settings.json 里配置图像编码格式。默认是 JPEG,画质有损失;如果做视觉 SLAM,建议改成 PNG 或直接输出 RGBA8 原始数据,但代价是带宽和 CPU 占用明显上升。

我实测的一组数据供参考:1080p 分辨率下,JPEG 编码大约占用 30-40 Mbps 带宽,PNG 或原始格式则可能超过 200 Mbps。跨机器通信时,千兆网卡基本能扛住,但如果你用无线网络,建议分辨率降到 720p,否则丢包会严重。

8.2 多机并行仿真的扩展思路

这套架构可以很自然地扩展到多机集群。思路是:一台高性能机器跑 UE5 渲染,多台机器跑不同的算法节点,通过共享的 ROS 2 拓扑共享感知数据。

不过有一个前置条件:整个集群必须使用同一个 ROS 2 Domain ID,并且 Multicast 能跨网段传播——如果不可以,就得用我之前说的 Fast DDS 静态发现配置,把所有参与的机器 IP 都列在配置里。

8.3 与主流算法框架的衔接

Cosys-AirSim 发布的 ROS 2 话题和标准格式是兼容的,所以可以直接接 Autoware、Nav2 这些框架。我实际跑过 Nav2 的仿真验证,只需要做一步坐标转换:AirSim 的东北天坐标系和 Nav2 的地图坐标系在初始朝向角上需要对齐,否则机器人会自行旋转。

从一个仿真环境迁移到另一个的具体操作,往往卡在坐标约定和数据格式的匹配上。AirSim 本身提供了 getTransform 接口,配合它的 reset 功能,可以在场景启动时把载具摆放到指定位置和朝向,用这个机制可以避免很多坐标系上的头疼问题。

写到这里,想起第一次成功跑通整套流程的那个晚上——UE5 视口里车辆在逼真的柏油路上行驶,RViz 里同步刷新着激光点云,那种“整个世界终于连起来了”的感觉还是很值的。这套环境搭建起来确实繁琐,但一旦跑顺,它给你的是一个质量完全不同的仿真平台。我个人的经验是,遇到问题多想想底层协议和通信链路,很多坑其实不在仿真代码里,而在我们轻易不会去检查的网络配置上。希望这篇记录能帮你顺利跨过这些坎。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询