From 5a49411da60b4ea26cf18f179b58182a61c81643 Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Mon, 29 Mar 2021 03:08:49 +0530 Subject: [PATCH 1/4] Store Settings text during initialization --- AirLib/include/common/AirSimSettings.hpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/AirLib/include/common/AirSimSettings.hpp b/AirLib/include/common/AirSimSettings.hpp index 2f01fb22c5..8300f7a777 100644 --- a/AirLib/include/common/AirSimSettings.hpp +++ b/AirLib/include/common/AirSimSettings.hpp @@ -377,6 +377,8 @@ struct AirSimSettings { std::map> sensor_defaults; Vector3r wind = Vector3r::Zero(); + std::string settings_text_ = ""; + public: //methods static AirSimSettings& singleton() { @@ -417,6 +419,7 @@ struct AirSimSettings { static void initializeSettings(const std::string& json_settings_text) { + singleton().settings_text_ = json_settings_text; Settings& settings_json = Settings::loadJSonString(json_settings_text); if (! settings_json.isLoadSuccess()) throw std::invalid_argument("Cannot parse JSON settings_json string."); @@ -424,12 +427,14 @@ struct AirSimSettings { static void createDefaultSettingsFile() { - std::string settings_filename = Settings::getUserDirectoryFullPath("settings.json"); - Settings& settings_json = Settings::loadJSonString("{}"); + initializeSettings("{}"); + + Settings& settings_json = Settings::singleton(); //write some settings_json in new file otherwise the string "null" is written if all settings_json are empty settings_json.setString("SeeDocsAt", "https://github.com/Microsoft/AirSim/blob/master/docs/settings.md"); settings_json.setDouble("SettingsVersion", 1.2); + std::string settings_filename = Settings::getUserDirectoryFullPath("settings.json"); //TODO: there is a crash in Linux due to settings_json.saveJSonString(). Remove this workaround after we only support Unreal 4.17 //https://answers.unrealengine.com/questions/664905/unreal-crashes-on-two-lines-of-extremely-simple-st.html settings_json.saveJSonFile(settings_filename); From aaef18e15435fcdb333b782fda4e28e4c2fb2f06 Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Mon, 29 Mar 2021 03:10:21 +0530 Subject: [PATCH 2/4] Add API for getting the settings text being used --- AirLib/include/api/RpcLibClientBase.hpp | 2 ++ AirLib/include/api/WorldSimApiBase.hpp | 2 ++ AirLib/src/api/RpcLibClientBase.cpp | 5 +++++ AirLib/src/api/RpcLibServerBase.cpp | 4 ++++ PythonClient/airsim/client.py | 9 +++++++++ Unreal/Plugins/AirSim/Source/WorldSimApi.cpp | 5 +++++ Unreal/Plugins/AirSim/Source/WorldSimApi.h | 2 ++ 7 files changed, 29 insertions(+) diff --git a/AirLib/include/api/RpcLibClientBase.hpp b/AirLib/include/api/RpcLibClientBase.hpp index 56e9ce567a..841b464030 100644 --- a/AirLib/include/api/RpcLibClientBase.hpp +++ b/AirLib/include/api/RpcLibClientBase.hpp @@ -120,6 +120,8 @@ class RpcLibClientBase { void simSetWind(const Vector3r& wind) const; + std::string getSettingsString() const; + protected: void* getClient(); const void* getClient() const; diff --git a/AirLib/include/api/WorldSimApiBase.hpp b/AirLib/include/api/WorldSimApiBase.hpp index baaa3c6714..e7114c2bdc 100644 --- a/AirLib/include/api/WorldSimApiBase.hpp +++ b/AirLib/include/api/WorldSimApiBase.hpp @@ -79,6 +79,8 @@ class WorldSimApiBase { virtual bool isRecording() const = 0; virtual void setWind(const Vector3r& wind) const = 0; + + virtual std::string getSettingsString() const = 0; }; diff --git a/AirLib/src/api/RpcLibClientBase.cpp b/AirLib/src/api/RpcLibClientBase.cpp index 01ad714045..7e392b9b48 100644 --- a/AirLib/src/api/RpcLibClientBase.cpp +++ b/AirLib/src/api/RpcLibClientBase.cpp @@ -470,6 +470,11 @@ void RpcLibClientBase::simSetWind(const Vector3r& wind) const pimpl_->client.call("simSetWind", conv_wind); } +std::string RpcLibClientBase::getSettingsString() const +{ + return pimpl_->client.call("getSettingsString").as(); +} + void* RpcLibClientBase::getClient() { return &pimpl_->client; diff --git a/AirLib/src/api/RpcLibServerBase.cpp b/AirLib/src/api/RpcLibServerBase.cpp index fcc6db0793..f1dab7bebe 100644 --- a/AirLib/src/api/RpcLibServerBase.cpp +++ b/AirLib/src/api/RpcLibServerBase.cpp @@ -383,6 +383,10 @@ RpcLibServerBase::RpcLibServerBase(ApiProvider* api_provider, const std::string& getWorldSimApi()->setWind(wind.to()); }); + pimpl_->server.bind("getSettingsString", [&]() -> std::string { + return getWorldSimApi()->getSettingsString(); + }); + //if we don't suppress then server will bomb out for exceptions raised by any method pimpl_->server.suppress_exceptions(true); } diff --git a/PythonClient/airsim/client.py b/PythonClient/airsim/client.py index d779595de2..3111f5d0b4 100644 --- a/PythonClient/airsim/client.py +++ b/PythonClient/airsim/client.py @@ -872,6 +872,15 @@ def simAddVehicle(self, vehicle_name, vehicle_type, pose, pawn_path = ""): """ return self.client.call('simAddVehicle', vehicle_name, vehicle_type, pose, pawn_path) + 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 --------------------------------------------- class MultirotorClient(VehicleClient, object): def __init__(self, ip = "", port = 41451, timeout_value = 3600): diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp index 6de0bacc01..164778352f 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.cpp @@ -573,3 +573,8 @@ void WorldSimApi::setWind(const Vector3r& wind) const { simmode_->setWind(wind); } + +std::string WorldSimApi::getSettingsString() const +{ + return msr::airlib::AirSimSettings::singleton().settings_text_; +} diff --git a/Unreal/Plugins/AirSim/Source/WorldSimApi.h b/Unreal/Plugins/AirSim/Source/WorldSimApi.h index 8ca7b8de7e..9b1afdec86 100644 --- a/Unreal/Plugins/AirSim/Source/WorldSimApi.h +++ b/Unreal/Plugins/AirSim/Source/WorldSimApi.h @@ -70,6 +70,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase { virtual void setWind(const Vector3r& wind) const override; 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) override; + virtual std::string getSettingsString() const override; + private: AActor* createNewActor(const FActorSpawnParameters& spawn_params, const FTransform& actor_transform, const Vector3r& scale, UStaticMesh* static_mesh); void spawnPlayer(); From cbd72ca21845098a959b414e659da4047a703c5f Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Mon, 29 Mar 2021 03:12:14 +0530 Subject: [PATCH 3/4] ROS: Use settings text from API call rather than reading from Documents folder --- .../include/airsim_ros_wrapper.h | 1 - .../include/airsim_settings_parser.h | 9 ++-- .../src/airsim_ros_wrapper.cpp | 7 +-- .../src/airsim_settings_parser.cpp | 43 ++++++------------- 4 files changed, 21 insertions(+), 39 deletions(-) diff --git a/ros/src/airsim_ros_pkgs/include/airsim_ros_wrapper.h b/ros/src/airsim_ros_pkgs/include/airsim_ros_wrapper.h index 958ea1e70f..9d51cae4b1 100644 --- a/ros/src/airsim_ros_pkgs/include/airsim_ros_wrapper.h +++ b/ros/src/airsim_ros_pkgs/include/airsim_ros_wrapper.h @@ -319,7 +319,6 @@ class AirsimROSWrapper msr::airlib::GeoPoint origin_geo_point_;// gps coord of unreal origin airsim_ros_pkgs::GPSYaw origin_geo_point_msg_; // todo duplicate - std::vector vehicle_setting_vec_; AirSimSettingsParser airsim_settings_parser_; std::unordered_map< std::string, std::unique_ptr< VehicleROS > > vehicle_name_ptr_map_; static const std::unordered_map image_type_int_to_string_map_; diff --git a/ros/src/airsim_ros_pkgs/include/airsim_settings_parser.h b/ros/src/airsim_ros_pkgs/include/airsim_settings_parser.h index 69fdc72a3c..3f0e380c3f 100644 --- a/ros/src/airsim_ros_pkgs/include/airsim_settings_parser.h +++ b/ros/src/airsim_ros_pkgs/include/airsim_settings_parser.h @@ -17,20 +17,19 @@ class AirSimSettingsParser { public: typedef msr::airlib::AirSimSettings AirSimSettings; - typedef msr::airlib::AirSimSettings::VehicleSetting VehicleSetting; public: - AirSimSettingsParser(); + AirSimSettingsParser(const std::string& host_ip); ~AirSimSettingsParser() {}; bool success(); private: std::string getSimMode(); - bool readSettingsTextFromFile(std::string settingsFilepath, std::string& settingsText); - bool getSettingsText(std::string& settingsText); + bool getSettingsText(std::string& settings_text) const; bool initializeSettings(); bool success_; - std::string settingsText_; + std::string settings_text_; + std::string host_ip_; }; \ No newline at end of file diff --git a/ros/src/airsim_ros_pkgs/src/airsim_ros_wrapper.cpp b/ros/src/airsim_ros_pkgs/src/airsim_ros_wrapper.cpp index 1ede93e4a7..3738161d6b 100644 --- a/ros/src/airsim_ros_pkgs/src/airsim_ros_wrapper.cpp +++ b/ros/src/airsim_ros_pkgs/src/airsim_ros_wrapper.cpp @@ -34,13 +34,14 @@ AirsimROSWrapper::AirsimROSWrapper(const ros::NodeHandle& nh, const ros::NodeHan host_ip_(host_ip), airsim_client_images_(host_ip), airsim_client_lidar_(host_ip), + airsim_settings_parser_(host_ip), tf_listener_(tf_buffer_) { ros_clock_.clock.fromSec(0); is_used_lidar_timer_cb_queue_ = false; is_used_img_timer_cb_queue_ = false; - if (AirSimSettings::singleton().simmode_name != "Car") + if (AirSimSettings::singleton().simmode_name != AirSimSettings::kSimModeTypeCar) { airsim_mode_ = AIRSIM_MODE::DRONE; ROS_INFO("Setting ROS wrapper to DRONE mode"); @@ -68,7 +69,7 @@ void AirsimROSWrapper::initialize_airsim() } else { - airsim_client_ = std::move(std::unique_ptr(new msr::airlib::CarRpcLibClient(host_ip_))); + airsim_client_ = std::unique_ptr(new msr::airlib::CarRpcLibClient(host_ip_)); } airsim_client_->confirmConnection(); airsim_client_images_.confirmConnection(); @@ -189,7 +190,7 @@ void AirsimROSWrapper::create_ros_pubs_from_settings_json() { auto& camera_setting = curr_camera_elem.second; auto& curr_camera_name = curr_camera_elem.first; - // vehicle_setting_vec_.push_back(*vehicle_setting.get()); + set_nans_to_zeros_in_pose(*vehicle_setting, camera_setting); append_static_camera_tf(vehicle_ros.get(), curr_camera_name, camera_setting); // camera_setting.gimbal diff --git a/ros/src/airsim_ros_pkgs/src/airsim_settings_parser.cpp b/ros/src/airsim_ros_pkgs/src/airsim_settings_parser.cpp index e0be99330d..de5c7e4658 100644 --- a/ros/src/airsim_ros_pkgs/src/airsim_settings_parser.cpp +++ b/ros/src/airsim_ros_pkgs/src/airsim_settings_parser.cpp @@ -1,6 +1,7 @@ #include "airsim_settings_parser.h" -AirSimSettingsParser::AirSimSettingsParser() +AirSimSettingsParser::AirSimSettingsParser(const std::string& host_ip) + : host_ip_(host_ip) { success_ = initializeSettings(); } @@ -10,52 +11,34 @@ bool AirSimSettingsParser::success() return success_; } -bool AirSimSettingsParser::readSettingsTextFromFile(std::string settingsFilepath, std::string& settingsText) +bool AirSimSettingsParser::getSettingsText(std::string& settings_text) const { - // check if path exists - bool found = std::ifstream(settingsFilepath.c_str()).good(); - if (found) - { - std::ifstream ifs(settingsFilepath); - std::stringstream buffer; - buffer << ifs.rdbuf(); - // todo airsim's simhud.cpp does error checking here - settingsText = buffer.str(); // todo convert to utf8 as done in simhud.cpp? - } + msr::airlib::RpcLibClientBase airsim_client(host_ip_); + airsim_client.confirmConnection(); - return found; -} + settings_text = airsim_client.getSettingsString(); -bool AirSimSettingsParser::getSettingsText(std::string& settingsText) -{ - bool success = readSettingsTextFromFile(msr::airlib::Settings::Settings::getUserDirectoryFullPath("settings.json"), settingsText); - return success; + return !settings_text.empty(); } std::string AirSimSettingsParser::getSimMode() { - Settings& settings_json = Settings::loadJSonString(settingsText_); + Settings& settings_json = Settings::loadJSonString(settings_text_); return settings_json.getString("SimMode", ""); } // mimics void ASimHUD::initializeSettings() bool AirSimSettingsParser::initializeSettings() { - if (getSettingsText(settingsText_)) + if (getSettingsText(settings_text_)) { - AirSimSettings::initializeSettings(settingsText_); - - // not sure where settings_json initialized in AirSimSettings::initializeSettings() is actually used - Settings& settings_json = Settings::loadJSonString(settingsText_); - std::string simmode_name = settings_json.getString("SimMode", ""); - std::cout << "simmode_name: " << simmode_name << std::endl; + AirSimSettings::initializeSettings(settings_text_); AirSimSettings::singleton().load(std::bind(&AirSimSettingsParser::getSimMode, this)); + std::cout << "SimMode: " << AirSimSettings::singleton().simmode_name << std::endl; return true; } - else - { - return false; - } + + return false; } \ No newline at end of file From 7ffdcec85328c5fb23316043df3b50f57201230e Mon Sep 17 00:00:00 2001 From: Rajat Singhal Date: Mon, 29 Mar 2021 03:24:19 +0530 Subject: [PATCH 4/4] Add Unity implementation --- Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp | 5 +++++ Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp index cc881cad32..73a01368ab 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.cpp @@ -202,5 +202,10 @@ bool WorldSimApi::addVehicle(const std::string& vehicle_name, const std::string& return false; } +std::string WorldSimApi::getSettingsString() const +{ + return msr::airlib::AirSimSettings::singleton().settings_text_; +} + #pragma endregion diff --git a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h index 548f4b2149..9dfcde4852 100644 --- a/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h +++ b/Unity/AirLibWrapper/AirsimWrapper/Source/WorldSimApi.h @@ -66,6 +66,8 @@ class WorldSimApi : public msr::airlib::WorldSimApiBase 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) override; virtual bool addVehicle(const std::string& vehicle_name, const std::string& vehicle_type, const Pose& pose, const std::string& pawn_path = "") override; + virtual std::string getSettingsString() const override; + private: SimModeBase * simmode_; std::string vehicle_name_;