knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
knowrob.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of KnowRob, please consult
3  * https://github.com/knowrob/knowrob for license details.
4  */
5 
6 #include <boost/python.hpp>
7 #include <knowrob/knowrob.h>
8 #include <knowrob/Logger.h>
9 #include <knowrob/ThreadPool.h>
10 #include <filesystem>
11 #include <iostream>
12 #include <boost/uuid/uuid_generators.hpp>
13 #include <boost/uuid/uuid_io.hpp>
14 #include "knowrob/integration/python/PythonError.h"
15 #include "knowrob/integration/prolog/PrologEngine.h"
16 
18 
20  IRIAtom::Tabled("http://knowrob.org/kb/knowrob.owl#Self");
21 
22 #define KNOWROB_EXECUTABLE_NAME "knowrob"
23 
24 static bool initialized = false;
25 
26 namespace knowrob {
27  // stores the name of the executable as provided in argv[0]
28  char *NAME_OF_EXECUTABLE = nullptr;
29 
31  if (NAME_OF_EXECUTABLE) {
33  } else {
34  static char noExec[] = "<no-executable>";
35  return noExec;
36  }
37  }
38 
39  void hashCombine(std::size_t &seed, const std::size_t &v) {
40  static const auto GOLDEN_RATIO_HASH = static_cast<size_t>(0x9e3779b9);
41  seed ^= v + GOLDEN_RATIO_HASH + (seed << 6) + (seed >> 2);
42  }
43 
44  void insertUnique(std::ostream &os) {
45  static boost::uuids::random_generator generator;
46  std::hash<std::string> str_hash;
47  os << std::setfill('0') << std::setw(8) << std::hex <<
48  str_hash(to_string(generator()));
49  }
50 
51  void InitPythonPath() {
52  std::stringstream pythonPath;
53  auto oldPath = std::getenv("PYTHONPATH");
54  if (oldPath) {
55  pythonPath << oldPath << ":";
56  }
57  pythonPath <<
58  (std::filesystem::path(KNOWROB_INSTALL_PREFIX) / "knowrob").string() << ":"
59  << KNOWROB_SOURCE_DIR << ":"
60  << KNOWROB_BUILD_DIR;
61  auto pythonPathStr = pythonPath.str();
62  KB_DEBUG("[KnowRob] using python path: {}", pythonPathStr);
63  setenv("PYTHONPATH", pythonPathStr.c_str(), 1);
64  }
65 
66  void InitKnowRob(char *nameOfExecutable, bool initPython) {
67  if (initialized) return;
68  // remember the program name.
69  // it is assumed here that argv stays valid during program execution.
70  knowrob::NAME_OF_EXECUTABLE = nameOfExecutable;
71  // set the locale to classic to avoid problems with number formatting,
72  // especially regarding use of dot or comma as decimal separator.
73  std::cout.imbue(std::locale::classic());
74  // configure the logger
76  // Allow Python to load modules KnowRob-related directories.
78  if (initPython) {
79  // Start a Python interpreter if it is not already initialized
80  Py_Initialize();
81  // Release the GIL which is acquired by Py_Initialize.
82  // If we do not release it, then no other thread would be able
83  // to run Python code.
84  // So instead we always need to acquire the GIL in C++ code sections
85  // that interact with Python (except of when the C++ code is launched
86  // within Python in which case it actually already has the GIL).
87  PyEval_SaveThread();
88  }
89  KB_INFO("[KnowRob] static initialization done.");
90  KB_DEBUG("[KnowRob] source directory: {}", KNOWROB_SOURCE_DIR);
91  KB_DEBUG("[KnowRob] install prefix: {}", KNOWROB_INSTALL_PREFIX);
92  KB_DEBUG("[KnowRob] build directory: {}", KNOWROB_BUILD_DIR);
93  initialized = true;
94  }
95 
96  void InitKnowRob(int argc, char **argv, bool initPython) {
97  if (argc > 0) {
98  InitKnowRob(argv[0], initPython);
99  } else {
100  static std::string nameOfExecutable = KNOWROB_EXECUTABLE_NAME;
101  InitKnowRob(nameOfExecutable.data(), initPython);
102  }
103  }
104 
105  static void py_InitKnowRob1(boost::python::list py_argv) {
106  static std::string nameOfExecutable = KNOWROB_EXECUTABLE_NAME;
107  auto argc = boost::python::len(py_argv);
108  if (argc > 0) {
109  auto extracted = boost::python::extract<std::string>(py_argv[0]);
110  if (extracted.check() && !extracted().empty()) {
111  nameOfExecutable = extracted();
112  }
113  }
114  knowrob::InitKnowRob(nameOfExecutable.data(), false);
115  }
116 
117  static void py_InitKnowRob2() {
118  auto sys = boost::python::import("sys");
119  auto py_argv = boost::python::extract<boost::python::list>(sys.attr("argv"));
120  py_InitKnowRob1(py_argv);
121  }
122 
124  // NOTE: Py_Finalize() should not be called when using boost python according to docs.
125  //Py_Finalize();
126  // stop the thread pool, join all remaining threads
127  DefaultThreadPool()->shutdown();
129  KB_INFO("[KnowRob] shutdown complete.");
130  }
131 }
132 
133 namespace knowrob::py {
135  using namespace boost::python;
136  using namespace knowrob;
137 
139  // mappings for static functions
140  def("InitKnowRobWithArgs", &py_InitKnowRob1, "Initialize the Knowledge Base with arguments.");
141  def("InitKnowRob", &py_InitKnowRob2, "Initialize the Knowledge Base using sys.argv.");
142  def("ShutdownKnowRob", &ShutdownKnowRob);
143  }
144 }
#define KB_DEBUG
Definition: Logger.h:25
#define KB_INFO
Definition: Logger.h:26
static uint32_t batchSize_
Definition: knowrob.h:88
static IRIAtomPtr egoIRI_
Definition: knowrob.h:89
static void initialize()
Definition: Logger.cpp:45
static void finalizeProlog()
#define KNOWROB_EXECUTABLE_NAME
Definition: knowrob.cpp:22
TermRule & string()
Definition: terms.cpp:63
void staticKnowRobModuleInit()
Definition: knowrob.cpp:134
char * NAME_OF_EXECUTABLE
Definition: knowrob.cpp:28
std::shared_ptr< ThreadPool > DefaultThreadPool()
Definition: ThreadPool.cpp:19
void hashCombine(std::size_t &seed, const std::size_t &v)
Definition: knowrob.cpp:39
void InitKnowRob(int argc, char **argv, bool initPython=true)
Definition: knowrob.cpp:96
char * getNameOfExecutable()
Definition: knowrob.cpp:30
std::shared_ptr< IRIAtom > IRIAtomPtr
Definition: IRIAtom.h:57
void InitPythonPath()
Definition: knowrob.cpp:51
void insertUnique(std::ostream &os)
Definition: knowrob.cpp:44
void ShutdownKnowRob()
Definition: knowrob.cpp:123