diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index 1528ac3d8f..a69bd85394 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -15,7 +15,7 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): if (ip == ""): ip = "127.0.0.1" self.client = msgpackrpc.Client(msgpackrpc.Address(ip, port), timeout = timeout_value, pack_encoding = 'utf-8', unpack_encoding = 'utf-8') - + # ----------------------------------- Common vehicle APIs --------------------------------------------- def reset(self): self.client.call('reset') @@ -37,18 +37,58 @@ def getMinRequiredClientVersion(self): # basic flight control def enableApiControl(self, is_enabled, vehicle_name = ''): + """ + Enables or disables API control for vehicle corresponding to vehicle_name + + Args: + is_enabled (bool): True to enable, False to disable API control + vehicle_name (str, optional): Name of the vehicle to send this command to + Returns: + msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() + """ return self.client.call('enableApiControl', is_enabled, vehicle_name) def isApiControlEnabled(self, vehicle_name = ''): + """ + Returns true if API control is established. + + If false (which is default) then API calls would be ignored. After a successful call to enableApiControl, the isApiControlEnabled should return true. + + Args: + vehicle_name (str, optional): Name of the vehicle + Returns: + bool: If API control is enabled + """ return self.client.call('isApiControlEnabled', vehicle_name) def armDisarm(self, arm, vehicle_name = ''): + """ + Arms or disarms vehicle corresponding to vehicle_name + + Args: + arm (bool): True to arm, False to disarm the vehicle + vehicle_name (str, optional): Name of the vehicle to send this command to + Returns: + bool: Success + """ return self.client.call('armDisarm', arm, vehicle_name) - + def simPause(self, is_paused): + """ + Pauses simulation + + Args: + is_paused (bool): True to pause the simulation, False to release + """ self.client.call('simPause', is_paused) def simIsPause(self): + """ + Returns true if the simulation is paused + + Returns: + bool: If the simulation is paused + """ return self.client.call("simIsPaused") def simContinueForTime(self, seconds): @@ -66,7 +106,7 @@ def confirmConnection(self): client_ver = self.getClientVersion() server_min_ver = self.getMinRequiredServerVersion() client_min_ver = self.getMinRequiredClientVersion() - + ver_info = "Client Ver:" + str(client_ver) + " (Min Req: " + str(client_min_ver) + \ "), Server Ver:" + str(server_ver) + " (Min Req: " + str(server_min_ver) + ")" @@ -137,6 +177,17 @@ def simSetObjectPose(self, object_name, pose, teleport = True): return self.client.call('simSetObjectPose', object_name, pose, teleport) def simListSceneObjects(self, name_regex = '.*'): + """ + Lists the objects present in the environment + + Default behaviour is to list all objects, regex can be used to return smaller list of matching objects or actors + + Args: + name_regex (str, optional): String to match actor names against, e.g. "Cylinder.*" + + Returns: + List(str): List containing all the names + """ return self.client.call('simListSceneObjects', name_regex) def simSetSegmentationObjectID(self, mesh_name, object_id, is_name_regex = False): @@ -163,7 +214,7 @@ def simSetCameraOrientation(self, camera_name, orientation, vehicle_name = ''): """ # TODO: below str() conversion is only needed for legacy reason and should be removed in future self.client.call('simSetCameraOrientation', str(camera_name), orientation, vehicle_name) - + def simSetCameraFov(self, camera_name, fov_degrees, vehicle_name = ''): """ - Control the field of view of a selected camera @@ -188,23 +239,65 @@ def simGetGroundTruthEnvironment(self, vehicle_name = ''): # sensor APIs def getImuData(self, imu_name = '', vehicle_name = ''): + """ + Args: + imu_name (str, optional): Name of IMU to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + ImuData + """ return ImuData.from_msgpack(self.client.call('getImuData', imu_name, vehicle_name)) def getBarometerData(self, barometer_name = '', vehicle_name = ''): + """ + Args: + barometer_name (str, optional): Name of Barometer to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + BarometerData + """ return BarometerData.from_msgpack(self.client.call('getBarometerData', barometer_name, vehicle_name)) def getMagnetometerData(self, magnetometer_name = '', vehicle_name = ''): + """ + Args: + magnetometer_name (str, optional): Name of Magnetometer to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + MagnetometerData + """ return MagnetometerData.from_msgpack(self.client.call('getMagnetometerData', magnetometer_name, vehicle_name)) def getGpsData(self, gps_name = '', vehicle_name = ''): + """ + Args: + gps_name (str, optional): Name of GPS to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + GpsData + """ return GpsData.from_msgpack(self.client.call('getGpsData', gps_name, vehicle_name)) def getDistanceSensorData(self, distance_sensor_name = '', vehicle_name = ''): + """ + Args: + distance_sensor_name (str, optional): Name of Distance Sensor to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + DistanceSensorData + """ return DistanceSensorData.from_msgpack(self.client.call('getDistanceSensorData', distance_sensor_name, vehicle_name)) def getLidarData(self, lidar_name = '', vehicle_name = ''): + """ + Args: + lidar_name (str, optional): Name of Lidar to get data from, specified in settings.json + vehicle_name (str, optional): Name of vehicle to which the sensor corresponds to + Returns: + LidarData + """ return LidarData.from_msgpack(self.client.call('getLidarData', lidar_name, vehicle_name)) - + def simGetLidarSegmentation(self, lidar_name = '', vehicle_name = ''): return self.client.call('simGetLidarSegmentation', lidar_name, vehicle_name) @@ -218,9 +311,9 @@ def simFlushPersistentMarkers(self): def simPlotPoints(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], size = 10.0, duration = -1.0, is_persistent = False): """ Plot a list of 3D points in World NED frame - + Args: - points (list[Vector3r]): List of Vector3r objects + points (list[Vector3r]): List of Vector3r objects color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 size (float, optional): Size of plotted point duration (float, optional): Duration (seconds) to plot for @@ -231,7 +324,7 @@ def simPlotPoints(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], size = 10.0, du def simPlotLineStrip(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5.0, duration = -1.0, is_persistent = False): """ Plots a line strip in World NED frame, defined from points[0] to points[1], points[1] to points[2], ... , points[n-2] to points[n-1] - + Args: points (list[Vector3r]): List of 3D locations of line start and end points, specified as Vector3r objects color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 @@ -244,7 +337,7 @@ def simPlotLineStrip(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = def simPlotLineList(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5.0, duration = -1.0, is_persistent = False): """ Plots a line strip in World NED frame, defined from points[0] to points[1], points[2] to points[3], ... , points[n-2] to points[n-1] - + Args: points (list[Vector3r]): List of 3D locations of line start and end points, specified as Vector3r objects. Must be even color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 @@ -272,7 +365,7 @@ def simPlotArrows(self, points_start, points_end, color_rgba=[1.0, 0.0, 0.0, 1.0 def simPlotStrings(self, strings, positions, scale = 5, color_rgba=[1.0, 0.0, 0.0, 1.0], duration = -1.0): """ - Plots a list of strings at desired positions in World NED frame. + Plots a list of strings at desired positions in World NED frame. Args: strings (list[String], optional): List of strings to plot @@ -285,12 +378,12 @@ def simPlotStrings(self, strings, positions, scale = 5, color_rgba=[1.0, 0.0, 0. def simPlotTransforms(self, poses, scale = 5.0, thickness = 5.0, duration = -1.0, is_persistent = False): """ - Plots a list of transforms in World NED frame. + Plots a list of transforms in World NED frame. Args: poses (list[Pose]): List of Pose objects representing the transforms to plot scale (float, optional): Length of transforms' axes - thickness (float, optional): Thickness of transforms' axes + thickness (float, optional): Thickness of transforms' axes duration (float, optional): Duration (seconds) to plot for is_persistent (bool, optional): If set to True, the desired object will be plotted for infinite time. """ @@ -298,13 +391,13 @@ def simPlotTransforms(self, poses, scale = 5.0, thickness = 5.0, duration = -1.0 def simPlotTransformsWithNames(self, poses, names, tf_scale = 5.0, tf_thickness = 5.0, text_scale = 10.0, text_color_rgba = [1.0, 0.0, 0.0, 1.0], duration = -1.0): """ - Plots a list of transforms with their names in World NED frame. - + Plots a list of transforms with their names in World NED frame. + Args: poses (list[Pose]): List of Pose objects representing the transforms to plot names (list[string]): List of strings with one-to-one correspondence to list of poses tf_scale (float, optional): Length of transforms' axes - tf_thickness (float, optional): Thickness of transforms' axes + tf_thickness (float, optional): Thickness of transforms' axes text_scale (float, optional): Font scale of transform name text_color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 for the transform name duration (float, optional): Duration (seconds) to plot for @@ -322,12 +415,42 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): super(MultirotorClient, self).__init__(ip, port, timeout_value) def takeoffAsync(self, timeout_sec = 20, vehicle_name = ''): - return self.client.call_async('takeoff', timeout_sec, vehicle_name) + """ + Takeoff vehicle to 3m above ground. Vehicle should not be moving when this API is used + + Args: + timeout_sec (int, optional): Timeout for the vehicle to reach desired altitude + vehicle_name (str, optional): Name of the vehicle to send this command to + + Returns: + msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() + """ + return self.client.call_async('takeoff', timeout_sec, vehicle_name) def landAsync(self, timeout_sec = 60, vehicle_name = ''): - return self.client.call_async('land', timeout_sec, vehicle_name) + """ + Land the vehicle + + Args: + timeout_sec (int, optional): Timeout for the vehicle to land + vehicle_name (str, optional): Name of the vehicle to send this command to + + Returns: + msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() + """ + return self.client.call_async('land', timeout_sec, vehicle_name) def goHomeAsync(self, timeout_sec = 3e+38, vehicle_name = ''): + """ + Return vehicle to Home i.e. Launch location + + Args: + timeout_sec (int, optional): Timeout for the vehicle to reach desired altitude + vehicle_name (str, optional): Name of the vehicle to send this command to + + Returns: + msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() + """ return self.client.call_async('goHome', timeout_sec, vehicle_name) # APIs for control @@ -343,11 +466,11 @@ def moveByVelocityAsync(self, vx, vy, vz, duration, drivetrain = DrivetrainType. def moveByVelocityZAsync(self, vx, vy, z, duration, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), vehicle_name = ''): return self.client.call_async('moveByVelocityZ', vx, vy, z, duration, drivetrain, yaw_mode, vehicle_name) - def moveOnPathAsync(self, path, velocity, timeout_sec = 3e+38, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), + def moveOnPathAsync(self, path, velocity, timeout_sec = 3e+38, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), lookahead = -1, adaptive_lookahead = 1, vehicle_name = ''): return self.client.call_async('moveOnPath', path, velocity, timeout_sec, drivetrain, yaw_mode, lookahead, adaptive_lookahead, vehicle_name) - def moveToPositionAsync(self, x, y, z, velocity, timeout_sec = 3e+38, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), + def moveToPositionAsync(self, x, y, z, velocity, timeout_sec = 3e+38, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), lookahead = -1, adaptive_lookahead = 1, vehicle_name = ''): return self.client.call_async('moveToPosition', x, y, z, velocity, timeout_sec, drivetrain, yaw_mode, lookahead, adaptive_lookahead, vehicle_name) @@ -355,18 +478,23 @@ def moveToZAsync(self, z, velocity, timeout_sec = 3e+38, yaw_mode = YawMode(), l return self.client.call_async('moveToZ', z, velocity, timeout_sec, yaw_mode, lookahead, adaptive_lookahead, vehicle_name) def moveByManualAsync(self, vx_max, vy_max, z_min, duration, drivetrain = DrivetrainType.MaxDegreeOfFreedom, yaw_mode = YawMode(), vehicle_name = ''): - """Read current RC state and use it to control the vehicles. + """ + - Read current RC state and use it to control the vehicles. Parameters sets up the constraints on velocity and minimum altitude while flying. If RC state is detected to violate these constraints then that RC state would be ignored. - :param vx_max: max velocity allowed in x direction - :param vy_max: max velocity allowed in y direction - :param vz_max: max velocity allowed in z direction - :param z_min: min z allowed for vehicle position - :param duration: after this duration vehicle would switch back to non-manual mode - :param drivetrain: when ForwardOnly, vehicle rotates itself so that its front is always facing the direction of travel. If MaxDegreeOfFreedom then it doesn't do that (crab-like movement) - :param yaw_mode: Specifies if vehicle should face at given angle (is_rate=False) or should be rotating around its axis at given rate (is_rate=True) + Args: + vx_max (float): max velocity allowed in x direction + vy_max (float): max velocity allowed in y direction + vz_max (float): max velocity allowed in z direction + z_min (float): min z allowed for vehicle position + duration (float): after this duration vehicle would switch back to non-manual mode + drivetrain (Drivetrain): when ForwardOnly, vehicle rotates itself so that its front is always facing the direction of travel. If MaxDegreeOfFreedom then it doesn't do that (crab-like movement) + yaw_mode (YawMode): Specifies if vehicle should face at given angle (is_rate=False) or should be rotating around its axis at given rate (is_rate=True) + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: + msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ return self.client.call_async('moveByManual', vx_max, vy_max, z_min, duration, drivetrain, yaw_mode, vehicle_name) @@ -400,31 +528,31 @@ def moveByMotorPWMsAsync(self, front_right_pwm, rear_left_pwm, front_left_pwm, r def moveByRollPitchYawZAsync(self, roll, pitch, yaw, z, duration, vehicle_name = ''): """ - - z is given in local NED frame of the vehicle. - - Roll angle, pitch angle, and yaw angle set points are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - z is given in local NED frame of the vehicle. + - Roll angle, pitch angle, and yaw angle set points are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. yaw (float): Desired yaw angle, in radians. z (float): Desired Z value (in local NED frame of the vehicle) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -433,30 +561,30 @@ def moveByRollPitchYawZAsync(self, roll, pitch, yaw, z, duration, vehicle_name = def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, vehicle_name = ''): """ - Desired throttle is between 0.0 to 1.0 - - Roll angle, pitch angle, and yaw angle are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - Roll angle, pitch angle, and yaw angle are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. yaw (float): Desired yaw angle, in radians. throttle (float): Desired throttle (between 0.0 to 1.0) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -465,30 +593,30 @@ def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, duration, vehicle_name = ''): """ - Desired throttle is between 0.0 to 1.0 - - Roll angle, pitch angle, and yaw rate set points are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - Roll angle, pitch angle, and yaw rate set points are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. yaw_rate (float): Desired yaw rate, in radian per second. throttle (float): Desired throttle (between 0.0 to 1.0) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -496,31 +624,31 @@ def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, d def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehicle_name = ''): """ - - z is given in local NED frame of the vehicle. - - Roll angle, pitch angle, and yaw rate set points are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - z is given in local NED frame of the vehicle. + - Roll angle, pitch angle, and yaw rate set points are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. yaw_rate (float): Desired yaw rate, in radian per second. z (float): Desired Z value (in local NED frame of the vehicle) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -528,31 +656,31 @@ def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehic def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, vehicle_name = ''): """ - - z is given in local NED frame of the vehicle. - - Roll rate, pitch rate, and yaw rate set points are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - z is given in local NED frame of the vehicle. + - Roll rate, pitch rate, and yaw rate set points are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. - Args: roll_rate (float): Desired roll rate, in radians / second pitch_rate (float): Desired pitch rate, in radians / second yaw_rate (float): Desired yaw rate, in radians / second z (float): Desired Z value (in local NED frame of the vehicle) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -561,21 +689,21 @@ def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, v def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttle, duration, vehicle_name = ''): """ - Desired throttle is between 0.0 to 1.0 - - Roll rate, pitch rate, and yaw rate set points are given in **radians**, in the body frame. - - The body frame follows the Front Left Up (FLU) convention, and right-handedness. + - Roll rate, pitch rate, and yaw rate set points are given in **radians**, in the body frame. + - The body frame follows the Front Left Up (FLU) convention, and right-handedness. - Frame Convention: - - X axis is along the **Front** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **roll** angle. - | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. + - X axis is along the **Front** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **roll** angle. + | Hence, rolling with a positive angle is equivalent to translating in the **right** direction, w.r.t. our FLU body frame. - - Y axis is along the **Left** direction of the quadrotor. - | Clockwise rotation about this axis defines a positive **pitch** angle. - | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. + - Y axis is along the **Left** direction of the quadrotor. + | Clockwise rotation about this axis defines a positive **pitch** angle. + | Hence, pitching with a positive angle is equivalent to translating in the **front** direction, w.r.t. our FLU body frame. - - Z axis is along the **Up** direction. - | Clockwise rotation about this axis defines a positive **yaw** angle. - | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. + - Z axis is along the **Up** direction. + | Clockwise rotation about this axis defines a positive **yaw** angle. + | Hence, yawing with a positive angle is equivalent to rotated towards the **left** direction wrt our FLU body frame. Or in an anticlockwise fashion in the body XY / FL plane. Args: roll_rate (float): Desired roll rate, in radians / second @@ -583,8 +711,8 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl yaw_rate (float): Desired yaw rate, in radians / second throttle (float): Desired throttle (between 0.0 to 1.0) duration (float): Desired amount of time (seconds), to send this command for - vehicle_name (str, optional): Name of the multirotor to send this command to - + vehicle_name (str, optional): Name of the multirotor to send this command to + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -592,32 +720,32 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl def setAngleRateControllerGains(self, angle_rate_gains=AngleRateControllerGains(), vehicle_name = ''): """ - - Modifying these gains will have an affect on *ALL* move*() APIs. - This is because any velocity setpoint is converted to an angle level setpoint which is tracked with an angle level controllers. - That angle level setpoint is itself tracked with and angle rate controller. + - Modifying these gains will have an affect on *ALL* move*() APIs. + This is because any velocity setpoint is converted to an angle level setpoint which is tracked with an angle level controllers. + That angle level setpoint is itself tracked with and angle rate controller. - This function should only be called if the default angle rate control PID gains need to be modified. Args: - angle_rate_gains (AngleRateControllerGains): - - Correspond to the roll, pitch, yaw axes, defined in the body frame. + angle_rate_gains (AngleRateControllerGains): + - Correspond to the roll, pitch, yaw axes, defined in the body frame. - Pass AngleRateControllerGains() to reset gains to default recommended values. - vehicle_name (str, optional): Name of the multirotor to send this command to + vehicle_name (str, optional): Name of the multirotor to send this command to """ self.client.call('setAngleRateControllerGains', *(angle_rate_gains.to_lists()+(vehicle_name,))) def setAngleLevelControllerGains(self, angle_level_gains=AngleLevelControllerGains(), vehicle_name = ''): """ - Sets angle level controller gains (used by any API setting angle references - for ex: moveByRollPitchYawZAsync(), moveByRollPitchYawThrottleAsync(), etc) - - Modifying these gains will also affect the behaviour of moveByVelocityAsync() API. - This is because the AirSim flight controller will track velocity setpoints by converting them to angle set points. + - Modifying these gains will also affect the behaviour of moveByVelocityAsync() API. + This is because the AirSim flight controller will track velocity setpoints by converting them to angle set points. - This function should only be called if the default angle level control PID gains need to be modified. - - Passing AngleLevelControllerGains() sets gains to default airsim values. + - Passing AngleLevelControllerGains() sets gains to default airsim values. Args: - angle_level_gains (AngleLevelControllerGains): - - Correspond to the roll, pitch, yaw axes, defined in the body frame. + angle_level_gains (AngleLevelControllerGains): + - Correspond to the roll, pitch, yaw axes, defined in the body frame. - Pass AngleLevelControllerGains() to reset gains to default recommended values. - vehicle_name (str, optional): Name of the multirotor to send this command to + vehicle_name (str, optional): Name of the multirotor to send this command to """ self.client.call('setAngleLevelControllerGains', *(angle_level_gains.to_lists()+(vehicle_name,))) @@ -625,14 +753,14 @@ def setVelocityControllerGains(self, velocity_gains=VelocityControllerGains(), v """ - Sets velocity controller gains for moveByVelocityAsync(). - This function should only be called if the default velocity control PID gains need to be modified. - - Passing VelocityControllerGains() sets gains to default airsim values. + - Passing VelocityControllerGains() sets gains to default airsim values. Args: - velocity_gains (VelocityControllerGains): - - Correspond to the world X, Y, Z axes. + velocity_gains (VelocityControllerGains): + - Correspond to the world X, Y, Z axes. - Pass VelocityControllerGains() to reset gains to default recommended values. - - Modifying velocity controller gains will have an affect on the behaviour of moveOnSplineAsync() and moveOnSplineVelConstraintsAsync(), as they both use velocity control to track the trajectory. - vehicle_name (str, optional): Name of the multirotor to send this command to + - Modifying velocity controller gains will have an affect on the behaviour of moveOnSplineAsync() and moveOnSplineVelConstraintsAsync(), as they both use velocity control to track the trajectory. + vehicle_name (str, optional): Name of the multirotor to send this command to """ self.client.call('setVelocityControllerGains', *(velocity_gains.to_lists()+(vehicle_name,))) @@ -643,10 +771,10 @@ def setPositionControllerGains(self, position_gains=PositionControllerGains(), v This function should only be called if the default position control PID gains need to be modified. Args: - position_gains (PositionControllerGains): - - Correspond to the X, Y, Z axes. + position_gains (PositionControllerGains): + - Correspond to the X, Y, Z axes. - Pass PositionControllerGains() to reset gains to default recommended values. - vehicle_name (str, optional): Name of the multirotor to send this command to + vehicle_name (str, optional): Name of the multirotor to send this command to """ self.client.call('setPositionControllerGains', *(position_gains.to_lists()+(vehicle_name,))) @@ -662,12 +790,37 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): super(CarClient, self).__init__(ip, port, timeout_value) def setCarControls(self, controls, vehicle_name = ''): + """ + Control the car using throttle, steering, brake, etc. + + Args: + controls (CarControls): Struct containing control values + vehicle_name (str, optional): Name of vehicle to be controlled + """ self.client.call('setCarControls', controls, vehicle_name) def getCarState(self, vehicle_name = ''): + """ + Get current car state + + Args: + vehicle_name (str, optional): Name of vehicle + + Returns: + CarState + """ state_raw = self.client.call('getCarState', vehicle_name) return CarState.from_msgpack(state_raw) def getCarControls(self, vehicle_name=''): + """ + Get current car controls + + Args: + vehicle_name (str, optional): Name of vehicle + + Returns: + CarControls + """ controls_raw = self.client.call('getCarControls', vehicle_name) - return CarControls.from_msgpack(controls_raw) \ No newline at end of file + return CarControls.from_msgpack(controls_raw)