一、为什么选择 Project AirSim

近年来,微软开源的AirSim 项目成为了无人机与自动驾驶研究中的重要仿真平台,但AirSim有个限制:同一仿真中无法同时使用车辆(Car)和无人机(Multirotor)。在 AirSim 中,我们需要通过修改 SimMode(SimMode=Multirotor 或 SimMode=Car)来切换模式,这意味着两种载具无法在一个世界中同时存在。

Project AirSim在原版 AirSim 的基础上进行了大量改进和重构,可以在同一场景中同时渲染无人机与地面车辆。(Issue #61 - Can ProjectAirSim support both cars and UAVs simulation?

二、无人机避障算法解析

项目中自带了多个示例脚本,其中一个典型案例是:

ProjectAirSim/client/python/airsimv1_scripts_migrated/multirotor/navigate.py

它展示了如何让无人机基于深度图(Depth Image)实现一个简单的前向避障算法。下面我将结合源代码来详细分析其执行逻辑。

2.1 初始化与连接

首先,脚本通过 ProjectAirSimClient() 连接到仿真服务器,并加载场景与无人机对象:

client = ProjectAirSimClient()
client.connect() 
world = World(client, "scene_drone_classic.jsonc", delay_after_load_sec=2) 
drone = Drone(client, world, "Drone1")

其中,ProjectAirSimClient 模块负责与后端进行通信。World 会加载与 navigate.py 位于同一目录下的 sim_config 文件夹中的 scene_drone_classic.jsonc 配置文件。该配置文件中通过 "robot-config": "robot_quadrotor_classic.jsonc" 指定了机器人配置,从而进一步导入 robot_quadrotor_classic.jsonc 中的详细参数设置。

2.2 图像订阅与显示

前面,脚本使用ImageDisplay()创建显示窗口,并分别订阅追踪相机(ChaseCam)和前向深度相机(front_center depth)。

image_display = ImageDisplay() 

chase_cam_window = "ChaseCam" 
image_display.add_chase_cam(chase_cam_window) 
client.subscribe( 
    drone.sensors["Chase"]["scene_camera"], 
    lambda _, chase: image_display.receive(chase, chase_cam_window), 
) 

depth_name = "Depth-Image" 
image_display.add_image(depth_name, subwin_idx=0) 
client.subscribe( 
    drone.sensors["front_center"]["depth_planar_camera"], 
    lambda _, depth: image_display.receive(depth, depth_name), 
)

这一步的目的是在本地实时显示仿真画面,便于调试。相机传感器(sensors)中第一个键(key)的获取,是根据前文提到的 robot_quadrotor_classic.jsonc 文件中的 id 进行匹配得到的。部分配置内容如下所示。

"sensors": [ 
{ 
    "id": "Chase", 
    "type": "camera", 
    "enabled": true, 
    "parent-link": "Frame", 
    "capture-interval": 0.03, 
    "capture-settings": [

2.3 起飞与准备工作

image_display.start() 
drone.enable_api_control() 
drone.arm() 
await drone.takeoff_async()

无人机起飞后,将进入主循环。

2.4 深度图避障逻辑核心

主循环中,算法每一帧执行如下步骤:

2.4.1 获取前置深度图

result = drone.get_images("front_center", [ImageType.DEPTH_PLANAR]) 
depth_image = unpack_image(result[ImageType.DEPTH_PLANAR])

这里的 depth_image 是一个 NumPy 数组,表示视场内每个像素的深度信息。值越小表示越近。

2.4.2 取图像上半部分

top = np.vsplit(depth_image, 2)[0]

算法只分析上半部分(前方视野),忽略地面区域。

2.4.3 横向分割为五个区域

bands = np.hsplit(top, [50,100,150,200]) 
mins = [np.min(x) for x in bands]

将画面从左到右分为 5 个区域,并计算每个区域的最小深度值(代表最近的障碍距离)。

例如:索引 0 → 最左侧,索引 2 → 正前方,索引 4 → 最右侧。

2.4.4 判断最近障碍与最开阔方向

max = np.argmax(mins) 
distance = mins[max] current = mins[2]

mins[max] 最大的区域表示“最开阔的方向”; current 是当前正前方的障碍距离。

2.4.5 悬停操作避免碰撞

if (current < 20): 
    await drone.hover_async() 
    projectairsim_log().info("whoops - we are about to crash, so stopping!") 
    input()

若正前方障碍过近(阈值为 20),无人机悬停并等待人工干预。

2.4.6 动态调整航向(yaw)

if (distance > current + 300): 
    if (max == 0): 
        change = -2*pi/10 
    elif (max == 1): 
        change = -pi/10 
    elif (max == 2): 
        change = 0 
    elif (max == 3): 
        change = pi/10 
    else: change = 2*pi/10 

yaw += change 
vx = math.cos(yaw) 
vy = math.sin(yaw)

算法把 90° 视场分为 5 段,每段约 18°。当检测到某侧更“开阔”时,无人机偏航一定角度(±18° 或 ±36°),并重新计算速度向量。

2.4.7 以固定高度和速度前进

await drone.move_by_velocity_z_async( vx, vy, -6, 1, YawControlMode.ForwardOnly, yaw=0, yaw_is_rate=False )

move_by_velocity_z_async 是 Project AirSim 提供的用于控制无人机飞行的 API 接口。该函数使无人机在 高度 z = -6(由于 Project AirSim 采用 NED 坐标系,即 North–East–Down)时,以指定的 水平速度 vx、vy 飞行 1 秒。飞行结束后,系统会重新采样图像,并进入下一次循环。

值得注意的是,YawControlMode.ForwardOnly (= 1)(在drone.py中定义) 表示偏航角(Yaw)被限制为与运动方向保持一致,即无人机的机头始终朝向其当前的运动方向。 这也解释了在 2.4.6 节中,vx 和 vy 是根据偏航角的正弦与余弦计算得到的原因。除此之外,在drone.py文件中还定义一个MaxDegreeOfFreedom = 0,表示偏航与速度向量相互独立,即可以让无人机头朝向和移动方向不一致。

2.5 循环退出与资源释放

按下 Esc / q / x 键退出,程序会停止显示并断开连接:

image_display.stop() 
client.disconnect()

3 相关连接

AirSim:https://github.com/microsoft/AirSim.git

Project AirSim:https://github.com/iamaisim/ProjectAirSim.git

为了方便使用,我在 Project AirSim 基础上略作修改:

https://github.com/QinCheng0928/UAV_UGV_Navigation_ProjectAirSim.git

本文仅为个人学习与理解笔记,水平有限,如有错误或理解偏差,欢迎评论区指正,轻喷。

希望这篇文章能帮到正在研究 Project AirSim 的同学!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐