Fawkes API  Fawkes Development Version
execution_thread.cpp
1 /***************************************************************************
2  * execution_thread.cpp - Execution thread for Golog++
3  *
4  * Created: Mon 26 Aug 2019 CEST 15:38
5  * Copyright 2019 Victor MatarĂ© <matare@fh-aachen.de>
6  ****************************************************************************/
7 
8 /* This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Library General Public License for more details.
17  *
18  * Read the full text in the LICENSE.GPL file in the doc directory.
19  */
20 
21 #include "execution_thread.h"
22 
23 #include "exog_manager.h"
24 #include "gologpp_fawkes_backend.h"
25 
26 #include <golog++/model/procedural.h>
27 #include <golog++/parser/parser.h>
28 #include <golog++/semantics/readylog/execution.h>
29 
30 #include <filesystem>
31 
32 namespace fawkes {
33 namespace gpp {
34 
35 using namespace gologpp;
36 
37 const std::string cfg_prefix("/plugins/gologpp");
38 
39 /** @class GologppThread
40  * Main golog++ thread that handles program execution, i.e. spawns an execution
41  * context, loads a program and executes it.
42  */
43 
44 GologppThread::GologppThread() : Thread("gologpp_agent", Thread::OPMODE_WAITFORWAKEUP)
45 {
46  set_prepfin_conc_loop(true);
47 }
48 
49 void
50 GologppThread::init()
51 {
52  std::filesystem::path spec{config->get_string(cfg_prefix + "/spec")};
53  auto prog_file = find_prog_file(spec);
54  std::string spec_cfg_prefix{cfg_prefix + "/specs/" + spec.string()};
55  logger->log_debug(name(), "spec config: %s", spec_cfg_prefix.c_str());
56 
57  // Clear the global scope because it's a static variable that may already contain
58  // things from a previous (unsuccessful) attempt to initialize this plugin.
59  gologpp::global_scope().clear();
60 
61  // We know that lists of elementary types will most likely occur, so simply
62  // define the types unconditionally. The elementary types themselves are
63  // already defined.
64  global_scope().register_type_raw(
65  new ListType(*global_scope().lookup_type(BoolType::static_name())));
66  global_scope().register_type_raw(
67  new ListType(*global_scope().lookup_type(NumberType::static_name())));
68  global_scope().register_type_raw(
69  new ListType(*global_scope().lookup_type(SymbolType::static_name())));
70 
71  logger->log_info(name(), "Parsing %s...", prog_file.c_str());
72  main_prog_ = gologpp::parser::parse_file(prog_file);
73  logger->log_info(name(), "... parsing done");
74 
75  logger->log_info(name(), "Initializing ReadyLog context...");
76 
77  exog_mgr_ = new ExogManager(this, config, spec_cfg_prefix, blackboard, logger);
78 
79  gologpp::eclipse_opts options;
80  options.trace = config->get_bool_or_default((cfg_prefix + "/trace").c_str(), false);
81  options.guitrace = options.trace;
82  gologpp::ReadylogContext::init(
83  options, std::make_unique<GologppFawkesBackend>(config, spec_cfg_prefix, logger, blackboard));
84 
85  logger->log_info(name(), "... initialization done");
86 }
87 
88 void
89 GologppThread::once()
90 {
91  try {
92  std::lock_guard<std::mutex> l{run_mutex_};
93  gologpp::ReadylogContext::instance().run(
94  gologpp::Block{new gologpp::Scope{gologpp::global_scope()}, {main_prog_.release()}});
95  logger->log_info(name(), "golog++ main program has ended");
96  } catch (gologpp::UserError &e) {
97  logger->log_error(name(), "User Error: %s", e.what());
98  } catch (gologpp::EclipseError &e) {
99  logger->log_error(name(), "Eclipse Error: %s", e.what());
100  }
101 }
102 
103 bool
104 GologppThread::prepare_finalize_user()
105 {
106  gologpp::ReadylogContext::instance().terminate();
107  std::lock_guard<std::mutex> l{run_mutex_};
108  return true;
109 }
110 
111 void
112 GologppThread::finalize()
113 {
114  main_prog_.reset();
115  delete exog_mgr_;
116  gologpp::global_scope().clear();
117  gologpp::ReadylogContext::shutdown();
118 }
119 
120 /**
121  * @brief GologppThread::gologpp_context
122  * @return the currently used golog++ execution context.
123  */
124 gologpp::ExecutionContext &
125 GologppThread::gologpp_context()
126 {
127  return gologpp::ReadylogContext::instance();
128 }
129 
130 std::filesystem::path
131 GologppThread::find_prog_file(const std::filesystem::path &spec) const
132 {
133  const std::unordered_map<std::string, std::string> mapping = {{"@BASEDIR@", BASEDIR},
134  {"@SRCDIR@", SRCDIR}};
135  auto gologpp_cfg_dirs = config->get_strings(cfg_prefix + "/gologpp-dirs");
136  std::vector<std::filesystem::path> gologpp_dirs;
137  for (auto &dir : gologpp_cfg_dirs) {
138  for (auto &entry : mapping) {
139  size_t start_pos = 0;
140  while ((start_pos = dir.find(entry.first, start_pos)) != std::string::npos) {
141  dir.replace(start_pos, entry.first.length(), entry.second);
142  start_pos += entry.second.length();
143  }
144  }
145  gologpp_dirs.push_back(std::filesystem::path{dir});
146  logger->log_debug(name(), "Golog++ dir: %s", dir.c_str());
147  }
148  std::filesystem::path prog_file;
149  std::filesystem::path spec_file{spec};
150  spec_file += ".gpp";
151  for (auto &dir : gologpp_dirs) {
152  prog_file = dir / spec / spec_file;
153  if (std::filesystem::exists(prog_file)) {
154  return prog_file;
155  }
156  }
157  throw Exception("Could not find Golog++ spec dir for '%s'", spec.c_str());
158 }
159 
160 } // namespace gpp
161 } // namespace fawkes
virtual std::vector< std::string > get_strings(const char *path)=0
Get list of values from configuration which is of type string.
virtual bool get_bool_or_default(const char *path, const bool &default_val)
Get value from configuration which is of type bool, or the given default if the path does not exist.
Definition: config.cpp:726
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
virtual void log_info(const char *component, const char *format,...)
Log informational message.
Definition: multi.cpp:195
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
Definition: multi.cpp:174
virtual void log_error(const char *component, const char *format,...)
Log error message.
Definition: multi.cpp:237
Watch/observe blackboard interfaces according to the mappings specified for exogenous actions in the ...
Definition: exog_manager.h:51
Fawkes library namespace.