手把手带你搭建基于UE4虚幻引擎开发的AirSim仿真平台

1,749 阅读4分钟

一、学学知识

① UE4 是什么?

  • 来自百度百科:ue4,又名:虚拟引擎4,《虚幻引擎4》是由Epic Games公司推出的一款游戏开发引擎,相比其他引擎,虚幻引擎不仅高效、全能,还能直接预览开发效果,赋予了开发商更强的能力。虚幻引擎4在大约2分半的Demo演示中,将其强大的功能发挥得淋漓尽致。与之相关的热门游戏有《绝地求生》《和平精英》《实况足球2022》《跑跑卡丁车:漂移》等等。《手机QQ》也内置了虚幻引擎4。

② AirSim 是什么?

  • AirSim 是微软开源的一个跨平台的建立在虚幻引擎(Unreal Engine)上的无人机以及其它自主移动设备的模拟器。它支持硬件在循环与流行的飞行控制器的物理和视觉逼真模拟。它被开发为一个虚幻的插件,可以简单地放到任何你想要的虚幻环境中。
  • 该模拟器创造了一个高还原的逼真虚拟环境,模拟了阴影、反射等其它现实世界中容易干扰的环境,让无人机不用经历真实世界的风险就能进行训练。
  • AirSim 的目标是作为 AI 研究的平台,以测试深度学习、计算机视觉和自主车辆的增强学习算法。为此,AirSim 还公开了 API ,以平台独立的方式检索数据和控制车辆。

③ UE4 和 AirSim 的关系

  • AirSim 是基于虚幻引擎开发的仿真平台,是作为虚幻引擎的插件而存在的。

二、开始配置

① 硬件要求

  • 来自 Unreal Engine 官网:为了最大程度发挥 Nanite 、虚拟阴影贴图和 Lumen 的潜力,我们目前推荐 NVIDIA GTX 1080 或 AMD VEGA 64 显卡及同类或更高端的产品。要配合 Lunmen 使用硬件光线追踪,我们推荐 NVIDIA RTX 20 系列或 AMD RX 6000 系列显卡,或更高端产品。我们还推荐将您的显卡驱动更新到最新版本。
  • 虽然 AirSim 支持 Linux,但是如果使用 Linux系统,则会造成很多麻烦。比如目前还没有 Linux 版本的 Epic Games 启动程序,如果想要新建仿真场景,则需要先在 Windows 电脑上创建场景工程文件,然后将其拷贝到 Linux 电脑上。

② 安装虚幻引擎

  • www.unrealengine.com/zh-CN/ 首先注册登录 Epic Game 账号,然后按提示一步步下载平台就行。
  • image.png 推荐安装4.26及以上版本。

③ 下载 AirSim 源码

  • 先进入到预备放置的文件夹中(不建议C盘)。输入指令:git clone https://github.com/Microsoft/AirSim.git下载 AirSim 源码。
  • CD AirSim 进入 “AirSim” 文件夹,输入build.cmd,开始编译AirSim。编译好之后会在 “AirSim\Unreal” 文件夹中生成 “Plugins” 文件夹,将它复制到虚幻引擎的工程中就可以使用 AirSim 插件了。

④ Block 环境测试

  • 打开 “Developer Command Prompt for VS 2019”,CD Airsim\Unreal\Environments\Blocks进入 “Airsim\Unreal\Environments\Blocks” 文件夹,输入 update_from_git.bat生成 “Blocks.sln” 工程文件,双击打开此工程文件,会自动运行 Visual Studio。
  • 在 Visual Studio 中,将 “Block工程” 设为启动项目,编译选项设为 “DebugGame_Editor” 和 “Win64”,然后点击 “调试” -> “开始调试”,这时就会打开Unreal Engine。
  • 点击“运行”,此时会跳出一个对话框,点击 “No”,就会出现一个四旋翼无人机。

三、尝试让无人机在场景中飞行

① 下载并配置 Landscape Mountains

  • image.png
  • 在安装的地址中找到LandscpeMountains.uproject,双击打开。 image.png
  • 为了能够使用 Visual Studio 编译.sln文件,我们需要创建自己的。点击左上角的文件,选择新建C++类,父类选择,所以直接点击下一步;命名和路径都是默认就好了,直接点击创建类。这时Unreal会自动编译C++代码,然后会自动打开Visual Studio。到此 Landscape Mountain环境就下载安装好了。 image.png

② 添加 AirSim 插件

  • 找到AirSim\Unreal\Plugins文件夹,并将其复制到LandscapeMountains文件夹中。 image.png
  • 右键LandscapeMountains.uproject打开,并用英文输入法将内容改为如下所示。 image.png image.png
  • 然后右键点击LandscapeMountains.uproject选择Generate Visual Studio project filesimage.png

③ 跑起来!

  • 双击打开LandscapeMountains.sln,会自动打开 Visual Studio,选择编译选项为 DebugGame Editor 和 Win64,同时确保LandscapeMountais为启动项目。 image.png
  • 用 pyCharm 打开预先写好的控制代码,右键跑起来! image.png image.png
"""
 airsim 四旋翼飞圆形
 """
import airsim
import numpy as np
import math
import time

client = airsim.MultirotorClient()  # connect to the AirSim simulator
client.enableApiControl(True)  # 获取控制权
client.armDisarm(True)  # 解锁
client.takeoffAsync().join()  # 起飞
client.moveToZAsync(-3, 1).join()  # 第二阶段:上升到2米高度
center = np.array([[0], [5]])  # 圆心设置
speed = 2  # 速度设置
radius = 5  # 半径设置
clock_wise = True  # 顺时针或逆时针设置
pos_reserve = np.array([[0.], [0.], [-3.]])
# 速度控制
for i in range(2000):
    # 获取无人机当前位置
    state = client.simGetGroundTruthKinematics()
    pos = np.array([[state.position.x_val], [state.position.y_val], [state.position.z_val]])
    # 计算径向速度的方向向量
    dp = pos[0:2] - center
    if np.linalg.norm(dp) - radius > 0.1:
        vel_dir_1 = -dp
    elif np.linalg.norm(dp) - radius < 0.1:
        vel_dir_1 = dp
    # 计算切向速度的方向向量
    theta = math.atan2(dp[1, 0], dp[0, 0])
    if clock_wise:
        theta += math.pi / 2
    else:
        theta -= math.pi / 2
    v_dir_2 = np.array([[math.cos(theta)], [math.sin(theta)]])
    # 计算最终速度的方向向量
    v_dir = 0.08 * vel_dir_1 + v_dir_2
    # 计算最终速度指令
    v_cmd = speed * v_dir / np.linalg.norm(v_dir)
    # 速度控制
    client.moveByVelocityZAsync(v_cmd[0, 0], v_cmd[1, 0], -3, 1)
    # 画图
    point_reserve = [airsim.Vector3r(pos_reserve[0, 0], pos_reserve[1, 0], pos_reserve[2, 0])]
    point = [airsim.Vector3r(pos[0, 0], pos[1, 0], pos[2, 0])]
    point_end = pos + np.vstack((v_cmd, np.array([[0]])))
    point_end = [airsim.Vector3r(point_end[0, 0], point_end[1, 0], point_end[2, 0])]
    client.simPlotArrows(point, point_end, arrow_size=8.0, color_rgba=[0.0, 0.0, 1.0, 1.0])
    client.simPlotLineList(point_reserve + point, color_rgba=[1.0, 0.0, 0.0, 1.0], is_persistent=True)
    # 循环
    pos_reserve = pos
    time.sleep(0.02)