diff --git a/AirLib/include/common/common_utils/FileSystem.hpp b/AirLib/include/common/common_utils/FileSystem.hpp
index 6034a0ec73..90195b2e6c 100644
--- a/AirLib/include/common/common_utils/FileSystem.hpp
+++ b/AirLib/include/common/common_utils/FileSystem.hpp
@@ -46,6 +46,8 @@ class FileSystem
 
     static std::string getUserDocumentsFolder();
 
+	static std::string getExecutableFolder();
+
     static std::string getAppDataFolder() {
         return ensureFolder(combine(getUserDocumentsFolder(), ProductFolderName));
     }
diff --git a/AirLib/include/controllers/Settings.hpp b/AirLib/include/controllers/Settings.hpp
index 9deba615f1..7c5b7b6042 100644
--- a/AirLib/include/controllers/Settings.hpp
+++ b/AirLib/include/controllers/Settings.hpp
@@ -40,11 +40,17 @@ class Settings {
 
     std::string getFileName() { return file_; }
 
-    static std::string getFullPath(std::string fileName)
-    {
-        std::string path = common_utils::FileSystem::getAppDataFolder();
-        return common_utils::FileSystem::combine(path, fileName);
-    }
+	static std::string getUserDirectoryFullPath(std::string fileName)
+	{
+		std::string path = common_utils::FileSystem::getAppDataFolder();
+		return common_utils::FileSystem::combine(path, fileName);
+	}
+
+	static std::string getExecutableFullPath(std::string fileName)
+	{
+		std::string path = common_utils::FileSystem::getExecutableFolder();
+		return common_utils::FileSystem::combine(path, fileName);
+	}
 
     static Settings& loadJSonString(const std::string& json_str)
     {
@@ -72,7 +78,7 @@ class Settings {
     static Settings& loadJSonFile(std::string fileName)
     {
         std::lock_guard<std::mutex> guard(getFileAccessMutex());
-        std::string path = getFullPath(fileName);
+        std::string path = getUserDirectoryFullPath(fileName);
         singleton().file_ = fileName;
 
         singleton().load_success_ = false;
@@ -100,7 +106,7 @@ class Settings {
     void saveJSonFile(std::string fileName)
     {
         std::lock_guard<std::mutex> guard(getFileAccessMutex());
-        std::string path = getFullPath(fileName);
+        std::string path = getUserDirectoryFullPath(fileName);
         std::ofstream s;
         common_utils::FileSystem::createTextFile(path, s);
         s << std::setw(2) << doc_ << std::endl;
diff --git a/AirLib/src/common/common_utils/FileSystem.cpp b/AirLib/src/common/common_utils/FileSystem.cpp
index 2e7cc6aa57..ac28a036ca 100644
--- a/AirLib/src/common/common_utils/FileSystem.cpp
+++ b/AirLib/src/common/common_utils/FileSystem.cpp
@@ -37,7 +37,7 @@ using namespace common_utils;
 // File names are unicode (std::wstring), because users can create folders containing unicode characters on both
 // Windows, OSX and Linux.
 std::string FileSystem::createDirectory(const std::string& fullPath) {
-    
+
 #ifdef _WIN32
     std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
     std::wstring wide_path = converter.from_bytes(fullPath);
@@ -82,4 +82,37 @@ std::string FileSystem::getUserDocumentsFolder() {
     return ensureFolder(path);
 }
 
-#endif
\ No newline at end of file
+#endif
+
+std::string FileSystem::getExecutableFolder() {
+    std::string path;
+#ifdef _WIN32
+    wchar_t szPath[MAX_PATH];
+
+    HMODULE hModule = GetModuleHandle(NULL);
+
+    if (NULL != hModule) {
+        if (0 < GetModuleFileName(hModule, szPath, sizeof(szPath))) {
+            std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+            path = converter.to_bytes(szPath);
+        }
+        else {
+            HRESULT hr = GetLastError();
+            throw std::invalid_argument(Utils::stringf("Error getting executable folder, hr = %d", hr));
+        }
+    }
+    else {
+        HRESULT hr = GetLastError();
+        throw std::invalid_argument(Utils::stringf("Error getting executable folder - hModule is null. Last error = %d", hr));
+    }
+#else
+    char szPath[8192];
+    readlink("/proc/self/exe", szPath, sizeof(szPath));
+    path = std::string(szPath);
+#endif
+
+    size_t pathSeparatorIndex = path.find_last_of(kPathSeparator);
+    path = path.substr(0, pathSeparatorIndex);
+
+    return ensureFolder(path);
+}
\ No newline at end of file
diff --git a/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.cpp b/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.cpp
index ee847025f0..bca578db2c 100644
--- a/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.cpp
+++ b/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.cpp
@@ -6,6 +6,8 @@
 #include "MessageDialog.h"
 #include "Kismet/KismetSystemLibrary.h"
 
+#include <stdexcept>
+
 ASimHUD* ASimHUD::instance_ = nullptr;
 
 ASimHUD::ASimHUD()
@@ -20,7 +22,7 @@ void ASimHUD::BeginPlay()
     Super::BeginPlay();
 
     initializeSettings();
-    
+
     //TODO: should we only do below on SceneCapture2D components and cameras?
     //avoid motion blur so capture images don't get
     GetWorld()->GetGameViewport()->GetEngineShowFlags()->SetMotionBlur(false);
@@ -56,7 +58,7 @@ void ASimHUD::BeginPlay()
     updateWidgetSubwindowVisibility();
 }
 
-void ASimHUD::Tick( float DeltaSeconds )
+void ASimHUD::Tick(float DeltaSeconds)
 {
     if (simmode_->EnableReport)
         widget_->updateReport(simmode_->getReport());
@@ -144,7 +146,7 @@ void ASimHUD::updateWidgetSubwindowVisibility()
         if (camera != nullptr)
             camera->setCameraTypeEnabled(camera_type, is_visible);
 
-        widget_->setSubwindowVisibility(window_index, 
+        widget_->setSubwindowVisibility(window_index,
             is_visible,
             is_visible ? camera->getRenderTarget(camera_type, false) : nullptr
         );
@@ -203,9 +205,9 @@ void ASimHUD::createSimMode()
     std::string simmode_name = settings.getString("SimMode", "");
     if (simmode_name == "") {
         FText title = FText::FromString("Choose Vehicle");
-        if (EAppReturnType::No == FMessageDialog::Open(EAppMsgType::YesNo, 
-            FText::FromString("Would you like to use car simulation? Choose no to use quadrotor simulation."), 
-            & title))
+        if (EAppReturnType::No == FMessageDialog::Open(EAppMsgType::YesNo,
+            FText::FromString("Would you like to use car simulation? Choose no to use quadrotor simulation."),
+            &title))
         {
             simmode_name = "Multirotor";
         }
@@ -250,12 +252,12 @@ void ASimHUD::initializeSubWindows()
     Settings json_settings_parent;
     if (json_settings_root.getChild("SubWindows", json_settings_parent)) {
         for (size_t child_index = 0; child_index < json_settings_parent.size(); ++child_index) {
-            Settings json_settings_child;     
+            Settings json_settings_child;
             if (json_settings_parent.getChild(child_index, json_settings_child)) {
                 int index = json_settings_child.getInt("WindowID", -1);
 
                 if (index == -1) {
-                    UAirBlueprintLib::LogMessageString("WindowID not set in <SubWindows> element(s) in settings.json", 
+                    UAirBlueprintLib::LogMessageString("WindowID not set in <SubWindows> element(s) in settings.json",
                         std::to_string(child_index), LogDebugLevel::Failure);
                     continue;
                 }
@@ -266,9 +268,9 @@ void ASimHUD::initializeSubWindows()
                 int camera_id = json_settings_child.getInt("CameraID", 0);
                 if (camera_id >= 0 && camera_id < camera_count)
                     subwindow_cameras_[index] = wrapper->getCamera(camera_id);
-                else 
+                else
 
-                    UAirBlueprintLib::LogMessageString("CameraID in <SubWindows> element in settings.json is invalid", 
+                    UAirBlueprintLib::LogMessageString("CameraID in <SubWindows> element in settings.json is invalid",
                         std::to_string(child_index), LogDebugLevel::Failure);
             }
         }
@@ -281,34 +283,30 @@ void ASimHUD::initializeSettings()
     //load settings file if found
     typedef msr::airlib::Settings Settings;
     try {
-        FString settings_filename = FString(Settings::getFullPath("settings.json").c_str());
-        FString json_fstring;
+        std::string settings_str;
+        std::string json_settings_text;
         bool load_success = false;
-        bool file_found = FPaths::FileExists(settings_filename);
-        if (file_found) {
-            bool read_sucess = FFileHelper::LoadFileToString(json_fstring, *settings_filename);
-            if (read_sucess) {
-                Settings& settings = Settings::loadJSonString(TCHAR_TO_UTF8(*json_fstring));
-                if (settings.isLoadSuccess()) {
-                    UAirBlueprintLib::setLogMessagesHidden(!settings.getBool("LogMessagesVisible", true));
-                    UAirBlueprintLib::LogMessageString("Loaded settings from ", TCHAR_TO_UTF8(*settings_filename), LogDebugLevel::Informational);
-                    load_success = true;
-                }
-                else
-                    UAirBlueprintLib::LogMessageString("Possibly invalid json string in ", TCHAR_TO_UTF8(*settings_filename), LogDebugLevel::Failure);
+        bool settings_found = getSettingsText(json_settings_text);
+        if (settings_found && json_settings_text.size() > 0) {
+            Settings& settings = Settings::loadJSonString(json_settings_text);
+            if (settings.isLoadSuccess()) {
+                UAirBlueprintLib::setLogMessagesHidden(!settings.getBool("LogMessagesVisible", true));
+                load_success = true;
+            }
+            else {
+                UAirBlueprintLib::LogMessageString("Cannot parse JSON settings string.", "", LogDebugLevel::Failure);
             }
-            else
-                UAirBlueprintLib::LogMessageString("Cannot read settings from ", TCHAR_TO_UTF8(*settings_filename), LogDebugLevel::Failure);
         }
 
         if (!load_success) {
+            FString settings_filename = FString(Settings::getUserDirectoryFullPath("settings.json").c_str());
             //create default settings
             Settings& settings = Settings::loadJSonString("{}");
             //write some settings in new file otherwise the string "null" is written if all settigs are empty
             settings.setString("SeeDocsAt", "https://github.com/Microsoft/AirSim/blob/master/docs/settings.md");
             settings.setDouble("SettingsVersion", 1.0);
 
-            if (!file_found) {
+            if (!settings_found) {
                 std::string json_content;
                 //TODO: there is a crash in Linux due to settings.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
@@ -317,13 +315,69 @@ void ASimHUD::initializeSettings()
 #else
                 json_content = "{ \"SettingsVersion\": 1, \"SeeDocsAt\": \"https://github.com/Microsoft/AirSim/blob/master/docs/settings.md\"}";
 #endif
-                json_fstring = FString(json_content.c_str());
+                FString json_fstring = FString(json_content.c_str());
                 FFileHelper::SaveStringToFile(json_fstring, *settings_filename);
-                UAirBlueprintLib::LogMessageString("Created settings file at ", TCHAR_TO_UTF8(*settings_filename), LogDebugLevel::Informational);
+                UAirBlueprintLib::LogMessageString("Settings not provided. Created defalut settings file at ", TCHAR_TO_UTF8(*settings_filename), LogDebugLevel::Informational);
             }
         }
     }
     catch (std::exception& ex) {
-        UAirBlueprintLib::LogMessage(FString("Error loading settings from ~/Documents/AirSim/settings.json"), FString(ex.what()), LogDebugLevel::Failure, 30);
+        UAirBlueprintLib::LogMessage(FString("Error loading settings"), FString(ex.what()), LogDebugLevel::Failure, 30);
+    }
+}
+
+// Attempts to parse the settings text from one of multiple locations.
+// First, check the command line for settings provided via "-s" or "--settings" arguments
+// Next, check the executable's working directory for the settings file.
+// Finally, check the user's documents folder. 
+// If the settings file cannot be read, throw an exception
+
+bool ASimHUD::getSettingsText(std::string& settingsText) {
+    return (getSettingsTextFromCommandLine(settingsText)
+        ||
+        readSettingsTextFromFile(FString(Settings::getExecutableFullPath("settings.json").c_str()), settingsText)
+        ||
+        readSettingsTextFromFile(FString(Settings::getUserDirectoryFullPath("settings.json").c_str()), settingsText));
+}
+
+// Attempts to parse the settings text from the command line
+// Looks for the flag "--settings". If it exists, settingsText will be set to the value.
+// Example: AirSim.exe -s '{"foo" : "bar"}' -> settingsText will be set to {"foo": "bar"}
+// Returns true if the argument is present, false otherwise.
+bool ASimHUD::getSettingsTextFromCommandLine(std::string& settingsText) {
+
+    bool found = false;
+    FString settingsTextFString;
+    const TCHAR* commandLineArgs = FCommandLine::Get();
+
+    if (FParse::Param(commandLineArgs, TEXT("-settings"))) {
+        FString commandLineArgsFString = FString(commandLineArgs);
+        int idx = commandLineArgsFString.Find(TEXT("-settings"));
+        FString settingsJsonFString = commandLineArgsFString.RightChop(idx + 10);
+        if (FParse::QuotedString(*settingsJsonFString, settingsTextFString)) {
+            settingsText = std::string(TCHAR_TO_UTF8(*settingsTextFString));
+            found = true;
+        }
+    }
+
+    return found;
+}
+
+bool ASimHUD::readSettingsTextFromFile(FString settingsFilepath, std::string& settingsText) {
+
+    bool found = FPaths::FileExists(settingsFilepath);
+    if (found) {
+        FString settingsTextFStr;
+        bool readSuccessful = FFileHelper::LoadFileToString(settingsTextFStr, *settingsFilepath);
+        if (readSuccessful) {
+            UAirBlueprintLib::LogMessageString("Loaded settings from ", TCHAR_TO_UTF8(*settingsFilepath), LogDebugLevel::Informational);
+            settingsText = TCHAR_TO_UTF8(*settingsTextFStr);
+        }
+        else {
+            UAirBlueprintLib::LogMessageString("Cannot read file ", TCHAR_TO_UTF8(*settingsFilepath), LogDebugLevel::Failure);
+            throw std::runtime_error("Cannot read settings file.");
+        }
     }
+
+    return found;
 }
\ No newline at end of file
diff --git a/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.h b/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.h
index b328286fab..04fdb4f397 100644
--- a/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.h
+++ b/Unreal/Plugins/AirSim/Source/SimHUD/SimHUD.h
@@ -11,7 +11,7 @@
 UENUM(BlueprintType)
 enum class ESimulatorMode : uint8
 {
-    SIM_MODE_HIL 	UMETA(DisplayName="Hardware-in-loop")
+    SIM_MODE_HIL 	UMETA(DisplayName = "Hardware-in-loop")
 };
 
 UCLASS()
@@ -39,11 +39,11 @@ class AIRSIM_API ASimHUD : public AHUD
     void setSubwindowCamera(int window_index, APIPCamera* camera);
     bool getSubwindowVisible(int window_index);
     void setSubwindowVisible(int window_index, bool is_visible);
-        
+
     ASimHUD();
     virtual void BeginPlay() override;
     virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
-    virtual void Tick( float DeltaSeconds ) override;
+    virtual void Tick(float DeltaSeconds) override;
 
     static ASimHUD* GetInstance() {
         return instance_;
@@ -61,6 +61,10 @@ class AIRSIM_API ASimHUD : public AHUD
     void initializeSubWindows();
     void createSimMode();
 
+    bool getSettingsText(std::string& settingsText);
+    bool getSettingsTextFromCommandLine(std::string& settingsText);
+    bool readSettingsTextFromFile(FString fileName, std::string& settingsText);
+
 private:
     typedef common_utils::Utils Utils;
     UClass* widget_class_;
