23 #include "exec_thread.h"
25 #include <core/exceptions/software.h>
26 #include <core/exceptions/system.h>
27 #include <core/threading/mutex.h>
28 #include <logging/component.h>
29 #ifdef SKILLER_TIMETRACKING
30 # include <utils/time/tracker.h>
33 #include <lua/context.h>
34 #include <lua/interface_importer.h>
36 #include <interfaces/SkillerInterface.h>
37 #include <interfaces/SkillerDebugInterface.h>
46 using namespace fawkes;
58 :
Thread(
"SkillerExecutionThread",
Thread::OPMODE_WAITFORWAKEUP),
62 __continuous_run =
false;
63 __continuous_reset =
false;
64 __error_written =
false;
80 SkillerExecutionThread::init_failure_cleanup()
94 "Fawkes is no longer in a clean state. Restart!");
102 __last_exclusive_controller = 0;
103 __reader_just_left =
false;
104 __continuous_run =
false;
105 __continuous_reset =
false;
106 __skdbg_what =
"ACTIVE";
107 __skdbg_graphdir =
"TB";
108 __skdbg_graphcolored =
true;
110 __sksf_pushed =
false;
116 e.
append(
"Insufficient configuration for Skiller");
120 logger->
log_debug(
"SkillerExecutionThread",
"Skill space: %s", __cfg_skillspace.c_str());
129 std::string reading_prefix =
"/skiller/interfaces/" + __cfg_skillspace +
"/reading/";
130 std::string writing_prefix =
"/skiller/interfaces/" + __cfg_skillspace +
"/writing/";
137 if (__cfg_watch_files) {
138 __lua->setup_fam(
true,
false);
147 __lua->add_package_dir(LUADIR);
148 __lua->add_cpackage_dir(LUALIBDIR);
150 __lua->add_package(
"fawkesutils");
151 __lua->add_package(
"fawkesconfig");
152 __lua->add_package(
"fawkeslogging");
153 __lua->add_package(
"fawkesinterface");
154 __lua->add_package(
"fawkesgeometry");
156 __lua->add_package(
"fawkestf");
159 __lua->set_string(
"SKILLSPACE", __cfg_skillspace.c_str());
160 __lua->set_usertype(
"config",
config,
"Configuration",
"fawkes");
161 __lua->set_usertype(
"logger", __clog,
"ComponentLogger",
"fawkes");
162 __lua->set_usertype(
"clock",
clock,
"Clock",
"fawkes");
164 __lua->set_usertype(
"tf", tf_listener,
"Transformer",
"fawkes::tf");
169 __lua->set_start_script(LUADIR
"/skiller/start.lua");
172 __skiller_if->
set_status(SkillerInterface::S_INACTIVE);
173 __skiller_if->
write();
175 __skdbg_if->set_graph(
"");
176 __skdbg_if->set_graph_fsm(
"ACTIVE");
179 init_failure_cleanup();
187 #ifdef SKILLER_TIMETRACKING
189 __ttc_total = __tt->add_class(
"Total");
190 __ttc_msgproc = __tt->add_class(
"Message Processing");
191 __ttc_luaprep = __tt->add_class(
"Lua Preparation");
192 __ttc_luaexec = __tt->add_class(
"Lua Execution");
193 __ttc_publish = __tt->add_class(
"Publishing");
202 #ifdef SKILLER_TIMETRACKING
218 unsigned int instance_serial)
throw()
220 if ( instance_serial == __skiller_if->exclusive_controller() ) {
221 logger->
log_debug(
"SkillerExecutionThread",
"Controlling interface instance was closed, "
222 "revoking exclusive control");
224 __last_exclusive_controller = instance_serial;
225 __reader_just_left =
true;
227 __skiller_if->set_exclusive_controller(0);
228 __skiller_if->write();
239 SkillerExecutionThread::publish_skill_status(std::string &curss)
242 LUA_INTEGER
running = 0,
final = 0, failed = 0;
252 __skiller_if->
set_status(SkillerInterface::S_INACTIVE);
267 throw LuaRuntimeException(
"C++:publish_skill_status",
"skillenv.get_status is not a function");
272 new_status = SkillerInterface::S_FAILED;
273 }
else if ( (
final > 0) && (running == 0) ) {
275 new_status = SkillerInterface::S_FINAL;
276 }
else if ( running > 0 ) {
278 new_status = SkillerInterface::S_RUNNING;
282 new_status = SkillerInterface::S_INACTIVE;
286 if ( (old_status != new_status) ||
301 if ( ! __error_written && (new_status == SkillerInterface::S_FAILED) ) {
303 __error_written = __continuous_run;
304 }
else if (new_status == SkillerInterface::S_RUNNING ||
305 new_status == SkillerInterface::S_FINAL) {
307 __error_written =
false;
310 __skiller_if->
write();
314 logger->
log_error(
"SkillerExecutionThread",
"Failed to retrieve skill status");
317 __skiller_if->
set_status(SkillerInterface::S_FAILED);
319 logger->
log_error(
"SkillerExecutionThread",
"Failed to set FAILED as skill "
320 "status value during error handling");
329 SkillerExecutionThread::publish_skdbg()
332 __lua->
do_string(
"skillenv.write_skiller_debug(interfaces.writing.skdbg, \"%s\", \"%s\", %s)",
333 __skdbg_what.c_str(), __skdbg_graphdir.c_str(),
334 __skdbg_graphcolored ?
"true" :
"false");
336 logger->
log_warn(
"SkillerExecutionThread",
"Error writing graph");
342 SkillerExecutionThread::lua_loop_reset()
345 __lua->
do_string(
"skillenv.reset_loop()");
347 logger->
log_warn(
"SkillerExecutionThread",
"Lua Loop Reset failed");
354 SkillerExecutionThread::publish_error()
357 __lua->
do_string(
"skillenv.write_fsm_error(skillenv.get_skill_fsm(skillenv.get_active_skills()), interfaces.writing.skiller)");
359 logger->
log_warn(
"SkillerExecutionThread",
"Error writing error");
361 __skiller_if->
set_error(
"Failed to set Lua error");
362 __skiller_if->
write();
368 SkillerExecutionThread::process_skdbg_messages()
378 case SkillerDebugInterface::GD_BOTTOM_TOP: __skdbg_graphdir =
"BT";
break;
379 case SkillerDebugInterface::GD_LEFT_RIGHT: __skdbg_graphdir =
"LR";
break;
380 case SkillerDebugInterface::GD_RIGHT_LEFT: __skdbg_graphdir =
"RL";
break;
381 default: __skdbg_graphdir =
"TB";
break;
397 #ifdef SKILLER_TIMETRACKING
398 __tt->ping_start(__ttc_total);
406 std::string curss =
"";
409 bool write_skiller_if =
false;
410 bool last_was_continuous = __continuous_run;
412 #ifdef SKILLER_TIMETRACKING
413 __tt->ping_start(__ttc_msgproc);
415 process_skdbg_messages();
420 if ( excl_ctrl == 0 ) {
421 logger->
log_debug(
"SkillerExecutionThread",
"%s is new exclusive controller",
424 write_skiller_if =
true;
426 }
else if (excl_ctrl == m->
sender_id()) {
430 "exclusive control, but another controller exists "
437 logger->
log_debug(
"SkillerExecutionThread",
"%s releases exclusive control",
440 if ( __continuous_run ) {
441 __continuous_run =
false;
442 __continuous_reset =
true;
446 write_skiller_if =
true;
449 if ( !__reader_just_left || (m->
sender_id() != __last_exclusive_controller)) {
450 logger->
log_warn(
"SkillerExecutionThread",
"%s tried to release exclusive control, "
459 logger->
log_warn(
"SkillerExecutionThread",
"More than one skill string enqueued, "
460 "ignoring previous string (%s).", curss.c_str());
462 logger->
log_debug(
"SkillerExecutionThread",
"%s wants me to execute '%s'",
465 if ( __continuous_run ) {
466 __continuous_run =
false;
467 __continuous_reset =
true;
471 logger->
log_debug(
"SkillerExecutionThread",
"%s tries to exec while not controller",
480 logger->
log_warn(
"SkillerExecutionThread",
"More than one skill string enqueued, "
483 logger->
log_debug(
"SkillerExecutionThread",
"%s wants me to continuously execute '%s'",
487 __continuous_reset = last_was_continuous;
488 __continuous_run =
true;
491 logger->
log_debug(
"SkillerExecutionThread",
"%s tries to exec while not controller",
499 (__reader_just_left && (m->
sender_id() == __last_exclusive_controller)) ) {
500 logger->
log_debug(
"SkillerExecutionThread",
"Stopping continuous execution");
501 if ( __continuous_run ) {
502 __continuous_run =
false;
503 __continuous_reset =
true;
507 logger->
log_debug(
"SkillerExecutionThread",
"%s tries to stop exec while not controller",
511 logger->
log_warn(
"SkillerExecutionThread",
"Unhandled message of type %s in "
518 if ( __continuous_run && (curss ==
"") ) {
522 #ifdef SKILLER_TIMETRACKING
523 __tt->ping_end(__ttc_msgproc);
526 if ( __continuous_reset ) {
527 logger->
log_debug(
"SkillerExecutionThread",
"Continuous reset forced");
try {
529 __sksf_pushed =
false;
532 __lua->
do_string(
"skillenv.reset_all()");
534 logger->
log_warn(
"SkillerExecutionThread",
"Caught exception while resetting skills, ignored, output follows");
538 __skiller_if->
set_status(SkillerInterface::S_INACTIVE);
543 __error_written =
false;
544 __continuous_reset =
false;
545 write_skiller_if =
true;
548 if ( write_skiller_if ) __skiller_if->
write();
553 #ifdef SKILLER_TIMETRACKING
554 __tt->ping_start(__ttc_luaprep);
558 if ( __continuous_run ) {
562 __lua->
do_string(
"skillenv.reset_status()");
564 logger->
log_warn(
"SkillerExecutionThread",
"Caught exception while resetting status, ignored, output follows");
570 if (! __sksf_pushed) {
573 __lua->
do_string(
"return skillenv.gensandbox()");
575 __sksf_pushed =
true;
577 #ifdef SKILLER_TIMETRACKING
578 __tt->ping_end(__ttc_luaprep);
579 __tt->ping_start(__ttc_luaexec);
586 __skiller_if->
set_error(
"Skill string execution failed with Lua error, see log");
587 __skiller_if->
write();
588 __continuous_reset =
true;
589 __continuous_run =
false;
591 #ifdef SKILLER_TIMETRACKING
592 __tt->ping_end(__ttc_luaexec);
595 if ( ! __continuous_run ) {
600 __sksf_pushed =
false;
603 __lua->
do_string(
"skillenv.reset_all()");
605 logger->
log_warn(
"SkillerExecutionThread",
"Caught exception while resetting skills, ignored, output follows");
612 #ifdef SKILLER_TIMETRACKING
613 __tt->ping_start(__ttc_publish);
615 publish_skill_status(curss);
619 __reader_just_left =
false;
622 #ifdef SKILLER_TIMETRACKING
623 __tt->ping_end(__ttc_publish);
624 __tt->ping_end(__ttc_total);
625 if (++__tt_loopcount >= SKILLER_TT_MOD) {
628 __tt->print_to_stdout();
SkillerDebugInterface Fawkes BlackBoard Interface.
Base class for all messages passed through interfaces in Fawkes BlackBoard.
virtual ~SkillerExecutionThread()
Destructor.
bool msgq_empty()
Check if queue is empty.
uint32_t exclusive_controller() const
Get exclusive_controller value.
SkillStatusEnum status() const
Get status value.
virtual void loop()
Code to execute in the thread.
SkillerExecutionThread()
Constructor.
const char * type() const
Get message type.
void bb_interface_reader_removed(fawkes::Interface *interface, unsigned int instance_serial)
A reading instance has been closed for a watched interface.
void set_exclusive_controller(const uint32_t new_exclusive_controller)
Set exclusive_controller value.
virtual bool get_bool(const char *path)=0
Get value from configuration which is of type bool.
StopExecMessage Fawkes BlackBoard Interface Message.
void pop(int n)
Pop value(s) from stack.
GraphDirectionEnum graph_dir() const
Get graph_dir value.
ReleaseControlMessage Fawkes BlackBoard Interface Message.
void load_string(const char *s)
Load Lua string.
SkillStatusEnum
This determines the current status of skill execution.
virtual void unregister_listener(BlackBoardInterfaceListener *listener)
Unregister BB interface listener.
Thread class encapsulation of pthreads.
SetGraphMessage Fawkes BlackBoard Interface Message.
void write()
Write from local copy into BlackBoard memory.
Base class for all Fawkes BlackBoard interfaces.
char * graph_fsm() const
Get graph_fsm value.
void open_writing_interfaces(std::string &prefix)
Open interfaces for writing.
Logger * logger
This is the Logger member used to access the logger.
AcquireControlMessage Fawkes BlackBoard Interface Message.
virtual Interface * open_for_writing(const char *interface_type, const char *identifier)=0
Open interface for writing.
Clock * clock
By means of this member access to the clock is given.
bool is_continuous() const
Get continuous value.
Thread aspect to use blocked timing.
virtual void register_listener(BlackBoardInterfaceListener *listener, ListenerRegisterFlag flag=BBIL_FLAG_ALL)
Register BB event listener.
void msgq_pop()
Erase first message from queue.
void push_value(int idx)
Push a copy of the element at the given index on top of the stack.
void set_error(const char *new_error)
Set error value.
void pcall(int nargs=0, int nresults=0, int errfunc=0)
Protected call.
Base class for exceptions in Fawkes.
Message * msgq_first()
Get the first message from the message queue.
const char * sender_thread_name() const
Get sender of message.
void do_string(const char *format,...)
Execute string.
void setfenv(int idx=-2)
Set function environment.
void open_reading_interfaces(std::string &prefix)
Open interfaces for reading.
unsigned int sender_id() const
Get ID of sender.
bool running() const
Check if the thread is running.
void get_field(int idx, const char *k)
Get named value from table.
ExecSkillMessage Fawkes BlackBoard Interface Message.
lua_Integer to_integer(int idx)
Retrieve stack value as integer.
bool msgq_first_is()
Check if first message has desired type.
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.
const char * name() const
Get name of thread.
void add_interface(std::string varname, Interface *interface)
Add a single interface to be pushed to the context.
SetGraphColoredMessage Fawkes BlackBoard Interface Message.
void read()
Read from all reading interfaces.
void process_fam_events()
Process FAM events.
void bbil_add_reader_interface(Interface *interface)
Add an interface to the reader addition/removal watch list.
virtual void init()
Initialize the thread.
char * skill_string() const
Get skill_string value.
void get_global(const char *name)
Get global variable.
virtual void log_debug(const char *component, const char *format,...)=0
Log debug message.
void set_continuous(const bool new_continuous)
Set continuous value.
bool is_function(int idx)
Check if stack value is a function.
void set_skill_string(const char *new_skill_string)
Set skill_string value.
char * skill_string() const
Get skill_string value.
void write()
Write all writing interfaces.
SkillerInterface Fawkes BlackBoard Interface.
virtual void finalize()
Finalize the thread.
void set_status(const SkillStatusEnum new_status)
Set status value.
ExecSkillContinuousMessage Fawkes BlackBoard Interface Message.
bool is_graph_colored() const
Get graph_colored value.
Configuration * config
This is the Configuration member used to access the configuration.
SetGraphDirectionMessage Fawkes BlackBoard Interface Message.
virtual void log_debug(const char *component, const char *format,...)
Log debug message.
char * skill_string() const
Get skill_string value.
void push_interfaces()
Push interfaces to Lua environment.
void append(const char *format,...)
Append messages to the message list.
virtual std::string get_string(const char *path)=0
Get value from configuration which is of type string.
BlackBoard interface listener.
BlackBoard * blackboard
This is the BlackBoard instance you can use to interact with the BlackBoard.
virtual void close(Interface *interface)=0
Close interface.