Fawkes API Fawkes Development Version
engine_thread.cpp
1
2/***************************************************************************
3 * engine_thread.cpp - Thread driving the XABSL Engine
4 *
5 * Created: Thu Aug 07 17:01:29 2008
6 * Copyright 2006-2008 Tim Niemueller [www.niemueller.de]
7 *
8 ****************************************************************************/
9
10/* This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Library General Public License for more details.
19 *
20 * Read the full text in the LICENSE.GPL file in the doc directory.
21 */
22
23#include "engine_thread.h"
24
25#include "skill_wrapper.h"
26#include "xabsl_tools.h"
27
28#include <XabslEngine/XabslEngine.h>
29#include <core/exceptions/software.h>
30#include <interfaces/ObjectPositionInterface.h>
31#include <interfaces/SkillerInterface.h>
32#include <utils/time/time.h>
33
34using namespace fawkes;
35
36/** Global XabslEngineThread required for xet_current_time(). */
37static XabslEngineThread *g_xe = NULL;
38
39/** Get current time.
40 * Uses a globally set XabslEngineThread instance to determine the current
41 * time, may be simulated time!
42 * @return continuous time in miliseconds
43 */
44static unsigned long int
45xet_current_time()
46{
47 if (!g_xe) {
48 throw NullPointerException("No XabslEngineThread instance exists");
49 }
50
51 return g_xe->current_time();
52}
53
54/** @class XabslEngineThread "engine_thread.h"
55 * Xabsl Engine Thread.
56 * This thread drives the Xabsl engine.
57 * @author Tim Niemueller
58 */
59
60/** Constructor. */
62: Thread("XabslEngineThread", Thread::OPMODE_WAITFORWAKEUP),
64{
65}
66
67void
69{
70 if (g_xe) {
71 throw Exception("Global XabslEngineThread has already been set.");
72 }
73 g_xe = this;
74
75 xe_ = NULL;
76 xleh_ = NULL;
77 now_ = NULL;
78 ball_rx_ = NULL;
79 ball_ry_ = NULL;
80 skiller_if_ = NULL;
81 wm_ball_if_ = NULL;
82
83 now_ = new Time(clock);
85 xe_ = new xabsl::Engine(*xleh_, &xet_current_time);
86
87 wm_ball_if_ = blackboard->open_for_reading<ObjectPositionInterface>("WM Ball");
88 skiller_if_ = blackboard->open_for_reading<SkillerInterface>("Skiller");
89
91 params.push_back(std::make_pair("x", "double"));
92 params.push_back(std::make_pair("y", "double"));
93 params.push_back(std::make_pair("ori", "double"));
94 XabslSkillWrapper *sw = new XabslSkillWrapper("relgoto", *xleh_, params);
95 wrappers_[sw->name()] = sw;
96 xe_->registerBasicBehavior(*sw);
97
98 ball_ry_ = ball_rx_ = NULL;
99 for (InterfaceFieldIterator i = wm_ball_if_->fields(); i != wm_ball_if_->fields_end(); ++i) {
100 if (strcmp(i.get_name(), "relative_x") == 0) {
101 ball_rx_ = new XabslInterfaceFieldWrapper<double, float>(i.get_type(),
102 i.get_name(),
103 (float *)i.get_value());
104 xe_->registerDecimalInputSymbol("ball.relative_x",
105 ball_rx_,
106 (double (xabsl::FunctionProvider::*)())
108 } else if (strcmp(i.get_name(), "relative_y") == 0) {
109 ball_ry_ = new XabslInterfaceFieldWrapper<double, float>(i.get_type(),
110 i.get_name(),
111 (float *)i.get_value());
112 xe_->registerDecimalInputSymbol("ball.relative_y",
113 ball_ry_,
114 (double (xabsl::FunctionProvider::*)())
116 }
117 }
118
119 XabslFileInputSource xinput(XABSLDIR "agent.xabslc");
120 xe_->createOptionGraph(xinput);
121
122 if (xleh_->errorsOccurred) {
123 finalize();
124 throw Exception("Error while creating XABSL engine, see log for details");
125 }
126
127 /* Test code, exporting interfaces to allow for real skill-level programming
128 * is an overly complex and error prone task.
129 * Since C++ methods for basic behaviors for sending a message cannot be
130 * created on-the-fly wrappers would need to be written or generated for each
131 * possible message type.
132
133 navi_if_ = blackboard->open_for_reading<NavigatorInterface>("Navigator");
134
135 std::string base_name = "navi_";
136 InterfaceFieldIterator i;
137 for (i = navi_if_->fields(); i != navi_if_->fields_end(); ++i) {
138 switch (i.get_type()) {
139 case Interface::IFT_BOOL:
140 {
141 XabslInterfaceFieldWrapper<bool> *ifw = new XabslInterfaceFieldWrapper<bool>(new InterfaceFieldPointer<bool>(i.get_type(), i.get_name(), (bool *)i.get_value()));
142 xe_->registerBooleanInputSymbol((base_name + ifw->get_name()).c_str(),
143 ifw,
144 (bool (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<bool>::get_value);
145 xe_->registerBooleanOutputSymbol((base_name + ifw->get_name()).c_str(),
146 ifw,
147 (void (xabsl::FunctionProvider::*)(bool))&XabslInterfaceFieldWrapper<bool>::set_value,
148 (bool (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<bool>::get_value);
149 }
150 break;
151 case Interface::IFT_INT:
152 case Interface::IFT_UINT:
153 case Interface::IFT_LONGINT:
154 case Interface::IFT_LONGUINT:
155 case Interface::IFT_FLOAT:
156 {
157 XabslInterfaceFieldWrapper<double> *ifw = new XabslInterfaceFieldWrapper<double>(new InterfaceFieldPointer<double>(i.get_type(), i.get_name(), (double *)i.get_value()));
158 xe_->registerDecimalInputSymbol((base_name + ifw->get_name()).c_str(),
159 ifw,
160 (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double>::get_value);
161 xe_->registerDecimalOutputSymbol((base_name + ifw->get_name()).c_str(),
162 ifw,
163 (void (xabsl::FunctionProvider::*)(double))&XabslInterfaceFieldWrapper<double>::set_value,
164 (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double>::get_value);
165 }
166 break;
167 case Interface::IFT_STRING:
168 // ignored, XABSL can't handle that
169 break;
170 }
171 }
172 */
173}
174
175void
177{
178 g_xe = NULL;
179
180 for (wit_ = wrappers_.begin(); wit_ != wrappers_.end(); ++wit_) {
181 delete wit_->second;
182 }
183 wrappers_.clear();
184
185 delete xe_;
186 delete xleh_;
187 delete now_;
188 delete ball_rx_;
189 delete ball_ry_;
190
191 if (skiller_if_)
192 blackboard->close(skiller_if_);
193 if (wm_ball_if_)
194 blackboard->close(wm_ball_if_);
195}
196
197void
199{
200 try {
202 } catch (Exception &e) {
203 logger->log_error("XabslEngineThread",
204 "Cannot aquire exclusive skiller "
205 "control, exception follows");
206 logger->log_error("XabslEngineThread", e);
207 }
208}
209
210void
212{
213 now_->stamp();
214
215 wm_ball_if_->read();
216 skiller_if_->read();
217
218 xe_->execute();
219
220 std::string skill_string = "";
221 for (wit_ = wrappers_.begin(); wit_ != wrappers_.end(); ++wit_) {
222 std::string css = wit_->second->skill_string();
223 if (css != "") {
224 skill_string += css + "; ";
225 }
226 }
227 if (skill_string != "") {
228 logger->log_debug(name(), "Skill string: %s", skill_string.c_str());
229 }
230
231 try {
232 skiller_if_->msgq_enqueue(new SkillerInterface::ExecSkillMessage(skill_string.c_str()));
233 } catch (Exception &e) {
234 logger->log_warn("XabslEngineThread", "Executing skill failed, exception follows");
235 logger->log_warn("XabslEngineThread", e);
236 }
237}
238
239/** Get current time.
240 * @return continuous time in miliseconds
241 */
242unsigned long int
244{
245 return now_->in_msec();
246}
Xabsl Engine Thread.
Definition: engine_thread.h:58
virtual void once()
Execute an action exactly once.
virtual void init()
Initialize the thread.
virtual void loop()
Code to execute in the thread.
virtual void finalize()
Finalize the thread.
XabslEngineThread()
Constructor.
unsigned long int current_time()
Get current time.
File input class for Xabsl integration.
Definition: xabsl_tools.h:47
Logging error handler for XABSL integration.
Definition: xabsl_tools.h:35
Xabsl Skill Wrapper.
Definition: skill_wrapper.h:34
std::list< std::pair< std::string, std::string > > ParameterList
Parameter list.
Definition: skill_wrapper.h:40
const char * name()
Get name of the skill.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:44
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
virtual void close(Interface *interface)=0
Close interface.
Thread aspect to use blocked timing.
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:42
Base class for exceptions in Fawkes.
Definition: exception.h:36
Interface field iterator.
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: interface.cpp:1240
unsigned int msgq_enqueue(Message *message, bool proxy=false)
Enqueue message at end of queue.
Definition: interface.cpp:915
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: interface.cpp:1231
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:479
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
virtual void log_warn(const char *component, const char *format,...)=0
Log warning message.
virtual void log_error(const char *component, const char *format,...)=0
Log error message.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:41
A NULL pointer was supplied where not allowed.
Definition: software.h:32
ObjectPositionInterface Fawkes BlackBoard Interface.
AcquireControlMessage Fawkes BlackBoard Interface Message.
ExecSkillMessage Fawkes BlackBoard Interface Message.
SkillerInterface Fawkes BlackBoard Interface.
Thread class encapsulation of pthreads.
Definition: thread.h:46
const char * name() const
Get name of thread.
Definition: thread.h:100
A class for handling time.
Definition: time.h:93
Time & stamp()
Set this time to the current time.
Definition: time.cpp:704
long in_msec() const
Convert the stored time into milli-seconds.
Definition: time.cpp:228
Fawkes library namespace.