From c6d89f49b0ca70de66746bdea8946fda4d9e792f Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Sun, 8 Aug 2021 19:04:44 +0530 Subject: [PATCH 1/4] Add API to list all assets --- AirLib/include/api/RpcLibClientBase.hpp | 2 ++ AirLib/include/api/WorldSimApiBase.hpp | 1 + AirLib/src/api/RpcLibClientBase.cpp | 5 +++ AirLib/src/api/RpcLibServerBase.cpp | 4 +++ PythonClient/airsim/client.py | 35 ++++++++++++------- .../Plugins/AirSim/Source/AirBlueprintLib.cpp | 2 +- Unreal/Plugins/AirSim/Source/WorldSimApi.cpp | 11 ++++++ Unreal/Plugins/AirSim/Source/WorldSimApi.h | 1 + 8 files changed, 47 insertions(+), 14 deletions(-) diff --git a/AirLib/include/api/RpcLibClientBase.hpp b/AirLib/include/api/RpcLibClientBase.hpp index e840c4fae7..5b26488ed0 100644 --- a/AirLib/include/api/RpcLibClientBase.hpp +++ b/AirLib/include/api/RpcLibClientBase.hpp @@ -144,6 +144,8 @@ namespace airlib std::string getSettingsString() const; + std::vector simListAssets() const; + protected: void* getClient(); const void* getClient() const; diff --git a/AirLib/include/api/WorldSimApiBase.hpp b/AirLib/include/api/WorldSimApiBase.hpp index c15c0f8ef5..52e002e0be 100644 --- a/AirLib/include/api/WorldSimApiBase.hpp +++ b/AirLib/include/api/WorldSimApiBase.hpp @@ -34,6 +34,7 @@ namespace airlib virtual bool loadLevel(const std::string& level_name) = 0; virtual string spawnObject(const std::string& object_name, const std::string& load_component, const Pose& pose, const Vector3r& scale, bool physics_enabled, bool is_blueprint) = 0; virtual bool destroyObject(const std::string& object_name) = 0; + virtual std::vector listAssets() const = 0; virtual bool isPaused() const = 0; virtual void reset() = 0; diff --git a/AirLib/src/api/RpcLibClientBase.cpp b/AirLib/src/api/RpcLibClientBase.cpp index 0b4713d4f9..3f5e9392b3 100644 --- a/AirLib/src/api/RpcLibClientBase.cpp +++ b/AirLib/src/api/RpcLibClientBase.cpp @@ -543,6 +543,11 @@ __pragma(warning(disable : 4239)) return pimpl_->client.call("getSettingsString").as(); } + std::vector RpcLibClientBase::simListAssets() const + { + return pimpl_->client.call("simListAssets").as>(); + } + void* RpcLibClientBase::getClient() { return &pimpl_->client; diff --git a/AirLib/src/api/RpcLibServerBase.cpp b/AirLib/src/api/RpcLibServerBase.cpp index 2b0e0e551e..f8a4aa3a24 100644 --- a/AirLib/src/api/RpcLibServerBase.cpp +++ b/AirLib/src/api/RpcLibServerBase.cpp @@ -310,6 +310,10 @@ namespace airlib return getWorldSimApi()->destroyObject(object_name); }); + pimpl_->server.bind("simListAssets", [&]() -> std::vector { + return getWorldSimApi()->listAssets(); + }); + pimpl_->server.bind("simGetObjectPose", [&](const std::string& object_name) -> RpcLibAdaptorsBase::Pose { const auto& pose = getWorldSimApi()->getObjectPose(object_name); return RpcLibAdaptorsBase::Pose(pose); diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index af96560178..6bf3e32d60 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -110,7 +110,7 @@ def simContinueForTime(self, seconds): seconds (float): Time to run the simulation for """ self.client.call('simContinueForTime', 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. @@ -305,7 +305,7 @@ 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] - + def simTestLineOfSightToPoint(self, point, vehicle_name = ''): """ Returns whether the target point is visible from the perspective of the inputted vehicle @@ -318,7 +318,7 @@ def simTestLineOfSightToPoint(self, point, vehicle_name = ''): [bool]: Success """ return self.client.call('simTestLineOfSightToPoint', point, vehicle_name) - + def simTestLineOfSightBetweenPoints(self, point1, point2): """ Returns whether the target point is visible from the perspective of the source point @@ -331,7 +331,7 @@ def simTestLineOfSightBetweenPoints(self, point1, point2): [bool]: Success """ return self.client.call('simTestLineOfSightBetweenPoints', point1, point2) - + def simGetWorldExtents(self): """ Returns a list of GeoPoints representing the minimum and maximum extents of the world @@ -483,7 +483,7 @@ def simListSceneObjects(self, name_regex = '.*'): list[str]: List containing all the names """ return self.client.call('simListSceneObjects', name_regex) - + def simLoadLevel(self, level_name): """ Loads a level specified by its name @@ -496,9 +496,18 @@ def simLoadLevel(self, level_name): """ return self.client.call('simLoadLevel', level_name) + def simListAssets(self): + """ + Lists all the assets present in the Asset Registry + + Returns: + list[str]: Names of all the assets + """ + return self.client.call('simListAssets') + 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 @@ -506,7 +515,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 """ @@ -514,10 +523,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 """ @@ -567,7 +576,7 @@ def simAddDetectionFilterMeshName(self, camera_name, image_type, mesh_name, vehi """ 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 @@ -580,7 +589,7 @@ def simSetDetectionFilterRadius(self, camera_name, image_type, radius_cm, vehicl external (bool, optional): Whether the camera is an External Camera """ self.client.call('simSetDetectionFilterRadius', camera_name, image_type, radius_cm, vehicle_name, external) - + def simClearDetectionMeshNames(self, camera_name, image_type, vehicle_name = '', external = False): """ Clear all mesh names from detection filter @@ -654,7 +663,7 @@ def simGetDistortionParams(self, camera_name, vehicle_name = '', external = Fals Returns: List (float): List of distortion parameter values corresponding to K1, K2, K3, P1, P2 respectively. """ - + return self.client.call('simGetDistortionParams', str(camera_name), vehicle_name, external) def simSetDistortionParams(self, camera_name, distortion_params, vehicle_name = '', external = False): @@ -975,7 +984,7 @@ 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 + wind (Vector3r): Wind, in World frame, NED direction, in m/s """ self.client.call('simSetWind', wind) diff --git a/Unreal/Plugins/AirSim/Source/AirBlueprintLib.cpp b/Unreal/Plugins/AirSim/Source/AirBlueprintLib.cpp index 063eaa4ff9..e7289d6998 100644 --- a/Unreal/Plugins/AirSim/Source/AirBlueprintLib.cpp +++ b/Unreal/Plugins/AirSim/Source/AirBlueprintLib.cpp @@ -248,7 +248,7 @@ void UAirBlueprintLib::GenerateAssetRegistryMap(const UObject* context, TMap WorldSimApi::listAssets() const +{ + std::vector all_assets; + + for (const TPair& pair : simmode_->asset_map) { + all_assets.push_back(std::string(TCHAR_TO_UTF8(*pair.Key))); + } + + return all_assets; +} + std::string WorldSimApi::spawnObject(const std::string& object_name, const std::string& load_object, const WorldSimApi::Pose& pose, const WorldSimApi::Vector3r& scale, bool physics_enabled, bool is_blueprint) { FString asset_name(load_object.c_str()); diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.h b/Unreal/Plugins/AirSim/Source/WorldSimApi.h index 51c1e2a302..e672fdb5f5 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.h +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.h @@ -26,6 +26,7 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual std::string spawnObject(const std::string& object_name, const std::string& load_name, const WorldSimApi::Pose& pose, const WorldSimApi::Vector3r& scale, bool physics_enabled, bool is_blueprint) override; virtual bool destroyObject(const std::string& object_name) override; + virtual std::vector listAssets() const override; virtual bool isPaused() const override; virtual void reset() override; From 5d8d4c95fbd9cf2723e678dbfe074b68a8e2e2a1 Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Sun, 8 Aug 2021 19:05:33 +0530 Subject: [PATCH 2/4] PythonClient: Add example script to create objects --- PythonClient/environment/create_objects.py | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 PythonClient/environment/create_objects.py diff --git a/PythonClient/environment/create_objects.py b/PythonClient/environment/create_objects.py new file mode 100644 index 0000000000..5dc445d1ce --- /dev/null +++ b/PythonClient/environment/create_objects.py @@ -0,0 +1,32 @@ +import setup_path +import airsim +import random +import time + +client = airsim.VehicleClient() +client.confirmConnection() + +assets = client.simListAssets() +print(f"Assets: {assets}") + +scale = airsim.Vector3r(1.0, 1.0, 1.0) + +# asset_name = random.choice(assets) +asset_name = '1M_Cube_Chamfer' + +desired_name = f"{asset_name}_spawn_{random.randint(0, 100)}" +pose = airsim.Pose(position_val=airsim.Vector3r(5.0, 0.0, 0.0)) + +obj_name = client.simSpawnObject(desired_name, asset_name, pose, scale, True) + +print(f"Created object {obj_name} from asset {asset_name} " + f"at pose {pose}, scale {scale}") + +all_objects = client.simListSceneObjects() +if obj_name not in all_objects: + print(f"Object {obj_name} not present!") + +time.sleep(10.0) + +print(f"Destroying {obj_name}") +client.simDestroyObject(obj_name) From 912b6d60c67a97b0f1ed4187d5f57de4c317d787 Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Sun, 8 Aug 2021 21:07:27 +0530 Subject: [PATCH 3/4] Add C++ simSpawn|Destroy object APIs --- AirLib/include/api/RpcLibClientBase.hpp | 3 +++ AirLib/src/api/RpcLibClientBase.cpp | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/AirLib/include/api/RpcLibClientBase.hpp b/AirLib/include/api/RpcLibClientBase.hpp index 5b26488ed0..c0fffa55c7 100644 --- a/AirLib/include/api/RpcLibClientBase.hpp +++ b/AirLib/include/api/RpcLibClientBase.hpp @@ -65,6 +65,9 @@ namespace airlib Vector3r simGetObjectScale(const std::string& object_name) const; bool simSetObjectPose(const std::string& object_name, const Pose& pose, bool teleport = true); bool simSetObjectScale(const std::string& object_name, const Vector3r& scale); + std::string simSpawnObject(const std::string& object_name, const std::string& load_component, const Pose& pose, + const Vector3r& scale, bool physics_enabled); + bool simDestroyObject(const std::string& object_name); //task management APIs void cancelLastTask(const std::string& vehicle_name = ""); diff --git a/AirLib/src/api/RpcLibClientBase.cpp b/AirLib/src/api/RpcLibClientBase.cpp index 3f5e9392b3..df9039e5ce 100644 --- a/AirLib/src/api/RpcLibClientBase.cpp +++ b/AirLib/src/api/RpcLibClientBase.cpp @@ -431,6 +431,17 @@ __pragma(warning(disable : 4239)) return pimpl_->client.call("simLoadLevel", level_name).as(); } + std::string RpcLibClientBase::simSpawnObject(const std::string& object_name, const std::string& load_component, const Pose& pose, + const Vector3r& scale, bool physics_enabled) + { + return pimpl_->client.call("simSpawnObject", object_name, load_component, RpcLibAdaptorsBase::Pose(pose), RpcLibAdaptorsBase::Vector3r(scale), physics_enabled).as(); + } + + bool RpcLibClientBase::simDestroyObject(const std::string& object_name) + { + return pimpl_->client.call("simDestroyObject", object_name).as(); + } + msr::airlib::Vector3r RpcLibClientBase::simGetObjectScale(const std::string& object_name) const { return pimpl_->client.call("simGetObjectScale", object_name).as().to(); From 92a887b695c05a09515d7b79e16cf5c6117cc272 Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Sun, 8 Aug 2021 21:07:57 +0530 Subject: [PATCH 4/4] Add Unity simListAssets API placeholder --- Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp | 8 ++++++++ Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h | 1 + 2 files changed, 9 insertions(+) diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp index 1e6442f201..3fc62a70d9 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp @@ -397,4 +397,12 @@ std::vector WorldSimApi::getDetections(ImageCaptureB return std::vector(); } +std::vector WorldSimApi::listAssets() const +{ + throw std::invalid_argument(common_utils::Utils::stringf( + "listAssets API is not supported on Unity") + .c_str()); + return {}; +} + #pragma endregion diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h index 9389db1c61..c88ea68e65 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h @@ -20,6 +20,7 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase virtual bool loadLevel(const std::string& level_name) override { return false; }; virtual std::string spawnObject(const std::string& object_name, const std::string& load_component, const Pose& pose, const Vector3r& scale, bool physics_enabled, bool is_blueprint) override { return ""; }; virtual bool destroyObject(const std::string& object_name) override { return false; }; + virtual std::vector listAssets() const override; virtual bool isPaused() const override; virtual void reset() override;