44#include <Ice/Communicator.h>
45#include <Ice/Initialize.h>
46#include <Ice/LocalException.h>
47#include <Ice/NativePropertiesAdmin.h>
48#include <Ice/ObjectF.h>
49#include <Ice/Process.h>
50#include <Ice/Properties.h>
51#include <Ice/Properties.h>
52#include <Ice/PropertiesAdmin.h>
53#include <Ice/PropertiesAdmin.h>
54#include <IceUtil/Time.h>
56#include <SimoxUtility/algorithm/string/string_tools.h>
71#include "ArmarXCore/interface/core/Log.h"
72#include "ArmarXCore/interface/core/Profiler.h"
100std::mutex Application::instanceMutex;
102Ice::StringSeq Application::ProjectDependendencies;
103std::string Application::ProjectName;
105std::string
errormsg =
"Segmentation fault - Backtrace: \n";
120 std::array<void*, 20> array;
122 size = backtrace(array.data(), 20);
124#pragma GCC diagnostic push
125#pragma GCC diagnostic ignored "-Wunused-result"
127#pragma GCC diagnostic pop
128 backtrace_symbols_fd(array.data(), size, STDERR_FILENO);
134 std::stringstream
str;
138 str <<
"Error: Abort\nBacktrace:\n";
142 str <<
"Error: signal " << sig;
155 s <<
"qtcreator -debug " << getpid();
157 res = system(s.str().c_str());
174Application::loadLibrariesFromProperties()
177 if (!loadLibString.empty())
179 if (!libLoadingEnabled)
181 throw LocalException(
"Loading of dynamic libraries is not enabled in this application. "
182 "The Application needs to call enableLibLoading()");
184 auto entries =
armarx::Split(loadLibString,
";",
true,
true);
185 for (
auto& entry : entries)
189 std::filesystem::path path;
196 auto elements =
Split(entry,
":");
199 CMakePackageFinder p(elements.at(0));
203 std::string libFileName =
"lib" + elements.at(1) +
"." +
207 std::filesystem::path testPath(libDir);
208 testPath /= libFileName;
209 if (std::filesystem::exists(testPath))
219 std::string libFileName =
"lib" + elements.at(0) +
"_" + elements.at(1) +
224 std::filesystem::path testPath(libDir);
225 testPath /= libFileName;
226 if (std::filesystem::exists(testPath))
237 <<
"' in any of the following paths: " << p.getLibraryPaths();
258 return forbidThreadCreation;
264 forbidThreadCreation = value;
265 if (forbidThreadCreation)
267 ARMARX_INFO <<
"Thread creation with RunningTask and PeriodicTask is now forbidden in this "
272 ARMARX_INFO <<
"Thread creation with RunningTask and PeriodicTask is now allowed again in "
280 this->libLoadingEnabled = enable;
287 <<
"Command line arguments were already set: " <<
VAROUT(commandLineArguments);
288 commandLineArguments.reserve(argc);
289 for (
int i = 0; i < argc; ++i)
291 commandLineArguments.emplace_back(argv[i]);
295const std::vector<std::string>&
298 return commandLineArguments;
318 std::unique_lock lock(instanceMutex);
326 std::unique_lock lock(instanceMutex);
339 armarXManager->setComponentIceProperties(properties);
351 armarXManager->updateComponentIceProperties(properties);
360 if (changedProperties.count(
"DisableLogging") &&
367 if (changedProperties.count(
"EnableProfiling"))
371 if (changedProperties.count(
"Verbosity"))
373 armarXManager->setGlobalMinimumLoggingLevel(
422 std::cout <<
"Version: " <<
GetVersion() << std::endl;
434 const Ice::PropertyDict& env_props =
437 for (
const auto& [name, value] : env_props)
439 const std::string short_name = name.substr(4);
443 ARMARX_INFO <<
"Setting environment variable '" << short_name <<
"' to value '" << envVarResolved
445 setenv(short_name.c_str(), envVarResolved.c_str(), 1);
452 ARMARX_INFO <<
"startup delay: " << delay <<
" seconds";
453 std::this_thread::sleep_for(std::chrono::seconds{delay});
471 std::streambuf* cout_sbuf =
nullptr;
472 std::streambuf* cerr_sbuf =
nullptr;
475 cout_sbuf = std::cout.rdbuf();
476 cerr_sbuf = std::cerr.rdbuf();
477 std::cout.rdbuf(&buf);
478 std::cerr.rdbuf(&errbuf);
485 std::cout.rdbuf(cout_sbuf);
486 std::cerr.rdbuf(cerr_sbuf);
490 int result = EXIT_SUCCESS;
496 armarXManager =
new ArmarXManager(applicationName, communicator());
498 catch (Ice::ConnectFailedException&)
512 callbackOnInterrupt();
516 if (applicationNetworkStats)
518 ProfilerListenerPrx profilerTopic =
519 armarXManager->getIceManager()->getTopic<ProfilerListenerPrx>(
520 armarx::Profiler::PROFILER_TOPIC_NAME);
521 applicationNetworkStats->start(profilerTopic, applicationName);
524 loadLibrariesFromProperties();
529 setup(armarXManager, properties);
534 armarXManager->shutdown();
538 result =
exec(armarXManager);
544 shutdownThread->join();
557 armarXManager->waitForShutdown();
572 std::string configFiles = communicator()->getProperties()->getProperty(
"ArmarX.Config");
578 if (!configFiles.empty() && configFiles.compare(
"1") != 0)
580 std::vector<std::string> configFileList = simox::alg::split(configFiles,
",");
582 for (std::string configFile : configFileList)
584 if (!configFile.empty())
586 properties->load(configFile);
609 std::ofstream out(options.
outfile);
619 std::cout <<
"Could not write to file " << options.
outfile << std::endl;
633 this->applicationName = name;
639 return applicationName;
646 if (applicationNetworkStats)
648 applicationNetworkStats->stopTask();
651 shutdownThread.reset(
new std::thread{[
this]
654 this->armarXManager->shutdown();
661 IceUtil::Time start = IceUtil::Time::now();
663 dependencies = simox::alg::replace_all(dependencies,
"\"",
"");
664 Ice::StringSeq resultList = simox::alg::split(dependencies,
"/");
666 for (
size_t i = 0; i < resultList.size(); i++)
676 ARMARX_INFO_S <<
"loading took " << (IceUtil::Time::now() - start).toMilliSeconds();
682 const std::string autodiscoverPropertyName =
"AutodiscoverPackages";
686 ARMARX_VERBOSE <<
"`" << autodiscoverPropertyName <<
"` property available.";
693std::vector<std::string>
707 result.insert(result.end(), additional.begin(), additional.end());
715 char* env_armarx_workspace = getenv(
"ARMARX_WORKSPACE");
716 char* env_armarx_default_config_dir_name = getenv(
"ARMARX_CONFIG_DIR_NAME");
718 std::filesystem::path armarx_workspace;
719 std::filesystem::path armarx_config_dir;
721 if (env_armarx_workspace)
723 armarx_workspace = std::filesystem::path(env_armarx_workspace);
727 char* home = getenv(
"HOME");
731 armarx_workspace = std::filesystem::path(home);
735 armarx_workspace =
"~/";
739 if (env_armarx_default_config_dir_name)
741 armarx_config_dir = std::filesystem::path(env_armarx_default_config_dir_name);
745 if (env_armarx_workspace)
747 armarx_config_dir =
"armarx_config";
752 armarx_config_dir =
".armarx";
758 return (armarx_workspace / armarx_config_dir).string();
762 if (env_armarx_workspace)
764 return "${ARMARX_WORKSPACE}/" + armarx_config_dir.string();
769 return "${HOME}/" + armarx_config_dir.string();
777 return armarXManager;
785 Ice::InitializationData id(initData);
790 if (
id.properties->getProperty(
"Ice.Admin.InstanceName").empty())
792 id.properties->setProperty(
"Ice.Admin.InstanceName", this->
getName());
794 if (
id.properties->getProperty(
"Ice.Admin.Endpoints").empty())
796 id.properties->setProperty(
"Ice.Admin.Endpoints",
"tcp -h 127.0.0.1");
799 if (initData.properties->getProperty(
"ArmarX.NetworkStats") ==
"1")
802 id.observer = applicationNetworkStats;
804 const auto oldFacets = initData.properties->getPropertyAsList(
"Ice.Admin.Facets");
805 if (oldFacets.empty())
807 initData.properties->setProperty(
"Ice.Admin.Facets",
"Metrics");
809 else if (std::find(oldFacets.begin(), oldFacets.end(),
"Metrics") == oldFacets.end())
811 std::stringstream
str;
813 for (
const auto& facet : oldFacets)
817 initData.properties->setProperty(
"Ice.Admin.Facets",
str.str());
819 initData.properties->setProperty(
"IceMX.Metrics.NetworkStats.GroupBy",
"none");
822 return Ice::Application::doMain(argc, argv,
id, i);
828 const std::string configFileName =
"default.cfg";
829 const std::string generatedConfigFileName =
"default.generated.cfg";
830 Ice::StringSeq defaultsPaths;
832 std::filesystem::path absBasePath;
835 absBasePath = defaultsPathVar;
841 defaultsPaths.push_back((absBasePath / configFileName).
string());
842 defaultsPaths.push_back((absBasePath / generatedConfigFileName).
string());
843 return defaultsPaths;
858 for (std::string path : defaultsPath)
864 Ice::PropertyDict defaultCfg = p->getPropertiesForPrefix(
"");
867 for (
auto e : defaultCfg)
869 if (properties->getProperty(e.first).empty())
871 properties->setProperty(e.first, e.second);
875 catch (Ice::FileException& e)
891 return ProjectDependendencies;
903 std::string dependenciesConfig =
getIceProperties()->getProperty(
"ArmarX.DependenciesConfig");
905 if (!dependenciesConfig.empty())
907 if (std::filesystem::exists(dependenciesConfig))
910 prop->load(dependenciesConfig);
912 ProjectName = prop->getProperty(
"ArmarX.ProjectName");
913 std::string dependencies = prop->getProperty(
"ArmarX.ProjectDependencies");
914 ProjectDependendencies = simox::alg::split(dependencies,
";");
930 "Config",
"",
"Comma-separated list of configuration files ");
932 "DependenciesConfig",
933 "./config/dependencies.cfg",
934 "Path to the (usually generated) config file containing all data paths of all dependent "
935 "projects. This property usually does not need to be edited.");
943 "RobotSkillTemplates",
949 "List of ArmarX packages which are accessible by default. Comma separated List. If you "
950 "want to add your own packages and use all default ArmarX packages, use the property "
951 "'AdditionalPackages'.");
953 "AdditionalPackages",
955 "List of additional ArmarX packages which should be in the list of default packages. If "
956 "you have custom packages, which should be found by the gui or other apps, specify them "
957 "here. Comma separated List.");
960 "AutodiscoverPackages",
962 "If enabled, will discover all ArmarX packages based on the environment variables. "
963 "Otherwise, the `DefaultPackages` and `AdditionalPackages` properties are used.");
969 "Turn logging off in whole application",
974 "Global logging level for whole application",
980 "The logging group is transmitted with every ArmarX log message over Ice in order to group "
981 "the message in the GUI.");
985 "DataPath",
"",
"Semicolon-separated search list for data files");
990 std::string(
"Path for cache files. If relative path AND env. variable ") +
992 " is set, the cache path will be made relative to " +
994 ". Otherwise if relative it will be relative to the default ArmarX config dir (" +
999 "Enable profiling of CPU load produced by this application",
1003 "RedirectStdout",
true,
"Redirect std::cout and std::cerr to ArmarXLog");
1008 "Suffix appended to all topic names for outgoing topics. This is mainly used to direct all "
1009 "topics to another name for TopicReplaying purposes.");
1012 "UseTimeServer",
false,
"Enable using a global Timeserver (e.g. from ArmarXSimulator)");
1015 "RemoteHandlesDeletionTimeout",
1017 "The timeout (in ms) before a remote handle deletes the managed object after the use count "
1018 "reached 0. This time can be used by a client to increment the count again (may be "
1019 "required when transmitting remote handles)");
1022 "If this application crashes (segmentation fault) qtcreator will "
1023 "attach to this process and start the debugger.");
1025 "ThreadPoolSize", 1,
"Size of the ArmarX ThreadPool that is always running.");
1029 "Libraries to load at start up of the application. Must be enabled by the Application with "
1030 "enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...");
1032 "SecondsStartupDelay",
1034 "The startup will be delayed by this number of seconds (useful for debugging)");
The ApplicationNetworkStats class implements the Ice::Instrumentation::CommunicatorObserver interface...
Application property definition container.
ApplicationPropertyDefinitions(std::string prefix)
static void HandlerInterrupt(int sig)
handlerInterrupt handles interrupt signals sent to the application (Linux)
void loadDefaultConfig(int argc, char *argv[], const Ice::InitializationData &initData)
int run(int argc, char *argv[]) override
Ice::Application replacement for the main function.
void icePropertiesUpdated(const std::set< std::string > &changedProperties) override
This method is called when new Properties are set via setIceProperties().
std::vector< std::string > getArmarXPackageNames()
getDefaultPackageNames returns the value of the ArmarX.DefaultPackages property It splits the string ...
int doMain(int argc, char *argv[], const Ice::InitializationData &initData, Ice::Int i) override
Ice::Application::doMain() is called by Ice::Application::main() and does setup of Ice::Communicator ...
void updateIceProperties(const Ice::PropertyDict &properties) override
const std::vector< std::string > & getCommandLineArguments() const
virtual std::string getDomainName()
Retrieve the domain name used for property parsing.
static void LoadDefaultConfig(Ice::PropertiesPtr properties)
static void HandlerFault(int sig)
handlerFault handles signals sendt to the application such as SIGSEGF or SIGABRT (Linux)
std::string getName() const
Retrieve name of the application.
void showHelp(ApplicationOptions::Options &options)
Print help onto the screen or into a file.
ArmarXManagerPtr getArmarXManager()
const ThreadPoolPtr & getThreadPool() const
void setName(const std::string &name)
Set name of the application.
static void setInstance(ApplicationPtr const &inst)
void loadDependentProjectDatapaths()
PropertyDefinitionsPtr createPropertyDefinitions() override
void registerDataPathsFromDependencies(std::string dependencies)
static ApplicationPtr getInstance()
Retrieve shared pointer to the application object.
bool getForbidThreadCreation() const
void enableLibLoading(bool enable=true)
static const std::string & GetProjectName()
static const std::string ArmarXUserConfigDirEnvVar
void interruptCallback(int signal) override
Cleans up connections with IceStorm before terminating the app.
virtual void setup(const ManagedIceObjectRegistryInterfacePtr ®istry, Ice::PropertiesPtr properties)=0
Setup method to be implemented by user applications.
static Ice::StringSeq GetDefaultsPaths()
void storeCommandLineArguments(int argc, char *argv[])
void setForbidThreadCreation(bool value)
Ice::PropertiesPtr parseOptionsMergeProperties(int argc, char *argv[])
Parse options given on the commandline and merge them into the regular properties.
static std::string GetArmarXConfigDefaultPath(bool envVarExpanded=true)
static const Ice::StringSeq & GetProjectDependencies()
bool isPackageAutoDiscoveryEnabled()
Application()
Application initalizes the Ice::Application base class.
void setIceProperties(Ice::PropertiesPtr properties) override
Overrides PropertyUser::setIceProperties() which is called internally.
virtual int exec(const ArmarXManagerPtr &armarXManager)
Exec method is the main process of the application.
static std::string GetVersion()
static void addDataPaths(const std::string &dataPathList)
Handles help and documentation generation but does not provide Ice functionality.
Main class of an ArmarX process.
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
bool packageFound() const
Returns whether or not this package was found with cmake.
static std::vector< std::string > FindAllArmarXSourcePackages()
std::string getIncludePaths() const
Returns the include paths separated by semi-colons.
void setUnloadOnDestruct(bool unload)
void load(std::filesystem::path libPath)
Loads a shared library from the specified path.
static std::string GetSharedLibraryFileExtension()
static Ice::PropertiesPtr create(const Ice::PropertiesPtr &iceProperties=nullptr)
static std::string CreateBackTrace(int linesToSkip=1)
static void SetLoggingGroup(const std::string &loggingGroup)
static void SetSendLoggingActivated(bool activated=true)
static void SetLoggingActivated(bool activated=true, bool showMessage=true)
setLoggingActivated() is used to activate or disable the logging facilities in the whole application
PropertyDefinitionContainer(const std::string &prefix)
std::string prefix
Prefix of the properties such as namespace, domain, component name, etc.
PropertyDefinition< PropertyType > & defineOptionalProperty(const std::string &name, PropertyType defaultValue, const std::string &description="", PropertyDefinitionBase::PropertyConstness constness=PropertyDefinitionBase::eConstant)
bool removeQuotes() const
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
PropertyDefinitionsPtr getPropertyDefinitions()
Returns the component's property definition container.
bool hasProperty(const std::string &name)
virtual void updateIceProperties(const std::map< std::string, std::string > &changes)
virtual void setIceProperties(Ice::PropertiesPtr properties)
Sets the Ice properties.
Property< PropertyType > getProperty(const std::string &name)
Property creation and retrieval.
static std::string expandVariables(const std::string &value)
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_FATAL_S
The logging level for unexpected behaviour, that will lead to a seriously malfunctioning program and ...
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_VERBOSE
The logging level for verbose information.
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_ON_SCOPE_EXIT
Executes given code when the enclosing scope is left.
::IceInternal::Handle<::Ice::Properties > PropertiesPtr
Options parseHelpOptions(Ice::PropertiesPtr properties, int argc, char *argv[])
Parse the help options.
Ice::PropertiesPtr mergeProperties(Ice::PropertiesPtr properties, int argc, char *argv[])
Merge command line options into properties.
void showHelp(ApplicationPtr application, ArmarXDummyManagerPtr dummyManager, Options options, Ice::PropertiesPtr properties, std::ostream &out=std::cout)
Prints help according to the format selection in options.
This file offers overloads of toIce() and fromIce() functions for STL container types.
IceUtil::Handle< ArmarXManager > ArmarXManagerPtr
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceUtil::Handle< Application > ApplicationPtr
std::shared_ptr< ThreadPool > ThreadPoolPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
bool Contains(const ContainerType &container, const ElementType &searchElement)
IceUtil::Handle< ArmarXDummyManager > ArmarXDummyManagerPtr
Stucture containing the parsed options of the application.