Source code for airsim.types

from __future__ import print_function
import msgpackrpc  # install as admin: pip install msgpack-rpc-python
import numpy as np  # pip install numpy
import math
import enum


[docs]class MsgpackMixin: def __repr__(self): from pprint import pformat return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)
[docs] def to_msgpack(self, *args, **kwargs): return self.__dict__
[docs] @classmethod def from_msgpack(cls, encoded): obj = cls() # obj.__dict__ = {k.decode('utf-8'): (from_msgpack(v.__class__, v) if hasattr(v, "__dict__") else v) for k, v in encoded.items()} obj.__dict__ = { k: ( v if not isinstance(v, dict) else getattr(getattr(obj, k).__class__, "from_msgpack")(v) ) for k, v in encoded.items() } # return cls(**msgpack.unpack(encoded)) return obj
class _ImageType(type): @property def Scene(cls): return 0 def DepthPlanar(cls): return 1 def DepthPerspective(cls): return 2 def DepthVis(cls): return 3 def DisparityNormalized(cls): return 4 def Segmentation(cls): return 5 def SurfaceNormals(cls): return 6 def Infrared(cls): return 7 def OpticalFlow(cls): return 8 def OpticalFlowVis(cls): return 9 def __getattr__(self, key): if key == "DepthPlanner": print( "\033[31m" + "DepthPlanner has been (correctly) renamed to DepthPlanar. Please use ImageType.DepthPlanar instead." + "\033[0m" ) raise AttributeError
[docs]class ImageType(metaclass=_ImageType): Scene = 0 DepthPlanar = 1 DepthPerspective = 2 DepthVis = 3 DisparityNormalized = 4 Segmentation = 5 SurfaceNormals = 6 Infrared = 7 OpticalFlow = 8 OpticalFlowVis = 9
[docs]class DrivetrainType: MaxDegreeOfFreedom = 0 ForwardOnly = 1
[docs]class LandedState: Landed = 0 Flying = 1
[docs]class WeatherParameter(int, enum.Enum): Rain = 0 Roadwetness = 1 Snow = 2 RoadSnow = 3 MapleLeaf = 4 RoadLeaf = 5 Dust = 6 Fog = 7 Enabled = 8 def __str__(self): return self.value
[docs]class Vector2r(MsgpackMixin): x_val = 0.0 y_val = 0.0 def __init__(self, x_val=0.0, y_val=0.0): self.x_val = x_val self.y_val = y_val
[docs]class Vector3r(MsgpackMixin): x_val = 0.0 y_val = 0.0 z_val = 0.0 def __init__(self, x_val=0.0, y_val=0.0, z_val=0.0): self.x_val = x_val self.y_val = y_val self.z_val = z_val
[docs] @staticmethod def nanVector3r(): return Vector3r(np.nan, np.nan, np.nan)
[docs] def containsNan(self): return ( math.isnan(self.x_val) or math.isnan(self.y_val) or math.isnan(self.z_val) )
def __add__(self, other): return Vector3r( self.x_val + other.x_val, self.y_val + other.y_val, self.z_val + other.z_val ) def __sub__(self, other): return Vector3r( self.x_val - other.x_val, self.y_val - other.y_val, self.z_val - other.z_val ) def __truediv__(self, other): if ( type(other) in [int, float] + np.sctypes["int"] + np.sctypes["uint"] + np.sctypes["float"] ): return Vector3r(self.x_val / other, self.y_val / other, self.z_val / other) else: raise TypeError( "unsupported operand type(s) for /: %s and %s" % (str(type(self)), str(type(other))) ) def __mul__(self, other): if ( type(other) in [int, float] + np.sctypes["int"] + np.sctypes["uint"] + np.sctypes["float"] ): return Vector3r(self.x_val * other, self.y_val * other, self.z_val * other) else: raise TypeError( "unsupported operand type(s) for *: %s and %s" % (str(type(self)), str(type(other))) )
[docs] def dot(self, other): if type(self) == type(other): return ( self.x_val * other.x_val + self.y_val * other.y_val + self.z_val * other.z_val ) else: raise TypeError( "unsupported operand type(s) for 'dot': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def cross(self, other): if type(self) == type(other): cross_product = np.cross(self.to_numpy_array(), other.to_numpy_array()) return Vector3r(cross_product[0], cross_product[1], cross_product[2]) else: raise TypeError( "unsupported operand type(s) for 'cross': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def get_length(self): return (self.x_val**2 + self.y_val**2 + self.z_val**2) ** 0.5
[docs] def distance_to(self, other): return ( (self.x_val - other.x_val) ** 2 + (self.y_val - other.y_val) ** 2 + (self.z_val - other.z_val) ** 2 ) ** 0.5
[docs] def to_Quaternionr(self): return Quaternionr(self.x_val, self.y_val, self.z_val, 0)
[docs] def to_numpy_array(self): return np.array([self.x_val, self.y_val, self.z_val], dtype=np.float32)
def __iter__(self): return iter((self.x_val, self.y_val, self.z_val))
[docs]class Quaternionr(MsgpackMixin): w_val = 0.0 x_val = 0.0 y_val = 0.0 z_val = 0.0 def __init__(self, x_val=0.0, y_val=0.0, z_val=0.0, w_val=1.0): self.x_val = x_val self.y_val = y_val self.z_val = z_val self.w_val = w_val
[docs] @staticmethod def nanQuaternionr(): return Quaternionr(np.nan, np.nan, np.nan, np.nan)
[docs] def containsNan(self): return ( math.isnan(self.w_val) or math.isnan(self.x_val) or math.isnan(self.y_val) or math.isnan(self.z_val) )
def __add__(self, other): if type(self) == type(other): return Quaternionr( self.x_val + other.x_val, self.y_val + other.y_val, self.z_val + other.z_val, self.w_val + other.w_val, ) else: raise TypeError( "unsupported operand type(s) for +: %s and %s" % (str(type(self)), str(type(other))) ) def __mul__(self, other): if type(self) == type(other): t, x, y, z = self.w_val, self.x_val, self.y_val, self.z_val a, b, c, d = other.w_val, other.x_val, other.y_val, other.z_val return Quaternionr( w_val=a * t - b * x - c * y - d * z, x_val=b * t + a * x + d * y - c * z, y_val=c * t + a * y + b * z - d * x, z_val=d * t + z * a + c * x - b * y, ) else: raise TypeError( "unsupported operand type(s) for *: %s and %s" % (str(type(self)), str(type(other))) ) def __truediv__(self, other): if type(other) == type(self): return self * other.inverse() elif ( type(other) in [int, float] + np.sctypes["int"] + np.sctypes["uint"] + np.sctypes["float"] ): return Quaternionr( self.x_val / other, self.y_val / other, self.z_val / other, self.w_val / other, ) else: raise TypeError( "unsupported operand type(s) for /: %s and %s" % (str(type(self)), str(type(other))) )
[docs] def dot(self, other): if type(self) == type(other): return ( self.x_val * other.x_val + self.y_val * other.y_val + self.z_val * other.z_val + self.w_val * other.w_val ) else: raise TypeError( "unsupported operand type(s) for 'dot': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def cross(self, other): if type(self) == type(other): return (self * other - other * self) / 2 else: raise TypeError( "unsupported operand type(s) for 'cross': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def outer_product(self, other): if type(self) == type(other): return (self.inverse() * other - other.inverse() * self) / 2 else: raise TypeError( "unsupported operand type(s) for 'outer_product': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def rotate(self, other): if type(self) == type(other): if other.get_length() == 1: return other * self * other.inverse() else: raise ValueError("length of the other Quaternionr must be 1") else: raise TypeError( "unsupported operand type(s) for 'rotate': %s and %s" % (str(type(self)), str(type(other))) )
[docs] def conjugate(self): return Quaternionr(-self.x_val, -self.y_val, -self.z_val, self.w_val)
[docs] def star(self): return self.conjugate()
[docs] def inverse(self): return self.star() / self.dot(self)
[docs] def sgn(self): return self / self.get_length()
[docs] def get_length(self): return ( self.x_val**2 + self.y_val**2 + self.z_val**2 + self.w_val**2 ) ** 0.5
[docs] def to_numpy_array(self): return np.array( [self.x_val, self.y_val, self.z_val, self.w_val], dtype=np.float32 )
def __iter__(self): return iter((self.x_val, self.y_val, self.z_val, self.w_val))
[docs]class Pose(MsgpackMixin): position = Vector3r() orientation = Quaternionr() def __init__(self, position_val=None, orientation_val=None): position_val = position_val if position_val is not None else Vector3r() orientation_val = ( orientation_val if orientation_val is not None else Quaternionr() ) self.position = position_val self.orientation = orientation_val
[docs] @staticmethod def nanPose(): return Pose(Vector3r.nanVector3r(), Quaternionr.nanQuaternionr())
[docs] def containsNan(self): return self.position.containsNan() or self.orientation.containsNan()
def __iter__(self): return iter((self.position, self.orientation))
[docs]class CollisionInfo(MsgpackMixin): has_collided = False normal = Vector3r() impact_point = Vector3r() position = Vector3r() penetration_depth = 0.0 time_stamp = 0.0 object_name = "" object_id = -1
[docs]class GeoPoint(MsgpackMixin): latitude = 0.0 longitude = 0.0 altitude = 0.0
[docs]class YawMode(MsgpackMixin): is_rate = True yaw_or_rate = 0.0 def __init__(self, is_rate=True, yaw_or_rate=0.0): self.is_rate = is_rate self.yaw_or_rate = yaw_or_rate
[docs]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
[docs]class ImageRequest(MsgpackMixin): camera_name = "0" image_type = ImageType.Scene pixels_as_float = False compress = False def __init__(self, camera_name, image_type, pixels_as_float=False, compress=True): # todo: in future remove str(), it's only for compatibility to pre v1.2 self.camera_name = str(camera_name) self.image_type = image_type self.pixels_as_float = pixels_as_float self.compress = compress
[docs]class ImageResponse(MsgpackMixin): image_data_uint8 = np.uint8(0) image_data_float = 0.0 camera_position = Vector3r() camera_orientation = Quaternionr() time_stamp = np.uint64(0) message = "" pixels_as_float = 0.0 compress = True width = 0 height = 0 image_type = ImageType.Scene
[docs]class CarControls(MsgpackMixin): throttle = 0.0 steering = 0.0 brake = 0.0 handbrake = False is_manual_gear = False manual_gear = 0 gear_immediate = True def __init__( self, throttle=0, steering=0, brake=0, handbrake=False, is_manual_gear=False, manual_gear=0, gear_immediate=True, ): self.throttle = throttle self.steering = steering self.brake = brake self.handbrake = handbrake self.is_manual_gear = is_manual_gear self.manual_gear = manual_gear self.gear_immediate = gear_immediate
[docs] def set_throttle(self, throttle_val, forward): if forward: self.is_manual_gear = False self.manual_gear = 0 self.throttle = abs(throttle_val) else: self.is_manual_gear = False self.manual_gear = -1 self.throttle = -abs(throttle_val)
[docs]class KinematicsState(MsgpackMixin): position = Vector3r() orientation = Quaternionr() linear_velocity = Vector3r() angular_velocity = Vector3r() linear_acceleration = Vector3r() angular_acceleration = Vector3r()
[docs]class EnvironmentState(MsgpackMixin): position = Vector3r() geo_point = GeoPoint() gravity = Vector3r() air_pressure = 0.0 temperature = 0.0 air_density = 0.0
[docs]class CarState(MsgpackMixin): speed = 0.0 gear = 0 rpm = 0.0 maxrpm = 0.0 handbrake = False collision = CollisionInfo() kinematics_estimated = KinematicsState() timestamp = np.uint64(0)
[docs]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
[docs]class RotorStates(MsgpackMixin): timestamp = np.uint64(0) rotors = []
[docs]class ProjectionMatrix(MsgpackMixin): matrix = []
[docs]class CameraInfo(MsgpackMixin): pose = Pose() fov = -1 proj_mat = ProjectionMatrix()
[docs]class LidarData(MsgpackMixin): point_cloud = 0.0 time_stamp = np.uint64(0) pose = Pose() segmentation = 0
[docs]class ImuData(MsgpackMixin): time_stamp = np.uint64(0) orientation = Quaternionr() angular_velocity = Vector3r() linear_acceleration = Vector3r()
[docs]class BarometerData(MsgpackMixin): time_stamp = np.uint64(0) altitude = Quaternionr() pressure = Vector3r() qnh = Vector3r()
[docs]class MagnetometerData(MsgpackMixin): time_stamp = np.uint64(0) magnetic_field_body = Vector3r() magnetic_field_covariance = 0.0
[docs]class GnssFixType(MsgpackMixin): GNSS_FIX_NO_FIX = 0 GNSS_FIX_TIME_ONLY = 1 GNSS_FIX_2D_FIX = 2 GNSS_FIX_3D_FIX = 3
[docs]class GnssReport(MsgpackMixin): geo_point = GeoPoint() eph = 0.0 epv = 0.0 velocity = Vector3r() fix_type = GnssFixType() time_utc = np.uint64(0)
[docs]class GpsData(MsgpackMixin): time_stamp = np.uint64(0) gnss = GnssReport() is_valid = False
[docs]class DistanceSensorData(MsgpackMixin): time_stamp = np.uint64(0) distance = 0.0 min_distance = 0.0 max_distance = 0.0 relative_pose = Pose()
[docs]class Box2D(MsgpackMixin): min = Vector2r() max = Vector2r()
[docs]class Box3D(MsgpackMixin): min = Vector3r() max = Vector3r()
[docs]class DetectionInfo(MsgpackMixin): name = "" geo_point = GeoPoint() box2D = Box2D() box3D = Box3D() relative_pose = Pose() world_position = Vector3r() time_stamp = np.uint64(0)
[docs]class PIDGains: """ Struct to store values of PID gains. Used to transmit controller gain values while instantiating AngleLevel/AngleRate/Velocity/PositionControllerGains objects. Attributes: kP (float): Proportional gain kI (float): Integrator gain kD (float): Derivative gain """ def __init__(self, kp, ki, kd): self.kp = kp self.ki = ki self.kd = kd
[docs] def to_list(self): return [self.kp, self.ki, self.kd]
[docs]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
[docs] 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], )
[docs]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
[docs] 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], )
[docs]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
[docs] 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], )
[docs]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
[docs] 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], )
[docs]class MeshPositionVertexBuffersResponse(MsgpackMixin): position = Vector3r() orientation = Quaternionr() vertices = 0.0 indices = 0.0 name = ""