Fawkes API Fawkes Development Version
clips_pddl_parser_feature.cpp
1/***************************************************************************
2 * clips_pddl_parser_feature.cpp - CLIPS PDDL Parser Feature
3 *
4 * Created: Mon 16 Oct 2017 11:14:41 CEST 11:14
5 * Copyright 2017 Till Hofmann <hofmann@kbsg.rwth-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 "clips_pddl_parser_feature.h"
22
23#include "effect_visitor.h"
24#include "precondition_visitor.h"
25
26#include <core/threading/mutex_locker.h>
27#include <logging/logger.h>
28#include <pddl_parser/pddl_parser.h>
29
30#include <clipsmm.h>
31#include <fstream>
32
33using namespace std;
34using namespace pddl_parser;
35
36/** @class PDDLCLIPSFeature "clips_pddl_parser_feature.h"
37 * Provide a PDDL parser to a CLIPS environment.
38 * @author Till Hofmann
39 */
40
41/** Initialize the CLIPS feature.
42 */
43PDDLCLIPSFeature::PDDLCLIPSFeature() : CLIPSFeature("pddl-parser")
44{
45}
46
47/** Initialize the looger to use.
48 * @param logger The logger to use for logging in the feature
49 */
50void
52{
53 logger_ = logger;
54}
55
56/** Initialize the context and add a parse-pddl-domain CLIPS function.
57 * @param env_name The name of the environment.
58 * @param clips The CLIPS environment to add the parser functionality to.
59 */
60void
63{
64 envs_[env_name] = clips;
65 //clips->evaluate("(path-load \"pddl.clp\")");
66 clips->add_function("parse-pddl-domain",
67 sigc::slot<void, string>(
68 sigc::bind<0>(sigc::mem_fun(*this, &PDDLCLIPSFeature::parse_domain),
69 env_name)));
70}
71
72/** Clean up a context.
73 * @param env_name The name of the environment to clean.
74 */
75void
77{
78 envs_.erase(env_name);
79}
80
81/** CLIPS function to parse a PDDL domain.
82 * This parses the given domain and asserts domain facts for all parts of the
83 * domain.
84 * @param env_name The name of the calling environment
85 * @param domain_file The path of the domain file to parse.
86 */
87void
88PDDLCLIPSFeature::parse_domain(std::string env_name, std::string domain_file)
89{
90 fawkes::MutexLocker lock(envs_[env_name].objmutex_ptr());
91 CLIPS::Environment &env = **(envs_[env_name]);
92 Domain domain;
93 try {
94 ifstream df(domain_file);
95 stringstream buffer;
96 buffer << df.rdbuf();
97 domain = PddlParser::parseDomain(buffer.str());
98 } catch (PddlParserException &e) {
99 logger_->log_error(("PDDLCLIPS|" + env_name).c_str(),
100 "Failed to parse domain: %s",
102 return;
103 }
104 for (auto &type : domain.types) {
105 string super_type = "";
106 if (!type.second.empty()) {
107 super_type = "(super-type " + type.second + ")";
108 }
109 env.assert_fact("(domain-object-type "
110 "(name "
111 + type.first + ")" + super_type + ")");
112 }
113 for (auto &predicate : domain.predicates) {
114 string param_string = "";
115 string type_string = "";
116 for (auto &param : predicate.second) {
117 param_string += " " + param.first;
118 type_string += " " + param.second;
119 }
120 env.assert_fact("(domain-predicate"
121 " (name "
122 + predicate.first
123 + ")"
124 " (param-names "
125 + param_string
126 + ")"
127 " (param-types "
128 + type_string
129 + ")"
130 ")");
131 }
132
133 for (auto &action : domain.actions) {
134 string params_string = "(param-names";
135 for (auto &param_pair : action.action_params) {
136 string param_name = param_pair.first;
137 string param_type = param_pair.second;
138 params_string += " " + param_name;
139 env.assert_fact("(domain-operator-parameter"
140 " (name "
141 + param_name
142 + ")"
143 " (operator "
144 + action.name
145 + ")"
146 " (type "
147 + param_type
148 + ")"
149 ")");
150 }
151 params_string += ")";
152 env.assert_fact("(domain-operator (name " + action.name + ")" + params_string + ")");
153 vector<string> precondition_facts =
154 boost::apply_visitor(PreconditionToCLIPSFactVisitor(action.name, 1, true),
155 action.precondition.expression);
156 for (auto &fact : precondition_facts) {
157 env.assert_fact(fact);
158 }
159 vector<string> effect_facts =
160 boost::apply_visitor(EffectToCLIPSFactVisitor(action.name, true), action.effect.expression);
161 for (auto &fact : effect_facts) {
162 env.assert_fact(fact);
163 }
164 }
165}
Translate a PDDL effect into CLIPS facts.
PDDLCLIPSFeature()
Initialize the CLIPS feature.
virtual void clips_context_destroyed(const std::string &env_name)
Clean up a context.
void init_logger(fawkes::Logger *logger)
Initialize the looger to use.
virtual void clips_context_init(const std::string &env_name, fawkes::LockPtr< CLIPS::Environment > &clips)
Initialize the context and add a parse-pddl-domain CLIPS function.
Translate a PDDL precondition into CLIPS facts.
virtual const char * what_no_backtrace() const noexcept
Get primary string (does not implicitly print the back trace).
Definition: exception.cpp:663
Interface for logging.
Definition: logger.h:42
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
Mutex locking helper.
Definition: mutex_locker.h:34
Exception thrown by the parser if an error occurs during parsing.
A structured representation of a PDDL domain.
Definition: pddl_ast.h:157
std::vector< Action > actions
A list of actions defined in the domain.
Definition: pddl_ast.h:173
pairs_type types
A list of types with their super types.
Definition: pddl_ast.h:163
std::vector< predicate_type > predicates
A list of predicate names in the domain, including the types of their arguments.
Definition: pddl_ast.h:169