Application.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore::core
19  * @author Nils Adermann (naderman at naderman dot de)
20  * @author Kai Welke (welke at kit dot edu)
21  * @author Jan Issac (jan dot issac at gmail dot com)
22  * @author Mirko Waechter (waechter at kit dot edu)
23  * @author Manfred Kroehnert (manfred dot kroehnert at kit dot edu)
24  * @date 2010
25  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
26  * GNU General Public License
27  */
28 
29 #include "Application.h"
30 
31 #include <stddef.h> // for size_t
32 #include <stdlib.h> // for NULL, getenv, system, exit, etc
33 
34 #include <filesystem>
35 #include <fstream>
36 #include <iostream> // for operator<<, ostream, etc
37 #include <sstream> // for basic_stringbuf<>::int_type, etc
38 #include <thread>
39 #include <thread> // for thread
40 #include <utility> // for pair, move
41 
42 #include <unistd.h> // for getpid
43 
44 #include <Ice/Communicator.h> // for Communicator, etc
45 #include <Ice/Initialize.h> // for InitializationData
46 #include <Ice/LocalException.h> // for FileException, etc
47 #include <Ice/NativePropertiesAdmin.h>
48 #include <Ice/ObjectF.h> // for upCast
49 #include <Ice/Process.h> // for ProcessPtr, Process
50 #include <Ice/Properties.h> // for Properties, PropertiesPtr
51 #include <Ice/Properties.h>
52 #include <Ice/PropertiesAdmin.h> // for PropertyDict
53 #include <Ice/PropertiesAdmin.h>
54 #include <IceUtil/Time.h> // for Time
55 
56 #include <SimoxUtility/algorithm/string/string_tools.h>
57 
58 #include "ArmarXCore/core/IceManager.h" // for IceManager
69 #include "ArmarXCore/core/logging/LogSender.h" // for LogSender
70 #include "ArmarXCore/core/logging/Logging.h" // for ARMARX_INFO_S, etc
71 #include "ArmarXCore/interface/core/Log.h" // for MessageType, etc
72 #include "ArmarXCore/interface/core/Profiler.h"
76 
77 #include "../logging/ArmarXLogBuf.h" // for ArmarXLogBuf
78 #include "ApplicationNetworkStats.h" // for ApplicationNetworkStatsPtr
79 #include "ApplicationOptions.h" // for Options, showHelp, etc
80 #include "ApplicationProcessFacet.h" // for ArmarXManagerPtr, etc
81 #include "properties/IceProperties.h" // for IceProperties
82 
83 #ifndef WIN32
84 #include <signal.h> // for signal, SIGABRT, SIGSEGV, etc
85 
86 #include <cstdio>
87 
88 #include <ArmarXCore/core/util/OnScopeExit.h> // for ARMARX_ON_SCOPE_EXIT
89 
90 #include <execinfo.h>
91 #endif
92 
93 #include <stdlib.h>
94 
95 
96 using namespace armarx;
97 
98 // static members for the one application instance (maybe not required anymore???)
99 std::mutex Application::instanceMutex;
100 ApplicationPtr Application::instance;
101 Ice::StringSeq Application::ProjectDependendencies;
102 std::string Application::ProjectName;
103 const std::string Application::ArmarXUserConfigDirEnvVar = "ARMARX_CONFIG_DIR";
104 std::string errormsg = "Segmentation fault - Backtrace: \n";
105 bool crashed = false;
106 
107 
108 void
110 {
111  if (crashed)
112  {
113  return;
114  }
115  crashed = true;
116 
117  // dont allocate memory in segfault
118  if (sig == SIGSEGV)
119  {
120  std::array<void*, 20> array;
121  size_t size;
122  size = backtrace(array.data(), 20);
123 
124 #pragma GCC diagnostic push
125 #pragma GCC diagnostic ignored "-Wunused-result"
126  write(STDERR_FILENO, errormsg.data(), errormsg.size());
127 #pragma GCC diagnostic pop
128  backtrace_symbols_fd(array.data(), size, STDERR_FILENO);
129  exit(EXIT_FAILURE);
130  }
131  // print out all the frames to stderr
132  try {
133  std::stringstream str;
134 
135  if (sig == SIGABRT) {
136  str << "Error: Abort\nBacktrace:\n";
137  } else {
138  str << "Error: signal " << sig;
139  }
140 
141  ARMARX_FATAL_S << str.str() << "\nBacktrace:\n" << LogSender::CreateBackTrace();
142  if ((sig == SIGSEGV || sig == SIGABRT) && Application::getInstance() &&
143  Application::getInstance()->getProperty<bool>("StartDebuggerOnCrash").getValue()) {
144  std::stringstream s;
145  int res;
146  // res = system("which qtcreator");
147  // res = WEXITSTATUS(res);
148  // if (res == EXIT_SUCCESS)
149  {
150  s << "qtcreator -debug " << getpid();
151  ARMARX_IMPORTANT << s.str();
152  res = system(s.str().c_str());
153  res++; // suppress warning
154  }
155  // else
156  // {
157  // ARMARX_INFO_S << "Could not find qtcreator";
158  // }
159  }
160  } catch (...)
161  {
162  // do nothing
163  }
164  exit(EXIT_FAILURE);
165 }
166 
167 void
168 Application::loadLibrariesFromProperties()
169 {
170  auto loadLibString = getProperty<std::string>("LoadLibraries").getValue();
171  if (!loadLibString.empty())
172  {
173  if (!libLoadingEnabled)
174  {
175  throw LocalException("Loading of dynamic libraries is not enabled in this application. "
176  "The Application needs to call enableLibLoading()");
177  }
178  auto entries = armarx::Split(loadLibString, ";", true, true);
179  for (auto& entry : entries)
180  {
181  try
182  {
183  std::filesystem::path path;
184  if (armarx::Contains(entry, "/"))
185  {
186  path = entry;
187  }
188  else
189  {
190  auto elements = Split(entry, ":");
191  ARMARX_CHECK_EQUAL(elements.size(), 2);
192  std::string libFileName = "lib" + elements.at(1) + "." +
194  CMakePackageFinder p(elements.at(0));
195  for (auto& libDir : armarx::Split(p.getLibraryPaths(), ";"))
196  {
197  std::filesystem::path testPath(libDir);
198  testPath /= libFileName;
199  if (std::filesystem::exists(testPath))
200  {
201  path = testPath;
202  break;
203  }
204  }
205  if (path.empty())
206  {
207  ARMARX_ERROR << "Could find library '" << libFileName
208  << "' in any of the following paths: " << p.getLibraryPaths();
209  continue;
210  }
211  }
212  ARMARX_CHECK_EXPRESSION(!path.empty());
213  DynamicLibrary lib;
214  lib.setUnloadOnDestruct(false);
215  ARMARX_VERBOSE << "Loading library " << path.string();
216  lib.load(path);
217  }
218  catch (...)
219  {
221  }
222  }
223  }
224 }
225 
226 bool
228 {
229  return forbidThreadCreation;
230 }
231 
232 void
234 {
235  forbidThreadCreation = value;
236  if (forbidThreadCreation)
237  {
238  ARMARX_INFO << "Thread creation with RunningTask and PeriodicTask is now forbidden in this "
239  "process.";
240  }
241  else
242  {
243  ARMARX_INFO << "Thread creation with RunningTask and PeriodicTask is now allowed again in "
244  "this process.";
245  }
246 }
247 
248 void
250 {
251  this->libLoadingEnabled = enable;
252 }
253 
254 void
256 {
257  ARMARX_CHECK_EXPRESSION(commandLineArguments.empty())
258  << "Command line arguments were already set: " << VAROUT(commandLineArguments);
259  commandLineArguments.reserve(argc);
260  for (int i = 0; i < argc; ++i)
261  {
262  commandLineArguments.emplace_back(argv[i]);
263  }
264 }
265 
266 const std::vector<std::string>&
268 {
269  return commandLineArguments;
270 }
271 
272 void
274 {
276  {
277  Application::getInstance()->interruptCallback(sig);
278  }
279 }
280 
281 
282 // main entry point of Ice::Application
284 {
285 }
286 
287 
290 {
291  std::unique_lock lock(instanceMutex);
292 
293  return instance;
294 }
295 
296 void
298 {
299  std::unique_lock lock(instanceMutex);
300 
301  instance = inst;
302 }
303 
304 
305 void
307 {
308  // call base class method
309  PropertyUser::setIceProperties(properties);
310  // set the properties of all components
311  if (armarXManager)
312  {
313  armarXManager->setComponentIceProperties(properties);
314  }
315 }
316 
317 
318 void
319 Application::updateIceProperties(const Ice::PropertyDict& properties)
320 {
321  // call base class method
323  // update the properties of all components
324  if (armarXManager)
325  {
326  armarXManager->updateComponentIceProperties(properties);
327  }
328 }
329 
330 
331 void
332 Application::icePropertiesUpdated(const std::set<std::string>& changedProperties)
333 {
334  if (armarXManager)
335  {
336  if (changedProperties.count("DisableLogging") &&
337  getProperty<bool>("DisableLogging").isSet())
338  {
339  // ARMARX_INFO << "Logging disabled: " << getProperty<bool>("DisableLogging").getValue();
340  armarXManager->enableLogging(!getProperty<bool>("DisableLogging").getValue());
341  }
342 
343  if (changedProperties.count("EnableProfiling"))
344  {
345  armarXManager->enableProfiling(getProperty<bool>("EnableProfiling").getValue());
346  }
347  if (changedProperties.count("Verbosity"))
348  {
349  armarXManager->setGlobalMinimumLoggingLevel(
350  getProperty<MessageTypeT>("Verbosity").getValue());
351  }
352  }
353 }
354 
355 const ThreadPoolPtr&
357 {
358  return threadPool;
359 }
360 
361 
362 int
363 Application::run(int argc, char* argv[])
364 {
365 #ifndef WIN32
366  // register signal handler
367  signal(SIGILL, Application::HandlerFault);
368  signal(SIGSEGV, Application::HandlerFault);
369  signal(SIGABRT, Application::HandlerFault);
370 
371  signal(SIGHUP, Application::HandlerInterrupt);
372  signal(SIGINT, Application::HandlerInterrupt);
373  signal(SIGTERM, Application::HandlerInterrupt);
374 #endif
375 
376  ARMARX_TRACE;
377 
378  // parse options and merge these with properties passed via Ice.Config
379  Ice::PropertiesPtr properties = parseOptionsMergeProperties(argc, argv);
380 
381  // parse help options
382  ARMARX_TRACE;
383 
385  ApplicationOptions::parseHelpOptions(properties, argc, argv);
386 
387  if (options.error)
388  {
389  // error in options
390  return EXIT_FAILURE;
391  }
392  else if (options.showHelp) // display help
393  {
394  showHelp(options);
395  return EXIT_SUCCESS;
396  }
397  else if (options.showVersion)
398  {
399  std::cout << "Version: " << GetVersion() << std::endl;
400  return EXIT_SUCCESS;
401  }
402 
403  ARMARX_TRACE;
404 
405  setIceProperties(properties);
406 
407  // Override environment variables if set.
408  {
409  ARMARX_TRACE;
410 
411  const Ice::PropertyDict& env_props =
412  getPropertyDefinitions()->getProperties()->getPropertiesForPrefix("env");
413 
414  for (const auto& [name, value] : env_props)
415  {
416  const std::string short_name = name.substr(4); // Cut "env.".
417  ARMARX_INFO << "Setting environment variable '" << short_name << "' to value '" << value
418  << "'.";
419  setenv(short_name.c_str(), value.c_str(), 1);
420  }
421  }
422 
423  if (getProperty<std::uint64_t>("SecondsStartupDelay").isSet())
424  {
425  const auto delay = getProperty<std::uint64_t>("SecondsStartupDelay").getValue();
426  ARMARX_INFO << "startup delay: " << delay << " seconds";
427  std::this_thread::sleep_for(std::chrono::seconds{delay});
428  }
429  else
430  {
431  ARMARX_DEBUG << "startup delay is not set";
432  }
433 
434  // extract application name
435  if (getProperty<std::string>("ApplicationName").isSet())
436  {
437  applicationName = getProperty<std::string>("ApplicationName").getValue();
438  }
439  LogSender::SetLoggingGroup(getProperty<std::string>("LoggingGroup").getValue());
440 
441  // Redirect std::cout and std::cerr
442  const bool redirectStdout = getProperty<bool>("RedirectStdout").getValue();
443  ArmarXLogBuf buf("std::cout", MessageTypeT::INFO, false);
444  ArmarXLogBuf errbuf("std::cerr", MessageTypeT::WARN, true);
445  std::streambuf* cout_sbuf = nullptr;
446  std::streambuf* cerr_sbuf = nullptr;
447  if (redirectStdout)
448  {
449  cout_sbuf = std::cout.rdbuf();
450  cerr_sbuf = std::cerr.rdbuf();
451  std::cout.rdbuf(&buf);
452  std::cerr.rdbuf(&errbuf);
453  }
455  {
456  //reset std::cout and std::cerr to original stream
457  if (redirectStdout)
458  {
459  std::cout.rdbuf(cout_sbuf);
460  std::cerr.rdbuf(cerr_sbuf);
461  }
462  };
463 
464  int result = EXIT_SUCCESS;
465 
466  threadPool.reset(new ThreadPool(getProperty<unsigned int>("ThreadPoolSize").getValue()));
467  // create the ArmarXManager and set its properties
468  try
469  {
470  armarXManager = new ArmarXManager(applicationName, communicator());
471  }
472  catch (Ice::ConnectFailedException&)
473  {
474  return EXIT_FAILURE;
475  }
476 
477  armarXManager->setDataPaths(getProperty<std::string>("DataPath").getValue());
478 
479  // set the properties again, since the armarx manager is now available
480  setIceProperties(properties);
481 
483 
484 #ifdef WIN32
485  // register interrupt handler
486  callbackOnInterrupt();
487 #endif
488 
489 
490  if (applicationNetworkStats)
491  {
492  ProfilerListenerPrx profilerTopic =
493  armarXManager->getIceManager()->getTopic<ProfilerListenerPrx>(
494  armarx::Profiler::PROFILER_TOPIC_NAME);
495  applicationNetworkStats->start(profilerTopic, applicationName);
496  }
497 
498  loadLibrariesFromProperties();
499 
500  try
501  {
502  // calls virtual setup in order to allow subclass to add components to the application
503  setup(armarXManager, properties);
504  }
505  catch (...)
506  {
508  armarXManager->shutdown();
509  }
510 
511  // calls exec implementation
512  result = exec(armarXManager);
514 
515  if (shutdownThread)
516  {
517  ARMARX_VERBOSE << "joining shutdown thread!";
518  shutdownThread->join();
519  }
520  ARMARX_VERBOSE << "Application run finished";
521  return result;
522 }
523 
524 /*
525  * the default exec implementation. Exec is always blocking and waits for
526  * shutdown
527  */
528 int
529 Application::exec(const ArmarXManagerPtr& armarXManager)
530 {
531  armarXManager->waitForShutdown();
532 
533  return 0;
534 }
535 
536 
539 {
540  // parse options and merge these with properties passed via Ice.Config
541  // Here, use armarx::IceProperties instead of Ice::Properties
542  // to support property inheritance.
544  ApplicationOptions::mergeProperties(communicator()->getProperties()->clone(), argc, argv));
545 
546  // Load config files passed via ArmarX.Config
547  std::string configFiles = communicator()->getProperties()->getProperty("ArmarX.Config");
548 
549  PropertyDefinition<std::string>::removeQuotes(configFiles, configFiles);
550 
551  // if not set, size is zero
552  // if set with out value (== "1" as TRUE), size is one
553  if (!configFiles.empty() && configFiles.compare("1") != 0)
554  {
555  std::vector<std::string> configFileList = simox::alg::split(configFiles, ",");
556 
557  for (std::string configFile : configFileList)
558  {
559  if (!configFile.empty())
560  {
561  properties->load(configFile);
562  }
563  }
564  }
565  return properties;
566 }
567 
568 
569 void
571 {
572  // perform dummy setup to register ManagedIceObjects
573  ArmarXDummyManagerPtr dummyManager = new ArmarXDummyManager();
574 
575  LogSender::SetLoggingActivated(false, false);
576 
577  setup(dummyManager, getIceProperties());
578 
579  if (options.outfile.empty())
580  {
581  ApplicationOptions::showHelp(this, dummyManager, options, nullptr);
582  }
583  else
584  {
585  std::ofstream out(options.outfile);
586  if (out.is_open())
587  {
588  ApplicationOptions::showHelp(this, dummyManager, options, nullptr, out);
589  }
590  else
591  {
593  ApplicationOptions::showHelp(this, dummyManager, options, nullptr);
594 
595  std::cout << "Could not write to file " << options.outfile << std::endl;
596  }
597  }
598 }
599 
600 
601 std::string
603 {
604  return "ArmarX";
605 }
606 
607 void
608 Application::setName(const std::string& name)
609 {
610  this->applicationName = name;
611 }
612 
613 std::string
615 {
616  return applicationName;
617 }
618 
619 void
621 {
622  ARMARX_INFO_S << "Interrupt received: " << signal;
623  if (applicationNetworkStats)
624  {
625  applicationNetworkStats->stopTask();
626  }
627  if (!shutdownThread)
628  shutdownThread.reset(new std::thread{[this]
629  {
630  if (armarXManager)
631  this->armarXManager->shutdown();
632  }});
633 }
634 
635 void
637 {
638  IceUtil::Time start = IceUtil::Time::now();
639  ARMARX_INFO_S << "Deps: " << dependencies;
640  dependencies = simox::alg::replace_all(dependencies, "\"", "");
641  Ice::StringSeq resultList = simox::alg::split(dependencies, "/");
642 
643  for (size_t i = 0; i < resultList.size(); i++)
644  {
645  CMakePackageFinder pack(resultList[i]);
646 
647  if (pack.packageFound())
648  {
650  }
651  }
652 
653  ARMARX_INFO_S << "loading took " << (IceUtil::Time::now() - start).toMilliSeconds();
654 }
655 
657 {
658  if(hasProperty("AutodiscoverPackages"))
659  {
660  ARMARX_VERBOSE << "`AutodiscoverPackages` property available.";
661  return getProperty<bool>("AutodiscoverPackages").getValue();
662  }
663 
664  return false; // Property not available. Default: don't use autodiscovery
665 }
666 
667 std::vector<std::string>
669 {
671  {
672  ARMARX_VERBOSE << "ArmarX package autodiscovery activated.";
674  }
675 
676  ARMARX_VERBOSE << "ArmarX package autodiscovery not activated.";
677 
678  // legacy: use only those packages listed in the config file (e.g. default.cfg)
679  Ice::StringSeq result = getProperty<Ice::StringSeq>("DefaultPackages").getValue();
680  Ice::StringSeq additional = getProperty<Ice::StringSeq>("AdditionalPackages").getValue();
681  result.insert(result.end(), additional.begin(), additional.end());
682 
683  return result;
684 }
685 
686 std::string
688 {
689  char* env_armarx_workspace = getenv("ARMARX_WORKSPACE");
690  char* env_armarx_default_config_dir_name = getenv("ARMARX_CONFIG_DIR_NAME");
691 
692  std::filesystem::path armarx_workspace;
693  std::filesystem::path armarx_config_dir;
694 
695  if (env_armarx_workspace)
696  {
697  armarx_workspace = std::filesystem::path(env_armarx_workspace);
698  }
699  else
700  {
701  char* home = getenv("HOME");
702 
703  if (home)
704  {
705  armarx_workspace = std::filesystem::path(home);
706  }
707  else
708  {
709  armarx_workspace = "~/";
710  }
711  }
712 
713  if (env_armarx_default_config_dir_name)
714  {
715  armarx_config_dir = std::filesystem::path(env_armarx_default_config_dir_name);
716  }
717  else
718  {
719  if (env_armarx_workspace)
720  {
721  armarx_config_dir = "armarx_config";
722  }
723  // Legacy mode.
724  else
725  {
726  armarx_config_dir = ".armarx";
727  }
728  }
729 
730  if (envVarExpanded)
731  {
732  return (armarx_workspace / armarx_config_dir).string();
733  }
734  else
735  {
736  if (env_armarx_workspace)
737  {
738  return "${ARMARX_WORKSPACE}/" + armarx_config_dir.string();
739  }
740  // Legacy mode.
741  else
742  {
743  return "${HOME}/" + armarx_config_dir.string();
744  }
745  }
746 }
747 
750 {
751  return armarXManager;
752 }
753 
754 
755 int
756 Application::doMain(int argc, char* argv[], const Ice::InitializationData& initData, Ice::Int i)
757 {
758  // create copy of initData so the stats object can be added
759  // using const_cast leads to unexpected errors
760  Ice::InitializationData id(initData);
761  loadDefaultConfig(argc, argv, id);
762 
763  // enable the PropertyAdmin ObjectAdapter
764  // https://doc.zeroc.com/display/Ice35/The+Administrative+Object+Adapter
765  if (id.properties->getProperty("Ice.Admin.InstanceName").empty())
766  {
767  id.properties->setProperty("Ice.Admin.InstanceName", this->getName());
768  }
769  if (id.properties->getProperty("Ice.Admin.Endpoints").empty())
770  {
771  id.properties->setProperty("Ice.Admin.Endpoints", "tcp -h 127.0.0.1");
772  }
773 
774  if (initData.properties->getProperty("ArmarX.NetworkStats") == "1")
775  {
776  applicationNetworkStats = new ApplicationNetworkStats();
777  id.observer = applicationNetworkStats;
778 
779  const auto oldFacets = initData.properties->getPropertyAsList("Ice.Admin.Facets");
780  if (oldFacets.empty())
781  {
782  initData.properties->setProperty("Ice.Admin.Facets", "Metrics");
783  }
784  else if (std::find(oldFacets.begin(), oldFacets.end(), "Metrics") == oldFacets.end())
785  {
786  std::stringstream str;
787  str << "Metrics";
788  for (const auto& facet : oldFacets)
789  {
790  str << "," << facet;
791  }
792  initData.properties->setProperty("Ice.Admin.Facets", str.str());
793  }
794  initData.properties->setProperty("IceMX.Metrics.NetworkStats.GroupBy", "none");
795  }
796 
797  return Ice::Application::doMain(argc, argv, id, i);
798 }
799 
800 
801 Ice::StringSeq
803 {
804  const std::string configFileName = "default.cfg";
805  const std::string generatedConfigFileName = "default.generated.cfg";
806  Ice::StringSeq defaultsPaths;
807  char* defaultsPathVar = getenv(ArmarXUserConfigDirEnvVar.c_str());
808  std::filesystem::path absBasePath;
809  if (defaultsPathVar)
810  {
811  absBasePath = defaultsPathVar;
812  }
813  else
814  {
815  absBasePath = std::filesystem::path(GetArmarXConfigDefaultPath());
816  }
817  defaultsPaths.push_back((absBasePath / configFileName).string());
818  defaultsPaths.push_back((absBasePath / generatedConfigFileName).string());
819  return defaultsPaths;
820 }
821 
822 
823 void
824 Application::loadDefaultConfig(int argc, char* argv[], const Ice::InitializationData& initData)
825 {
826  LoadDefaultConfig(initData.properties);
827 }
828 
829 void
831 {
832  const Ice::StringSeq defaultsPath = GetDefaultsPaths();
834 
835  for (std::string path : defaultsPath)
836  {
837  try
838  {
839  p->load(path);
840 
841  Ice::PropertyDict defaultCfg = p->getPropertiesForPrefix("");
842 
843  // copy default config into current config (if values are not already there)
844  for (auto e : defaultCfg)
845  {
846  if (properties->getProperty(e.first).empty())
847  {
848  properties->setProperty(e.first, e.second);
849  }
850  }
851  }
852  catch (Ice::FileException& e)
853  {
854  ARMARX_WARNING_S << "Loading default config failed: " << e.what();
855  }
856  }
857 }
858 
859 
860 const std::string&
862 {
863  return ProjectName;
864 }
865 
866 
867 const Ice::StringSeq&
869 {
870  return ProjectDependendencies;
871 }
872 
873 
876 {
878 }
879 
880 
881 void
883 {
884  std::string dependenciesConfig = getIceProperties()->getProperty("ArmarX.DependenciesConfig");
885 
886  if (!dependenciesConfig.empty())
887  {
888  if (std::filesystem::exists(dependenciesConfig))
889  {
891  prop->load(dependenciesConfig);
892  ArmarXDataPath::addDataPaths(prop->getProperty("ArmarX.ProjectDatapath"));
893  ProjectName = prop->getProperty("ArmarX.ProjectName");
894  std::string dependencies = prop->getProperty("ArmarX.ProjectDependencies");
895  ProjectDependendencies = simox::alg::split(dependencies, ";");
896  }
897  else
898  {
899  /*
900  ARMARX_WARNING_S << "The given project datapath config file '" << datapathConfig << "', that this app depends on, could not be found. \
901  Relative paths to subprojects are not available. Set the property ArmarX.ProjectDatapath to empty, if you do not need the paths.";
902  */
903  }
904  }
905 }
906 
907 
910 {
911  defineOptionalProperty<std::string>(
912  "Config", "", "Comma-separated list of configuration files ");
913  defineOptionalProperty<std::string>(
914  "DependenciesConfig",
915  "./config/dependencies.cfg",
916  "Path to the (usually generated) config file containing all data paths of all dependent "
917  "projects. This property usually does not need to be edited.");
918  defineOptionalProperty<Ice::StringSeq>(
919  "DefaultPackages",
920  {"ArmarXCore",
921  "ArmarXGui",
922  "MemoryX",
923  "RobotAPI",
924  "RobotComponents",
925  "RobotSkillTemplates",
926  "ArmarXSimulation",
927  "VisionX",
928  "SpeechX",
929  "Armar3",
930  "Spoac"},
931  "List of ArmarX packages which are accessible by default. Comma separated List. If you "
932  "want to add your own packages and use all default ArmarX packages, use the property "
933  "'AdditionalPackages'.");
934  defineOptionalProperty<Ice::StringSeq>(
935  "AdditionalPackages",
936  {},
937  "List of additional ArmarX packages which should be in the list of default packages. If "
938  "you have custom packages, which should be found by the gui or other apps, specify them "
939  "here. Comma separated List.");
940 
941  defineOptionalProperty<bool>("AutodiscoverPackages", true, "If enabled, will discover all ArmarX packages based on the environment variables. Otherwise, the `DefaultPackages` and `AdditionalPackages` properties are used.");
942 
943  defineOptionalProperty<std::string>("ApplicationName", "", "Application name");
944 
945  defineOptionalProperty<bool>("DisableLogging",
946  false,
947  "Turn logging off in whole application",
949 
950  defineOptionalProperty<MessageTypeT>("Verbosity",
952  "Global logging level for whole application",
954 
955  defineOptionalProperty<std::string>(
956  "LoggingGroup",
957  "",
958  "The logging group is transmitted with every ArmarX log message over Ice in order to group "
959  "the message in the GUI.");
960 
961 
962  defineOptionalProperty<std::string>(
963  "DataPath", "", "Semicolon-separated search list for data files");
964 
965  defineOptionalProperty<std::string>(
966  "CachePath",
967  "mongo/.cache",
968  std::string("Path for cache files. If relative path AND env. variable ") +
970  " is set, the cache path will be made relative to " +
972  ". Otherwise if relative it will be relative to the default ArmarX config dir (" +
974 
975  defineOptionalProperty<bool>("EnableProfiling",
976  false,
977  "Enable profiling of CPU load produced by this application",
979 
980  defineOptionalProperty<bool>(
981  "RedirectStdout", true, "Redirect std::cout and std::cerr to ArmarXLog");
982 
983  defineOptionalProperty<std::string>(
984  "TopicSuffix",
985  "",
986  "Suffix appended to all topic names for outgoing topics. This is mainly used to direct all "
987  "topics to another name for TopicReplaying purposes.");
988 
989  defineOptionalProperty<bool>(
990  "UseTimeServer", false, "Enable using a global Timeserver (e.g. from ArmarXSimulator)");
991 
992  defineOptionalProperty<unsigned int>(
993  "RemoteHandlesDeletionTimeout",
994  3000,
995  "The timeout (in ms) before a remote handle deletes the managed object after the use count "
996  "reached 0. This time can be used by a client to increment the count again (may be "
997  "required when transmitting remote handles)");
998  defineOptionalProperty<bool>("StartDebuggerOnCrash",
999  false,
1000  "If this application crashes (segmentation fault) qtcreator will "
1001  "attach to this process and start the debugger.");
1002  defineOptionalProperty<unsigned int>(
1003  "ThreadPoolSize", 1, "Size of the ArmarX ThreadPool that is always running.");
1004  defineOptionalProperty<std::string>(
1005  "LoadLibraries",
1006  "",
1007  "Libraries to load at start up of the application. Must be enabled by the Application with "
1008  "enableLibLoading(). Format: PackageName:LibraryName;... or /absolute/path/to/library;...");
1009  defineOptionalProperty<std::uint64_t>(
1010  "SecondsStartupDelay",
1011  0,
1012  "The startup will be delayed by this number of seconds (useful for debugging)");
1013 }
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:180
armarx::Application::run
int run(int argc, char *argv[]) override
Ice::Application replacement for the main function.
Definition: Application.cpp:363
armarx::Application::GetProjectName
static const std::string & GetProjectName()
Definition: Application.cpp:861
armarx::Application::Application
Application()
Application initalizes the Ice::Application base class.
Definition: Application.cpp:283
str
std::string str(const T &t)
Definition: UserAssistedSegmenterGuiWidgetController.cpp:42
armarx::Application::getCommandLineArguments
const std::vector< std::string > & getCommandLineArguments() const
Definition: Application.cpp:267
armarx::ApplicationOptions::mergeProperties
Ice::PropertiesPtr mergeProperties(Ice::PropertiesPtr properties, int argc, char *argv[])
Merge command line options into properties.
Definition: ApplicationOptions.cpp:59
errormsg
std::string errormsg
Definition: Application.cpp:104
armarx::Application::exec
virtual int exec(const ArmarXManagerPtr &armarXManager)
Exec method is the main process of the application.
Definition: Application.cpp:529
armarx::MessageTypeT::WARN
@ WARN
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::CMakePackageFinder::packageFound
bool packageFound() const
Returns whether or not this package was found with cmake.
Definition: CMakePackageFinder.cpp:485
armarx::Application::setup
virtual void setup(const ManagedIceObjectRegistryInterfacePtr &registry, Ice::PropertiesPtr properties)=0
Setup method to be implemented by user applications.
OnScopeExit.h
armarx::Application::storeCommandLineArguments
void storeCommandLineArguments(int argc, char *argv[])
Definition: Application.cpp:255
ArmarXManager.h
armarx::MessageTypeT::INFO
@ INFO
armarx::Application::parseOptionsMergeProperties
Ice::PropertiesPtr parseOptionsMergeProperties(int argc, char *argv[])
Parse options given on the commandline and merge them into the regular properties.
Definition: Application.cpp:538
DynamicLibrary.h
armarx::CMakePackageFinder::FindAllArmarXSourcePackages
static std::vector< std::string > FindAllArmarXSourcePackages()
Definition: CMakePackageFinder.cpp:438
armarx::Contains
bool Contains(const ContainerType &container, const ElementType &searchElement)
Definition: algorithm.h:295
armarx::ThreadPool
The ThreadPool class.
Definition: ThreadPool.h:45
armarx::DynamicLibrary::load
void load(std::filesystem::path libPath)
Loads a shared library from the specified path.
Definition: DynamicLibrary.cpp:54
armarx::Application::HandlerFault
static void HandlerFault(int sig)
handlerFault handles signals sendt to the application such as SIGSEGF or SIGABRT (Linux)
Definition: Application.cpp:109
armarx::Application::createPropertyDefinitions
PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: Application.cpp:875
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:35
armarx::LogSender::SetSendLoggingActivated
static void SetSendLoggingActivated(bool activated=true)
Definition: LogSender.cpp:708
armarx::Application::GetDefaultsPaths
static Ice::StringSeq GetDefaultsPaths()
Definition: Application.cpp:802
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:53
armarx::Application::loadDefaultConfig
void loadDefaultConfig(int argc, char *argv[], const Ice::InitializationData &initData)
Definition: Application.cpp:824
armarx::ApplicationOptions::eHelpBrief
@ eHelpBrief
Definition: ApplicationOptions.h:64
armarx::ApplicationOptions::parseHelpOptions
Options parseHelpOptions(Ice::PropertiesPtr properties, int argc, char *argv[])
Parse the help options.
Definition: ApplicationOptions.cpp:68
armarx::LogSender::SetLoggingGroup
static void SetLoggingGroup(const std::string &loggingGroup)
Definition: LogSender.cpp:161
ARMARX_ON_SCOPE_EXIT
#define ARMARX_ON_SCOPE_EXIT
Executes given code when the enclosing scope is left.
Definition: OnScopeExit.h:112
armarx::Application::GetArmarXConfigDefaultPath
static std::string GetArmarXConfigDefaultPath(bool envVarExpanded=true)
Definition: Application.cpp:687
armarx::ApplicationOptions::Options::showHelp
bool showHelp
Definition: ApplicationOptions.h:78
armarx::DynamicLibrary::GetSharedLibraryFileExtension
static std::string GetSharedLibraryFileExtension()
Definition: DynamicLibrary.cpp:157
armarx::PropertyUser::hasProperty
bool hasProperty(const std::string &name)
Definition: PropertyUser.cpp:243
ApplicationOptions.h
armarx::Application::getArmarXManager
ArmarXManagerPtr getArmarXManager()
Definition: Application.cpp:749
armarx::ThreadPoolPtr
std::shared_ptr< ThreadPool > ThreadPoolPtr
Definition: Application.h:76
armarx::Application::HandlerInterrupt
static void HandlerInterrupt(int sig)
handlerInterrupt handles interrupt signals sent to the application (Linux)
Definition: Application.cpp:273
IceInternal::Handle< ::Ice::Properties >
armarx::ApplicationNetworkStats
The ApplicationNetworkStats class implements the Ice::Instrumentation::CommunicatorObserver interface...
Definition: ApplicationNetworkStats.h:51
armarx::Application::icePropertiesUpdated
void icePropertiesUpdated(const std::set< std::string > &changedProperties) override
This method is called when new Properties are set via setIceProperties().
Definition: Application.cpp:332
ArmarXDummyManager.h
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:69
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::Application::getDomainName
virtual std::string getDomainName()
Retrieve the domain name used for property parsing.
Definition: Application.cpp:602
Property.h
armarx::DynamicLibrary::setUnloadOnDestruct
void setUnloadOnDestruct(bool unload)
Definition: DynamicLibrary.cpp:142
armarx::Application::isPackageAutoDiscoveryEnabled
bool isPackageAutoDiscoveryEnabled()
Definition: Application.cpp:656
armarx::Application::setInstance
static void setInstance(ApplicationPtr const &inst)
Definition: Application.cpp:297
ManagedIceObject.h
ThreadPool.h
PropertyUser.h
armarx::ApplicationOptions::Options::format
OptionsFormat format
Definition: ApplicationOptions.h:82
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:177
armarx::ApplicationOptions::Options::showVersion
bool showVersion
Definition: ApplicationOptions.h:79
armarx::PropertyUser::updateIceProperties
virtual void updateIceProperties(const std::map< std::string, std::string > &changes)
Definition: PropertyUser.cpp:115
armarx::Application::getForbidThreadCreation
bool getForbidThreadCreation() const
Definition: Application.cpp:227
armarx::Application::registerDataPathsFromDependencies
void registerDataPathsFromDependencies(std::string dependencies)
Definition: Application.cpp:636
armarx::ApplicationPropertyDefinitions::ApplicationPropertyDefinitions
ApplicationPropertyDefinitions(std::string prefix)
Definition: Application.cpp:908
armarx::ApplicationOptions::Options
Stucture containing the parsed options of the application.
Definition: ApplicationOptions.h:76
IceManager.h
armarx::LogSender::CreateBackTrace
static std::string CreateBackTrace(int linesToSkip=1)
Definition: LogSender.cpp:508
armarx::IceProperties::create
static Ice::PropertiesPtr create(const Ice::PropertiesPtr &iceProperties=nullptr)
Definition: IceProperties.cpp:32
ApplicationNetworkStats.h
armarx::Application::getThreadPool
const ThreadPoolPtr & getThreadPool() const
Definition: Application.cpp:356
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::PropertyDefinitionContainer
PropertyDefinitionContainer.
Definition: PropertyDefinitionContainer.h:53
armarx::Application::getInstance
static ApplicationPtr getInstance()
Retrieve shared pointer to the application object.
Definition: Application.cpp:289
armarx::Application
Baseclass for all ArmarX applications.
Definition: Application.h:193
armarx::ApplicationPropertyDefinitions
Application property definition container.
Definition: Application.h:101
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:206
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::Application::getName
std::string getName() const
Retrieve name of the application.
Definition: Application.cpp:614
ExpressionException.h
CMakePackageFinder.h
Ice
Definition: DBTypes.cpp:64
armarx::Application::setIceProperties
void setIceProperties(Ice::PropertiesPtr properties) override
Overrides PropertyUser::setIceProperties() which is called internally.
Definition: Application.cpp:306
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
armarx::Application::LoadDefaultConfig
static void LoadDefaultConfig(Ice::PropertiesPtr properties)
Definition: Application.cpp:830
armarx::LogSender::SetLoggingActivated
static void SetLoggingActivated(bool activated=true, bool showMessage=true)
setLoggingActivated() is used to activate or disable the logging facilities in the whole application
Definition: LogSender.cpp:694
PropertyDefinition.hpp
armarx::ApplicationOptions::Options::error
bool error
Definition: ApplicationOptions.h:80
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::ArmarXDummyManager
Handles help and documentation generation but does not provide Ice functionality.
Definition: ArmarXDummyManager.h:52
armarx::ArmarXDataPath::addDataPaths
static void addDataPaths(const std::string &dataPathList)
Definition: ArmarXDataPath.cpp:559
armarx::PropertyDefinition::removeQuotes
bool removeQuotes() const
Definition: PropertyDefinition.hpp:266
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
IceUtil::Handle
Definition: forward_declarations.h:29
armarx::CMakePackageFinder::getIncludePaths
std::string getIncludePaths() const
Returns the include paths separated by semi-colons.
Definition: CMakePackageFinder.h:110
armarx::Application::getArmarXPackageNames
std::vector< std::string > getArmarXPackageNames()
getDefaultPackageNames returns the value of the ArmarX.DefaultPackages property It splits the string ...
Definition: Application.cpp:668
LogSender.h
crashed
bool crashed
Definition: Application.cpp:105
armarx::PropertyUser::getPropertyDefinitions
PropertyDefinitionsPtr getPropertyDefinitions()
Returns the component's property definition container.
Definition: PropertyUser.cpp:61
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:916
ARMARX_FATAL_S
#define ARMARX_FATAL_S
Definition: Logging.h:212
armarx::Application::GetVersion
static std::string GetVersion()
Definition: Application.h:234
armarx::aron::write
requires data::isWriter< WriterT > void write(WriterT &aron_w, const Eigen::Matrix< EigenT, rows, cols, options > &input, typename WriterT::ReturnType &ret, const armarx::aron::Path &aron_p=armarx::aron::Path())
Definition: eigen.h:130
armarx::Application::setForbidThreadCreation
void setForbidThreadCreation(bool value)
Definition: Application.cpp:233
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
armarx::PropertyUser::getIceProperties
Ice::PropertiesPtr getIceProperties() const
Returns the set of Ice properties.
Definition: PropertyUser.cpp:229
armarx::DynamicLibrary
The DynamicLibrary class provides a mechanism to load libraries at runtime.
Definition: DynamicLibrary.h:49
armarx::Application::enableLibLoading
void enableLibLoading(bool enable=true)
Definition: Application.cpp:249
Logging.h
armarx::ApplicationOptions::showHelp
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.
Definition: ApplicationOptions.cpp:169
armarx::ApplicationOptions::Options::outfile
std::string outfile
Definition: ApplicationOptions.h:81
ARMARX_CHECK_EQUAL
#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...
Definition: ExpressionException.h:130
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:141
ApplicationProcessFacet.h
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:34
IceProperties.h
armarx::ArmarXLogBuf
Definition: ArmarXLogBuf.h:33
armarx::Application::interruptCallback
void interruptCallback(int signal) override
Cleans up connections with IceStorm before terminating the app.
Definition: Application.cpp:620
ArmarXDataPath.h
armarx::PropertyDefinitionBase::eModifiable
@ eModifiable
Definition: PropertyDefinitionInterface.h:57
armarx::Application::ArmarXUserConfigDirEnvVar
static const std::string ArmarXUserConfigDirEnvVar
Definition: Application.h:296
armarx::Application::setName
void setName(const std::string &name)
Set name of the application.
Definition: Application.cpp:608
armarx::PropertyUser::setIceProperties
virtual void setIceProperties(Ice::PropertiesPtr properties)
Sets the Ice properties.
Definition: PropertyUser.cpp:89
armarx::Application::loadDependentProjectDatapaths
void loadDependentProjectDatapaths()
Definition: Application.cpp:882
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::ArmarXManager
Main class of an ArmarX process.
Definition: ArmarXManager.h:97
armarx::Application::updateIceProperties
void updateIceProperties(const Ice::PropertyDict &properties) override
Definition: Application.cpp:319
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::Application::GetProjectDependencies
static const Ice::StringSeq & GetProjectDependencies()
Definition: Application.cpp:868
PropertyDefinition.h
Application.h
armarx::split
std::vector< std::string > split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelpers.cpp:36
armarx::Application::doMain
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 ...
Definition: Application.cpp:756
armarx::Application::showHelp
void showHelp(ApplicationOptions::Options &options)
Print help onto the screen or into a file.
Definition: Application.cpp:570