在之前这篇、这篇和这篇博客中,我们使用汽车作为采集平台进行了数据采集。但前面我们也说过,AirSim还支持无人机的仿真。所以这篇博客主要介绍如何使用无人机作为平台来采集数据。而且这也是十分有必要的。因为有些仿真场景真的不适合用车来开啊,比如LandscapeMountains、或者Zhangjiajie场景,汽车在里面基本动不了,如下图所示。 汽车会卡在山上动不了,无法顺利探索。
1.无人机控制
AirSim切换成无人机模式十分简单,只需要在配置文件settings.json
中将SimMode
属性设为Multirotor
即可。但问题在于无人机的控制。因为AirSim默认是通过外部的手柄操控无人机,而非普通键盘,所以直接用键盘是操作不了无人机的。但我们手边又没有可以控制的手柄,所以必须要先研究如何利用键盘操控无人机。
怎么解决这个办法呢?答案是可以通过AirSim提供的API来操控无人机。通过编写脚本监听键盘事件,根据不同的按键对应不同的API,即可实现对于无人机的操控。网上也有现成的代码,下面的代码主要参考了这个网页。关于AirSim的可编程API,我们会在之后的笔记中再介绍。这里就先“无脑”使用即可。
# coding=utf-8
import keyboard
import airsim
def callBackFunc(x):
w = keyboard.KeyboardEvent('down', 28, 'w') # 前进
s = keyboard.KeyboardEvent('down', 28, 's') # 后退
a = keyboard.KeyboardEvent('down', 28, 'a') # 左移
d = keyboard.KeyboardEvent('down', 28, 'd') # 右移
up = keyboard.KeyboardEvent('down', 28, 'up') # 上升
down = keyboard.KeyboardEvent('down', 28, 'down') # 下降
left = keyboard.KeyboardEvent('down', 28, 'left') # 左转
right = keyboard.KeyboardEvent('down', 28, 'right') # 右转
k = keyboard.KeyboardEvent('down', 28, 'k') # 获取控制
l = keyboard.KeyboardEvent('down', 28, 'l') # 释放控制
if x.event_type == 'down' and x.name == w.name:
# 前进
client.moveByVelocityBodyFrameAsync(3, 0, 0, 0.5)
print("前进")
elif x.event_type == 'down' and x.name == s.name:
# 后退
client.moveByVelocityBodyFrameAsync(-3, 0, 0, 0.5)
print("后退")
elif x.event_type == 'down' and x.name == a.name:
# 左移
client.moveByVelocityBodyFrameAsync(0, -2, 0, 0.5)
print("左移")
elif x.event_type == 'down' and x.name == d.name:
# 右移
client.moveByVelocityBodyFrameAsync(0, 2, 0, 0.5)
print("右移")
elif x.event_type == 'down' and x.name == up.name:
# 上升
client.moveByVelocityBodyFrameAsync(0, 0, -0.5, 0.5)
print("上升")
elif x.event_type == 'down' and x.name == down.name:
# 下降
client.moveByVelocityBodyFrameAsync(0, 0, 0.5, 0.5)
print("下降")
elif x.event_type == 'down' and x.name == left.name:
# 左转
client.rotateByYawRateAsync(-20, 0.5)
print("左转")
elif x.event_type == 'down' and x.name == right.name:
# 右转
client.rotateByYawRateAsync(20, 0.5)
print("右转")
elif x.event_type == 'down' and x.name == k.name:
# 无人机起飞
# get control
client.enableApiControl(True)
print("get control")
# unlock
client.armDisarm(True)
print("unlock")
# Async methods returns Future. Call join() to wait for task to complete.
client.takeoffAsync().join()
print("takeoff")
elif x.event_type == 'down' and x.name == l.name:
# 无人机降落
client.landAsync().join()
print("land")
# lock
client.armDisarm(False)
print("lock")
# release control
client.enableApiControl(False)
print("release control")
else:
# 没有按下按键
client.moveByVelocityBodyFrameAsync(0, 0, 0, 0.5).join()
client.hoverAsync().join() # 第四阶段:悬停6秒钟
print("悬停")
if __name__ == '__main__':
# 建立脚本与AirSim环境的连接
client = airsim.MultirotorClient()
client.confirmConnection()
# 监听键盘事件,执行回调函数
keyboard.hook(callBackFunc)
keyboard.wait()
使用脚本前需要确保有keyboard
和airsim
两个包,如果没有pip install
一下。启动脚本后,按k
键获取控制,按l
键释放控制。W、S、A、D键用于控制前进后退、左右平移,方向键控制上升下降以及左转右转。这个脚本也放到了Github项目中,叫AirSimDroneKeyboardController.py
,点击查看源文件。
2.数据录制
在可以完整控制无人机以后,后面的操作就和用汽车采集数据一样了。比如,这里给出一个利用无人机录制双目影像的配置文件。
{
"SeeDocsAt": "https://github.com/Microsoft/AirSim/blob/master/docs/settings.md",
"SettingsVersion": 1.2,
"SimMode": "Multirotor",
"Recording": {
"RecordInterval": 0.05,
"Cameras": [
{ "CameraName": "front_left", "ImageType": 0, "PixelsAsFloat": false, "Compress": true },
{ "CameraName": "front_right", "ImageType": 0, "PixelsAsFloat": false, "Compress": true }
]
},
"CameraDefaults": {
"CaptureSettings": [
{
"ImageType": 0,
"Width": 600,
"Height": 400,
"FOV_Degrees": 90
}
]
}
}
然后我们启动AirSim,进入Zhangjiajie环境,如下图所示。
然后,我们开启一个终端,运行脚本,然后按k
键即可获取控制,如下所示。
然后就可以移动了。最后,在仿真环境中按下R
键开始录制,再切回终端一边移动一边录制,结束时再切回仿真环境按R
键结束录制即可,如下图所示。
就会得到和之前一样的采集好的数据了。我们当然可以进一步用之前写好的脚本进行处理,然后跑SLAM。
3.跑ORB-SLAM
这一部分其实是和这篇博客说的内容是一样的,可以参考。为了完整性,这里再简单列一下。
3.1 数据处理
在之前的博客中也提到了,AirSim直接保存的影像由于格式的问题,不能直接拿来跑ORB-SLAM。因此,需要对数据进行一些预处理。预处理可以使用之前已经写好的脚本,这里就不再赘述了。
3.2 ORB-SLAM运行
数据准备好以后,就可以跑ORB-SLAM了。配置好相关文件,运行即可。利用无人机采集数据,并跑SLAM的效果如下动图所示。 可视化的轨迹以及和真值的比较如下所示。
4.参考资料
- [1] https://blog.csdn.net/weixin_44691296/article/details/119605213
本文作者原创,未经许可不得转载,谢谢配合