00001 #include <QInputDialog> 00002 #include "mrta/system.h" 00003 #include <ros/package.h> 00004 #include <ros/console.h> 00005 #include "rqt_mrta/config/architecture/rqt_mrta_architecture.h" 00006 #include "rqt_mrta/config/application/rqt_mrta_application.h" 00007 #include "rqt_mrta/labeled_status_widget.h" 00008 #include "rqt_mrta/new_application_wizard.h" 00009 #include "rqt_mrta/new_architecture_wizard.h" 00010 #include "rqt_mrta/rqt_mrta_widget.h" 00011 #include "rqt_mrta/ui_rqt_mrta_widget.h" 00012 #include "utilities/exception.h" 00013 #include "utilities/message_subscriber_registry.h" 00014 00015 namespace rqt_mrta 00016 { 00017 RqtMrtaWidget::RqtMrtaWidget(QWidget* parent, 00018 const qt_gui_cpp::PluginContext& context) 00019 : QWidget(parent), ui_(new Ui::RqtMrtaWidget()), 00020 architecture_config_(new RqtMrtaArchitectureConfig(this)), 00021 application_config_(new RqtMrtaApplicationConfig(this)), 00022 registry_(new utilities::MessageSubscriberRegistry(this)), 00023 context_(context), loader_("rqt_gui", "rqt_gui_cpp::Plugin"), 00024 system_(NULL) 00025 { 00026 ui_->setupUi(this); 00027 ui_->runtime_tab_widget->setCurrentIndex(0); 00028 ui_->architecture_tab->activateWindow(); 00029 ui_->new_application_push_button->setIcon(QIcon(QString::fromStdString( 00030 ros::package::getPath("rqt_mrta").append("/resource/22x22/new.png")))); 00031 ui_->open_application_push_button->setIcon(QIcon(QString::fromStdString( 00032 ros::package::getPath("rqt_mrta").append("/resource/22x22/open.png")))); 00033 ui_->launch_application_push_button->setIcon(QIcon(QString::fromStdString( 00034 ros::package::getPath("rqt_mrta").append("/resource/22x22/run.png")))); 00035 ui_->new_architecture_push_button->setIcon(QIcon(QString::fromStdString( 00036 ros::package::getPath("rqt_mrta").append("/resource/22x22/new.png")))); 00037 ui_->open_architecture_push_button->setIcon(QIcon(QString::fromStdString( 00038 ros::package::getPath("rqt_mrta").append("/resource/22x22/open.png")))); 00039 connect(ui_->new_application_push_button, SIGNAL(clicked()), this, 00040 SLOT(newApplicationPushButtonClicked())); 00041 connect(ui_->open_application_push_button, SIGNAL(clicked()), this, 00042 SLOT(openApplicationPushButtonClicked())); 00043 connect(ui_->new_architecture_push_button, SIGNAL(clicked()), this, 00044 SLOT(newArchitecturePushButtonClicked())); 00045 connect(ui_->open_architecture_push_button, SIGNAL(clicked()), this, 00046 SLOT(openArchitecturePushButtonClicked())); 00047 } 00048 00049 RqtMrtaWidget::~RqtMrtaWidget() 00050 { 00051 clear(); 00052 if (ui_) 00053 { 00054 delete ui_; 00055 ui_ = NULL; 00056 } 00057 if (system_) 00058 { 00059 delete system_; 00060 system_ = NULL; 00061 } 00062 if (architecture_config_) 00063 { 00064 delete architecture_config_; 00065 architecture_config_ = NULL; 00066 } 00067 if (application_config_) 00068 { 00069 delete application_config_; 00070 application_config_ = NULL; 00071 } 00072 if (registry_) 00073 { 00074 delete registry_; 00075 registry_ = NULL; 00076 } 00077 } 00078 00079 void RqtMrtaWidget::newApplicationPushButtonClicked() 00080 { 00081 RqtMrtaApplicationConfig config; 00082 NewApplicationWizard wizard(this, &config); 00083 if (wizard.exec() == QWizard::Accepted) 00084 { 00085 loadSystem(&config); 00086 } 00087 } 00088 00089 void RqtMrtaWidget::openApplicationPushButtonClicked() 00090 { 00091 QMap<QString, QString> applications(findPlugins("application")); 00092 if (applications.isEmpty()) 00093 { 00094 showMessage("Error while loading architecture ...", 00095 "There isn't any application registered yet."); 00096 return; 00097 } 00098 QString package( 00099 askItem("Opening application ...", "Application:", applications.keys())); 00100 if (package.isEmpty()) 00101 { 00102 return; 00103 } 00104 loadApplication(applications[package]); 00105 } 00106 00107 void RqtMrtaWidget::newArchitecturePushButtonClicked() 00108 { 00109 RqtMrtaArchitectureConfig config; 00110 NewArchitectureWizard wizard(this, &config); 00111 if (wizard.exec() == QWizard::Accepted) 00112 { 00113 std::string url( 00114 ros::package::getPath(config.getArchitecturePackage().toStdString())); 00115 loadArchitecture(QString::fromStdString(url)); 00116 } 00117 } 00118 00119 void RqtMrtaWidget::openArchitecturePushButtonClicked() 00120 { 00121 QMap<QString, QString> architectures(findPlugins("architecture")); 00122 if (architectures.isEmpty()) 00123 { 00124 showMessage("Error while loading architecture ...", 00125 "There isn't any architecture registered yet."); 00126 return; 00127 } 00128 QString package(askItem("Opening architecture ...", "Architecture:", 00129 architectures.keys())); 00130 if (package.isEmpty()) 00131 { 00132 return; 00133 } 00134 loadArchitecture(architectures[package]); 00135 } 00136 00137 void RqtMrtaWidget::loadApplication(const QString& url) 00138 { 00139 RqtMrtaApplicationConfig application_config(this); 00140 try 00141 { 00142 application_config.load(url); 00143 } 00144 catch (const utilities::Exception& e) 00145 { 00146 showMessage("Error while loading application ...", e.what()); 00147 } 00148 loadSystem(&application_config); 00149 } 00150 00151 void RqtMrtaWidget::loadArchitecture(const QString& url) 00152 { 00153 QString architecture_url(url); 00154 if (architecture_url.isEmpty()) 00155 { 00156 QString package( 00157 application_config_->getApplication()->getArchitecturePackage()); 00158 if (package.isEmpty()) 00159 { 00160 showMessage("Error while loading architecture ...", 00161 "The architecture package name must not be empty."); 00162 return; 00163 } 00164 QMap<QString, QString> architectures(findPlugins("architecture")); 00165 if (architectures.isEmpty()) 00166 { 00167 showMessage("Error while loading architecture ...", 00168 "There isn't any architecture registered yet."); 00169 return; 00170 } 00171 if (!architectures.contains(package)) 00172 { 00173 showMessage("Error while loading architecture ...", 00174 "The given package does not have the architecture " 00175 "configuration file."); 00176 return; 00177 } 00178 architecture_url = architectures[package]; 00179 } 00180 try 00181 { 00182 architecture_config_->load(architecture_url); 00183 } 00184 catch (const utilities::Exception e) 00185 { 00186 showMessage("Error while loading architecture ...", e.what()); 00187 return; 00188 } 00189 for (size_t index(0); index < architecture_config_->getWidgets()->count(); 00190 index++) 00191 { 00192 QString plugin_name( 00193 architecture_config_->getWidgets()->getWidget(index)->getPluginName()); 00194 try 00195 { 00196 PluginPtr external_plugin( 00197 loader_.createInstance(plugin_name.toStdString())); 00198 external_plugin->initPlugin(context_); 00199 external_plugins_.push_back(external_plugin); 00200 } 00201 catch (pluginlib::PluginlibException& e) 00202 { 00203 showMessage("Error while loading architecture ...", 00204 "The " + plugin_name + 00205 " plugin failed to load for some reason. Error: " + 00206 e.what()); 00207 } 00208 } 00209 } 00210 00211 void RqtMrtaWidget::clear() 00212 { 00213 for (size_t index(0); index < external_plugins_.count(); index++) 00214 { 00215 external_plugins_[index]->shutdownPlugin(); 00216 } 00217 context_.closePlugin(); 00218 external_plugins_.clear(); 00219 ui_->robots_list_widget->clear(); 00220 for (size_t index(1); index < ui_->runtime_tab_widget->count(); index++) 00221 { 00222 ui_->runtime_tab_widget->removeTab(index); 00223 } 00224 if (system_) 00225 { 00226 delete system_; 00227 system_ = NULL; 00228 } 00229 } 00230 00231 void RqtMrtaWidget::loadSystem(RqtMrtaApplicationConfig* application_config) 00232 { 00233 clear(); 00234 if (application_config) 00235 { 00236 *application_config_ = *application_config; 00237 } 00238 loadArchitecture(); 00239 system_ = new mrta::System(this, application_config_, architecture_config_, 00240 registry_); 00241 QList<mrta::Robot*> robots(system_->getRobots()); 00242 for (size_t index(0); index < robots.count(); index++) 00243 { 00244 LabeledStatusWidget* widget = new LabeledStatusWidget(this, robots[index]); 00245 QListWidgetItem* item = new QListWidgetItem(ui_->robots_list_widget); 00246 item->setSizeHint(widget->sizeHint()); 00247 ui_->robots_list_widget->addItem(item); 00248 ui_->robots_list_widget->setItemWidget(item, widget); 00249 } 00250 } 00251 00252 void RqtMrtaWidget::showMessage(const QString& title, const QString& message, 00253 QMessageBox::Icon icon) const 00254 { 00255 switch (icon) 00256 { 00257 case QMessageBox::NoIcon: 00258 case QMessageBox::Information: 00259 ROS_INFO("%s", message.toStdString().c_str()); 00260 break; 00261 case QMessageBox::Warning: 00262 ROS_WARN("%s", message.toStdString().c_str()); 00263 break; 00264 case QMessageBox::Critical: 00265 ROS_ERROR("%s", message.toStdString().c_str()); 00266 break; 00267 } 00268 QMessageBox msg_box; 00269 msg_box.setText(title); 00270 msg_box.setInformativeText(message); 00271 msg_box.setIcon(icon); 00272 msg_box.exec(); 00273 } 00274 00275 QMap<QString, QString> 00276 RqtMrtaWidget::findPlugins(const QString& attribute) const 00277 { 00278 typedef std::map<std::string, std::string> StdMap; 00279 StdMap map; 00280 ros::package::getPlugins("rqt_mrta", attribute.toStdString(), map, true); 00281 QMap<QString, QString> applications; 00282 for (StdMap::const_iterator it(map.begin()); it != map.end(); it++) 00283 { 00284 ROS_WARN_STREAM("[RqtMrtaWidget::findPlugins] " << it->first << ": " 00285 << it->second); 00286 applications[QString::fromStdString(it->first)] = 00287 QString::fromStdString(it->second); 00288 } 00289 return applications; 00290 } 00291 00292 QString RqtMrtaWidget::askItem(const char* title, const char* label, 00293 const QStringList& items) 00294 { 00295 bool ok(false); 00296 QString item( 00297 QInputDialog::getItem(this, tr(title), tr(label), items, 0, false, &ok)); 00298 return ok ? item : ""; 00299 } 00300 }