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 #include "xabsl_tools.h"
25 #include "skill_wrapper.h"
26 
27 #include <core/exceptions/software.h>
28 #include <utils/time/time.h>
29 #include <interfaces/SkillerInterface.h>
30 #include <interfaces/ObjectPositionInterface.h>
31 
32 #include <XabslEngine/XabslEngine.h>
33 
34 using namespace fawkes;
35 
36 
37 /** Global XabslEngineThread required for xet_current_time(). */
38 static XabslEngineThread *g_xe = NULL;
39 
40 /** Get current time.
41  * Uses a globally set XabslEngineThread instance to determine the current
42  * time, may be simulated time!
43  * @return continuous time in miliseconds
44  */
45 static unsigned long int
46 xet_current_time()
47 {
48  if ( ! g_xe) {
49  throw NullPointerException("No XabslEngineThread instance exists");
50  }
51 
52  return g_xe->current_time();
53 }
54 
55 /** @class XabslEngineThread "engine_thread.h"
56  * Xabsl Engine Thread.
57  * This thread drives the Xabsl engine.
58  * @author Tim Niemueller
59  */
60 
61 
62 /** Constructor. */
64  : Thread("XabslEngineThread", Thread::OPMODE_WAITFORWAKEUP),
65  BlockedTimingAspect(BlockedTimingAspect::WAKEUP_HOOK_THINK)
66 {
67 }
68 
69 
70 void
72 {
73  if ( g_xe ) {
74  throw Exception("Global XabslEngineThread has already been set.");
75  }
76  g_xe = this;
77 
78  __xe = NULL;
79  __xleh = NULL;
80  __now = NULL;
81  __ball_rx = NULL;
82  __ball_ry = NULL;
83  __skiller_if = NULL;
84  __wm_ball_if = NULL;
85 
86  __now = new Time(clock);
87  __xleh = new XabslLoggingErrorHandler(logger);
88  __xe = new xabsl::Engine(*__xleh, &xet_current_time);
89 
90  __wm_ball_if = blackboard->open_for_reading<ObjectPositionInterface>("WM Ball");
91  __skiller_if = blackboard->open_for_reading<SkillerInterface>("Skiller");
92 
94  params.push_back(std::make_pair("x", "double"));
95  params.push_back(std::make_pair("y", "double"));
96  params.push_back(std::make_pair("ori", "double"));
97  XabslSkillWrapper *sw = new XabslSkillWrapper("relgoto", *__xleh, params);
98  __wrappers[sw->name()] = sw;
99  __xe->registerBasicBehavior(*sw);
100 
101  __ball_ry = __ball_rx = NULL;
102  for (Interface::FieldIterator i = __wm_ball_if->fields(); i != __wm_ball_if->fields_end(); ++i) {
103  if ( strcmp(i.get_name(), "relative_x") == 0 ) {
104  __ball_rx = new XabslInterfaceFieldWrapper<double, float>(i.get_type(), i.get_name(), (float *)i.get_value());
105  __xe->registerDecimalInputSymbol("ball.relative_x", __ball_rx,
106  (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double, float>::get_value);
107  } else if ( strcmp(i.get_name(), "relative_y") == 0 ) {
108  __ball_ry = new XabslInterfaceFieldWrapper<double, float>(i.get_type(), i.get_name(), (float *)i.get_value());
109  __xe->registerDecimalInputSymbol("ball.relative_y", __ball_ry,
110  (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double, float>::get_value);
111  }
112  }
113 
114  XabslFileInputSource xinput(XABSLDIR"agent.xabslc");
115  __xe->createOptionGraph(xinput);
116 
117  if ( __xleh->errorsOccurred ) {
118  finalize();
119  throw Exception("Error while creating XABSL engine, see log for details");
120  }
121 
122  /* Test code, exporting interfaces to allow for real skill-level programming
123  * is an overly complex and error prone task.
124  * Since C++ methods for basic behaviors for sending a message cannot be
125  * created on-the-fly wrappers would need to be written or generated for each
126  * possible message type.
127 
128  __navi_if = blackboard->open_for_reading<NavigatorInterface>("Navigator");
129 
130  std::string base_name = "navi_";
131  Interface::FieldIterator i;
132  for (i = __navi_if->fields(); i != __navi_if->fields_end(); ++i) {
133  switch (i.get_type()) {
134  case Interface::IFT_BOOL:
135  {
136  XabslInterfaceFieldWrapper<bool> *ifw = new XabslInterfaceFieldWrapper<bool>(new InterfaceFieldPointer<bool>(i.get_type(), i.get_name(), (bool *)i.get_value()));
137  __xe->registerBooleanInputSymbol((base_name + ifw->get_name()).c_str(),
138  ifw,
139  (bool (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<bool>::get_value);
140  __xe->registerBooleanOutputSymbol((base_name + ifw->get_name()).c_str(),
141  ifw,
142  (void (xabsl::FunctionProvider::*)(bool))&XabslInterfaceFieldWrapper<bool>::set_value,
143  (bool (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<bool>::get_value);
144  }
145  break;
146  case Interface::IFT_INT:
147  case Interface::IFT_UINT:
148  case Interface::IFT_LONGINT:
149  case Interface::IFT_LONGUINT:
150  case Interface::IFT_FLOAT:
151  {
152  XabslInterfaceFieldWrapper<double> *ifw = new XabslInterfaceFieldWrapper<double>(new InterfaceFieldPointer<double>(i.get_type(), i.get_name(), (double *)i.get_value()));
153  __xe->registerDecimalInputSymbol((base_name + ifw->get_name()).c_str(),
154  ifw,
155  (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double>::get_value);
156  __xe->registerDecimalOutputSymbol((base_name + ifw->get_name()).c_str(),
157  ifw,
158  (void (xabsl::FunctionProvider::*)(double))&XabslInterfaceFieldWrapper<double>::set_value,
159  (double (xabsl::FunctionProvider::*)())&XabslInterfaceFieldWrapper<double>::get_value);
160  }
161  break;
162  case Interface::IFT_STRING:
163  // ignored, XABSL can't handle that
164  break;
165  }
166  }
167  */
168 }
169 
170 
171 void
173 {
174  g_xe = NULL;
175 
176  for (__wit = __wrappers.begin(); __wit != __wrappers.end(); ++__wit) {
177  delete __wit->second;
178  }
179  __wrappers.clear();
180 
181  delete __xe;
182  delete __xleh;
183  delete __now;
184  delete __ball_rx;
185  delete __ball_ry;
186 
187  if (__skiller_if) blackboard->close(__skiller_if);
188  if (__wm_ball_if) blackboard->close(__wm_ball_if);
189 }
190 
191 
192 void
194 {
195  try {
197  } catch (Exception &e) {
198  logger->log_error("XabslEngineThread", "Cannot aquire exclusive skiller "
199  "control, exception follows");
200  logger->log_error("XabslEngineThread", e);
201  }
202 }
203 
204 void
206 {
207  __now->stamp();
208 
209  __wm_ball_if->read();
210  __skiller_if->read();
211 
212  __xe->execute();
213 
214  std::string skill_string = "";
215  for (__wit = __wrappers.begin(); __wit != __wrappers.end(); ++__wit) {
216  std::string css = __wit->second->skill_string();
217  if ( css != "" ) {
218  skill_string += css + "; ";
219  }
220  }
221  if ( skill_string != "" ) {
222  logger->log_debug(name(), "Skill string: %s", skill_string.c_str());
223  }
224 
225  try {
226  __skiller_if->msgq_enqueue(new SkillerInterface::ExecSkillMessage(skill_string.c_str()));
227  } catch (Exception &e) {
228  logger->log_warn("XabslEngineThread", "Executing skill failed, exception follows");
229  logger->log_warn("XabslEngineThread", e);
230  }
231 }
232 
233 
234 /** Get current time.
235  * @return continuous time in miliseconds
236  */
237 unsigned long int
239 {
240  return __now->in_msec();
241 }
ObjectPositionInterface Fawkes BlackBoard Interface.
Fawkes library namespace.
unsigned long int current_time()
Get current time.
A class for handling time.
Definition: time.h:91
A NULL pointer was supplied where not allowed.
Definition: software.h:34
Thread class encapsulation of pthreads.
Definition: thread.h:42
virtual void finalize()
Finalize the thread.
Logger * logger
This is the Logger member used to access the logger.
Definition: logging.h:44
AcquireControlMessage Fawkes BlackBoard Interface Message.
File input class for Xabsl integration.
Definition: xabsl_tools.h:47
Clock * clock
By means of this member access to the clock is given.
Definition: clock.h:45
Thread aspect to use blocked timing.
long in_msec() const
Convert the stored time into milli-seconds.
Definition: time.cpp:242
Xabsl Engine Thread.
Definition: engine_thread.h:52
Base class for exceptions in Fawkes.
Definition: exception.h:36
void read()
Read from BlackBoard into local copy.
Definition: interface.cpp:477
ExecSkillMessage Fawkes BlackBoard Interface Message.
const char * name() const
Get name of thread.
Definition: thread.h:95
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.
virtual void once()
Execute an action exactly once.
unsigned int msgq_enqueue(Message *message)
Enqueue message at end of queue.
Definition: interface.cpp:903
const char * name()
Get name of the skill.
std::list< std::pair< std::string, std::string > > ParameterList
Parameter list.
Definition: skill_wrapper.h:40
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: interface.cpp:1218
XabslEngineThread()
Constructor.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
virtual Interface * open_for_reading(const char *interface_type, const char *identifier, const char *owner=NULL)=0
Open interface for reading.
SkillerInterface Fawkes BlackBoard Interface.
Time & stamp()
Set this time to the current time.
Definition: time.cpp:783
Logging error handler for XABSL integration.
Definition: xabsl_tools.h:34
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: interface.cpp:1208
virtual void init()
Initialize the thread.
virtual void loop()
Code to execute in the thread.
Xabsl Skill Wrapper.
Definition: skill_wrapper.h:33
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
Definition: blackboard.h:44
virtual void close(Interface *interface)=0
Close interface.