赞
踩
在上一篇博客中,VehicleClient
类已经被详细解读了,这篇博客将会介绍它用于无人机仿真的一个子类MultirotorClient
。
机体系X轴指向机体正前,Y轴指向机体正左,Z轴指向机体正下方,与ROS和MAVROS中常用的RFU机体坐标系不同。
调用父类的构造函数
使无人机起飞至起点上方3m的位置
timeout_sec
:整数,起飞至指定高度的超时时间,默认为20秒。vehicle_name
:字符串,无人机的名称,默认为空字符串。msgpackrpc.future.Future
对象,表示异步操作的未来结果,调用 .join()
等待操作完成。
使无人机降落,输入输出与takeoffAsync
相同
使无人机返航,输入输出与takeoffAsync
相同
在无人机局部NED坐标系中根据给定的速度(vx
, vy
, vz
)移动指定时间 duration
在无人机局部NED坐标系中根据给定的速度 (vx, vy) 和z轴位置移动指定时间 duration
在世界NED坐标系中根据给定的速度(vx
, vy
, vz
)移动指定时间 duration
在世界NED坐标系中根据给定的速度 (vx, vy) 和z轴位置移动指定时间 duration
沿着给定的路径path
按给定速度velocity
移动无人机。
按给定速度velocity
移动到(x
, y
, z
)
按给定速度velocity
移动到GPS坐标(latitude
, longitude
, altitude
)
按给定速度velocity
移动到指定高度z
按手动控制移动无人机
vx_max
:x方向速度上限
vy_max
:y方向速度上限
vz_max
:z方向速度上限
z_min
:世界NED坐标系下允许的无人机最小飞行高度
duration
:执行时间,结束后切换回非手动模式
旋转无人机到指定的偏航角
以指定的偏航角速度旋转无人机,持续duration
时间
使无人机悬停
使用遥控器数据移动无人机,遥控器数据类型如下
class RCData(MsgpackMixin): timestamp = 0 pitch, roll, throttle, yaw = (0.0,)*4 #init 4 variable to 0.0 switch1, switch2, switch3, switch4 = (0,)*4 switch5, switch6, switch7, switch8 = (0,)*4 is_initialized = False is_valid = False def __init__(self, timestamp = 0, pitch = 0.0, roll = 0.0, throttle = 0.0, yaw = 0.0, switch1 = 0, switch2 = 0, switch3 = 0, switch4 = 0, switch5 = 0, switch6 = 0, switch7 = 0, switch8 = 0, is_initialized = False, is_valid = False): self.timestamp = timestamp self.pitch = pitch self.roll = roll self.throttle = throttle self.yaw = yaw self.switch1 = switch1 self.switch2 = switch2 self.switch3 = switch3 self.switch4 = switch4 self.switch5 = switch5 self.switch6 = switch6 self.switch7 = switch7 self.switch8 = switch8 self.is_initialized = is_initialized self.is_valid = is_valid
电机PWM控制
姿态角-高度控制
姿态角-推力控制
姿态角速度-推力控制
设置角速度控制器增益,输入参数angle_rate_gains
类型:
class AngleRateControllerGains(): """ Struct to contain controller gains used by angle level PID controller Attributes: roll_gains (PIDGains): kP, kI, kD for roll axis pitch_gains (PIDGains): kP, kI, kD for pitch axis yaw_gains (PIDGains): kP, kI, kD for yaw axis """ def __init__(self, roll_gains = PIDGains(0.25, 0, 0), pitch_gains = PIDGains(0.25, 0, 0), yaw_gains = PIDGains(0.25, 0, 0)): self.roll_gains = roll_gains self.pitch_gains = pitch_gains self.yaw_gains = yaw_gains def to_lists(self): return [self.roll_gains.kp, self.pitch_gains.kp, self.yaw_gains.kp], [self.roll_gains.ki, self.pitch_gains.ki, self.yaw_gains.ki], [self.roll_gains.kd, self.pitch_gains.kd, self.yaw_gains.kd]
设置姿态控制器增益,该增益用于含有姿态控制的上层控制API,例如moveByRollPitchYawZAsync
、moveByRollPitchYawThrottleAsync
等。输入参数angle_level_gains
类型
class AngleLevelControllerGains(): """ Struct to contain controller gains used by angle rate PID controller Attributes: roll_gains (PIDGains): kP, kI, kD for roll axis pitch_gains (PIDGains): kP, kI, kD for pitch axis yaw_gains (PIDGains): kP, kI, kD for yaw axis """ def __init__(self, roll_gains = PIDGains(2.5, 0, 0), pitch_gains = PIDGains(2.5, 0, 0), yaw_gains = PIDGains(2.5, 0, 0)): self.roll_gains = roll_gains self.pitch_gains = pitch_gains self.yaw_gains = yaw_gains def to_lists(self): return [self.roll_gains.kp, self.pitch_gains.kp, self.yaw_gains.kp], [self.roll_gains.ki, self.pitch_gains.ki, self.yaw_gains.ki], [self.roll_gains.kd, self.pitch_gains.kd, self.yaw_gains.kd]
设置速度控制器增益,用于上层APImoveByVelocityAsync
,输入参数velocity_gains
类型:
class VelocityControllerGains(): """ Struct to contain controller gains used by velocity PID controller Attributes: x_gains (PIDGains): kP, kI, kD for X axis y_gains (PIDGains): kP, kI, kD for Y axis z_gains (PIDGains): kP, kI, kD for Z axis """ def __init__(self, x_gains = PIDGains(0.2, 0, 0), y_gains = PIDGains(0.2, 0, 0), z_gains = PIDGains(2.0, 2.0, 0)): self.x_gains = x_gains self.y_gains = y_gains self.z_gains = z_gains def to_lists(self): return [self.x_gains.kp, self.y_gains.kp, self.z_gains.kp], [self.x_gains.ki, self.y_gains.ki, self.z_gains.ki], [self.x_gains.kd, self.y_gains.kd, self.z_gains.kd]
设置位置控制器增益,用于上层APImoveByPositionAsync
,输入参数position_gains
类型:
class PositionControllerGains(): """ Struct to contain controller gains used by position PID controller Attributes: x_gains (PIDGains): kP, kI, kD for X axis y_gains (PIDGains): kP, kI, kD for Y axis z_gains (PIDGains): kP, kI, kD for Z axis """ def __init__(self, x_gains = PIDGains(0.25, 0, 0), y_gains = PIDGains(0.25, 0, 0), z_gains = PIDGains(0.25, 0, 0)): self.x_gains = x_gains self.y_gains = y_gains self.z_gains = z_gains def to_lists(self): return [self.x_gains.kp, self.y_gains.kp, self.z_gains.kp], [self.x_gains.ki, self.y_gains.ki, self.z_gains.ki], [self.x_gains.kd, self.y_gains.kd, self.z_gains.kd]
查询无人机状态,返回类型:
class MultirotorState(MsgpackMixin):
collision = CollisionInfo()
kinematics_estimated = KinematicsState()
gps_location = GeoPoint()
timestamp = np.uint64(0)
landed_state = LandedState.Landed
rc_data = RCData()
ready = False
ready_message = ""
can_arm = False
返回电机状态
class RotorStates(MsgpackMixin):
timestamp = np.uint64(0)
rotors = []
import setup_path #unused
import airsim
import numpy as np
import os
import tempfile
import pprint
import cv2
# connect to the AirSim simulator
client = airsim.MultirotorClient() # 初始化无人机客户端
client.confirmConnection() # 确认与UE4的连接
client.enableApiControl(True) # 使能API控制
state = client.getMultirotorState() # 获取无人机状态 s = pprint.pformat(state) print("state: %s" % s) imu_data = client.getImuData() # 获取IMU数据 s = pprint.pformat(imu_data) print("imu_data: %s" % s) barometer_data = client.getBarometerData() # 获取气压计数据 s = pprint.pformat(barometer_data) print("barometer_data: %s" % s) magnetometer_data = client.getMagnetometerData() # 获取磁力计数据 s = pprint.pformat(magnetometer_data) print("magnetometer_data: %s" % s) gps_data = client.getGpsData() # 获取GPS数据 s = pprint.pformat(gps_data) print("gps_data: %s" % s)
airsim.wait_key('Press any key to takeoff')
print("Taking off...")
client.armDisarm(True) # 无人机解锁
client.takeoffAsync().join() # 无人机起飞
state = client.getMultirotorState() # 查询无人机状态
print("state: %s" % pprint.pformat(state))
airsim.wait_key('Press any key to move vehicle to (-10, 10, -10) at 5 m/s')
client.moveToPositionAsync(-10, 10, -10, 5).join() # 位置控制
client.hoverAsync().join()
state = client.getMultirotorState()
print("state: %s" % pprint.pformat(state))
airsim.wait_key('Press any key to take images') # get camera images from the car responses = client.simGetImages([ airsim.ImageRequest("0", airsim.ImageType.DepthVis), #depth visualization image airsim.ImageRequest("1", airsim.ImageType.DepthPerspective, True), #depth in perspective projection airsim.ImageRequest("1", airsim.ImageType.Scene), #scene vision image in png format airsim.ImageRequest("1", airsim.ImageType.Scene, False, False)]) #scene vision image in uncompressed RGBA array print('Retrieved images: %d' % len(responses)) tmp_dir = os.path.join(tempfile.gettempdir(), "airsim_drone") print ("Saving images to %s" % tmp_dir) try: os.makedirs(tmp_dir) except OSError: if not os.path.isdir(tmp_dir): raise for idx, response in enumerate(responses): filename = os.path.join(tmp_dir, str(idx)) if response.pixels_as_float: print("Type %d, size %d" % (response.image_type, len(response.image_data_float))) airsim.write_pfm(os.path.normpath(filename + '.pfm'), airsim.get_pfm_array(response)) elif response.compress: #png format print("Type %d, size %d" % (response.image_type, len(response.image_data_uint8))) airsim.write_file(os.path.normpath(filename + '.png'), response.image_data_uint8) else: #uncompressed array print("Type %d, size %d" % (response.image_type, len(response.image_data_uint8))) img1d = np.fromstring(response.image_data_uint8, dtype=np.uint8) # get numpy array img_rgb = img1d.reshape(response.height, response.width, 3) # reshape array to 4 channel image array H X W X 3 cv2.imwrite(os.path.normpath(filename + '.png'), img_rgb) # write to png
airsim.wait_key('Press any key to reset to original state')
client.reset() # 重置无人机
client.armDisarm(False) # 无人机上锁
# that's enough fun for now. let's quit cleanly
client.enableApiControl(False) # 关闭API控制
AirSim官方例程 hello_drone.py
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。