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
32namespace fawkes {
33namespace gpp {
34
35using namespace gologpp;
36
37const 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
44GologppThread::GologppThread() : Thread("gologpp_agent", Thread::OPMODE_WAITFORWAKEUP)
45{
46 set_prepfin_conc_loop(true);
47}
48
49void
50GologppThread::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
88void
89GologppThread::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
103bool
104GologppThread::prepare_finalize_user()
105{
106 gologpp::ReadylogContext::instance().terminate();
107 std::lock_guard<std::mutex> l{run_mutex_};
108 return true;
109}
110
111void
112GologppThread::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 */
124gologpp::ExecutionContext &
125GologppThread::gologpp_context()
126{
127 return gologpp::ReadylogContext::instance();
128}
129
130std::filesystem::path
131GologppThread::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.