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;
181 s <<
"qtcreator -debug " << getpid();
183 res = system(s.str().c_str());
200Application::loadLibrariesFromProperties()
203 if (!loadLibString.empty())
205 if (!libLoadingEnabled)
207 throw LocalException(
"Loading of dynamic libraries is not enabled in this application. "
208 "The Application needs to call enableLibLoading()");
210 auto entries =
armarx::Split(loadLibString,
";",
true,
true);
211 for (
auto& entry : entries)
215 std::filesystem::path path;
222 auto elements =
Split(entry,
":");
225 CMakePackageFinder p(elements.at(0));
229 std::string libFileName =
"lib" + elements.at(1) +
"." +
233 std::filesystem::path testPath(libDir);
234 testPath /= libFileName;
235 if (std::filesystem::exists(testPath))
245 std::string libFileName =
"lib" + elements.at(0) +
"_" + elements.at(1) +
250 std::filesystem::path testPath(libDir);
251 testPath /= libFileName;
252 if (std::filesystem::exists(testPath))
263 <<
"' in any of the following paths: " << p.getLibraryPaths();
284 return forbidThreadCreation;
290 forbidThreadCreation = value;
291 if (forbidThreadCreation)
293 ARMARX_INFO <<
"Thread creation with RunningTask and PeriodicTask is now forbidden in this "
298 ARMARX_INFO <<
"Thread creation with RunningTask and PeriodicTask is now allowed again in "
306 this->libLoadingEnabled = enable;
313 <<
"Command line arguments were already set: " <<
VAROUT(commandLineArguments);
314 commandLineArguments.reserve(argc);
315 for (
int i = 0; i < argc; ++i)
317 commandLineArguments.emplace_back(argv[i]);
321const std::vector<std::string>&
324 return commandLineArguments;
344 std::unique_lock lock(instanceMutex);
352 std::unique_lock lock(instanceMutex);
365 armarXManager->setComponentIceProperties(properties);
377 armarXManager->updateComponentIceProperties(properties);
386 if (changedProperties.count(
"DisableLogging") &&
393 if (changedProperties.count(
"EnableProfiling"))
397 if (changedProperties.count(
"Verbosity"))
399 armarXManager->setGlobalMinimumLoggingLevel(
448 std::cout <<
"Version: " <<
GetVersion() << std::endl;
460 const Ice::PropertyDict& env_props =
463 for (
const auto& [name, value] : env_props)
465 const std::string short_name = name.substr(4);
469 ARMARX_INFO <<
"Setting environment variable '" << short_name <<
"' to value '" << envVarResolved
471 setenv(short_name.c_str(), envVarResolved.c_str(), 1);
478 ARMARX_INFO <<
"startup delay: " << delay <<
" seconds";
479 std::this_thread::sleep_for(std::chrono::seconds{delay});
497 std::streambuf* cout_sbuf =
nullptr;
498 std::streambuf* cerr_sbuf =
nullptr;
501 cout_sbuf = std::cout.rdbuf();
502 cerr_sbuf = std::cerr.rdbuf();
503 std::cout.rdbuf(&buf);
504 std::cerr.rdbuf(&errbuf);
511 std::cout.rdbuf(cout_sbuf);
512 std::cerr.rdbuf(cerr_sbuf);
516 int result = EXIT_SUCCESS;
522 armarXManager =
new ArmarXManager(applicationName, communicator());
524 catch (Ice::ConnectFailedException&)
538 callbackOnInterrupt();
542 if (applicationNetworkStats)
544 ProfilerListenerPrx profilerTopic =
545 armarXManager->getIceManager()->getTopic<ProfilerListenerPrx>(
546 armarx::Profiler::PROFILER_TOPIC_NAME);
547 applicationNetworkStats->start(profilerTopic, applicationName);
550 loadLibrariesFromProperties();
555 setup(armarXManager, properties);
560 armarXManager->shutdown();
564 result =
exec(armarXManager);
570 shutdownThread->join();
583 armarXManager->waitForShutdown();
598 std::string configFiles = communicator()->getProperties()->getProperty(
"ArmarX.Config");
604 if (!configFiles.empty() && configFiles.compare(
"1") != 0)
606 std::vector<std::string> configFileList = simox::alg::split(configFiles,
",");
608 for (std::string configFile : configFileList)
610 if (!configFile.empty())
612 properties->load(configFile);
635 std::ofstream out(options.
outfile);
645 std::cout <<
"Could not write to file " << options.
outfile << std::endl;
659 this->applicationName = name;
665 return applicationName;
672 if (applicationNetworkStats)
674 applicationNetworkStats->stopTask();
677 shutdownThread.reset(
new std::thread{[
this]
680 this->armarXManager->shutdown();
687 IceUtil::Time start = IceUtil::Time::now();
689 dependencies = simox::alg::replace_all(dependencies,
"\"",
"");
690 Ice::StringSeq resultList = simox::alg::split(dependencies,
"/");
692 for (
size_t i = 0; i < resultList.size(); i++)
702 ARMARX_INFO_S <<
"loading took " << (IceUtil::Time::now() - start).toMilliSeconds();
708 const std::string autodiscoverPropertyName =
"AutodiscoverPackages";
712 ARMARX_VERBOSE <<
"`" << autodiscoverPropertyName <<
"` property available.";
719std::vector<std::string>
733 result.insert(result.end(), additional.begin(), additional.end());
741 char* env_armarx_workspace = getenv(
"ARMARX_WORKSPACE");
742 char* env_armarx_default_config_dir_name = getenv(
"ARMARX_CONFIG_DIR_NAME");
744 std::filesystem::path armarx_workspace;
745 std::filesystem::path armarx_config_dir;
747 if (env_armarx_workspace)
749 armarx_workspace = std::filesystem::path(env_armarx_workspace);
753 char* home = getenv(
"HOME");
757 armarx_workspace = std::filesystem::path(home);
761 armarx_workspace =
"~/";
765 if (env_armarx_default_config_dir_name)
767 armarx_config_dir = std::filesystem::path(env_armarx_default_config_dir_name);
771 if (env_armarx_workspace)
773 armarx_config_dir =
"armarx_config";
778 armarx_config_dir =
".armarx";
784 return (armarx_workspace / armarx_config_dir).string();
788 if (env_armarx_workspace)
790 return "${ARMARX_WORKSPACE}/" + armarx_config_dir.string();
795 return "${HOME}/" + armarx_config_dir.string();
803 return armarXManager;
811 Ice::InitializationData id(initData);
816 if (
id.properties->getProperty(
"Ice.Admin.InstanceName").empty())
818 id.properties->setProperty(
"Ice.Admin.InstanceName", this->
getName());
820 if (
id.properties->getProperty(
"Ice.Admin.Endpoints").empty())
822 id.properties->setProperty(
"Ice.Admin.Endpoints",
"tcp -h 127.0.0.1");
825 if (initData.properties->getProperty(
"ArmarX.NetworkStats") ==
"1")
828 id.observer = applicationNetworkStats;
830 const auto oldFacets = initData.properties->getPropertyAsList(
"Ice.Admin.Facets");
831 if (oldFacets.empty())
833 initData.properties->setProperty(
"Ice.Admin.Facets",
"Metrics");
835 else if (std::find(oldFacets.begin(), oldFacets.end(),
"Metrics") == oldFacets.end())
837 std::stringstream
str;
839 for (
const auto& facet : oldFacets)
843 initData.properties->setProperty(
"Ice.Admin.Facets",
str.str());
845 initData.properties->setProperty(
"IceMX.Metrics.NetworkStats.GroupBy",
"none");
848 return Ice::Application::doMain(argc, argv,
id, i);
854 const std::string configFileName =
"default.cfg";
855 const std::string generatedConfigFileName =
"default.generated.cfg";
856 Ice::StringSeq defaultsPaths;
858 std::filesystem::path absBasePath;
861 absBasePath = defaultsPathVar;
867 defaultsPaths.push_back((absBasePath / configFileName).
string());
868 defaultsPaths.push_back((absBasePath / generatedConfigFileName).
string());
869 return defaultsPaths;
884 for (std::string path : defaultsPath)
890 Ice::PropertyDict defaultCfg = p->getPropertiesForPrefix(
"");
893 for (
auto e : defaultCfg)
895 if (properties->getProperty(e.first).empty())
897 properties->setProperty(e.first, e.second);
901 catch (Ice::FileException& e)
917 return ProjectDependendencies;
929 std::string dependenciesConfig =
getIceProperties()->getProperty(
"ArmarX.DependenciesConfig");
931 if (!dependenciesConfig.empty())
933 if (std::filesystem::exists(dependenciesConfig))
936 prop->load(dependenciesConfig);
938 ProjectName = prop->getProperty(
"ArmarX.ProjectName");
939 std::string dependencies = prop->getProperty(
"ArmarX.ProjectDependencies");
940 ProjectDependendencies = simox::alg::split(dependencies,
";");
956 "Config",
"",
"Comma-separated list of configuration files ");
958 "DependenciesConfig",
959 "./config/dependencies.cfg",
960 "Path to the (usually generated) config file containing all data paths of all dependent "
961 "projects. This property usually does not need to be edited.");
969 "RobotSkillTemplates",
975 "List of ArmarX packages which are accessible by default. Comma separated List. If you "
976 "want to add your own packages and use all default ArmarX packages, use the property "
977 "'AdditionalPackages'.");
979 "AdditionalPackages",
981 "List of additional ArmarX packages which should be in the list of default packages. If "
982 "you have custom packages, which should be found by the gui or other apps, specify them "
983 "here. Comma separated List.");
986 "AutodiscoverPackages",
988 "If enabled, will discover all ArmarX packages based on the environment variables. "
989 "Otherwise, the `DefaultPackages` and `AdditionalPackages` properties are used.");
995 "Turn logging off in whole application",
1000 "Global logging level for whole application",
1006 "The logging group is transmitted with every ArmarX log message over Ice in order to group "
1007 "the message in the GUI.");
1011 "DataPath",
"",
"Semicolon-separated search list for data files");
1016 std::string(
"Path for cache files. If relative path AND env. variable ") +
1018 " is set, the cache path will be made relative to " +
1020 ". Otherwise if relative it will be relative to the default ArmarX config dir (" +
1025 "Enable profiling of CPU load produced by this application",
1029 "RedirectStdout",
true,
"Redirect std::cout and std::cerr to ArmarXLog");
1034 "Suffix appended to all topic names for outgoing topics. This is mainly used to direct all "
1035 "topics to another name for TopicReplaying purposes.");
1038 "UseTimeServer",
false,
"Enable using a global Timeserver (e.g. from ArmarXSimulator)");
1041 "RemoteHandlesDeletionTimeout",
1043 "The timeout (in ms) before a remote handle deletes the managed object after the use count "
1044 "reached 0. This time can be used by a client to increment the count again (may be "
1045 "required when transmitting remote handles)");
1048 "If this application crashes (segmentation fault) qtcreator will "
1049 "attach to this process and start the debugger.");
1051 "ThreadPoolSize", 1,
"Size of the ArmarX ThreadPool that is always running.");
1055 "Libraries to load at start up of the application. Must be enabled by the Application with "
1056 "enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...");
1058 "SecondsStartupDelay",
1060 "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.