From 082683489039de7cd1cd03e4f11dd3aad1a981bb Mon Sep 17 00:00:00 2001 From: HSC-1 Date: Thu, 7 Apr 2022 11:20:32 +0900 Subject: [PATCH 1/4] add material element index --- AirLib/include/api/RpcLibClientBase.hpp | 4 ++-- AirLib/include/api/WorldSimApiBase.hpp | 6 ++++-- AirLib/src/api/RpcLibClientBase.cpp | 9 +++++---- AirLib/src/api/RpcLibServerBase.cpp | 8 ++++---- PythonClient/airsim/client.py | 10 ++++++---- .../AirsimWrapper/Source/WorldSimApi.cpp | 4 ++-- .../AirsimWrapper/Source/WorldSimApi.h | 4 ++-- Unreal/Plugins/AirSim/Source/WorldSimApi.cpp | 17 ++++++++++------- Unreal/Plugins/AirSim/Source/WorldSimApi.h | 6 ++++-- 9 files changed, 39 insertions(+), 29 deletions(-) diff --git a/AirLib/include/api/RpcLibClientBase.hpp b/AirLib/include/api/RpcLibClientBase.hpp index cc3914b6a1..53e27392fc 100644 --- a/AirLib/include/api/RpcLibClientBase.hpp +++ b/AirLib/include/api/RpcLibClientBase.hpp @@ -152,8 +152,8 @@ namespace airlib void simSetKinematics(const Kinematics::State& state, bool ignore_collision, const std::string& vehicle_name = ""); msr::airlib::Environment::State simGetGroundTruthEnvironment(const std::string& vehicle_name = "") const; std::vector simSwapTextures(const std::string& tags, int tex_id = 0, int component_id = 0, int material_id = 0); - bool simSetObjectMaterial(const std::string& object_name, const std::string& material_name); - bool simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path); + bool simSetObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0); + bool simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0); // Recording APIs void startRecording(); diff --git a/AirLib/include/api/WorldSimApiBase.hpp b/AirLib/include/api/WorldSimApiBase.hpp index e7fc7c3754..c9bf790088 100644 --- a/AirLib/include/api/WorldSimApiBase.hpp +++ b/AirLib/include/api/WorldSimApiBase.hpp @@ -74,8 +74,8 @@ namespace airlib virtual bool setObjectScale(const std::string& object_name, const Vector3r& scale) = 0; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) = 0; virtual bool setLightIntensity(const std::string& light_name, float intensity) = 0; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name) = 0; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) = 0; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) = 0; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) = 0; virtual vector getMeshPositionVertexBuffers() const = 0; virtual bool createVoxelGrid(const Vector3r& position, const int& x_size, const int& y_size, const int& z_size, const float& res, const std::string& output_file) = 0; @@ -104,6 +104,8 @@ namespace airlib const std::string& vehicle_name, bool external) const = 0; virtual std::vector getImage(ImageCaptureBase::ImageType image_type, const CameraDetails& camera_details) const = 0; + + //CinemAirSim virtual std::vector getPresetLensSettings(const CameraDetails& camera_details) = 0; virtual std::string getLensSettings(const CameraDetails& camera_details) = 0; diff --git a/AirLib/src/api/RpcLibClientBase.cpp b/AirLib/src/api/RpcLibClientBase.cpp index f9ea4b59ec..0cc4a621fc 100644 --- a/AirLib/src/api/RpcLibClientBase.cpp +++ b/AirLib/src/api/RpcLibClientBase.cpp @@ -272,6 +272,7 @@ __pragma(warning(disable : 4239)) return result; } + //CinemAirSim std::vector RpcLibClientBase::simGetPresetLensSettings(const std::string& camera_name, const std::string& vehicle_name, bool external) { @@ -493,14 +494,14 @@ __pragma(warning(disable : 4239)) return pimpl_->client.call("simSwapTextures", tags, tex_id, component_id, material_id).as>(); } - bool RpcLibClientBase::simSetObjectMaterial(const std::string& object_name, const std::string& material_name) + bool RpcLibClientBase::simSetObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id) { - return pimpl_->client.call("simSetObjectMaterial", object_name, material_name).as(); + return pimpl_->client.call("simSetObjectMaterial", object_name, material_name, component_id).as(); } - bool RpcLibClientBase::simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) + bool RpcLibClientBase::simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id) { - return pimpl_->client.call("simSetObjectMaterialFromTexture", object_name, texture_path).as(); + return pimpl_->client.call("simSetObjectMaterialFromTexture", object_name, texture_path, component_id).as(); } bool RpcLibClientBase::simLoadLevel(const string& level_name) diff --git a/AirLib/src/api/RpcLibServerBase.cpp b/AirLib/src/api/RpcLibServerBase.cpp index 6d1fc7b50a..0710bd8d5a 100644 --- a/AirLib/src/api/RpcLibServerBase.cpp +++ b/AirLib/src/api/RpcLibServerBase.cpp @@ -477,12 +477,12 @@ namespace airlib return *getWorldSimApi()->swapTextures(tag, tex_id, component_id, material_id); }); - pimpl_->server.bind("simSetObjectMaterial", [&](const std::string& object_name, const std::string& material_name) -> bool { - return getWorldSimApi()->setObjectMaterial(object_name, material_name); + pimpl_->server.bind("simSetObjectMaterial", [&](const std::string& object_name, const std::string& material_name, const int component_id) -> bool { + return getWorldSimApi()->setObjectMaterial(object_name, material_name, component_id); }); - pimpl_->server.bind("simSetObjectMaterialFromTexture", [&](const std::string& object_name, const std::string& texture_path) -> bool { - return getWorldSimApi()->setObjectMaterialFromTexture(object_name, texture_path); + pimpl_->server.bind("simSetObjectMaterialFromTexture", [&](const std::string& object_name, const std::string& texture_path, const int component_id) -> bool { + return getWorldSimApi()->setObjectMaterialFromTexture(object_name, texture_path, component_id); }); pimpl_->server.bind("startRecording", [&]() -> void { diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index bcda726478..fb6bccc4fe 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -190,31 +190,33 @@ def simSwapTextures(self, tags, tex_id = 0, component_id = 0, material_id = 0): """ return self.client.call("simSwapTextures", tags, tex_id, component_id, material_id) - def simSetObjectMaterial(self, object_name, material_name): + def simSetObjectMaterial(self, object_name, material_name, component_id = 0): """ Runtime Swap Texture API See https://microsoft.github.io/AirSim/retexturing/ for details Args: object_name (str): name of object to set material for material_name (str): name of material to set for object + component_id (int, optional) : index of material elements Returns: bool: True if material was set """ - return self.client.call("simSetObjectMaterial", object_name, material_name) + return self.client.call("simSetObjectMaterial", object_name, material_name, component_id) - def simSetObjectMaterialFromTexture(self, object_name, texture_path): + def simSetObjectMaterialFromTexture(self, object_name, texture_path, component_id = 0): """ Runtime Swap Texture API See https://microsoft.github.io/AirSim/retexturing/ for details Args: object_name (str): name of object to set material for texture_path (str): path to texture to set for object + component_id (int, optional) : index of material elements Returns: bool: True if material was set """ - return self.client.call("simSetObjectMaterialFromTexture", object_name, texture_path) + return self.client.call("simSetObjectMaterialFromTexture", object_name, texture_path, component_id) # time-of-day control diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp index 6bdbe80c5a..dac9eb939d 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp @@ -75,7 +75,7 @@ std::unique_ptr> WorldSimApi::swapTextures(const std::s return result; } -bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) +bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id) { throw std::invalid_argument(common_utils::Utils::stringf( "setObjectMaterialFromTexture is not supported on unity") @@ -83,7 +83,7 @@ bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, c return false; } -bool WorldSimApi::setObjectMaterial(const std::string& object_name, const std::string& material_name) +bool WorldSimApi::setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id) { throw std::invalid_argument(common_utils::Utils::stringf( "setObjectMaterial is not supported on unity") diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h index def2b04ed8..851cb1942c 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h @@ -40,8 +40,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool setLightIntensity(const std::string& light_name, float intensity) override; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) override; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name) override; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) override; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) override; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) override; virtual std::vector listSceneObjects(const std::string& name_regex) const override; virtual Pose getObjectPose(const std::string& object_name) const override; diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp index c832051340..afe88a5e97 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp @@ -476,10 +476,10 @@ std::unique_ptr> WorldSimApi::swapTextures(const std::s return swappedObjectNames; } -bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) +bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id) { bool success = false; - UAirBlueprintLib::RunCommandOnGameThread([this, &object_name, &texture_path, &success]() { + UAirBlueprintLib::RunCommandOnGameThread([this, &object_name, &texture_path, &success, &component_id]() { if (!IsValid(simmode_->domain_rand_material_)) { UAirBlueprintLib::LogMessageString("Cannot find material for domain randomization", "", @@ -495,7 +495,7 @@ bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, c for (UStaticMeshComponent* staticMeshComponent : components) { UMaterialInstanceDynamic* dynamic_material = UMaterialInstanceDynamic::Create(simmode_->domain_rand_material_, staticMeshComponent); dynamic_material->SetTextureParameterValue("TextureParameter", texture_desired); - staticMeshComponent->SetMaterial(0, dynamic_material); + staticMeshComponent->SetMaterial(component_id, dynamic_material); } success = true; } @@ -511,10 +511,10 @@ bool WorldSimApi::setObjectMaterialFromTexture(const std::string& object_name, c return success; } -bool WorldSimApi::setObjectMaterial(const std::string& object_name, const std::string& material_name) +bool WorldSimApi::setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id) { bool success = false; - UAirBlueprintLib::RunCommandOnGameThread([this, &object_name, &material_name, &success]() { + UAirBlueprintLib::RunCommandOnGameThread([this, &object_name, &material_name, &success, &component_id]() { AActor* actor = UAirBlueprintLib::FindActor(simmode_, FString(object_name.c_str())); UMaterial* material = static_cast(StaticLoadObject(UMaterial::StaticClass(), nullptr, *FString(material_name.c_str()))); @@ -528,7 +528,7 @@ bool WorldSimApi::setObjectMaterial(const std::string& object_name, const std::s TArray components; actor->GetComponents(components); for (UStaticMeshComponent* staticMeshComponent : components) { - staticMeshComponent->SetMaterial(0, material); + staticMeshComponent->SetMaterial(component_id, material); } success = true; } @@ -748,6 +748,8 @@ std::string WorldSimApi::getSettingsString() const return msr::airlib::AirSimSettings::singleton().settings_text_; } + + bool WorldSimApi::testLineOfSightBetweenPoints(const msr::airlib::GeoPoint& lla1, const msr::airlib::GeoPoint& lla2) const { bool hit; @@ -843,7 +845,6 @@ std::vector WorldSimApi::getWorldExtents() const return result; } - msr::airlib::CameraInfo WorldSimApi::getCameraInfo(const CameraDetails& camera_details) const { msr::airlib::CameraInfo info; @@ -919,6 +920,8 @@ std::vector WorldSimApi::getImage(ImageCaptureBase::ImageType image_typ return std::vector(); } + + //CinemAirSim std::vector WorldSimApi::getPresetLensSettings(const CameraDetails& camera_details) { diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.h b/Unreal/Plugins/AirSim/Source/WorldSimApi.h index 7174d89459..90ea6a5069 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.h +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.h @@ -50,8 +50,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool setLightIntensity(const std::string& light_name, float intensity) override; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) override; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name) override; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path) override; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) override; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) override; virtual std::vector listSceneObjects(const std::string& name_regex) const override; virtual Pose getObjectPose(const std::string& object_name) const override; virtual bool setObjectPose(const std::string& object_name, const Pose& pose, bool teleport) override; @@ -84,6 +84,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool testLineOfSightBetweenPoints(const msr::airlib::GeoPoint& point1, const msr::airlib::GeoPoint& point2) const override; virtual std::vector getWorldExtents() const override; + + // Camera APIs virtual msr::airlib::CameraInfo getCameraInfo(const CameraDetails& camera_details) const override; virtual void setCameraPose(const msr::airlib::Pose& pose, const CameraDetails& camera_details) override; From 378d8f9c4b9cfa6dee91b96ba5da13539e4dc942 Mon Sep 17 00:00:00 2001 From: HSC-1 Date: Wed, 27 Apr 2022 10:51:16 +0900 Subject: [PATCH 2/4] apply style from clang-format --- AirLib/include/api/RpcLibClientBase.hpp | 4 +- AirLib/include/api/WorldSimApiBase.hpp | 6 +- AirLib/src/api/RpcLibClientBase.cpp | 1 - PythonClient/airsim/client.py | 95 ++++++++++--------- .../AirsimWrapper/Source/WorldSimApi.h | 4 +- Unreal/Plugins/AirSim/Source/WorldSimApi.cpp | 4 - Unreal/Plugins/AirSim/Source/WorldSimApi.h | 6 +- 7 files changed, 56 insertions(+), 64 deletions(-) diff --git a/AirLib/include/api/RpcLibClientBase.hpp b/AirLib/include/api/RpcLibClientBase.hpp index 53e27392fc..47fdb7fa9b 100644 --- a/AirLib/include/api/RpcLibClientBase.hpp +++ b/AirLib/include/api/RpcLibClientBase.hpp @@ -152,8 +152,8 @@ namespace airlib void simSetKinematics(const Kinematics::State& state, bool ignore_collision, const std::string& vehicle_name = ""); msr::airlib::Environment::State simGetGroundTruthEnvironment(const std::string& vehicle_name = "") const; std::vector simSwapTextures(const std::string& tags, int tex_id = 0, int component_id = 0, int material_id = 0); - bool simSetObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0); - bool simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0); + bool simSetObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id = 0); + bool simSetObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id = 0); // Recording APIs void startRecording(); diff --git a/AirLib/include/api/WorldSimApiBase.hpp b/AirLib/include/api/WorldSimApiBase.hpp index c9bf790088..833e590d7d 100644 --- a/AirLib/include/api/WorldSimApiBase.hpp +++ b/AirLib/include/api/WorldSimApiBase.hpp @@ -74,8 +74,8 @@ namespace airlib virtual bool setObjectScale(const std::string& object_name, const Vector3r& scale) = 0; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) = 0; virtual bool setLightIntensity(const std::string& light_name, float intensity) = 0; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) = 0; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) = 0; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id = 0) = 0; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id = 0) = 0; virtual vector getMeshPositionVertexBuffers() const = 0; virtual bool createVoxelGrid(const Vector3r& position, const int& x_size, const int& y_size, const int& z_size, const float& res, const std::string& output_file) = 0; @@ -104,8 +104,6 @@ namespace airlib const std::string& vehicle_name, bool external) const = 0; virtual std::vector getImage(ImageCaptureBase::ImageType image_type, const CameraDetails& camera_details) const = 0; - - //CinemAirSim virtual std::vector getPresetLensSettings(const CameraDetails& camera_details) = 0; virtual std::string getLensSettings(const CameraDetails& camera_details) = 0; diff --git a/AirLib/src/api/RpcLibClientBase.cpp b/AirLib/src/api/RpcLibClientBase.cpp index 0cc4a621fc..36c0c1cf9b 100644 --- a/AirLib/src/api/RpcLibClientBase.cpp +++ b/AirLib/src/api/RpcLibClientBase.cpp @@ -272,7 +272,6 @@ __pragma(warning(disable : 4239)) return result; } - //CinemAirSim std::vector RpcLibClientBase::simGetPresetLensSettings(const std::string& camera_name, const std::string& vehicle_name, bool external) { diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index fb6bccc4fe..bed13c0c91 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -16,7 +16,7 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): 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 --------------------------------------------- +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Common vehicle APIs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - def reset(self): """ Reset the vehicle to its original starting state @@ -218,8 +218,7 @@ def simSetObjectMaterialFromTexture(self, object_name, texture_path, component_i """ return self.client.call("simSetObjectMaterialFromTexture", object_name, texture_path, component_id) - - # time-of-day control +#time - of - day control #time - of - day control def simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst = False, celestial_clock_speed = 1, update_interval_secs = 60, move_sun = True): """ @@ -309,8 +308,6 @@ def simGetImages(self, requests, vehicle_name = '', external = False): responses_raw = self.client.call('simGetImages', requests, vehicle_name, external) return [ImageResponse.from_msgpack(response_raw) for response_raw in responses_raw] - - #CinemAirSim def simGetPresetLensSettings(self, camera_name, vehicle_name = '', external = False): result = self.client.call('simGetPresetLensSettings', camera_name, vehicle_name, external) @@ -836,7 +833,6 @@ def simGetGroundTruthEnvironment(self, vehicle_name = ''): return EnvironmentState.from_msgpack(env_state) simGetGroundTruthEnvironment.__annotations__ = {'return': EnvironmentState} - #sensor APIs def getImuData(self, imu_name = '', vehicle_name = ''): """ @@ -1113,7 +1109,7 @@ def getSettingsString(self): """ return self.client.call('getSettingsString') -#----------------------------------- Multirotor APIs --------------------------------------------- +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Multirotor APIs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - class MultirotorClient(VehicleClient, object): def __init__(self, ip = "", port = 41451, timeout_value = 3600): super(MultirotorClient, self).__init__(ip, port, timeout_value) @@ -1579,43 +1575,48 @@ def getRotorStates(self, vehicle_name = ''): RotorStates: Containing a timestamp and the speed, thrust and torque of all rotors. """ return RotorStates.from_msgpack(self.client.call('getRotorStates', vehicle_name)) - getRotorStates.__annotations__ = {'return': RotorStates} - -#----------------------------------- Car APIs --------------------------------------------- -class CarClient(VehicleClient, object): - 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 = ''): - """ - The position inside the returned CarState is in the frame of the vehicle's starting point - - 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=''): - """ - Args: - vehicle_name (str, optional): Name of vehicle - - Returns: - CarControls: - """ - controls_raw = self.client.call('getCarControls', vehicle_name) - return CarControls.from_msgpack(controls_raw) + getRotorStates.__annotations__ = +{ + 'return' : RotorStates +} + +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Car APIs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +class CarClient(VehicleClient, object) + : 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 = '') + : "" + " + The position inside the returned CarState is in the frame of the vehicle's starting point + + 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 ='') + : "" + " + Args : vehicle_name(str, optional) + : Name of vehicle + + Returns : CarControls : "" + " + controls_raw = self.client.call('getCarControls', vehicle_name) return CarControls.from_msgpack(controls_raw) diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h index 851cb1942c..e458798c28 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h @@ -40,8 +40,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool setLightIntensity(const std::string& light_name, float intensity) override; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) override; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) override; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) override; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id = 0) override; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id = 0) override; virtual std::vector listSceneObjects(const std::string& name_regex) const override; virtual Pose getObjectPose(const std::string& object_name) const override; diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp index afe88a5e97..11e7b6cf97 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp @@ -748,8 +748,6 @@ std::string WorldSimApi::getSettingsString() const return msr::airlib::AirSimSettings::singleton().settings_text_; } - - bool WorldSimApi::testLineOfSightBetweenPoints(const msr::airlib::GeoPoint& lla1, const msr::airlib::GeoPoint& lla2) const { bool hit; @@ -920,8 +918,6 @@ std::vector WorldSimApi::getImage(ImageCaptureBase::ImageType image_typ return std::vector(); } - - //CinemAirSim std::vector WorldSimApi::getPresetLensSettings(const CameraDetails& camera_details) { diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.h b/Unreal/Plugins/AirSim/Source/WorldSimApi.h index 90ea6a5069..a65a8187ef 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.h +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.h @@ -50,8 +50,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool setLightIntensity(const std::string& light_name, float intensity) override; virtual std::unique_ptr> swapTextures(const std::string& tag, int tex_id = 0, int component_id = 0, int material_id = 0) override; - virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id=0) override; - virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id=0) override; + virtual bool setObjectMaterial(const std::string& object_name, const std::string& material_name, const int component_id = 0) override; + virtual bool setObjectMaterialFromTexture(const std::string& object_name, const std::string& texture_path, const int component_id = 0) override; virtual std::vector listSceneObjects(const std::string& name_regex) const override; virtual Pose getObjectPose(const std::string& object_name) const override; virtual bool setObjectPose(const std::string& object_name, const Pose& pose, bool teleport) override; @@ -84,8 +84,6 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool testLineOfSightBetweenPoints(const msr::airlib::GeoPoint& point1, const msr::airlib::GeoPoint& point2) const override; virtual std::vector getWorldExtents() const override; - - // Camera APIs virtual msr::airlib::CameraInfo getCameraInfo(const CameraDetails& camera_details) const override; virtual void setCameraPose(const msr::airlib::Pose& pose, const CameraDetails& camera_details) override; From 0946df38bc5f23f7a3d3890bb54c9df5d7b8a2c2 Mon Sep 17 00:00:00 2001 From: HSC-1 Date: Thu, 28 Apr 2022 09:53:50 +0900 Subject: [PATCH 3/4] apply style from clang-format --- PythonClient/airsim/client.py | 283 ++++++---------------------------- 1 file changed, 43 insertions(+), 240 deletions(-) diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index bed13c0c91..64ddca87ff 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -16,11 +16,10 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): 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 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +#----------------------------------- Common vehicle APIs --------------------------------------------- def reset(self): """ Reset the vehicle to its original starting state - Note that you must call `enableApiControl` and `armDisarm` again after the call to reset """ self.client.call('reset') @@ -28,7 +27,6 @@ def reset(self): def ping(self): """ If connection is established then this call will return true otherwise it will be blocked until timeout - Returns: bool: """ @@ -50,7 +48,6 @@ def getMinRequiredClientVersion(self): 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 @@ -60,12 +57,9 @@ def enableApiControl(self, 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`, `isApiControlEnabled` should return true. - Args: vehicle_name (str, optional): Name of the vehicle - Returns: bool: If API control is enabled """ @@ -74,11 +68,9 @@ def isApiControlEnabled(self, vehicle_name = ''): def armDisarm(self, arm, vehicle_name = ''): """ Arms or disarms vehicle - 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 """ @@ -87,7 +79,6 @@ def armDisarm(self, arm, vehicle_name = ''): def simPause(self, is_paused): """ Pauses simulation - Args: is_paused (bool): True to pause the simulation, False to release """ @@ -96,7 +87,6 @@ def simPause(self, is_paused): def simIsPause(self): """ Returns true if the simulation is paused - Returns: bool: If the simulation is paused """ @@ -105,7 +95,6 @@ def simIsPause(self): def simContinueForTime(self, seconds): """ Continue the simulation for the specified number of seconds - Args: seconds (float): Time to run the simulation for """ @@ -114,7 +103,6 @@ def simContinueForTime(self, seconds): def simContinueForFrames(self, frames): """ Continue (or resume if paused) the simulation for the specified number of frames, after which the simulation will be paused. - Args: frames (int): Frames to run the simulation for """ @@ -123,10 +111,8 @@ def simContinueForFrames(self, frames): def getHomeGeoPoint(self, vehicle_name = ''): """ Get the Home location of the vehicle - Args: vehicle_name (str, optional): Name of vehicle to get home location of - Returns: GeoPoint: Home location of the vehicle """ @@ -161,11 +147,9 @@ def confirmConnection(self): def simSetLightIntensity(self, light_name, intensity): """ Change intensity of named light - Args: light_name (str): Name of light to change intensity (float): New intensity value - Returns: bool: True if successful, otherwise False """ @@ -174,17 +158,13 @@ def simSetLightIntensity(self, light_name, intensity): def simSwapTextures(self, tags, tex_id = 0, component_id = 0, material_id = 0): """ Runtime Swap Texture API - See https://microsoft.github.io/AirSim/retexturing/ for details - Args: tags (str): string of "," or ", " delimited tags to identify on which actors to perform the swap tex_id (int, optional): indexes the array of textures assigned to each actor undergoing a swap - If out-of-bounds for some object's texture set, it will be taken modulo the number of textures that were available component_id (int, optional): material_id (int, optional): - Returns: list[str]: List of objects which matched the provided tags and had the texture swap perfomed """ @@ -198,7 +178,6 @@ def simSetObjectMaterial(self, object_name, material_name, component_id = 0): object_name (str): name of object to set material for material_name (str): name of material to set for object component_id (int, optional) : index of material elements - Returns: bool: True if material was set """ @@ -212,21 +191,19 @@ def simSetObjectMaterialFromTexture(self, object_name, texture_path, component_i object_name (str): name of object to set material for texture_path (str): path to texture to set for object component_id (int, optional) : index of material elements - Returns: bool: True if material was set """ return self.client.call("simSetObjectMaterialFromTexture", object_name, texture_path, component_id) -#time - of - day control + + # time-of-day control #time - of - day control def simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst = False, celestial_clock_speed = 1, update_interval_secs = 60, move_sun = True): """ Control the position of Sun in the environment - Sun's position is computed using the coordinates specified in `OriginGeopoint` in settings for the date-time specified in the argument, else if the string is empty, current date & time is used - Args: is_enabled (bool): True to enable time-of-day effect, False to reset the position to original start_datetime (str, optional): Date & Time in %Y-%m-%d %H:%M:%S format, e.g. `2018-02-12 15:20:00` @@ -243,7 +220,6 @@ def simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst def simEnableWeather(self, enable): """ Enable Weather effects. Needs to be called before using `simSetWeatherParameter` API - Args: enable (bool): True to enable, False to disable """ @@ -252,7 +228,6 @@ def simEnableWeather(self, enable): def simSetWeatherParameter(self, param, val): """ Enable various weather effects - Args: param (WeatherParameter): Weather effect to be enabled val (float): Intensity of the effect, Range 0-1 @@ -265,17 +240,14 @@ def simSetWeatherParameter(self, param, val): def simGetImage(self, camera_name, image_type, vehicle_name = '', external = False): """ Get a single image - Returns bytes of png format image which can be dumped into abinary file to create .png image `string_to_uint8_array()` can be used to convert into Numpy unit8 array See https://microsoft.github.io/AirSim/image_apis/ for details - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Name of the vehicle with the camera external (bool, optional): Whether the camera is an External Camera - Returns: Binary string literal of compressed png image """ @@ -294,20 +266,19 @@ def simGetImage(self, camera_name, image_type, vehicle_name = '', external = Fal def simGetImages(self, requests, vehicle_name = '', external = False): """ Get multiple images - See https://microsoft.github.io/AirSim/image_apis/ for details and examples - Args: requests (list[ImageRequest]): Images required vehicle_name (str, optional): Name of vehicle associated with the camera external (bool, optional): Whether the camera is an External Camera - Returns: list[ImageResponse]: """ responses_raw = self.client.call('simGetImages', requests, vehicle_name, external) return [ImageResponse.from_msgpack(response_raw) for response_raw in responses_raw] + + #CinemAirSim def simGetPresetLensSettings(self, camera_name, vehicle_name = '', external = False): result = self.client.call('simGetPresetLensSettings', camera_name, vehicle_name, external) @@ -373,11 +344,9 @@ def simGetCurrentFieldOfView(self, camera_name, vehicle_name = '', external = Fa def simTestLineOfSightToPoint(self, point, vehicle_name = ''): """ Returns whether the target point is visible from the perspective of the inputted vehicle - Args: point (GeoPoint): target point vehicle_name (str, optional): Name of vehicle - Returns: [bool]: Success """ @@ -386,11 +355,9 @@ def simTestLineOfSightToPoint(self, point, vehicle_name = ''): def simTestLineOfSightBetweenPoints(self, point1, point2): """ Returns whether the target point is visible from the perspective of the source point - Args: point1 (GeoPoint): source point point2 (GeoPoint): target point - Returns: [bool]: Success """ @@ -399,7 +366,6 @@ def simTestLineOfSightBetweenPoints(self, point1, point2): def simGetWorldExtents(self): """ Returns a list of GeoPoints representing the minimum and maximum extents of the world - Returns: list[GeoPoint] """ @@ -411,10 +377,8 @@ def simRunConsoleCommand(self, command): Allows the client to execute a command in Unreal's native console, via an API. Affords access to the countless built-in commands such as "stat unit", "stat fps", "open [map]", adjust any config settings, etc. etc. Allows the user to create bespoke APIs very easily, by adding a custom event to the level blueprint, and then calling the console command "ce MyEventName [args]". No recompilation of AirSim needed! - Args: command ([string]): Desired Unreal Engine Console command to run - Returns: [bool]: Success """ @@ -424,9 +388,7 @@ def simRunConsoleCommand(self, command): def simGetMeshPositionVertexBuffers(self): """ Returns the static meshes that make up the scene - See https://microsoft.github.io/AirSim/meshes/ for details and how to use this - Returns: list[MeshPositionVertexBuffersResponse]: """ @@ -437,7 +399,6 @@ def simGetCollisionInfo(self, vehicle_name = ''): """ Args: vehicle_name (str, optional): Name of the Vehicle to get the info of - Returns: CollisionInfo: """ @@ -446,9 +407,7 @@ def simGetCollisionInfo(self, vehicle_name = ''): def simSetVehiclePose(self, pose, ignore_collision, vehicle_name = ''): """ Set the pose of the vehicle - If you don't want to change position (or orientation) then just set components of position (or orientation) to floating point nan values - Args: pose (Pose): Desired Pose pf the vehicle ignore_collision (bool): Whether to ignore any collision or not @@ -462,7 +421,6 @@ def simGetVehiclePose(self, vehicle_name = ''): Args: vehicle_name (str, optional): Name of the vehicle to get the Pose of - Returns: Pose: """ @@ -472,9 +430,7 @@ def simGetVehiclePose(self, vehicle_name = ''): def simSetTraceLine(self, color_rgba, thickness=1.0, vehicle_name = ''): """ Modify the color and thickness of the line when Tracing is enabled - Tracing can be enabled by pressing T in the Editor or setting `EnableTrace` to `True` in the Vehicle Settings - Args: color_rgba (list): desired RGBA values from 0.0 to 1.0 thickness (float, optional): Thickness of the line @@ -485,10 +441,8 @@ def simSetTraceLine(self, color_rgba, thickness=1.0, vehicle_name = ''): def simGetObjectPose(self, object_name): """ The position inside the returned Pose is in the world frame - Args: object_name (str): Object to get the Pose of - Returns: Pose: """ @@ -498,15 +452,12 @@ def simGetObjectPose(self, object_name): def simSetObjectPose(self, object_name, pose, teleport = True): """ Set the pose of the object(actor) in the environment - The specified actor must have Mobility set to movable, otherwise there will be undefined behaviour. See https://www.unrealengine.com/en-US/blog/moving-physical-objects for details on how to set Mobility and the effect of Teleport parameter - Args: object_name (str): Name of the object(actor) to move pose (Pose): Desired Pose of the object teleport (bool, optional): Whether to move the object immediately without affecting their velocity - Returns: bool: If the move was successful """ @@ -515,10 +466,8 @@ def simSetObjectPose(self, object_name, pose, teleport = True): def simGetObjectScale(self, object_name): """ Gets scale of an object in the world - Args: object_name (str): Object to get the scale of - Returns: airsim.Vector3r: Scale """ @@ -528,11 +477,9 @@ def simGetObjectScale(self, object_name): def simSetObjectScale(self, object_name, scale_vector): """ Sets scale of an object in the world - Args: object_name (str): Object to set the scale of scale_vector (airsim.Vector3r): Desired scale of object - Returns: bool: True if scale change was successful """ @@ -541,12 +488,9 @@ def simSetObjectScale(self, object_name, scale_vector): 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 """ @@ -555,10 +499,8 @@ def simListSceneObjects(self, name_regex = '.*'): def simLoadLevel(self, level_name): """ Loads a level specified by its name - Args: level_name (str): Name of the level to load - Returns: bool: True if the level was successfully loaded """ @@ -567,7 +509,6 @@ def simLoadLevel(self, level_name): def simListAssets(self): """ Lists all the assets present in the Asset Registry - Returns: list[str]: Names of all the assets """ @@ -575,7 +516,6 @@ def simListAssets(self): def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=False, is_blueprint=False): """Spawned selected object in the world - Args: object_name (str): Desired name of new object asset_name (str): Name of asset(mesh) in the project database @@ -583,7 +523,6 @@ def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=F scale (airsim.Vector3r): Desired scale of object physics_enabled (bool, optional): Whether to enable physics for the object is_blueprint (bool, optional): Whether to spawn a blueprint or an actor - Returns: str: Name of spawned object, in case it had to be modified """ @@ -591,10 +530,8 @@ def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=F def simDestroyObject(self, object_name): """Removes selected object from the world - Args: object_name (str): Name of object to be removed - Returns: bool: True if object is queued up for removal """ @@ -603,16 +540,12 @@ def simDestroyObject(self, object_name): def simSetSegmentationObjectID(self, mesh_name, object_id, is_name_regex = False): """ Set segmentation ID for specific objects - See https://microsoft.github.io/AirSim/image_apis/#segmentation for details - Args: mesh_name (str): Name of the mesh to set the ID of (supports regex) object_id (int): Object ID to be set, range 0-255 - RBG values for IDs can be seen at https://microsoft.github.io/AirSim/seg_rgbs.txt is_name_regex (bool, optional): Whether the mesh name is a regex - Returns: bool: If the mesh was found """ @@ -621,9 +554,7 @@ def simSetSegmentationObjectID(self, mesh_name, object_id, is_name_regex = False def simGetSegmentationObjectID(self, mesh_name): """ Returns Object ID for the given mesh name - Mapping of Object IDs to RGB values can be seen at https://microsoft.github.io/AirSim/seg_rgbs.txt - Args: mesh_name (str): Name of the mesh to get the ID of """ @@ -632,23 +563,19 @@ def simGetSegmentationObjectID(self, mesh_name): def simAddDetectionFilterMeshName(self, camera_name, image_type, mesh_name, vehicle_name = '', external = False): """ Add mesh name to detect in wild card format - For example: simAddDetectionFilterMeshName("Car_*") will detect all instance named "Car_*" - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required mesh_name (str): mesh name in wild card format vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera - """ self.client.call('simAddDetectionFilterMeshName', camera_name, image_type, mesh_name, vehicle_name, external) def simSetDetectionFilterRadius(self, camera_name, image_type, radius_cm, vehicle_name = '', external = False): """ Set detection radius for all cameras - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required @@ -661,26 +588,22 @@ def simSetDetectionFilterRadius(self, camera_name, image_type, radius_cm, vehicl def simClearDetectionMeshNames(self, camera_name, image_type, vehicle_name = '', external = False): """ Clear all mesh names from detection filter - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera - """ self.client.call('simClearDetectionMeshNames', camera_name, image_type, vehicle_name, external) def simGetDetections(self, camera_name, image_type, vehicle_name = '', external = False): """ Get current detections - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera - Returns: DetectionInfo array """ @@ -690,13 +613,10 @@ def simGetDetections(self, camera_name, image_type, vehicle_name = '', external def simPrintLogMessage(self, message, message_param = "", severity = 0): """ Prints the specified message in the simulator's window. - If message_param is supplied, then it's printed next to the message and in that case if this API is called with same message value but different message_param again then previous line is overwritten with new line (instead of API creating new line on display). - For example, `simPrintLogMessage("Iteration: ", to_string(i))` keeps updating same line on display when API is called with different values of i. The valid values of severity parameter is 0 to 3 inclusive that corresponds to different colors. - Args: message (str): Message to be printed message_param (str, optional): Parameter to be printed next to the message @@ -707,12 +627,10 @@ def simPrintLogMessage(self, message, message_param = "", severity = 0): def simGetCameraInfo(self, camera_name, vehicle_name = '', external=False): """ Get details about the camera - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera - Returns: CameraInfo: """ @@ -722,12 +640,10 @@ def simGetCameraInfo(self, camera_name, vehicle_name = '', external=False): def simGetDistortionParams(self, camera_name, vehicle_name = '', external = False): """ Get camera distortion parameters - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera - Returns: List (float): List of distortion parameter values corresponding to K1, K2, K3, P1, P2 respectively. """ @@ -737,7 +653,6 @@ def simGetDistortionParams(self, camera_name, vehicle_name = '', external = Fals def simSetDistortionParams(self, camera_name, distortion_params, vehicle_name = '', external = False): """ Set camera distortion parameters - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used distortion_params (dict): Dictionary of distortion param names and corresponding values @@ -752,7 +667,6 @@ def simSetDistortionParams(self, camera_name, distortion_params, vehicle_name = def simSetDistortionParam(self, camera_name, param_name, value, vehicle_name = '', external = False): """ Set single camera distortion parameter - Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used param_name (str): Name of distortion parameter @@ -765,7 +679,6 @@ def simSetDistortionParam(self, camera_name, param_name, value, vehicle_name = ' def simSetCameraPose(self, camera_name, pose, vehicle_name = '', external = False): """ - Control the pose of a selected camera - Args: camera_name (str): Name of the camera to be controlled pose (Pose): Pose representing the desired position and orientation of the camera @@ -778,7 +691,6 @@ def simSetCameraPose(self, camera_name, pose, vehicle_name = '', external = Fals def simSetCameraFov(self, camera_name, fov_degrees, vehicle_name = '', external = False): """ - Control the field of view of a selected camera - Args: camera_name (str): Name of the camera to be controlled fov_degrees (float): Value of field of view in degrees @@ -791,12 +703,9 @@ def simSetCameraFov(self, camera_name, fov_degrees, vehicle_name = '', external def simGetGroundTruthKinematics(self, vehicle_name = ''): """ Get Ground truth kinematics of the vehicle - The position inside the returned KinematicsState is in the frame of the vehicle's starting point - Args: vehicle_name (str, optional): Name of the vehicle - Returns: KinematicsState: Ground truth of the vehicle """ @@ -807,9 +716,7 @@ def simGetGroundTruthKinematics(self, vehicle_name = ''): def simSetKinematics(self, state, ignore_collision, vehicle_name = ''): """ Set the kinematics state of the vehicle - If you don't want to change position (or orientation) then just set components of position (or orientation) to floating point nan values - Args: state (KinematicsState): Desired Pose pf the vehicle ignore_collision (bool): Whether to ignore any collision or not @@ -820,12 +727,9 @@ def simSetKinematics(self, state, ignore_collision, vehicle_name = ''): def simGetGroundTruthEnvironment(self, vehicle_name = ''): """ Get ground truth environment state - The position inside the returned EnvironmentState is in the frame of the vehicle's starting point - Args: vehicle_name (str, optional): Name of the vehicle - Returns: EnvironmentState: Ground truth environment state """ @@ -833,13 +737,13 @@ def simGetGroundTruthEnvironment(self, vehicle_name = ''): return EnvironmentState.from_msgpack(env_state) simGetGroundTruthEnvironment.__annotations__ = {'return': EnvironmentState} + #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: """ @@ -850,7 +754,6 @@ 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: """ @@ -861,7 +764,6 @@ 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: """ @@ -872,7 +774,6 @@ 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: """ @@ -883,7 +784,6 @@ 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: """ @@ -894,7 +794,6 @@ 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: """ @@ -904,11 +803,9 @@ def simGetLidarSegmentation(self, lidar_name = '', vehicle_name = ''): """ NOTE: Deprecated API, use `getLidarData()` API instead Returns Segmentation ID of each point's collided object in the last Lidar update - Args: lidar_name (str, optional): Name of Lidar sensor vehicle_name (str, optional): Name of the vehicle wth the sensor - Returns: list[int]: Segmentation IDs of the objects """ @@ -925,7 +822,6 @@ 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 color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 @@ -938,7 +834,6 @@ 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 @@ -951,7 +846,6 @@ 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 @@ -964,7 +858,6 @@ def simPlotLineList(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5 def simPlotArrows(self, points_start, points_end, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5.0, arrow_size = 2.0, duration = -1.0, is_persistent = False): """ Plots a list of arrows in World NED frame, defined from points_start[0] to points_end[0], points_start[1] to points_end[1], ... , points_start[n-1] to points_end[n-1] - Args: points_start (list[Vector3r]): List of 3D start positions of arrow start positions, specified as Vector3r objects points_end (list[Vector3r]): List of 3D end positions of arrow start positions, specified as Vector3r objects @@ -980,7 +873,6 @@ 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. - Args: strings (list[String], optional): List of strings to plot positions (list[Vector3r]): List of positions where the strings should be plotted. Should be in one-to-one correspondence with the strings' list @@ -993,7 +885,6 @@ 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. - Args: poses (list[Pose]): List of Pose objects representing the transforms to plot scale (float, optional): Length of transforms' axes @@ -1006,7 +897,6 @@ 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. - 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 @@ -1021,7 +911,6 @@ def simPlotTransformsWithNames(self, poses, names, tf_scale = 5.0, tf_thickness def cancelLastTask(self, vehicle_name = ''): """ Cancel previous Async task - Args: vehicle_name (str, optional): Name of the vehicle """ @@ -1031,7 +920,6 @@ def cancelLastTask(self, vehicle_name = ''): def startRecording(self): """ Start Recording - Recording will be done according to the settings """ self.client.call('startRecording') @@ -1045,7 +933,6 @@ def stopRecording(self): def isRecording(self): """ Whether Recording is running or not - Returns: bool: True if Recording, else False """ @@ -1054,7 +941,6 @@ def isRecording(self): def simSetWind(self, wind): """ Set simulated wind, in World frame, NED direction, m/s - Args: wind (Vector3r): Wind, in World frame, NED direction, in m/s """ @@ -1063,13 +949,11 @@ def simSetWind(self, wind): def simCreateVoxelGrid(self, position, x, y, z, res, of): """ Construct and save a binvox-formatted voxel grid of environment - Args: position (Vector3r): Position around which voxel grid is centered in m x, y, z (int): Size of each voxel grid dimension in m res (float): Resolution of voxel grid in m of (str): Name of output file to save voxel grid as - Returns: bool: True if output written to file successfully, else False """ @@ -1079,13 +963,11 @@ def simCreateVoxelGrid(self, position, x, y, z, res, of): def simAddVehicle(self, vehicle_name, vehicle_type, pose, pawn_path = ""): """ Create vehicle at runtime - Args: vehicle_name (str): Name of the vehicle being created vehicle_type (str): Type of vehicle, e.g. "simpleflight" pose (Pose): Initial pose of the vehicle pawn_path (str, optional): Vehicle blueprint path, default empty wbich uses the default blueprint for the vehicle type - Returns: bool: Whether vehicle was created """ @@ -1094,7 +976,6 @@ def simAddVehicle(self, vehicle_name, vehicle_type, pose, pawn_path = ""): def listVehicles(self): """ Lists the names of current vehicles - Returns: list[str]: List containing names of all vehicles """ @@ -1103,13 +984,12 @@ def listVehicles(self): def getSettingsString(self): """ Fetch the settings text being used by AirSim - Returns: str: Settings text in JSON format """ return self.client.call('getSettingsString') -#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Multirotor APIs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +#----------------------------------- Multirotor APIs --------------------------------------------- class MultirotorClient(VehicleClient, object): def __init__(self, ip = "", port = 41451, timeout_value = 3600): super(MultirotorClient, self).__init__(ip, port, timeout_value) @@ -1117,11 +997,9 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): def takeoffAsync(self, timeout_sec = 20, 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() """ @@ -1130,11 +1008,9 @@ def takeoffAsync(self, timeout_sec = 20, vehicle_name = ''): def landAsync(self, timeout_sec = 60, 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() """ @@ -1143,11 +1019,9 @@ def landAsync(self, timeout_sec = 60, 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() """ @@ -1164,7 +1038,6 @@ def moveByVelocityBodyFrameAsync(self, vx, vy, vz, duration, drivetrain = Drivet drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1180,7 +1053,6 @@ def moveByVelocityZBodyFrameAsync(self, vx, vy, z, duration, drivetrain = Drivet drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1205,7 +1077,6 @@ def moveByVelocityAsync(self, vx, vy, vz, duration, drivetrain = DrivetrainType. drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1232,10 +1103,8 @@ def moveToZAsync(self, z, velocity, timeout_sec = 3e+38, yaw_mode = YawMode(), l 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. - 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. - Args: vx_max (float): max velocity allowed in x direction vy_max (float): max velocity allowed in y direction @@ -1266,7 +1135,6 @@ def moveByRC(self, rcdata = RCData(), vehicle_name = ''): def moveByMotorPWMsAsync(self, front_right_pwm, rear_left_pwm, front_left_pwm, rear_right_pwm, duration, vehicle_name = ''): """ - Directly control the motors using PWM values - Args: front_right_pwm (float): PWM value for the front right motor (between 0.0 to 1.0) rear_left_pwm (float): PWM value for the rear left motor (between 0.0 to 1.0) @@ -1284,23 +1152,16 @@ 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. - - 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. - - 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. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1308,7 +1169,6 @@ def moveByRollPitchYawZAsync(self, roll, pitch, yaw, z, duration, vehicle_name = 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1319,23 +1179,16 @@ def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, - Desired throttle is between 0.0 to 1.0 - Roll angle, pitch angle, and yaw angle are given in **degrees** when using PX4 and in **radians** when using SimpleFlight, 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. - - 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. - Args: roll (float): Desired roll angle. pitch (float): Desired pitch angle. @@ -1343,7 +1196,6 @@ def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1354,23 +1206,16 @@ def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, d - 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. - - 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. - - 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. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1378,7 +1223,6 @@ def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, d 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1389,23 +1233,16 @@ def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehic - 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. - - 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. - Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1413,7 +1250,6 @@ def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehic 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1424,23 +1260,16 @@ def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, v - 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. - - 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. - Args: roll_rate (float): Desired roll rate, in radians / second pitch_rate (float): Desired pitch rate, in radians / second @@ -1448,7 +1277,6 @@ def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, v 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1459,23 +1287,16 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl - 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. - - 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. - - 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. - Args: roll_rate (float): Desired roll rate, in radians / second pitch_rate (float): Desired pitch rate, in radians / second @@ -1483,7 +1304,6 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl 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 - Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1495,7 +1315,6 @@ def setAngleRateControllerGains(self, angle_rate_gains=AngleRateControllerGains( 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. @@ -1511,7 +1330,6 @@ def setAngleLevelControllerGains(self, angle_level_gains=AngleLevelControllerGai 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. - Args: angle_level_gains (AngleLevelControllerGains): - Correspond to the roll, pitch, yaw axes, defined in the body frame. @@ -1525,7 +1343,6 @@ 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. - Args: velocity_gains (VelocityControllerGains): - Correspond to the world X, Y, Z axes. @@ -1540,7 +1357,6 @@ def setPositionControllerGains(self, position_gains=PositionControllerGains(), v """ Sets position controller gains for moveByPositionAsync. 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. @@ -1553,10 +1369,8 @@ def setPositionControllerGains(self, position_gains=PositionControllerGains(), v def getMultirotorState(self, vehicle_name = ''): """ The position inside the returned MultirotorState is in the frame of the vehicle's starting point - Args: vehicle_name (str, optional): Vehicle to get the state of - Returns: MultirotorState: """ @@ -1567,56 +1381,45 @@ def getRotorStates(self, vehicle_name = ''): """ Used to obtain the current state of all a multirotor's rotors. The state includes the speeds, thrusts and torques for all rotors. - Args: vehicle_name (str, optional): Vehicle to get the rotor state of - Returns: RotorStates: Containing a timestamp and the speed, thrust and torque of all rotors. """ return RotorStates.from_msgpack(self.client.call('getRotorStates', vehicle_name)) - getRotorStates.__annotations__ = -{ - 'return' : RotorStates -} - -#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Car APIs -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -class CarClient(VehicleClient, object) - : 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 = '') - : "" - " - The position inside the returned CarState is in the frame of the vehicle's starting point - - 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 ='') - : "" - " - Args : vehicle_name(str, optional) - : Name of vehicle - - Returns : CarControls : "" - " - controls_raw = self.client.call('getCarControls', vehicle_name) return CarControls.from_msgpack(controls_raw) + getRotorStates.__annotations__ = {'return': RotorStates} + +#----------------------------------- Car APIs --------------------------------------------- +class CarClient(VehicleClient, object): + 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 = ''): + """ + The position inside the returned CarState is in the frame of the vehicle's starting point + 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=''): + """ + 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 From cd0a687912f61d4296766631dd03cf27be870426 Mon Sep 17 00:00:00 2001 From: HSC-1 Date: Mon, 2 May 2022 10:17:16 +0900 Subject: [PATCH 4/4] Bringing Back the White Space --- PythonClient/airsim/client.py | 200 +++++++++++++++++++++++++++++++++- 1 file changed, 198 insertions(+), 2 deletions(-) diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index 64ddca87ff..4f139ac552 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -20,6 +20,7 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): def reset(self): """ Reset the vehicle to its original starting state + Note that you must call `enableApiControl` and `armDisarm` again after the call to reset """ self.client.call('reset') @@ -27,6 +28,7 @@ def reset(self): def ping(self): """ If connection is established then this call will return true otherwise it will be blocked until timeout + Returns: bool: """ @@ -48,6 +50,7 @@ def getMinRequiredClientVersion(self): 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 @@ -57,9 +60,12 @@ def enableApiControl(self, 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`, `isApiControlEnabled` should return true. + Args: vehicle_name (str, optional): Name of the vehicle + Returns: bool: If API control is enabled """ @@ -68,9 +74,11 @@ def isApiControlEnabled(self, vehicle_name = ''): def armDisarm(self, arm, vehicle_name = ''): """ Arms or disarms vehicle + 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 """ @@ -79,6 +87,7 @@ def armDisarm(self, arm, vehicle_name = ''): def simPause(self, is_paused): """ Pauses simulation + Args: is_paused (bool): True to pause the simulation, False to release """ @@ -87,6 +96,7 @@ def simPause(self, is_paused): def simIsPause(self): """ Returns true if the simulation is paused + Returns: bool: If the simulation is paused """ @@ -95,6 +105,7 @@ def simIsPause(self): def simContinueForTime(self, seconds): """ Continue the simulation for the specified number of seconds + Args: seconds (float): Time to run the simulation for """ @@ -103,6 +114,7 @@ def simContinueForTime(self, seconds): def simContinueForFrames(self, frames): """ Continue (or resume if paused) the simulation for the specified number of frames, after which the simulation will be paused. + Args: frames (int): Frames to run the simulation for """ @@ -111,8 +123,10 @@ def simContinueForFrames(self, frames): def getHomeGeoPoint(self, vehicle_name = ''): """ Get the Home location of the vehicle + Args: vehicle_name (str, optional): Name of vehicle to get home location of + Returns: GeoPoint: Home location of the vehicle """ @@ -147,9 +161,11 @@ def confirmConnection(self): def simSetLightIntensity(self, light_name, intensity): """ Change intensity of named light + Args: light_name (str): Name of light to change intensity (float): New intensity value + Returns: bool: True if successful, otherwise False """ @@ -158,13 +174,17 @@ def simSetLightIntensity(self, light_name, intensity): def simSwapTextures(self, tags, tex_id = 0, component_id = 0, material_id = 0): """ Runtime Swap Texture API + See https://microsoft.github.io/AirSim/retexturing/ for details + Args: tags (str): string of "," or ", " delimited tags to identify on which actors to perform the swap tex_id (int, optional): indexes the array of textures assigned to each actor undergoing a swap + If out-of-bounds for some object's texture set, it will be taken modulo the number of textures that were available component_id (int, optional): material_id (int, optional): + Returns: list[str]: List of objects which matched the provided tags and had the texture swap perfomed """ @@ -177,7 +197,8 @@ def simSetObjectMaterial(self, object_name, material_name, component_id = 0): Args: object_name (str): name of object to set material for material_name (str): name of material to set for object - component_id (int, optional) : index of material elements + component_id (int, optional) : index of material elements + Returns: bool: True if material was set """ @@ -190,7 +211,8 @@ def simSetObjectMaterialFromTexture(self, object_name, texture_path, component_i Args: object_name (str): name of object to set material for texture_path (str): path to texture to set for object - component_id (int, optional) : index of material elements + component_id (int, optional) : index of material elements + Returns: bool: True if material was set """ @@ -202,8 +224,10 @@ def simSetObjectMaterialFromTexture(self, object_name, texture_path, component_i def simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst = False, celestial_clock_speed = 1, update_interval_secs = 60, move_sun = True): """ Control the position of Sun in the environment + Sun's position is computed using the coordinates specified in `OriginGeopoint` in settings for the date-time specified in the argument, else if the string is empty, current date & time is used + Args: is_enabled (bool): True to enable time-of-day effect, False to reset the position to original start_datetime (str, optional): Date & Time in %Y-%m-%d %H:%M:%S format, e.g. `2018-02-12 15:20:00` @@ -220,6 +244,7 @@ def simSetTimeOfDay(self, is_enabled, start_datetime = "", is_start_datetime_dst def simEnableWeather(self, enable): """ Enable Weather effects. Needs to be called before using `simSetWeatherParameter` API + Args: enable (bool): True to enable, False to disable """ @@ -228,6 +253,7 @@ def simEnableWeather(self, enable): def simSetWeatherParameter(self, param, val): """ Enable various weather effects + Args: param (WeatherParameter): Weather effect to be enabled val (float): Intensity of the effect, Range 0-1 @@ -240,14 +266,17 @@ def simSetWeatherParameter(self, param, val): def simGetImage(self, camera_name, image_type, vehicle_name = '', external = False): """ Get a single image + Returns bytes of png format image which can be dumped into abinary file to create .png image `string_to_uint8_array()` can be used to convert into Numpy unit8 array See https://microsoft.github.io/AirSim/image_apis/ for details + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Name of the vehicle with the camera external (bool, optional): Whether the camera is an External Camera + Returns: Binary string literal of compressed png image """ @@ -266,11 +295,14 @@ def simGetImage(self, camera_name, image_type, vehicle_name = '', external = Fal def simGetImages(self, requests, vehicle_name = '', external = False): """ Get multiple images + See https://microsoft.github.io/AirSim/image_apis/ for details and examples + Args: requests (list[ImageRequest]): Images required vehicle_name (str, optional): Name of vehicle associated with the camera external (bool, optional): Whether the camera is an External Camera + Returns: list[ImageResponse]: """ @@ -344,9 +376,11 @@ def simGetCurrentFieldOfView(self, camera_name, vehicle_name = '', external = Fa def simTestLineOfSightToPoint(self, point, vehicle_name = ''): """ Returns whether the target point is visible from the perspective of the inputted vehicle + Args: point (GeoPoint): target point vehicle_name (str, optional): Name of vehicle + Returns: [bool]: Success """ @@ -355,9 +389,11 @@ def simTestLineOfSightToPoint(self, point, vehicle_name = ''): def simTestLineOfSightBetweenPoints(self, point1, point2): """ Returns whether the target point is visible from the perspective of the source point + Args: point1 (GeoPoint): source point point2 (GeoPoint): target point + Returns: [bool]: Success """ @@ -366,6 +402,7 @@ def simTestLineOfSightBetweenPoints(self, point1, point2): def simGetWorldExtents(self): """ Returns a list of GeoPoints representing the minimum and maximum extents of the world + Returns: list[GeoPoint] """ @@ -377,8 +414,10 @@ def simRunConsoleCommand(self, command): Allows the client to execute a command in Unreal's native console, via an API. Affords access to the countless built-in commands such as "stat unit", "stat fps", "open [map]", adjust any config settings, etc. etc. Allows the user to create bespoke APIs very easily, by adding a custom event to the level blueprint, and then calling the console command "ce MyEventName [args]". No recompilation of AirSim needed! + Args: command ([string]): Desired Unreal Engine Console command to run + Returns: [bool]: Success """ @@ -388,7 +427,9 @@ def simRunConsoleCommand(self, command): def simGetMeshPositionVertexBuffers(self): """ Returns the static meshes that make up the scene + See https://microsoft.github.io/AirSim/meshes/ for details and how to use this + Returns: list[MeshPositionVertexBuffersResponse]: """ @@ -399,6 +440,7 @@ def simGetCollisionInfo(self, vehicle_name = ''): """ Args: vehicle_name (str, optional): Name of the Vehicle to get the info of + Returns: CollisionInfo: """ @@ -407,7 +449,9 @@ def simGetCollisionInfo(self, vehicle_name = ''): def simSetVehiclePose(self, pose, ignore_collision, vehicle_name = ''): """ Set the pose of the vehicle + If you don't want to change position (or orientation) then just set components of position (or orientation) to floating point nan values + Args: pose (Pose): Desired Pose pf the vehicle ignore_collision (bool): Whether to ignore any collision or not @@ -421,6 +465,7 @@ def simGetVehiclePose(self, vehicle_name = ''): Args: vehicle_name (str, optional): Name of the vehicle to get the Pose of + Returns: Pose: """ @@ -430,7 +475,9 @@ def simGetVehiclePose(self, vehicle_name = ''): def simSetTraceLine(self, color_rgba, thickness=1.0, vehicle_name = ''): """ Modify the color and thickness of the line when Tracing is enabled + Tracing can be enabled by pressing T in the Editor or setting `EnableTrace` to `True` in the Vehicle Settings + Args: color_rgba (list): desired RGBA values from 0.0 to 1.0 thickness (float, optional): Thickness of the line @@ -441,8 +488,10 @@ def simSetTraceLine(self, color_rgba, thickness=1.0, vehicle_name = ''): def simGetObjectPose(self, object_name): """ The position inside the returned Pose is in the world frame + Args: object_name (str): Object to get the Pose of + Returns: Pose: """ @@ -452,12 +501,15 @@ def simGetObjectPose(self, object_name): def simSetObjectPose(self, object_name, pose, teleport = True): """ Set the pose of the object(actor) in the environment + The specified actor must have Mobility set to movable, otherwise there will be undefined behaviour. See https://www.unrealengine.com/en-US/blog/moving-physical-objects for details on how to set Mobility and the effect of Teleport parameter + Args: object_name (str): Name of the object(actor) to move pose (Pose): Desired Pose of the object teleport (bool, optional): Whether to move the object immediately without affecting their velocity + Returns: bool: If the move was successful """ @@ -466,8 +518,10 @@ def simSetObjectPose(self, object_name, pose, teleport = True): def simGetObjectScale(self, object_name): """ Gets scale of an object in the world + Args: object_name (str): Object to get the scale of + Returns: airsim.Vector3r: Scale """ @@ -477,9 +531,11 @@ def simGetObjectScale(self, object_name): def simSetObjectScale(self, object_name, scale_vector): """ Sets scale of an object in the world + Args: object_name (str): Object to set the scale of scale_vector (airsim.Vector3r): Desired scale of object + Returns: bool: True if scale change was successful """ @@ -488,9 +544,12 @@ def simSetObjectScale(self, object_name, scale_vector): 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 """ @@ -499,8 +558,10 @@ def simListSceneObjects(self, name_regex = '.*'): def simLoadLevel(self, level_name): """ Loads a level specified by its name + Args: level_name (str): Name of the level to load + Returns: bool: True if the level was successfully loaded """ @@ -509,6 +570,7 @@ def simLoadLevel(self, level_name): def simListAssets(self): """ Lists all the assets present in the Asset Registry + Returns: list[str]: Names of all the assets """ @@ -516,6 +578,7 @@ def simListAssets(self): def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=False, is_blueprint=False): """Spawned selected object in the world + Args: object_name (str): Desired name of new object asset_name (str): Name of asset(mesh) in the project database @@ -523,6 +586,7 @@ def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=F scale (airsim.Vector3r): Desired scale of object physics_enabled (bool, optional): Whether to enable physics for the object is_blueprint (bool, optional): Whether to spawn a blueprint or an actor + Returns: str: Name of spawned object, in case it had to be modified """ @@ -530,8 +594,10 @@ def simSpawnObject(self, object_name, asset_name, pose, scale, physics_enabled=F def simDestroyObject(self, object_name): """Removes selected object from the world + Args: object_name (str): Name of object to be removed + Returns: bool: True if object is queued up for removal """ @@ -540,12 +606,16 @@ def simDestroyObject(self, object_name): def simSetSegmentationObjectID(self, mesh_name, object_id, is_name_regex = False): """ Set segmentation ID for specific objects + See https://microsoft.github.io/AirSim/image_apis/#segmentation for details + Args: mesh_name (str): Name of the mesh to set the ID of (supports regex) object_id (int): Object ID to be set, range 0-255 + RBG values for IDs can be seen at https://microsoft.github.io/AirSim/seg_rgbs.txt is_name_regex (bool, optional): Whether the mesh name is a regex + Returns: bool: If the mesh was found """ @@ -554,7 +624,9 @@ def simSetSegmentationObjectID(self, mesh_name, object_id, is_name_regex = False def simGetSegmentationObjectID(self, mesh_name): """ Returns Object ID for the given mesh name + Mapping of Object IDs to RGB values can be seen at https://microsoft.github.io/AirSim/seg_rgbs.txt + Args: mesh_name (str): Name of the mesh to get the ID of """ @@ -563,19 +635,23 @@ def simGetSegmentationObjectID(self, mesh_name): def simAddDetectionFilterMeshName(self, camera_name, image_type, mesh_name, vehicle_name = '', external = False): """ Add mesh name to detect in wild card format + For example: simAddDetectionFilterMeshName("Car_*") will detect all instance named "Car_*" + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required mesh_name (str): mesh name in wild card format vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera + """ self.client.call('simAddDetectionFilterMeshName', camera_name, image_type, mesh_name, vehicle_name, external) def simSetDetectionFilterRadius(self, camera_name, image_type, radius_cm, vehicle_name = '', external = False): """ Set detection radius for all cameras + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required @@ -588,22 +664,26 @@ def simSetDetectionFilterRadius(self, camera_name, image_type, radius_cm, vehicl def simClearDetectionMeshNames(self, camera_name, image_type, vehicle_name = '', external = False): """ Clear all mesh names from detection filter + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera + """ self.client.call('simClearDetectionMeshNames', camera_name, image_type, vehicle_name, external) def simGetDetections(self, camera_name, image_type, vehicle_name = '', external = False): """ Get current detections + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used image_type (ImageType): Type of image required vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera + Returns: DetectionInfo array """ @@ -613,10 +693,13 @@ def simGetDetections(self, camera_name, image_type, vehicle_name = '', external def simPrintLogMessage(self, message, message_param = "", severity = 0): """ Prints the specified message in the simulator's window. + If message_param is supplied, then it's printed next to the message and in that case if this API is called with same message value but different message_param again then previous line is overwritten with new line (instead of API creating new line on display). + For example, `simPrintLogMessage("Iteration: ", to_string(i))` keeps updating same line on display when API is called with different values of i. The valid values of severity parameter is 0 to 3 inclusive that corresponds to different colors. + Args: message (str): Message to be printed message_param (str, optional): Parameter to be printed next to the message @@ -627,10 +710,12 @@ def simPrintLogMessage(self, message, message_param = "", severity = 0): def simGetCameraInfo(self, camera_name, vehicle_name = '', external=False): """ Get details about the camera + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera + Returns: CameraInfo: """ @@ -640,10 +725,12 @@ def simGetCameraInfo(self, camera_name, vehicle_name = '', external=False): def simGetDistortionParams(self, camera_name, vehicle_name = '', external = False): """ Get camera distortion parameters + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used vehicle_name (str, optional): Vehicle which the camera is associated with external (bool, optional): Whether the camera is an External Camera + Returns: List (float): List of distortion parameter values corresponding to K1, K2, K3, P1, P2 respectively. """ @@ -653,6 +740,7 @@ def simGetDistortionParams(self, camera_name, vehicle_name = '', external = Fals def simSetDistortionParams(self, camera_name, distortion_params, vehicle_name = '', external = False): """ Set camera distortion parameters + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used distortion_params (dict): Dictionary of distortion param names and corresponding values @@ -667,6 +755,7 @@ def simSetDistortionParams(self, camera_name, distortion_params, vehicle_name = def simSetDistortionParam(self, camera_name, param_name, value, vehicle_name = '', external = False): """ Set single camera distortion parameter + Args: camera_name (str): Name of the camera, for backwards compatibility, ID numbers such as 0,1,etc. can also be used param_name (str): Name of distortion parameter @@ -679,6 +768,7 @@ def simSetDistortionParam(self, camera_name, param_name, value, vehicle_name = ' def simSetCameraPose(self, camera_name, pose, vehicle_name = '', external = False): """ - Control the pose of a selected camera + Args: camera_name (str): Name of the camera to be controlled pose (Pose): Pose representing the desired position and orientation of the camera @@ -691,6 +781,7 @@ def simSetCameraPose(self, camera_name, pose, vehicle_name = '', external = Fals def simSetCameraFov(self, camera_name, fov_degrees, vehicle_name = '', external = False): """ - Control the field of view of a selected camera + Args: camera_name (str): Name of the camera to be controlled fov_degrees (float): Value of field of view in degrees @@ -703,9 +794,12 @@ def simSetCameraFov(self, camera_name, fov_degrees, vehicle_name = '', external def simGetGroundTruthKinematics(self, vehicle_name = ''): """ Get Ground truth kinematics of the vehicle + The position inside the returned KinematicsState is in the frame of the vehicle's starting point + Args: vehicle_name (str, optional): Name of the vehicle + Returns: KinematicsState: Ground truth of the vehicle """ @@ -716,7 +810,9 @@ def simGetGroundTruthKinematics(self, vehicle_name = ''): def simSetKinematics(self, state, ignore_collision, vehicle_name = ''): """ Set the kinematics state of the vehicle + If you don't want to change position (or orientation) then just set components of position (or orientation) to floating point nan values + Args: state (KinematicsState): Desired Pose pf the vehicle ignore_collision (bool): Whether to ignore any collision or not @@ -727,9 +823,12 @@ def simSetKinematics(self, state, ignore_collision, vehicle_name = ''): def simGetGroundTruthEnvironment(self, vehicle_name = ''): """ Get ground truth environment state + The position inside the returned EnvironmentState is in the frame of the vehicle's starting point + Args: vehicle_name (str, optional): Name of the vehicle + Returns: EnvironmentState: Ground truth environment state """ @@ -744,6 +843,7 @@ 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: """ @@ -754,6 +854,7 @@ 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: """ @@ -764,6 +865,7 @@ 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: """ @@ -774,6 +876,7 @@ 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: """ @@ -784,6 +887,7 @@ 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: """ @@ -794,6 +898,7 @@ 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: """ @@ -803,9 +908,11 @@ def simGetLidarSegmentation(self, lidar_name = '', vehicle_name = ''): """ NOTE: Deprecated API, use `getLidarData()` API instead Returns Segmentation ID of each point's collided object in the last Lidar update + Args: lidar_name (str, optional): Name of Lidar sensor vehicle_name (str, optional): Name of the vehicle wth the sensor + Returns: list[int]: Segmentation IDs of the objects """ @@ -822,6 +929,7 @@ 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 color_rgba (list, optional): desired RGBA values from 0.0 to 1.0 @@ -834,6 +942,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 @@ -846,6 +955,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 @@ -858,6 +968,7 @@ def simPlotLineList(self, points, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5 def simPlotArrows(self, points_start, points_end, color_rgba=[1.0, 0.0, 0.0, 1.0], thickness = 5.0, arrow_size = 2.0, duration = -1.0, is_persistent = False): """ Plots a list of arrows in World NED frame, defined from points_start[0] to points_end[0], points_start[1] to points_end[1], ... , points_start[n-1] to points_end[n-1] + Args: points_start (list[Vector3r]): List of 3D start positions of arrow start positions, specified as Vector3r objects points_end (list[Vector3r]): List of 3D end positions of arrow start positions, specified as Vector3r objects @@ -873,6 +984,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. + Args: strings (list[String], optional): List of strings to plot positions (list[Vector3r]): List of positions where the strings should be plotted. Should be in one-to-one correspondence with the strings' list @@ -885,6 +997,7 @@ 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. + Args: poses (list[Pose]): List of Pose objects representing the transforms to plot scale (float, optional): Length of transforms' axes @@ -897,6 +1010,7 @@ 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. + 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 @@ -911,6 +1025,7 @@ def simPlotTransformsWithNames(self, poses, names, tf_scale = 5.0, tf_thickness def cancelLastTask(self, vehicle_name = ''): """ Cancel previous Async task + Args: vehicle_name (str, optional): Name of the vehicle """ @@ -920,6 +1035,7 @@ def cancelLastTask(self, vehicle_name = ''): def startRecording(self): """ Start Recording + Recording will be done according to the settings """ self.client.call('startRecording') @@ -933,6 +1049,7 @@ def stopRecording(self): def isRecording(self): """ Whether Recording is running or not + Returns: bool: True if Recording, else False """ @@ -941,6 +1058,7 @@ def isRecording(self): def simSetWind(self, wind): """ Set simulated wind, in World frame, NED direction, m/s + Args: wind (Vector3r): Wind, in World frame, NED direction, in m/s """ @@ -949,11 +1067,13 @@ def simSetWind(self, wind): def simCreateVoxelGrid(self, position, x, y, z, res, of): """ Construct and save a binvox-formatted voxel grid of environment + Args: position (Vector3r): Position around which voxel grid is centered in m x, y, z (int): Size of each voxel grid dimension in m res (float): Resolution of voxel grid in m of (str): Name of output file to save voxel grid as + Returns: bool: True if output written to file successfully, else False """ @@ -963,11 +1083,13 @@ def simCreateVoxelGrid(self, position, x, y, z, res, of): def simAddVehicle(self, vehicle_name, vehicle_type, pose, pawn_path = ""): """ Create vehicle at runtime + Args: vehicle_name (str): Name of the vehicle being created vehicle_type (str): Type of vehicle, e.g. "simpleflight" pose (Pose): Initial pose of the vehicle pawn_path (str, optional): Vehicle blueprint path, default empty wbich uses the default blueprint for the vehicle type + Returns: bool: Whether vehicle was created """ @@ -976,6 +1098,7 @@ def simAddVehicle(self, vehicle_name, vehicle_type, pose, pawn_path = ""): def listVehicles(self): """ Lists the names of current vehicles + Returns: list[str]: List containing names of all vehicles """ @@ -984,6 +1107,7 @@ def listVehicles(self): def getSettingsString(self): """ Fetch the settings text being used by AirSim + Returns: str: Settings text in JSON format """ @@ -997,9 +1121,11 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): def takeoffAsync(self, timeout_sec = 20, 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() """ @@ -1008,9 +1134,11 @@ def takeoffAsync(self, timeout_sec = 20, vehicle_name = ''): def landAsync(self, timeout_sec = 60, 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() """ @@ -1019,9 +1147,11 @@ def landAsync(self, timeout_sec = 60, 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() """ @@ -1038,6 +1168,7 @@ def moveByVelocityBodyFrameAsync(self, vx, vy, vz, duration, drivetrain = Drivet drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1053,6 +1184,7 @@ def moveByVelocityZBodyFrameAsync(self, vx, vy, z, duration, drivetrain = Drivet drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1077,6 +1209,7 @@ def moveByVelocityAsync(self, vx, vy, vz, duration, drivetrain = DrivetrainType. drivetrain (DrivetrainType, optional): yaw_mode (YawMode, optional): 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() """ @@ -1103,8 +1236,10 @@ def moveToZAsync(self, z, velocity, timeout_sec = 3e+38, yaw_mode = YawMode(), l 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. + 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. + Args: vx_max (float): max velocity allowed in x direction vy_max (float): max velocity allowed in y direction @@ -1135,6 +1270,7 @@ def moveByRC(self, rcdata = RCData(), vehicle_name = ''): def moveByMotorPWMsAsync(self, front_right_pwm, rear_left_pwm, front_left_pwm, rear_right_pwm, duration, vehicle_name = ''): """ - Directly control the motors using PWM values + Args: front_right_pwm (float): PWM value for the front right motor (between 0.0 to 1.0) rear_left_pwm (float): PWM value for the rear left motor (between 0.0 to 1.0) @@ -1152,16 +1288,23 @@ 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. + - 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. + - 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. + Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1169,6 +1312,7 @@ def moveByRollPitchYawZAsync(self, roll, pitch, yaw, z, duration, vehicle_name = 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1179,16 +1323,23 @@ def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, - Desired throttle is between 0.0 to 1.0 - Roll angle, pitch angle, and yaw angle are given in **degrees** when using PX4 and in **radians** when using SimpleFlight, 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. + - 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. + Args: roll (float): Desired roll angle. pitch (float): Desired pitch angle. @@ -1196,6 +1347,7 @@ def moveByRollPitchYawThrottleAsync(self, roll, pitch, yaw, throttle, duration, 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1206,16 +1358,23 @@ def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, d - 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. + - 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. + - 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. + Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1223,6 +1382,7 @@ def moveByRollPitchYawrateThrottleAsync(self, roll, pitch, yaw_rate, throttle, d 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1233,16 +1393,23 @@ def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehic - 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. + - 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. + Args: roll (float): Desired roll angle, in radians. pitch (float): Desired pitch angle, in radians. @@ -1250,6 +1417,7 @@ def moveByRollPitchYawrateZAsync(self, roll, pitch, yaw_rate, z, duration, vehic 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1260,16 +1428,23 @@ def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, v - 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. + - 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. + Args: roll_rate (float): Desired roll rate, in radians / second pitch_rate (float): Desired pitch rate, in radians / second @@ -1277,6 +1452,7 @@ def moveByAngleRatesZAsync(self, roll_rate, pitch_rate, yaw_rate, z, duration, v 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1287,16 +1463,23 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl - 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. + - 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. + - 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. + Args: roll_rate (float): Desired roll rate, in radians / second pitch_rate (float): Desired pitch rate, in radians / second @@ -1304,6 +1487,7 @@ def moveByAngleRatesThrottleAsync(self, roll_rate, pitch_rate, yaw_rate, throttl 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 + Returns: msgpackrpc.future.Future: future. call .join() to wait for method to finish. Example: client.METHOD().join() """ @@ -1315,6 +1499,7 @@ def setAngleRateControllerGains(self, angle_rate_gains=AngleRateControllerGains( 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. @@ -1330,6 +1515,7 @@ def setAngleLevelControllerGains(self, angle_level_gains=AngleLevelControllerGai 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. + Args: angle_level_gains (AngleLevelControllerGains): - Correspond to the roll, pitch, yaw axes, defined in the body frame. @@ -1343,6 +1529,7 @@ 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. + Args: velocity_gains (VelocityControllerGains): - Correspond to the world X, Y, Z axes. @@ -1357,6 +1544,7 @@ def setPositionControllerGains(self, position_gains=PositionControllerGains(), v """ Sets position controller gains for moveByPositionAsync. 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. @@ -1369,8 +1557,10 @@ def setPositionControllerGains(self, position_gains=PositionControllerGains(), v def getMultirotorState(self, vehicle_name = ''): """ The position inside the returned MultirotorState is in the frame of the vehicle's starting point + Args: vehicle_name (str, optional): Vehicle to get the state of + Returns: MultirotorState: """ @@ -1381,8 +1571,10 @@ def getRotorStates(self, vehicle_name = ''): """ Used to obtain the current state of all a multirotor's rotors. The state includes the speeds, thrusts and torques for all rotors. + Args: vehicle_name (str, optional): Vehicle to get the rotor state of + Returns: RotorStates: Containing a timestamp and the speed, thrust and torque of all rotors. """ @@ -1397,6 +1589,7 @@ def __init__(self, ip = "", port = 41451, timeout_value = 3600): 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 @@ -1406,8 +1599,10 @@ def setCarControls(self, controls, vehicle_name = ''): def getCarState(self, vehicle_name = ''): """ The position inside the returned CarState is in the frame of the vehicle's starting point + Args: vehicle_name (str, optional): Name of vehicle + Returns: CarState: """ @@ -1418,6 +1613,7 @@ def getCarControls(self, vehicle_name=''): """ Args: vehicle_name (str, optional): Name of vehicle + Returns: CarControls: """