$search
00001 00002 /*************************************************************************** 00003 * skillgui.cpp - Skill GUI 00004 * 00005 * Created: Mon Nov 03 13:37:33 2008 00006 * Copyright 2008-2010 Tim Niemueller [www.niemueller.de] 00007 * 2010 Carnegie Mellon University 00008 * 2010 Intel Labs Pittsburgh 00009 ****************************************************************************/ 00010 00011 /* This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL file in the doc directory. 00022 */ 00023 00024 #include "skillgui.h" 00025 #ifdef USE_PAPYRUS 00026 # include "graph_viewport.h" 00027 #else 00028 # include "graph_drawing_area.h" 00029 #endif 00030 00031 #ifndef USE_ROS 00032 # include <utils/system/argparser.h> 00033 # include <blackboard/remote.h> 00034 # include <netcomm/fawkes/client.h> 00035 00036 # include <gui_utils/logview.h> 00037 # include <gui_utils/throbber.h> 00038 # include <gui_utils/service_chooser_dialog.h> 00039 # include <gui_utils/interface_dispatcher.h> 00040 # include <gui_utils/plugin_tree_view.h> 00041 #else 00042 # include "throbber.h" 00043 # include <functional> 00044 #endif 00045 00046 #include <cstring> 00047 #include <string> 00048 00049 #include <gvc.h> 00050 00051 #ifndef USE_ROS 00052 using namespace fawkes; 00053 #else 00054 using namespace ros; 00055 using namespace actionlib; 00056 #endif 00057 00058 #define ACTIVE_SKILL "Active Skill" 00059 00071 SkillGuiGtkWindow::SkillGuiGtkWindow(BaseObjectType* cobject, 00072 const Glib::RefPtr<Gnome::Glade::Xml> &refxml) 00073 : Gtk::Window(cobject), __rosnh(), __ac_exec(__rosnh, "/skiller/exec") 00074 { 00075 #ifndef USE_ROS 00076 bb = NULL; 00077 __skiller_if = NULL; 00078 __skdbg_if = NULL; 00079 __agdbg_if = NULL; 00080 #endif 00081 00082 #ifdef HAVE_GCONFMM 00083 __gconf = Gnome::Conf::Client::get_default_client(); 00084 __gconf->add_dir(GCONF_PREFIX); 00085 #endif 00086 00087 #ifndef USE_ROS 00088 refxml->get_widget_derived("trv_log", __logview); 00089 refxml->get_widget_derived("trv_plugins", __trv_plugins); 00090 #endif 00091 refxml->get_widget_derived("img_throbber", __throbber); 00092 refxml->get_widget("tb_throbber", tb_throbber); 00093 refxml->get_widget("toolbar", toolbar); 00094 refxml->get_widget("tb_connection", tb_connection); 00095 refxml->get_widget("tb_sep", tb_sep); 00096 refxml->get_widget("but_continuous", but_continuous); 00097 refxml->get_widget("but_clearlog", but_clearlog); 00098 refxml->get_widget("tb_exit", tb_exit); 00099 refxml->get_widget("cbe_skillstring", cbe_skillstring); 00100 refxml->get_widget("but_exec", but_exec); 00101 refxml->get_widget("but_stop", but_stop); 00102 refxml->get_widget("lab_status", lab_status); 00103 refxml->get_widget("lab_alive", lab_alive); 00104 refxml->get_widget("lab_continuous", lab_continuous); 00105 refxml->get_widget("lab_skillstring", lab_skillstring); 00106 refxml->get_widget("lab_error", lab_error); 00107 refxml->get_widget("scw_graph", scw_graph); 00108 //refxml->get_widget("drw_graph", drw_graph); 00109 refxml->get_widget("ntb_tabs", ntb_tabs); 00110 refxml->get_widget("tb_fsmgraph", tb_fsmgraph); 00111 refxml->get_widget("tb_skiller", tb_skiller); 00112 refxml->get_widget("tb_agent", tb_agent); 00113 refxml->get_widget("tb_graphlist", tb_graphlist); 00114 refxml->get_widget("tb_controller", tb_controller); 00115 refxml->get_widget("tb_graphsave", tb_graphsave); 00116 refxml->get_widget("tb_graphopen", tb_graphopen); 00117 refxml->get_widget("tb_graphupd", tb_graphupd); 00118 refxml->get_widget("tb_graphrecord", tb_graphrecord); 00119 refxml->get_widget("tb_zoomin", tb_zoomin); 00120 refxml->get_widget("tb_zoomout", tb_zoomout); 00121 refxml->get_widget("tb_zoomfit", tb_zoomfit); 00122 refxml->get_widget("tb_zoomreset", tb_zoomreset); 00123 refxml->get_widget("tb_graphdir", tb_graphdir); 00124 refxml->get_widget("tb_graphcolored", tb_graphcolored); 00125 refxml->get_widget("tb_followactivestate", tb_followactivestate); 00126 refxml->get_widget("mi_graphdir_title", mi_graphdir); 00127 refxml->get_widget("mi_top_bottom", mi_top_bottom); 00128 refxml->get_widget("mi_bottom_top", mi_bottom_top); 00129 refxml->get_widget("mi_left_right", mi_left_right); 00130 refxml->get_widget("mi_right_left", mi_right_left); 00131 00132 // This hack is required because setting expanding in Glade-3 does not 00133 // have the same effect of right-aligning the throbber 00134 Gtk::SeparatorToolItem *spacesep; 00135 refxml->get_widget("tb_spacesep", spacesep); 00136 spacesep->set_expand(); 00137 refxml->get_widget("tb_fsmgraph_spacesep", spacesep); 00138 spacesep->set_expand(); 00139 00140 Gtk::Label *mi_graphdir_label = dynamic_cast<Gtk::Label *>(mi_graphdir->get_child()); 00141 if ( mi_graphdir_label ) { 00142 mi_graphdir_label->set_markup("<b>Graph Direction</b>"); 00143 } 00144 mi_graphdir->set_sensitive(false); 00145 00146 // This should be in the Glade file, but is not restored for some reason 00147 tb_graphsave->set_homogeneous(false); 00148 tb_graphopen->set_homogeneous(false); 00149 tb_graphupd->set_homogeneous(false); 00150 tb_graphrecord->set_homogeneous(false); 00151 tb_zoomin->set_homogeneous(false); 00152 tb_zoomout->set_homogeneous(false); 00153 tb_zoomfit->set_homogeneous(false); 00154 tb_zoomreset->set_homogeneous(false); 00155 tb_graphdir->set_homogeneous(false); 00156 tb_graphcolored->set_homogeneous(false); 00157 tb_followactivestate->set_homogeneous(false); 00158 00159 __sks_list = Gtk::ListStore::create(__sks_record); 00160 cbe_skillstring->set_model(__sks_list); 00161 cbe_skillstring->set_text_column(__sks_record.skillstring); 00162 00163 #ifndef USE_ROS 00164 __trv_plugins->set_network_client(connection_dispatcher.get_client()); 00165 # ifdef HAVE_GCONFMM 00166 __trv_plugins->set_gconf_prefix(GCONF_PREFIX); 00167 # endif 00168 #else 00169 ntb_tabs->remove_page(0); 00170 ntb_tabs->remove_page(-1); 00171 toolbar->hide(); 00172 but_exec->set_sensitive(true); 00173 but_stop->set_sensitive(true); 00174 cbe_skillstring->set_sensitive(true); 00175 toolbar->remove(*tb_throbber); 00176 tb_fsmgraph->append(*tb_throbber); 00177 #endif 00178 00179 if (ntb_tabs->get_n_pages() == 1) { 00180 ntb_tabs->set_show_tabs(false); 00181 } 00182 00183 #ifdef USE_PAPYRUS 00184 pvp_graph = Gtk::manage(new SkillGuiGraphViewport()); 00185 scw_graph->add(*pvp_graph); 00186 pvp_graph->show(); 00187 #else 00188 gda = Gtk::manage(new SkillGuiGraphDrawingArea()); 00189 scw_graph->add(*gda); 00190 gda->show(); 00191 #endif 00192 00193 cb_graphlist = Gtk::manage(new Gtk::ComboBoxText()); 00194 cb_graphlist->append_text(ACTIVE_SKILL); 00195 cb_graphlist->set_active_text(ACTIVE_SKILL); 00196 tb_graphlist->add(*cb_graphlist); 00197 cb_graphlist->show(); 00198 00199 //ntb_tabs->set_current_page(1); 00200 00201 //connection_dispatcher.signal_connected().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connect)); 00202 //connection_dispatcher.signal_disconnected().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_disconnect)); 00203 00204 //tb_connection->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_connection_clicked)); 00205 //tb_controller->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_controller_clicked)); 00206 but_exec->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exec_clicked)); 00207 cbe_skillstring->get_entry()->signal_activate().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exec_clicked)); 00208 tb_exit->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_exit_clicked)); 00209 but_stop->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_stop_clicked)); 00210 but_continuous->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_contexec_toggled)); 00211 //but_clearlog->signal_clicked().connect(sigc::mem_fun(*__logview, &LogView::clear)); 00212 #ifdef USE_ROS 00213 tb_skiller->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graph_changed)); 00214 tb_agent->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graph_changed)); 00215 #else 00216 tb_skiller->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data__changed)); 00217 tb_agent->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data__changed)); 00218 #endif 00219 tb_skiller->signal_toggled().connect(sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive),true)); 00220 tb_agent->signal_toggled().connect(sigc::bind(sigc::mem_fun(*cb_graphlist, &Gtk::ComboBoxText::set_sensitive),false)); 00221 //cb_graphlist->signal_changed().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skill_changed)); 00222 //tb_graphupd->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphupd_clicked)); 00223 #ifndef USE_ROS 00224 mi_top_bottom->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_TOP_BOTTOM)); 00225 mi_bottom_top->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_BOTTOM_TOP)); 00226 mi_left_right->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_LEFT_RIGHT)); 00227 mi_right_left->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_changed), SkillerDebugInterface::GD_RIGHT_LEFT)); 00228 #else 00229 __graph_changed.connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graph_changed)); 00230 #endif 00231 tb_graphdir->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphdir_clicked)); 00232 tb_graphcolored->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_graphcolor_toggled)); 00233 tb_followactivestate->signal_toggled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_followactivestate_toggled)); 00234 #ifdef USE_PAPYRUS 00235 tb_graphsave->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::save)); 00236 tb_zoomin->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_in)); 00237 tb_zoomout->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_out)); 00238 tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_fit)); 00239 tb_zoomreset->signal_clicked().connect(sigc::mem_fun(*pvp_graph, &SkillGuiGraphViewport::zoom_reset)); 00240 #else 00241 tb_graphsave->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::save)); 00242 tb_graphopen->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::open)); 00243 tb_zoomin->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_in)); 00244 tb_zoomout->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_out)); 00245 tb_zoomfit->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_fit)); 00246 tb_zoomreset->signal_clicked().connect(sigc::mem_fun(*gda, &SkillGuiGraphDrawingArea::zoom_reset)); 00247 tb_graphrecord->signal_clicked().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_recording_toggled)); 00248 gda->signal_update_disabled().connect(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_update_disabled)); 00249 #endif 00250 00251 #ifdef USE_ROS 00252 __sub_graph_skiller = __rosnh.subscribe("/skiller/graph", 10, 00253 &SkillGuiGtkWindow::ros_skiller_graphmsg_cb, this); 00254 __sub_graph_agent = __rosnh.subscribe("/luaagent/graph", 10, 00255 &SkillGuiGtkWindow::ros_agent_graphmsg_cb, this); 00256 __srv_graph_color_skiller = __rosnh.serviceClient<skiller::SetGraphColored>("/skiller/graph/set_colored"); 00257 __srv_graph_direction_skiller = __rosnh.serviceClient<skiller::SetGraphDirection>("/skiller/graph/set_direction"); 00258 __srv_graph_color_agent = __rosnh.serviceClient<skiller::SetGraphColored>("/luaagent/graph/set_colored"); 00259 __srv_graph_direction_agent = __rosnh.serviceClient<skiller::SetGraphDirection>("/luaagent/graph/set_direction"); 00260 #endif 00261 00262 #ifdef HAVE_GCONFMM 00263 __gconf->signal_value_changed().connect(sigc::hide(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_config_changed)))); 00264 on_config_changed(); 00265 #endif 00266 } 00267 00268 00270 SkillGuiGtkWindow::~SkillGuiGtkWindow() 00271 { 00272 #ifdef HAVE_GCONFMM 00273 __gconf->remove_dir(GCONF_PREFIX); 00274 #endif 00275 #ifndef USE_ROS 00276 __logview->set_client(NULL); 00277 __trv_plugins->set_network_client(NULL); 00278 #endif 00279 } 00280 00281 00282 void 00283 SkillGuiGtkWindow::on_config_changed() 00284 { 00285 #ifdef HAVE_GCONFMM 00286 Gnome::Conf::SListHandle_ValueString l(__gconf->get_string_list(GCONF_PREFIX"/command_history")); 00287 00288 __sks_list->clear(); 00289 for (Gnome::Conf::SListHandle_ValueString::const_iterator i = l.begin(); i != l.end(); ++i) { 00290 Gtk::TreeModel::Row row = *__sks_list->append(); 00291 row[__sks_record.skillstring] = *i; 00292 } 00293 00294 #ifdef GLIBMM_EXCEPTIONS_ENABLED 00295 bool continuous = __gconf->get_bool(GCONF_PREFIX"/continuous_exec"); 00296 bool colored = __gconf->get_bool(GCONF_PREFIX"/graph_colored"); 00297 bool followactivestate = __gconf->get_bool(GCONF_PREFIX"/follow_active_state"); 00298 #else 00299 std::auto_ptr<Glib::Error> error; 00300 bool continuous = __gconf->get_bool(GCONF_PREFIX"/continuous_exec", error); 00301 bool colored = __gconf->get_bool(GCONF_PREFIX"/graph_colored", error); 00302 bool followactivestate = __gconf->get_bool(GCONF_PREFIX"/follow_active_state", error); 00303 #endif 00304 but_continuous->set_active(continuous); 00305 tb_graphcolored->set_active(colored); 00306 tb_followactivestate->set_active(followactivestate); 00307 on_followactivestate_toggled(); 00308 #endif 00309 } 00310 00311 00312 void 00313 SkillGuiGtkWindow::on_skill_changed() 00314 { 00315 Glib::ustring skill = cb_graphlist->get_active_text(); 00316 if ( skill == ACTIVE_SKILL ) { 00317 skill = "ACTIVE"; 00318 } 00319 #ifndef USE_ROS 00320 SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage(skill.c_str()); 00321 __skdbg_if->msgq_enqueue(sgm); 00322 #endif 00323 } 00324 00325 void 00326 SkillGuiGtkWindow::on_contexec_toggled() 00327 { 00328 #ifdef HAVE_GCONFMM 00329 __gconf->set(GCONF_PREFIX"/continuous_exec", but_continuous->get_active()); 00330 #endif 00331 } 00332 00333 00334 void 00335 SkillGuiGtkWindow::on_exit_clicked() 00336 { 00337 Gtk::Main::quit(); 00338 } 00339 00340 void 00341 SkillGuiGtkWindow::on_exec_clicked() 00342 { 00343 Glib::ustring sks = ""; 00344 if ( cbe_skillstring->get_active_row_number() == -1 ) { 00345 Gtk::Entry *entry = cbe_skillstring->get_entry(); 00346 sks = entry->get_text(); 00347 } else { 00348 Gtk::TreeModel::Row row = *cbe_skillstring->get_active(); 00349 row.get_value(cbe_skillstring->get_text_column(), sks); 00350 } 00351 00352 if ( sks != "" ) { 00353 __throbber->set_timeout(80); 00354 00355 #ifndef USE_ROS 00356 if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() && 00357 __skiller_if->exclusive_controller() == __skiller_if->serial()) { 00358 00359 if ( but_continuous->get_active() ) { 00360 SkillerInterface::ExecSkillContinuousMessage *escm = new SkillerInterface::ExecSkillContinuousMessage(sks.c_str()); 00361 __skiller_if->msgq_enqueue(escm); 00362 } else { 00363 SkillerInterface::ExecSkillMessage *esm = new SkillerInterface::ExecSkillMessage(sks.c_str()); 00364 __skiller_if->msgq_enqueue(esm); 00365 } 00366 00367 } else { 00368 Gtk::MessageDialog md(*this, "The exclusive control over the skiller has " 00369 "not been acquired yet and skills cannot be executed", 00370 /* markup */ false, 00371 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00372 /* modal */ true); 00373 md.set_title("Skill Execution Failure"); 00374 md.run(); 00375 } 00376 00377 #else // ROS 00378 printf("Starting execution of %s\n", sks.c_str()); 00379 skiller::ExecSkillGoal goal; 00380 goal.skillstring = sks; 00381 //__ac_exec.cancelGoalsAtAndBeforeTime(ros::Time::now()); 00382 __gh.reset(); 00383 __gh = __ac_exec.sendGoal(goal, 00384 boost::bind(&SkillGuiGtkWindow::ros_exec_transition_cb, this, _1), 00385 boost::bind(&SkillGuiGtkWindow::ros_exec_feedback_cb, this, _1, _2)); 00386 #endif 00387 Gtk::TreeModel::Children children = __sks_list->children(); 00388 if ( ! children.empty() ) { 00389 size_t num = 0; 00390 Gtk::TreeIter i = children.begin(); 00391 while ( i != children.end() ) { 00392 if ( num >= 9 ) { 00393 i = __sks_list->erase(i); 00394 } else { 00395 Gtk::TreeModel::Row row = *i; 00396 if (row[__sks_record.skillstring] == sks) { 00397 i = __sks_list->erase(i); 00398 } else { 00399 ++num; 00400 ++i; 00401 } 00402 } 00403 } 00404 } 00405 Gtk::TreeModel::Row row = *__sks_list->prepend(); 00406 row[__sks_record.skillstring] = sks; 00407 00408 std::list<Glib::ustring> l; 00409 for (Gtk::TreeIter i = children.begin(); i != children.end(); ++i) { 00410 Gtk::TreeModel::Row row = *i; 00411 l.push_back(row[__sks_record.skillstring]); 00412 } 00413 00414 #ifdef HAVE_GCONFMM 00415 __gconf->set_string_list(GCONF_PREFIX"/command_history", l); 00416 #endif 00417 } 00418 } 00419 00420 void 00421 SkillGuiGtkWindow::on_stop_clicked() 00422 { 00423 #ifndef USE_ROS 00424 if ( bb && __skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() ) { 00425 SkillerInterface::StopExecMessage *sem = new SkillerInterface::StopExecMessage(); 00426 __skiller_if->msgq_enqueue(sem); 00427 } 00428 #else 00429 if (! __gh.isExpired()) { 00430 CommState comm_state = __gh.getCommState(); 00431 if (comm_state.state_ != CommState::DONE) { 00432 __gh.cancel(); 00433 } 00434 } 00435 #endif 00436 } 00437 00438 00439 00440 #ifndef USE_ROS 00441 00443 void 00444 SkillGuiGtkWindow::on_connection_clicked() 00445 { 00446 if ( ! connection_dispatcher.get_client()->connected() ) { 00447 ServiceChooserDialog ssd(*this, connection_dispatcher.get_client()); 00448 ssd.run_and_connect(); 00449 } else { 00450 connection_dispatcher.get_client()->disconnect(); 00451 } 00452 } 00453 00454 void 00455 SkillGuiGtkWindow::on_controller_clicked() 00456 { 00457 if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() && 00458 __skiller_if->exclusive_controller() == __skiller_if->serial()) { 00459 // we are exclusive controller, release control 00460 SkillerInterface::ReleaseControlMessage *rcm = new SkillerInterface::ReleaseControlMessage(); 00461 __skiller_if->msgq_enqueue(rcm); 00462 } else if (__skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() && 00463 __skiller_if->exclusive_controller() == 0) { 00464 // there is no exclusive controller, try to acquire control 00465 SkillerInterface::AcquireControlMessage *acm = new SkillerInterface::AcquireControlMessage(); 00466 __skiller_if->msgq_enqueue(acm); 00467 } else { 00468 Gtk::MessageDialog md(*this, 00469 "Another component already acquired the exclusive " 00470 "control for the Skiller; not acquiring exclusive control.", 00471 /* markup */ false, 00472 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00473 /* modal */ true); 00474 md.set_title("Control Acquisition Failed"); 00475 md.run(); 00476 } 00477 } 00478 00479 void 00480 SkillGuiGtkWindow::close_bb() 00481 { 00482 if ( bb ) { 00483 bb->unregister_listener(__skiller_ifd); 00484 bb->unregister_listener(__skdbg_ifd); 00485 bb->unregister_listener(__agdbg_ifd); 00486 delete __skiller_ifd; 00487 delete __skdbg_ifd; 00488 delete __agdbg_ifd; 00489 if ( __skiller_if && __skiller_if->is_valid() && __skiller_if->has_writer() && 00490 (__skiller_if->exclusive_controller() == __skiller_if->serial()) ) { 00491 SkillerInterface::ReleaseControlMessage *rcm = new SkillerInterface::ReleaseControlMessage(); 00492 __skiller_if->msgq_enqueue(rcm); 00493 } 00494 bb->close(__skiller_if); 00495 bb->close(__skdbg_if); 00496 bb->close(__agdbg_if); 00497 delete bb; 00498 __skiller_if = NULL; 00499 __skdbg_if = NULL; 00500 __agdbg_if = NULL; 00501 bb = NULL; 00502 } 00503 } 00504 00506 void 00507 SkillGuiGtkWindow::on_connect() 00508 { 00509 try { 00510 if ( ! bb ) { 00511 bb = new RemoteBlackBoard(connection_dispatcher.get_client()); 00512 __skiller_if = bb->open_for_reading<SkillerInterface>("Skiller"); 00513 __skdbg_if = bb->open_for_reading<SkillerDebugInterface>("Skiller"); 00514 __agdbg_if = bb->open_for_reading<SkillerDebugInterface>("LuaAgent"); 00515 on_skiller_data_changed(); 00516 on_skdbg_data_changed(); 00517 on_agdbg_data_changed(); 00518 00519 __skiller_ifd = new InterfaceDispatcher("Skiller IFD", __skiller_if); 00520 __skdbg_ifd = new InterfaceDispatcher("SkillerDebug IFD", __skdbg_if); 00521 __agdbg_ifd = new InterfaceDispatcher("LuaAgent SkillerDebug IFD", __agdbg_if); 00522 bb->register_listener(__skiller_ifd, BlackBoard::BBIL_FLAG_DATA); 00523 bb->register_listener(__skdbg_ifd, BlackBoard::BBIL_FLAG_DATA); 00524 bb->register_listener(__agdbg_ifd, BlackBoard::BBIL_FLAG_DATA); 00525 __skiller_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skiller_data_changed))); 00526 __skdbg_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_skdbg_data_changed))); 00527 __agdbg_ifd->signal_data_changed().connect(sigc::hide(sigc::mem_fun(*this, &SkillGuiGtkWindow::on_agdbg_data_changed))); 00528 00529 // always try to acquire control on connect, this may well fail, for 00530 // example if agent is running, but we don't care 00531 __skiller_if->read(); 00532 if (__skiller_if->has_writer() && __skiller_if->exclusive_controller() == 0) { 00533 SkillerInterface::AcquireControlMessage *aqm = new SkillerInterface::AcquireControlMessage(); 00534 __skiller_if->msgq_enqueue(aqm); 00535 } 00536 if (__skdbg_if->has_writer()) { 00537 SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage("LIST"); 00538 __skdbg_if->msgq_enqueue(sgm); 00539 } 00540 } 00541 tb_connection->set_stock_id(Gtk::Stock::DISCONNECT); 00542 __logview->set_client(connection_dispatcher.get_client()); 00543 00544 but_continuous->set_sensitive(true); 00545 tb_controller->set_sensitive(true); 00546 cbe_skillstring->set_sensitive(true); 00547 00548 this->set_title(std::string("Skill GUI @ ") + connection_dispatcher.get_client()->get_hostname()); 00549 } catch (Exception &e) { 00550 Glib::ustring message = *(e.begin()); 00551 Gtk::MessageDialog md(*this, message, /* markup */ false, 00552 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00553 /* modal */ true); 00554 md.set_title("BlackBoard connection failed"); 00555 md.run(); 00556 00557 close_bb(); 00558 connection_dispatcher.get_client()->disconnect(); 00559 } 00560 } 00561 00563 void 00564 SkillGuiGtkWindow::on_disconnect() 00565 { 00566 but_continuous->set_sensitive(false); 00567 tb_controller->set_sensitive(false); 00568 cbe_skillstring->set_sensitive(false); 00569 but_exec->set_sensitive(false); 00570 but_stop->set_sensitive(false); 00571 00572 close_bb(); 00573 00574 tb_connection->set_stock_id(Gtk::Stock::CONNECT); 00575 #ifdef USE_PAPYRUS 00576 pvp_graph->queue_draw(); 00577 #endif 00578 __logview->set_client(NULL); 00579 00580 this->set_title("Skill GUI"); 00581 } 00582 00583 00584 void 00585 SkillGuiGtkWindow::on_skiller_data_changed() 00586 { 00587 try { 00588 __skiller_if->read(); 00589 00590 switch (__skiller_if->status()) { 00591 case SkillerInterface::S_INACTIVE: 00592 __throbber->stop_anim(); 00593 lab_status->set_text("S_INACTIVE"); 00594 break; 00595 case SkillerInterface::S_FINAL: 00596 __throbber->stop_anim(); 00597 __throbber->set_stock(Gtk::Stock::APPLY); 00598 lab_status->set_text("S_FINAL"); 00599 break; 00600 case SkillerInterface::S_RUNNING: 00601 __throbber->start_anim(); 00602 lab_status->set_text("S_RUNNING"); 00603 break; 00604 case SkillerInterface::S_FAILED: 00605 __throbber->stop_anim(); 00606 __throbber->set_stock(Gtk::Stock::DIALOG_WARNING); 00607 lab_status->set_text("S_FAILED"); 00608 break; 00609 } 00610 00611 lab_skillstring->set_text(__skiller_if->skill_string()); 00612 lab_error->set_text(__skiller_if->error()); 00613 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 ) 00614 lab_skillstring->set_tooltip_text(__skiller_if->skill_string()); 00615 lab_error->set_tooltip_text(__skiller_if->error()); 00616 #endif 00617 lab_continuous->set_text(__skiller_if->is_continuous() ? "Yes" : "No"); 00618 lab_alive->set_text(__skiller_if->has_writer() ? "Yes" : "No"); 00619 00620 if ( __skiller_if->exclusive_controller() == __skiller_if->serial() ) { 00621 if ( tb_controller->get_stock_id() == Gtk::Stock::NO.id ) { 00622 tb_controller->set_stock_id(Gtk::Stock::YES); 00623 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 ) 00624 tb_controller->set_tooltip_text("Release exclusive control"); 00625 #endif 00626 } 00627 but_exec->set_sensitive(true); 00628 but_stop->set_sensitive(true); 00629 } else { 00630 if ( tb_controller->get_stock_id() == Gtk::Stock::YES.id ) { 00631 tb_controller->set_stock_id(Gtk::Stock::NO); 00632 #if GTKMM_MAJOR_VERSION > 2 || ( GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION >= 12 ) 00633 tb_controller->set_tooltip_text("Gain exclusive control"); 00634 #endif 00635 } 00636 but_exec->set_sensitive(false); 00637 but_stop->set_sensitive(false); 00638 } 00639 00640 00641 } catch (Exception &e) { 00642 __throbber->stop_anim(); 00643 } 00644 } 00645 00646 00647 void 00648 SkillGuiGtkWindow::on_skdbg_data_changed() 00649 { 00650 if (tb_skiller->get_active() && __skdbg_if) { 00651 try { 00652 __skdbg_if->read(); 00653 00654 if (strcmp(__skdbg_if->graph_fsm(), "LIST") == 0) { 00655 Glib::ustring list = __skdbg_if->graph(); 00656 cb_graphlist->clear_items(); 00657 cb_graphlist->append_text(ACTIVE_SKILL); 00658 cb_graphlist->set_active_text(ACTIVE_SKILL); 00659 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14 ) 00660 Glib::RefPtr<Glib::Regex> regex = Glib::Regex::create("\n"); 00661 std::list<std::string> skills = regex->split(list); 00662 for (std::list<std::string>::iterator i = skills.begin(); i != skills.end(); ++i) { 00663 if (*i != "") cb_graphlist->append_text(*i); 00664 } 00665 #endif 00666 if (__skdbg_if->has_writer()) { 00667 SkillerDebugInterface::SetGraphMessage *sgm = new SkillerDebugInterface::SetGraphMessage("ACTIVE"); 00668 __skdbg_if->msgq_enqueue(sgm); 00669 } 00670 } else { 00671 update_graph(__skdbg_if->graph_fsm(), __skdbg_if->graph()); 00672 } 00673 00674 switch (__skdbg_if->graph_dir()) { 00675 case SkillerDebugInterface::GD_TOP_BOTTOM: 00676 tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN); break; 00677 case SkillerDebugInterface::GD_BOTTOM_TOP: 00678 tb_graphdir->set_stock_id(Gtk::Stock::GO_UP); break; 00679 case SkillerDebugInterface::GD_LEFT_RIGHT: 00680 tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD); break; 00681 case SkillerDebugInterface::GD_RIGHT_LEFT: 00682 tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK); break; 00683 } 00684 } catch (Exception &e) { 00685 // ignored 00686 } 00687 } 00688 } 00689 00690 00691 void 00692 SkillGuiGtkWindow::on_agdbg_data_changed() 00693 { 00694 if (tb_agent->get_active() && __agdbg_if) { 00695 try { 00696 __agdbg_if->read(); 00697 #ifdef USE_PAPYRUS 00698 pvp_graph->set_graph_fsm(__agdbg_if->graph_fsm()); 00699 pvp_graph->set_graph(__agdbg_if->graph()); 00700 pvp_graph->render(); 00701 #else 00702 gda->set_graph_fsm(__agdbg_if->graph_fsm()); 00703 gda->set_graph(__agdbg_if->graph()); 00704 #endif 00705 00706 switch (__agdbg_if->graph_dir()) { 00707 case SkillerDebugInterface::GD_TOP_BOTTOM: 00708 tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN); break; 00709 case SkillerDebugInterface::GD_BOTTOM_TOP: 00710 tb_graphdir->set_stock_id(Gtk::Stock::GO_UP); break; 00711 case SkillerDebugInterface::GD_LEFT_RIGHT: 00712 tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD); break; 00713 case SkillerDebugInterface::GD_RIGHT_LEFT: 00714 tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK); break; 00715 } 00716 } catch (Exception &e) { 00717 // ignored 00718 } 00719 } 00720 } 00721 #endif 00722 00723 void 00724 SkillGuiGtkWindow::on_graphupd_clicked() 00725 { 00726 #ifdef USE_PAPYRUS 00727 if ( pvp_graph->get_update_graph() ) { 00728 pvp_graph->set_update_graph(false); 00729 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP); 00730 } else { 00731 pvp_graph->set_update_graph(true); 00732 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY); 00733 pvp_graph->render(); 00734 } 00735 #else 00736 if ( gda->get_update_graph() ) { 00737 gda->set_update_graph(false); 00738 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP); 00739 } else { 00740 gda->set_update_graph(true); 00741 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_PLAY); 00742 } 00743 #endif 00744 } 00745 00746 00747 void 00748 SkillGuiGtkWindow::update_graph(std::string &graph_name, std::string &dotgraph) 00749 { 00750 #ifdef USE_PAPYRUS 00751 pvp_graph->set_graph_fsm(graph_name); 00752 pvp_graph->set_graph(dotgraph); 00753 pvp_graph->render(); 00754 #else 00755 gda->set_graph_fsm(graph_name); 00756 gda->set_graph(dotgraph); 00757 #endif 00758 } 00759 00760 00761 void 00762 SkillGuiGtkWindow::on_graphdir_clicked() 00763 { 00764 Glib::ustring stockid = tb_graphdir->get_stock_id(); 00765 #ifndef USE_ROS 00766 SkillerDebugInterface *iface = __skdbg_if; 00767 if (tb_agent->get_active()) { 00768 iface = __agdbg_if; 00769 } 00770 00771 if (stockid == Gtk::Stock::GO_DOWN.id) { 00772 send_graphdir_message(iface, SkillerDebugInterface::GD_BOTTOM_TOP); 00773 } else if (stockid == Gtk::Stock::GO_UP.id) { 00774 send_graphdir_message(iface, SkillerDebugInterface::GD_LEFT_RIGHT); 00775 } else if (stockid == Gtk::Stock::GO_FORWARD.id) { 00776 send_graphdir_message(iface, SkillerDebugInterface::GD_RIGHT_LEFT); 00777 } else if (stockid == Gtk::Stock::GO_BACK.id) { 00778 send_graphdir_message(iface, SkillerDebugInterface::GD_TOP_BOTTOM); 00779 } 00780 #else 00781 skiller::SetGraphDirection srvr; 00782 skiller::Graph graphmsg; 00783 if (stockid == Gtk::Stock::GO_DOWN.id) { 00784 srvr.request.direction = graphmsg.GRAPH_DIR_BOTTOM_TOP; 00785 } else if (stockid == Gtk::Stock::GO_UP.id) { 00786 srvr.request.direction = graphmsg.GRAPH_DIR_LEFT_RIGHT; 00787 } else if (stockid == Gtk::Stock::GO_FORWARD.id) { 00788 srvr.request.direction = graphmsg.GRAPH_DIR_RIGHT_LEFT; 00789 } else if (stockid == Gtk::Stock::GO_BACK.id) { 00790 srvr.request.direction = graphmsg.GRAPH_DIR_TOP_BOTTOM; 00791 } 00792 if (tb_agent->get_active()) { 00793 __srv_graph_direction_agent.call(srvr); 00794 } else { 00795 __srv_graph_direction_skiller.call(srvr); 00796 } 00797 #endif 00798 } 00799 00800 void 00801 SkillGuiGtkWindow::on_graphcolor_toggled() 00802 { 00803 bool colored = tb_graphcolored->get_active(); 00804 #ifdef HAVE_GCONFMM 00805 __gconf->set(GCONF_PREFIX"/graph_colored", colored); 00806 #endif 00807 #ifndef USE_ROS 00808 SkillerDebugInterface *iface = __skdbg_if; 00809 if (tb_agent->get_active()) { 00810 iface = __agdbg_if; 00811 } 00812 00813 try { 00814 if (iface) { 00815 SkillerDebugInterface::SetGraphColoredMessage *m; 00816 m = new SkillerDebugInterface::SetGraphColoredMessage(colored); 00817 iface->msgq_enqueue(m); 00818 } else { 00819 throw Exception("Not connected to Fawkes."); 00820 } 00821 } catch (Exception &e) { 00822 /* Ignore for now, causes error message on startup 00823 Gtk::MessageDialog md(*this, 00824 Glib::ustring("Setting graph color failed: ") + e.what(), 00825 / markup / false, 00826 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00827 / modal / true); 00828 md.set_title("Communication Failure"); 00829 md.run(); 00830 */ 00831 } 00832 #else 00833 skiller::SetGraphColored srvr; 00834 srvr.request.colored = colored; 00835 if (tb_agent->get_active() && __srv_graph_color_agent.exists()) { 00836 printf("Calling agent\n"); 00837 __srv_graph_color_agent.call(srvr); 00838 } else if (tb_skiller->get_active() && __srv_graph_color_skiller.exists()) { 00839 printf("Calling skiller\n"); 00840 __srv_graph_color_skiller.call(srvr); 00841 } 00842 #endif 00843 } 00844 00845 void 00846 SkillGuiGtkWindow::on_followactivestate_toggled() 00847 { 00848 #ifdef USE_PAPYRUS 00849 #else 00850 bool follow_active_state = tb_followactivestate->get_active(); 00851 #ifdef HAVE_GCONFMM 00852 __gconf->set(GCONF_PREFIX"/follow_active_state", follow_active_state); 00853 #endif 00854 gda->set_follow_active_state(follow_active_state); 00855 #endif 00856 } 00857 00858 #ifndef USE_ROS 00859 void 00860 SkillGuiGtkWindow::send_graphdir_message(fawkes::SkillerDebugInterface *iface, 00861 fawkes::SkillerDebugInterface::GraphDirectionEnum gd) 00862 { 00863 try { 00864 if (iface) { 00865 SkillerDebugInterface::SetGraphDirectionMessage *m; 00866 m = new SkillerDebugInterface::SetGraphDirectionMessage(gd); 00867 iface->msgq_enqueue(m); 00868 } else { 00869 throw Exception("Not connected to Fawkes."); 00870 } 00871 } catch (Exception &e) { 00872 Gtk::MessageDialog md(*this, 00873 Glib::ustring("Setting graph direction failed: ") + e.what(), 00874 /* markup */ false, 00875 Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, 00876 /* modal */ true); 00877 md.set_title("Communication Failure"); 00878 md.run(); 00879 } 00880 } 00881 00882 void 00883 SkillGuiGtkWindow::on_graphdir_changed(fawkes::SkillerDebugInterface::GraphDirectionEnum gd) 00884 { 00885 if (tb_agent->get_active()) { 00886 send_graphdir_message(__agdbg_if, gd); 00887 } else { 00888 send_graphdir_message(__skdbg_if, gd); 00889 } 00890 } 00891 00892 00893 #else 00894 00895 00896 void 00897 SkillGuiGtkWindow::on_graph_changed() 00898 { 00899 skiller::Graph::ConstPtr msg = tb_agent->get_active() ? __graph_msg_agent : __graph_msg_skiller; 00900 00901 std::string graph_name = ""; 00902 std::string dotgraph = ""; 00903 00904 if (! msg) { 00905 // clear 00906 update_graph(graph_name, dotgraph); 00907 return; 00908 } 00909 00910 graph_name = msg->name; 00911 dotgraph = msg->dotgraph; 00912 update_graph(graph_name, dotgraph); 00913 00914 switch (msg->direction) { 00915 case skiller::Graph::GRAPH_DIR_TOP_BOTTOM: 00916 tb_graphdir->set_stock_id(Gtk::Stock::GO_DOWN); break; 00917 case skiller::Graph::GRAPH_DIR_BOTTOM_TOP: 00918 tb_graphdir->set_stock_id(Gtk::Stock::GO_UP); break; 00919 case skiller::Graph::GRAPH_DIR_LEFT_RIGHT: 00920 tb_graphdir->set_stock_id(Gtk::Stock::GO_FORWARD); break; 00921 case skiller::Graph::GRAPH_DIR_RIGHT_LEFT: 00922 tb_graphdir->set_stock_id(Gtk::Stock::GO_BACK); break; 00923 default: break; 00924 } 00925 00926 msg.reset(); 00927 } 00928 00929 void 00930 SkillGuiGtkWindow::ros_skiller_graphmsg_cb(const skiller::Graph::ConstPtr &msg) 00931 { 00932 __graph_msg_skiller = msg; 00933 if (tb_skiller->get_active()) __graph_changed(); 00934 } 00935 00936 00937 void 00938 SkillGuiGtkWindow::ros_agent_graphmsg_cb(const skiller::Graph::ConstPtr &msg) 00939 { 00940 __graph_msg_agent = msg; 00941 if (tb_agent->get_active()) __graph_changed(); 00942 } 00943 00944 00945 void 00946 SkillGuiGtkWindow::ros_exec_transition_cb(actionlib::ClientGoalHandle<skiller::ExecSkillAction> &gh) 00947 { 00948 CommState comm_state_ = gh.getCommState(); 00949 printf("Transition to %i\n", comm_state_.state_); 00950 if (comm_state_.state_ == CommState::DONE) { 00951 printf("State: %i\n", gh.getTerminalState().state_); 00952 switch(gh.getTerminalState().state_) { 00953 case TerminalState::LOST: break; // do not change anything 00954 case TerminalState::SUCCEEDED: 00955 __throbber->stop_anim(); 00956 __throbber->set_stock(Gtk::Stock::APPLY); 00957 lab_status->set_text("S_FINAL"); 00958 break; 00959 default: 00960 __throbber->stop_anim(); 00961 __throbber->set_stock(Gtk::Stock::DIALOG_WARNING); 00962 lab_status->set_text("S_FAILED"); 00963 if (gh.getResult() != NULL) { 00964 lab_error->set_text(gh.getResult()->errmsg); 00965 } 00966 break; 00967 } 00968 gh.reset(); 00969 } else { 00970 __throbber->start_anim(); 00971 lab_status->set_text("S_RUNNING"); 00972 lab_error->set_text(""); 00973 } 00974 } 00975 00976 void 00977 SkillGuiGtkWindow::ros_exec_feedback_cb(actionlib::ClientGoalHandle<skiller::ExecSkillAction> &gh, 00978 const skiller::ExecSkillFeedbackConstPtr &feedback) 00979 { 00980 } 00981 00982 #endif 00983 00984 00985 SkillGuiGtkWindow::SkillStringRecord::SkillStringRecord() 00986 { 00987 add(skillstring); 00988 } 00989 00990 00991 void 00992 SkillGuiGtkWindow::on_update_disabled() 00993 { 00994 #ifdef USE_PAPYRUS 00995 #else 00996 tb_graphupd->set_stock_id(Gtk::Stock::MEDIA_STOP); 00997 #endif 00998 } 00999 01000 01001 void 01002 SkillGuiGtkWindow::on_recording_toggled() 01003 { 01004 #ifdef USE_PAPYRUS 01005 #else 01006 bool active = tb_graphrecord->get_active(); 01007 if (gda->set_recording(active) != active) { 01008 tb_graphrecord->set_active(!active); 01009 } 01010 #endif 01011 }