AirSim 中无人机控制主要分为 手动控制 和 编程(API)控制 两大类。手动控制依赖于 RC 遥控器、键盘或游戏手柄等外部输入设备;而编程控制则通过 AirSim 各语言客户端提供的 RPC 接口,按需调用相应命令,实现无人机的自动化飞行。
AirSim 支持硬件在环(HIL),可以将真实的飞控(如 PX4)和 RC 遥控器信号桥接到模拟环境中进行测试。通过在 settings.json
中配置相应端口和设备,即可在模拟器中使用手柄或遥杆直接操控无人机 。
借助第三方脚本(例如 Zartris/Airsim-terminal-drone-control),可以在终端通过命令或键盘按键(W/A/S/D 控制平移,E/Q 控制偏航,Z/X 控制上下,T 退出模式)实时操控无人机 。
所有客户端(C++/Python/…)都提供下列通用接口:
reset()
:重置无人机到初始状态。
confirmConnection()
:检查并确认与模拟器的连接状态。
enableApiControl(bool)
/ isApiControlEnabled()
:开启/查询 API 控制授权,若未授权则后续命令被忽略 。
armDisarm(bool)
:解锁(上锁)电机,必须在起飞前调用以启动飞控 。
ping()
、simPrintLogMessage()
等调试与仿真专用接口。
AirSim 对多旋翼(Multirotor)提供了一系列分层次的控制 API,从最高层的 路径点控制 到最低层的 电机 PWM 直写。
takeoffAsync(timeout_sec)
:异步起飞到离地 3 m 高度,返回 Future
,可通过 .join()
等待完成。
landAsync(timeout_sec)
:异步降落,返回 Future
。
goHomeAsync()
:返航至起始点并悬停,与 takeoffAsync
/landAsync
参数相同。
hoverAsync()
:在当前位置悬停。
moveToPositionAsync(x, y, z, velocity, max_wait_sec)
:以给定速度将无人机移动到指定 NED 坐标点。
moveOnPathAsync(path_points, velocity, drivetrain, yaw_mode, lookahead, adaptive_lookahead)
:按路径点序列跟踪飞行,内部使用“胡萝卜跟踪(carrot following)”算法。
moveToZAsync(z, velocity, max_wait_sec)
:保持 X/Y 不变,移动至指定 Z 轴高度 。
moveByVelocityAsync(vx, vy, vz, duration, drivetrain, yaw_mode)
:在持续时间内以指定 NED 速度分量飞行。
moveByVelocityZAsync(vx, vy, z, duration, drivetrain, yaw_mode)
:指定水平速度与目标高度同时控制。
moveByRollPitchYawThrottleAsync(roll, pitch, yaw, throttle, duration)
:按给定姿态角(弧度)和推力比控制飞行 。
moveByRollPitchYawZAsync(roll, pitch, yaw, z, duration)
:姿态角与高度混合控制 。
moveByAngleRatesThrottleAsync(roll_rate, pitch_rate, yaw_rate, throttle, duration)
:指定三轴角速度和推力比。
moveByAngleRatesZAsync(roll_rate, pitch_rate, yaw_rate, z, duration)
:角速度与高度混合控制 。
moveByMotorPWMsAsync(motor1, motor2, motor3, motor4, duration)
:直接对四个电机的 PWM 值进行设置,最低层控制 。
moveByRC(rc_data)
:模拟 RC 遥控器输入,适用于需要在仿真中测试手动飞控逻辑的场景 。
moveByManualAsync(vx_max, vy_max, z_min, duration, drivetrain, yaw_mode)
:读取实时 RC 状态并根据设定约束进行限制飞行。
Drivetrain:ForwardOnly
(机头始终指向速度方向)或 MaxDegreeOfFreedom
(机体可横向移动,如螃蟹行走)。
YawMode:由 yaw_or_rate
(角度或角速度)和 is_rate
(布尔)共同决定偏航角度设定的含义 。
lookahead/adaptive_lookahead:路径跟踪时“胡萝卜跟踪”算法的前视距离与自适应控制 。
PID 增益:可通过 setAngleLevelControllerGains()
、setVelocityControllerGains()
、setPositionControllerGains()
等接口调整底层控制器增益
!pip install numpy
import sys
sys.path.append('../external-libraries')
import airsim
import math
import numpy as np
# connect to the AirSim simulator
#client = airsim.MultirotorClient(ip="192.168.31.194") #ip不写就是本地,写了就是跑airsim的机器
client = airsim.MultirotorClient() #ip不写就是本地,写了就是跑airsim的机器
client.confirmConnection()
# get control,允许api控制,默认是不允许的
client.enableApiControl(True)
# unlock,解锁,流程和真实飞行器一样
client.armDisarm(True)
# takeoff,起飞,很多无人机或者汽车控制的函数都有 Async/异步作为后缀,执行的时候会立即返回,不阻塞
# 但命令本身还是顺序执行的,所以需要join等待命令执行完毕,上一个命令执行完成,才会执行下一个命令
# 也可以不join,直接执行下一个命令,但是这样的话,就不知道上一个命令是否执行完成了,需要自己控制
client.takeoffAsync().join()
print("起飞-------------------------")
#降落
client.landAsync().join()
print("降落-------------------------")
# lock
client.armDisarm(False)
# release control
client.enableApiControl(False)
# connect to the AirSim simulator
client = airsim.MultirotorClient()
client.confirmConnection()
# get control,允许api控制,默认是不允许的
client.enableApiControl(True)
# unlock,解锁,流程和真实飞行器一样
client.armDisarm(True)
# takeoff,起飞,很多无人机或者汽车控制的函数都有 Async/异步作为后缀,执行的时候会立即返回,不阻塞
# 但命令本身还是顺序执行的,所以需要join等待命令执行完毕,上一个命令执行完成,才会执行下一个命令
# 也可以不join,直接执行下一个命令,但是这样的话,就不知道上一个命令是否执行完成了,需要自己控制
client.takeoffAsync().join()
print("起飞--------------------------------")
#moveToZAsync,坐标系是NED,所以正数是向上,负数是向下
client.moveToZAsync(-3, 1).join() # 上升到3米高度,1是速度
# 初始化4个点的坐标,并在视口中标识出来
points = [airsim.Vector3r(5, 0, -3),
airsim.Vector3r(5, 5, -3),
airsim.Vector3r(0, 5, -3),
airsim.Vector3r(0, 0, -3)]
client.simPlotPoints(points, color_rgba=[0, 1, 0, 1], size=30, is_persistent=True)
# 方法1:按照逐个点飞,形成正方形
client.moveToPositionAsync(5, 0, -3, 1).join() # 移动到(5,0,-3)的位置,1是速度x, y, z
client.moveToPositionAsync(5, 5, -3, 1).join()
client.moveToPositionAsync(0, 5, -3, 1).join()
client.moveToPositionAsync(0, 0, -3, 1).join()
# 方法2:直接按照航路点飞正方形轨迹
client.moveOnPathAsync(points, 1)
#降落
client.landAsync().join()
print("降落----------------------------------------------")
# lock
client.armDisarm(False)
# release control
client.enableApiControl(False)
最终效果如下:
在AirSim中,simGetGroundTruthKinematics
和 simGetVehiclePose
都是获取无人机状态的接口,但返回数据的精度、用途和底层含义有本质区别。以下是两者的详细对比:
simGetVehiclePose()
Pose( position=Vector3r(x, y, z), # 位置(NED坐标系,单位:米) orientation=Quaternionr(w, x, y, z) # 四元数姿态(相对世界坐标系) )
simGetGroundTruthKinematics()
KinematicsState( position=Vector3r(x, y, z), # 位置(绝对精确,NED坐标系) orientation=Quaternionr(w, x, y, z), # 姿态(绝对精确) linear_velocity=Vector3r(vx, vy, vz), # 线速度(米/秒) angular_velocity=Vector3r(wx, wy, wz), # 角速度(弧度/秒) linear_acceleration=Vector3r(ax, ay, az), # 线加速度(米/秒²) angular_acceleration=Vector3r(αx, αy, αz) # 角加速度(弧度/秒²) )
特性 | simGetVehiclePose() |
simGetGroundTruthKinematics() |
---|---|---|
数据来源 | 传感器模型(可能含噪声) | 物理引擎(绝对精确) |
数据维度 | 仅位置和姿态 | 位置、姿态、速度、加速度 |
用途 | 模拟真实传感器输出 | 算法验证、控制闭环设计 |
计算开销 | 低(仅读取传感器数据) | 高(需从物理引擎获取完整状态) |
需要传感器级数据(如测试SLAM、避障):
使用 simGetVehiclePose()
,并启用传感器噪声(通过AirSim的设置文件配置)。
需要真实状态验证(如控制器调试、轨迹跟踪):
使用 simGetGroundTruthKinematics().position
或 linear_velocity
。
需要动力学参数(如速度反馈、加速度前馈):
直接读取 linear_velocity
和 linear_acceleration
。
import time
import airsim
# connect to the AirSim simulator
client = airsim.MultirotorClient()
client.confirmConnection()
# get control,允许api控制,默认是不允许的
client.enableApiControl(True)
# unlock,解锁,流程和真实飞行器一样
client.armDisarm(True)
# takeoff,起飞,很多无人机或者汽车控制的函数都有 Async/异步作为后缀,执行的时候会立即返回,不阻塞
# 但命令本身还是顺序执行的,所以需要join等待命令执行完毕,上一个命令执行完成,才会执行下一个命令
# 也可以不join,直接执行下一个命令,但是这样的话,就不知道上一个命令是否执行完成了,需要自己控制
client.takeoffAsync().join()
print("起飞--------------------------------")
#moveToZAsync,坐标系是NED,所以正数是向上,负数是向下
client.moveToZAsync(-3, 1).join() # 上升到3米高度,1是速度
for i in range(2):
kinematic_state_groundtruth = client.simGetGroundTruthKinematics(vehicle_name='')
#print("kinematic_state_groundtruth: ", kinematic_state_groundtruth)
# state_groundtruth 的6个属性
print(
"position", kinematic_state_groundtruth.position, # 位置信息
"\n\n linear_velocity", kinematic_state_groundtruth.linear_velocity, # 速度信息
"\n\n linear_acceleration", kinematic_state_groundtruth.linear_acceleration , # 加速度信息
"\n\n orientation", kinematic_state_groundtruth.orientation, # 姿态信息
"\n\n angular_velocity", kinematic_state_groundtruth.angular_velocity, # 姿态角速率信息
"\n\n angular_acceleration", kinematic_state_groundtruth.angular_acceleration, # 姿态角加速度信息
)
# 无人机全局位置坐标真值
x = kinematic_state_groundtruth.position.x_val # 全局坐标系下,x轴方向的坐标
y = kinematic_state_groundtruth.position.y_val # 全局坐标系下,y轴方向的坐标
z = kinematic_state_groundtruth.position.z_val # 全局坐标系下,z轴方向的坐标
print("x: ", x, "y: ", y, "z: ", z)
time.sleep(1)
print("-----------------------------------------------------------------------------------")
输出结果为:
position { 'x_val': 0.024876724928617477,
'y_val': -0.03703678771853447,
'z_val': -2.6352598667144775}
linear_velocity { 'x_val': 0.0,
'y_val': 0.0,
'z_val': 0.04969768971204758}
linear_acceleration { 'x_val': 0.0,
'y_val': 0.0,
'z_val': 1.3143653869628906}
orientation { 'w_val': 0.9999985098838806,
'x_val': 0.0,
'y_val': 0.0,
'z_val': -0.0016540370415896177}
angular_velocity { 'x_val': 0.0,
'y_val': 0.0,
'z_val': 0.0}
angular_acceleration { 'x_val': 0.0,
'y_val': 0.0,
'z_val': 0.0}
x: 0.024876724928617477 y: -0.03703678771853447 z: -2.6352598667144775
项目github:GitHub - maris205/airsim_agent
项目huggingface:dnagpt/airsim_agent · Hugging Face
网易云课堂:大模型驱动的智能无人机应用开发 - 网易云课堂