AirSim多台无人机第一视角键盘控制进阶版

目录

AirSim多台无人机第一视角键盘控制进阶版本文实现的效果前言一、环境依赖二、图像读取与显示1.使用的API2.实时显示的一种方法

三、键盘控制改进总结

本文实现的效果

前言

本篇文章实现的键盘控制较上一篇主要有三个地方的改进。第一个,更换控制API实现更自由的控制,第二是在该基础上增加图像读取与实时刷新显示功能,第三个是在两台及以上的无人机中自由切换控制对象以及对应的FPV视角。

一、环境依赖

除了上篇文章依赖的pygame库外,还需要安装opencv-python库,用来对AirSim图像API接口返回的数据进行图像编码,以及保存图像。

pip3 install opencv-python

pip3 install pygame

二、图像读取与显示

1.使用的API

python安装的AirSim库中提供了两种获取图像的API,一个是simGetImage,另外一个是simGetImages。对于后者,我们可以对一台无人机同时读取多个摄像头的图像,以及设置是否压缩,多次测试发现使用不压缩的数据类型可以提高图像读取的速率,在读取多个图像时十分管用。在这里为了降低程序阅读门槛,遵循循序渐进的方法,先介绍使用simGetImage接口来读取并处理一帧图像数据。

image = AirSim_client.simGetImage('0', airsim.ImageType.Scene, vehicle_name="Drone1")

第一个参数表示要读取的摄像头编号,'0’号代表的是正前方,此外默认的模型还有左前方右前方,正下方以及正后方的摄像头,具体对应关系如下。

'0': front_center '1': front_right '2': front_left '3': bottom_center '4': back_center

2.实时显示的一种方法

利用pygame库的图像加载API将实时的第一视角图像读取,然后在pygame主窗口实时更新,对于第一视角的图像使用opencv里面的imwrite函数进行图像保存,基本实现如下。

cv2.imwrite('visual.png', image)

# 利用pygame库加载保存的第一视角图像

screen_image = pygame.image.load("visual.png")

三、键盘控制改进

本次无人机各个方向控制使用了速率量,这样能有更大的自由空间,可以自行调节参数来获得更好的效果。具体请参照代码注释,不懂可留言提问。

import sys

import cv2

import time

import airsim

import pygame

# >------>>> pygame settings <<<------< #

pygame.init()

screen = pygame.display.set_mode((320, 240))

pygame.display.set_caption('keyboard ctrl @FPV')

screen.fill((0, 0, 0))

# >------>>> AirSim settings <<<------< #

# 这里改为你要控制的无人机名称(settings文件里面设置的)

base_name = "Drone"

vehicle_index = [1, 2]

now_index = vehicle_index[0]

AirSim_client = airsim.MultirotorClient()

AirSim_client.confirmConnection()

AirSim_client.enableApiControl(True, vehicle_name=base_name + str(vehicle_index[0]))

AirSim_client.enableApiControl(True, vehicle_name=base_name + str(vehicle_index[1]))

AirSim_client.armDisarm(True, vehicle_name=base_name + str(vehicle_index[0]))

AirSim_client.armDisarm(True, vehicle_name=base_name + str(vehicle_index[1]))

AirSim_client.takeoffAsync(vehicle_name=base_name + str(vehicle_index[0]))

AirSim_client.takeoffAsync(vehicle_name=base_name + str(vehicle_index[1])).join()

image_types = {

"scene": airsim.ImageType.Scene,

"depth": airsim.ImageType.DepthVis,

"seg": airsim.ImageType.Segmentation,

"normals": airsim.ImageType.SurfaceNormals,

"segmentation": airsim.ImageType.Segmentation,

"disparity": airsim.ImageType.DisparityNormalized

}

# 基础的控制速率

base_rate = 0.2

# 悬停时的油门

base_throttle = 0.55

# 设置临时加速比例

speedup_ratio = 4.0

# 用来设置临时加速

speedup_flag = False

change_time = 0.0

# 防止来回切换控制对象

enable_change = True

# 用来标记当前是否进行键盘控制

control_iteration = False

while True:

pitch_rate = 0.0

yaw_rate = 0.0

roll_rate = 0.0

throttle = base_throttle

control_iteration = False

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

scan_wrapper = pygame.key.get_pressed()

# 按下空格键加速10倍

if scan_wrapper[pygame.K_SPACE]:

scale_ratio = speedup_ratio

else:

scale_ratio = speedup_ratio / speedup_ratio

# 切换两秒后方可再次切换

if time.time() - change_time > 2:

enable_change = True

# 需要加上enable_change变量判断,否则会来回切换

if scan_wrapper[pygame.K_LCTRL] and scan_wrapper[pygame.K_c] and enable_change:

enable_change = False

change_time = time.time()

if now_index == vehicle_index[0]:

now_index = vehicle_index[1]

else:

now_index = vehicle_index[0]

print(f"change to drone{now_index} ···")

time.sleep(0.2)

# 根据 'A' 和 'D' 按键来设置偏航速率变量

if scan_wrapper[pygame.K_a] or scan_wrapper[pygame.K_d]:

control_iteration = True

yaw_rate = (scan_wrapper[pygame.K_a] - scan_wrapper[pygame.K_d]) * scale_ratio * base_rate

# 根据 'UP' 和 'DOWN' 按键来设置pitch轴速率变量(NED坐标系,pitch为机头向前)

if scan_wrapper[pygame.K_UP] or scan_wrapper[pygame.K_DOWN]:

control_iteration = True

pitch_rate = (scan_wrapper[pygame.K_UP] - scan_wrapper[pygame.K_DOWN]) * scale_ratio * base_rate

# 根据 'LEFT' 和 'RIGHT' 按键来设置roll轴速率变量(NED坐标系,roll为正右方)

if scan_wrapper[pygame.K_LEFT] or scan_wrapper[pygame.K_RIGHT]:

control_iteration = True

roll_rate = -(scan_wrapper[pygame.K_LEFT] - scan_wrapper[pygame.K_RIGHT]) * scale_ratio * base_rate

# 根据 'W' 和 'S' 按键来设置z轴速率变量(NED坐标系,z轴向上为负,油门为正数)

if scan_wrapper[pygame.K_w] or scan_wrapper[pygame.K_s]:

control_iteration = True

throttle = base_throttle + (scan_wrapper[pygame.K_w] - scan_wrapper[pygame.K_s]) * scale_ratio * base_rate

# 速率需要限幅

if pitch_rate > 1.0:

pitch_rate = 1.0

elif pitch_rate < -1.0:

pitch_rate = -1.0

if yaw_rate > 1.0:

yaw_rate = 1.0

elif yaw_rate < -1.0:

yaw_rate = -1.0

if roll_rate > 1.0:

roll_rate = 1.0

elif roll_rate < -1.0:

roll_rate = -1.0

if throttle > 1.0:

throttle = 1.0

elif throttle < 0.0:

throttle = 0.0

# 不控制的时候保持悬停,也可以用于刹车

if control_iteration:

# 设置速率控制以及设置偏航控制

AirSim_client.moveByRollPitchYawrateThrottleAsync(pitch=pitch_rate, roll=roll_rate, yaw_rate=yaw_rate,

throttle=throttle, duration=0.05,

vehicle_name=base_name + str(now_index))

else:

# 保持当前位置

AirSim_client.hoverAsync(vehicle_name=base_name + str(now_index))

# 获取正前方的一帧图像

temp_image = AirSim_client.simGetImage('0', image_types["scene"], vehicle_name=base_name + str(now_index))

if temp_image is None:

print("Warning: Failed to read a frame!! ")

pygame.quit()

else:

pass

# 将图像进行解码,变成像素值为0-255的范围,保存路径自行修改

image = cv2.imdecode(airsim.string_to_uint8_array(temp_image), cv2.IMREAD_COLOR)

cv2.imwrite('../data/screen/visual.png', image)

# 利用pygame库加载保存的第一视角图像,

screen_image = pygame.image.load("../data/screen/visual.png")

# 图像坐标系,左上角为(0, 0),在此放置图片

screen.blit(screen_image, (0, 0))

pygame.display.flip()

pygame.display.update()

# press 'Esc' to quit

if scan_wrapper[pygame.K_ESCAPE]:

pygame.quit()

sys.exit()

总结

本文使用更底层的控制API来实现无人机的运动控制,并使用opencv和pygame结合的方式来实现实时的图像读取与显示,较上一篇文章有更多拓展,只要自己能将各个参数调好,也能达到一种不错的控制效果。下一篇博客将开始使用程序收集图像数据集用于yolov5模型的训练,实现在AirSim中识别无人机以及其它需要识别的目标。

相关阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: