AirSim API#
简介#
AirSim公开了API,您可以通过编程方式与模拟中的车辆进行交互。您可以使用这些API检索图像、获取状态、控制车辆等。
Python快速入门#
如果您想使用Python调用AirSim API,我们建议使用Anaconda和Python 3.5或更高版本,但某些代码也可能适用于Python 2.7(帮助我们提高兼容性!)。
首先安装此包
pip install msgpack-rpc-python
您可以从发布版本获取AirSim二进制文件,也可以从源代码编译(Windows, Linux)。一旦您可以运行AirSim,选择Car作为车辆,然后导航到PythonClient\car\
文件夹并运行
python hello_car.py
如果您使用Visual Studio 2019,只需打开AirSim.sln,将PythonClient设置为启动项目,并选择car\hello_car.py
作为您的启动脚本。
安装AirSim包#
您也可以通过以下方式简单地安装airsim
包:
pip install airsim
您可以在存储库的PythonClient
文件夹中找到此包的源代码和示例。
注意 1. 您可能会在我们的示例文件夹中注意到一个文件setup_path.py
。此文件包含简单的代码,用于检测父文件夹中是否提供了airsim
包,如果提供了,则使用该包而不是通过pip安装的包,以便您始终使用最新代码。 2. AirSim仍在积极开发中,这意味着您可能需要经常更新包以使用新的API。
C++用户#
如果您想使用C++ API和示例,请参阅C++ API指南。
Hello Car#
以下是如何使用Python控制模拟汽车的AirSim API(另请参阅C++示例)
# ready to run example: PythonClient/car/hello_car.py
import airsim
import time
# connect to the AirSim simulator
client = airsim.CarClient()
client.confirmConnection()
client.enableApiControl(True)
car_controls = airsim.CarControls()
while True:
# get state of the car
car_state = client.getCarState()
print("Speed %d, Gear %d" % (car_state.speed, car_state.gear))
# set the controls for car
car_controls.throttle = 1
car_controls.steering = 1
client.setCarControls(car_controls)
# let car drive a bit
time.sleep(1)
# get camera images from the car
responses = client.simGetImages([
airsim.ImageRequest(0, airsim.ImageType.DepthVis),
airsim.ImageRequest(1, airsim.ImageType.DepthPlanar, True)])
print('Retrieved images: %d', len(responses))
# do something with images
for response in responses:
if response.pixels_as_float:
print("Type %d, size %d" % (response.image_type, len(response.image_data_float)))
airsim.write_pfm('py1.pfm', airsim.get_pfm_array(response))
else:
print("Type %d, size %d" % (response.image_type, len(response.image_data_uint8)))
airsim.write_file('py1.png', response.image_data_uint8)
Hello Drone#
以下是如何使用Python控制模拟四旋翼飞行器的AirSim API(另请参阅C++示例)
# ready to run example: PythonClient/multirotor/hello_drone.py
import airsim
import os
# connect to the AirSim simulator
client = airsim.MultirotorClient()
client.confirmConnection()
client.enableApiControl(True)
client.armDisarm(True)
# Async methods returns Future. Call join() to wait for task to complete.
client.takeoffAsync().join()
client.moveToPositionAsync(-10, 10, -10, 5).join()
# take images
responses = client.simGetImages([
airsim.ImageRequest("0", airsim.ImageType.DepthVis),
airsim.ImageRequest("1", airsim.ImageType.DepthPlanar, True)])
print('Retrieved images: %d', len(responses))
# do something with the images
for response in responses:
if response.pixels_as_float:
print("Type %d, size %d" % (response.image_type, len(response.image_data_float)))
airsim.write_pfm(os.path.normpath('/temp/py1.pfm'), airsim.get_pfm_array(response))
else:
print("Type %d, size %d" % (response.image_type, len(response.image_data_uint8)))
airsim.write_file(os.path.normpath('/temp/py1.png'), response.image_data_uint8)
通用API#
reset
: 这会将车辆重置到其原始起始状态。请注意,在调用reset
后,您必须再次调用enableApiControl
和armDisarm
。confirmConnection
: 每1秒检查连接状态并在控制台中报告,以便用户可以看到连接进度。enableApiControl
: 出于安全原因,默认情况下,自动驾驶车辆的API控制未启用,人工操作员拥有完全控制权(通常通过模拟器中的遥控器或操纵杆)。客户端必须进行此调用才能通过API请求控制。车辆的人工操作员可能已禁用API控制,这意味着enableApiControl无效。这可以通过isApiControlEnabled
进行检查。isApiControlEnabled
: 如果API控制已建立,则返回true。如果为false(默认值),则API调用将被忽略。成功调用enableApiControl
后,isApiControlEnabled
应返回true。ping
: 如果连接已建立,则此调用将返回true,否则它将被阻塞直到超时。simPrintLogMessage
: 在模拟器的窗口中打印指定的消息。如果还提供了message_param,则它会打印在消息旁边,在这种情况下,如果使用相同message值但不同message_param再次调用此API,则前一行将被新行覆盖(而不是API在显示器上创建新行)。例如,当使用不同的i值调用API时,simPrintLogMessage("Iteration: ", to_string(i))
会 계속更新显示器上的同一行。严重性参数的有效值为0到3(含),对应不同的颜色。simGetObjectPose
,simSetObjectPose
: 获取和设置虚幻环境中指定对象的姿态。这里的对象在虚幻术语中指“actor”。它们通过标签和名称进行搜索。请注意,UE Editor中显示的名称在每次运行中都是自动生成的,并非永久性。因此,如果您想按名称引用actor,您必须在UE Editor中更改其自动生成的名称。或者,您可以为actor添加标签,方法是在虚幻编辑器中单击该actor,然后转到标签属性,单击“+”号并添加一些字符串值。如果多个actor具有相同的标签,则返回第一个匹配项。如果未找到匹配项,则返回NaN姿态。返回的姿态是世界坐标系中SI单位的NED坐标。对于simSetObjectPose
,指定的actor必须将移动性设置为可移动,否则您将获得未定义行为。simSetObjectPose
有一个参数teleport
,这意味着对象在移动过程中会穿过其他对象,如果移动成功则返回true。
图像/计算机视觉API#
AirSim提供了全面的图像API,用于从多个摄像头检索同步图像以及包括深度、视差、表面法线和视觉在内的地面实况。您可以在settings.json中设置分辨率、FOV、运动模糊等参数。还有用于检测碰撞状态的API。另请参阅完整代码,该代码生成指定数量的立体图像和地面实况深度,并对相机平面进行归一化,计算视差图像并将其保存为pfm格式。
有关图像API和计算机视觉模式的更多信息。对于可以从领域随机化中受益的视觉问题,还有一个对象重纹理API,可在支持的场景中使用。
暂停和继续API#
AirSim允许通过pause(is_paused)
API暂停和继续模拟。要暂停模拟,请调用pause(True)
;要继续模拟,请调用pause(False)
。您可能会遇到这样的场景,尤其是在使用强化学习时,需要模拟运行指定时间量然后自动暂停。在模拟暂停期间,您可以进行一些耗时的计算,发送一个新命令,然后再次运行模拟指定时间量。这可以通过API continueForTime(seconds)
实现。此API运行模拟指定秒数,然后暂停模拟。有关示例用法,请参见pause_continue_car.py和pause_continue_drone.py。
碰撞API#
可以使用`simGetCollisionInfo` API获取碰撞信息。此调用返回一个结构体,其中包含碰撞是否发生以及碰撞位置、表面法线、穿透深度等信息。
时间API#
AirSim 假设您的环境中存在 `EngineSky/BP_Sky_Sphere` 类的天空球体,并带有一个 ADirectionalLight actor。默认情况下,场景中的太阳位置不随时间移动。您可以使用 settings 来设置经度、纬度、日期和时间,AirSim 将使用这些信息计算场景中太阳的位置。
您还可以使用以下API调用根据给定日期时间设置太阳位置
simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst = False, celestial_clock_speed = 1, update_interval_secs = 60, move_sun = True)
is_enabled
参数必须为 True
才能启用日照时间效果。如果为 False
,则太阳位置将重置为环境中的原始位置。
其他参数与设置中的相同。
视距和世界范围API#
要测试从车辆到某一点或两点之间在模拟中的视距,请分别参见simTestLineOfSightToPoint(point, vehicle_name)和simTestLineOfSightBetweenPoints(point1, point2)。模拟世界范围(以两个地理点的向量形式)可以使用simGetWorldExtents()检索。
天气API#
默认情况下,所有天气效果都被禁用。要启用天气效果,首先调用
simEnableWeather(True)
可以通过 `simSetWeatherParameter` 方法启用各种天气效果,该方法接受 `WeatherParameter`,例如:
client.simSetWeatherParameter(airsim.WeatherParameter.Rain, 0.25);
第二个参数值从0到1。第一个参数提供以下选项
class WeatherParameter:
Rain = 0
Roadwetness = 1
Snow = 2
RoadSnow = 3
MapleLeaf = 4
RoadLeaf = 5
Dust = 6
Fog = 7
请注意,`Roadwetness`、`RoadSnow` 和 `RoadLeaf` 效果需要在场景中添加材质。
更多详细信息请参阅示例代码。
录制API#
录制API可用于通过API开始录制数据。要录制的数据可以在设置中指定。要开始录制,请使用 -
client.startRecording()
同样,要停止录制,请使用client.stopRecording()
。要检查录制是否正在运行,请调用client.isRecording()
,它将返回一个bool
值。
此API与使用R键切换录制功能配合使用,因此如果使用R键启用录制,isRecording()
将返回True
,并且可以使用stopRecording()
通过API停止录制。同样,如果按下视口中的R键,通过API开始的录制也将停止。如果使用API开始或停止录制,视口左上角也会出现LogMessage。
请注意,这只会按照设置中指定的方式保存数据。要完全自由地存储数据(例如某些传感器信息,或以不同格式或布局),请使用其他API来获取数据并按需保存。有关如何修改正在录制的运动学数据的详细信息,请查看修改录制数据。
风API#
风可以在模拟期间使用`simSetWind()`进行更改。风以世界坐标系、NED方向和m/s值指定
例如,设置20米/秒的北向(前方)风 -
# Set wind to (20,0,0) in NED (forward direction)
wind = airsim.Vector3r(20, 0, 0)
client.simSetWind(wind)
另请参阅 set_wind.py 中的示例脚本。
激光雷达API#
AirSim提供了API,可以从车辆上的激光雷达传感器检索点云数据。您可以在settings.json中设置通道数、每秒点数、水平和垂直FOV等参数。
更多关于激光雷达API和设置以及传感器设置的信息
灯光控制API#
可以通过simSpawnObject()
API创建可在AirSim内部操作的灯光,方法是将PointLightBP
或SpotLightBP
作为asset_name
参数,并将True
作为is_blueprint
参数传递。一旦灯光被创建,就可以使用以下API对其进行操作
simSetLightIntensity
: 这允许您编辑灯光的强度或亮度。它接受两个参数,light_name
,即先前调用simSpawnObject()
返回的灯光对象的名称,以及intensity
,一个浮点值。
纹理API#
通过这些API可以动态设置对象的纹理
simSetObjectMaterial
: 这使用现有的虚幻材质资产设置对象的材质。它接受两个字符串参数,object_name
和material_name
。simSetObjectMaterialFromTexture
: 这使用纹理路径设置对象的材质。它接受两个字符串参数,object_name
和texture_path
。
多辆车#
AirSim支持多辆车并通过API控制它们。请参阅多辆车文档。
坐标系统#
所有 AirSim API 都使用 NED 坐标系,即 +X 为北,+Y 为东,+Z 为下。所有单位均采用 SI 单位制。请注意,这与 Unreal Engine 内部使用的坐标系不同。在 Unreal Engine 中,+Z 向上而不是向下,长度单位是厘米而不是米。AirSim API 会处理适当的转换。车辆的起始点始终是 NED 系统中的坐标 (0, 0, 0)。因此,从 Unreal 坐标转换为 NED 时,我们首先减去起始偏移量,然后乘以 100 进行厘米到米的转换。车辆在放置 Player Start 组件的 Unreal 环境中生成。在 settings.json 中有一个名为 `OriginGeopoint` 的设置,它将地理经度、纬度和海拔分配给 Player Start 组件。
特定车辆API#
汽车API#
汽车有以下可用API
setCarControls
: 这允许您设置油门、转向、手刹以及自动或手动挡位。getCarState
: 这会检索状态信息,包括速度、当前档位和6个运动学量:位置、姿态、线速度和角速度、线加速度和角加速度。所有量都以NED坐标系、世界坐标系中的SI单位表示,但角速度和角加速度除外,它们以机体坐标系表示。- 图像 API.
多旋翼飞行器API#
多旋翼飞行器可以通过指定角度、速度矢量、目标位置或这些的组合进行控制。为此,有相应的move*
API。进行位置控制时,我们需要使用一些路径跟踪算法。默认情况下,AirSim使用胡萝卜跟踪算法。这通常被称为“高级控制”,因为您只需要指定高级目标,其余由固件处理。目前AirSim中可用的最低级别控制是moveByAngleThrottleAsync
API。
获取多旋翼飞行器状态#
此API一次性返回车辆的状态。状态包括碰撞、估计运动学(即通过融合传感器计算的运动学)和时间戳(自纪元以来的纳秒)。这里的运动学指六个量:位置、姿态、线速度和角速度、线加速度和角加速度。请注意,simple_flight目前不支持状态估计器,这意味着simple_flight的估计运动学值和地面真值运动学值将相同。然而,PX4可以获得估计运动学,但角加速度除外。所有量都以NED坐标系、世界坐标系中的SI单位表示,但角速度和角加速度以机体坐标系表示。
异步方法、持续时间和最大等待秒数#
许多API方法具有名为`duration`或`max_wait_seconds`的参数,并且它们以_Async_为后缀,例如`takeoffAsync`。这些方法在AirSim中开始任务后会立即返回,以便您的客户端代码可以在任务执行期间执行其他操作。如果您想等待此任务完成,则可以像这样调用`waitOnLastTask`
//C++
client.takeoffAsync()->waitOnLastTask();
# Python
client.takeoffAsync().join()
如果您开始另一个命令,它会自动取消上一个任务并开始新命令。这允许您使用以下模式:您的代码持续进行感知,计算要遵循的新轨迹,并将该路径发送给AirSim中的车辆。每个新发布的轨迹都会取消上一个轨迹,从而允许您的代码在新传感器数据到达时持续进行更新。
所有Async方法在Python中返回concurrent.futures.Future
(C++中为std::future
)。请注意,这些Future类目前不允许检查状态或取消任务;它们只允许等待任务完成。然而,AirSim确实提供了API cancelLastTask
。
传动系统#
您可以飞行车辆的两种模式是:`drivetrain`参数设置为`airsim.DrivetrainType.ForwardOnly`或`airsim.DrivetrainType.MaxDegreeOfFreedom`。当您指定`ForwardOnly`时,您是说车辆的前部应始终指向行进方向。因此,如果您想让无人机左转,它会首先旋转,使前部指向左侧。这种模式在您只有前置摄像头并使用第一人称视角操作车辆时很有用。这或多或少就像汽车行驶,您总是拥有前方视野。`MaxDegreeOfFreedom`意味着您不关心前部指向何处。因此,当您左转时,您会像螃蟹一样直接向左移动。四旋翼飞行器可以向任何方向移动,无论前部指向何处。`MaxDegreeOfFreedom`启用此模式。
偏航模式#
`yaw_mode`是一个名为`YawMode`的结构体,包含两个字段:`yaw_or_rate`和`is_rate`。如果`is_rate`字段为True,则`yaw_or_rate`字段被解释为角速度(度/秒),这意味着您希望车辆在移动时以该角速度持续绕其轴旋转。如果`is_rate`为False,则`yaw_or_rate`被解释为角度(度),这意味着您希望车辆旋转到特定角度(即偏航)并在移动时保持该角度。
您可能会发现,当`yaw_mode.is_rate == true`时,`drivetrain`参数不应设置为`ForwardOnly`,因为您正在矛盾地说要保持前部向前,但又要持续旋转。但是,如果您在`ForwardOnly`模式下设置`yaw_mode.is_rate = false`,那么您可以做一些有趣的事情。例如,您可以让无人机做圆周运动,并将`yaw_or_rate`设置为90,这样摄像头始终指向中心(“超酷自拍模式”)。在`MaxDegreeofFreedom`模式下,您也可以通过设置`yaw_mode.is_rate = true`并假设`yaw_mode.yaw_or_rate = 20`来获得一些有趣的效果。这将导致无人机在旋转的同时沿其路径飞行,这可能允许进行360度扫描。
在大多数情况下,您不希望偏航改变,您可以通过将偏航率设置为 0 来实现。其简写为 `airsim.YawMode.Zero()`(或在 C++ 中为:`YawMode::Zero()`)。
前瞻和自适应前瞻#
当您要求车辆沿路径行驶时,AirSim 使用“胡萝卜跟随”算法。该算法通过向前看路径并调整其速度矢量来操作。该算法的参数由 `lookahead` 和 `adaptive_lookahead` 指定。大多数情况下,您希望算法通过简单地设置 `lookahead = -1` 和 `adaptive_lookahead = 0` 来自动决定值。
在真实车辆上使用API#
我们希望能够在真实车辆上运行与模拟中运行的相同代码。这允许您在模拟器中测试代码并部署到真实车辆上。
一般来说,API不应该允许您做在真实车辆上无法完成的事情(例如,获取地面真值)。但是,当然,模拟器有更多的信息,这在可能不关心在真实车辆上运行应用程序的情况下会很有用。因此,我们通过添加sim
前缀来明确区分仅模拟API,例如simGetGroundTruthKinematics
。这样,如果您关心在真实车辆上运行代码,就可以避免使用这些仅模拟API。
AirLib是一个独立的库,您可以将其放置在离线计算模块(例如Gigabyte准系统迷你电脑)上。然后,该模块可以使用完全相同的代码和飞行控制器协议与PX4等飞行控制器进行通信。您为在模拟器中测试而编写的代码保持不变。请参阅自定义无人机上的AirLib。
向AirSim添加新API#
请参阅添加新API页面
参考和示例#
常见问题#
运行API时,虚幻引擎速度显著变慢#
如果虚幻引擎窗口失去焦点时,您发现虚幻引擎速度显著变慢,请在虚幻编辑器中转到“编辑->编辑器偏好设置”,在“搜索”框中输入“CPU”,并确保取消选中“在后台时使用较少CPU”。
我在Windows上还需要其他东西吗?#
您应该安装带有VC++、Windows SDK 10.0和Python的VS2019。要使用Python API,您需要Python 3.5或更高版本(使用Anaconda安装)。
我应该使用哪个版本的Python?#
我们推荐使用Anaconda来获取Python工具和库。我们的代码经过Python 3.5.3 :: Anaconda 4.4.0的测试。这很重要,因为已知旧版本存在问题。
导入cv2
时出错#
您可以使用以下方法安装OpenCV
conda install opencv
pip install opencv-python
TypeError: 'AsyncIOLoop' 和 'float' 的操作数类型不受支持#
如果您安装了Jupyter,就会发生此错误,这会以某种方式破坏msgpackrpc库。创建一个包含最少所需包的新Python环境。