start_screen_widget.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2012, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Dave Coleman */
00036 
00037 // Qt
00038 #include <QLabel>
00039 #include <QTimer>
00040 #include <QVBoxLayout>
00041 #include <QHBoxLayout>
00042 #include <QMessageBox>
00043 #include <QString>
00044 #include <QApplication>
00045 #include <QFont>
00046 #include <QFileDialog>
00047 #include <QTextEdit>
00048 // ROS
00049 #include <ros/ros.h>
00050 #include <ros/package.h>  // for getting file path for loadng images
00051 // SA
00052 #include "header_widget.h"  // title and instructions
00053 #include "start_screen_widget.h"
00054 // C
00055 #include <fstream>  // for reading in urdf
00056 #include <streambuf>
00057 // Boost
00058 #include <boost/algorithm/string.hpp>  // for trimming whitespace from user input
00059 #include <boost/filesystem.hpp>        // for reading folders/files
00060 #include <boost/algorithm/string.hpp>  // for string find and replace in paths
00061 
00062 namespace moveit_setup_assistant
00063 {
00064 // Boost file system
00065 namespace fs = boost::filesystem;
00066 
00067 // ******************************************************************************************
00068 // Start screen user interface for MoveIt Configuration Assistant
00069 // ******************************************************************************************
00070 StartScreenWidget::StartScreenWidget(QWidget* parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
00071   : SetupScreenWidget(parent), config_data_(config_data)
00072 {
00073   // Basic widget container
00074   QVBoxLayout* layout = new QVBoxLayout(this);
00075 
00076   // Horizontal layout splitter
00077   QHBoxLayout* hlayout = new QHBoxLayout();
00078   // Left side of screen
00079   QVBoxLayout* left_layout = new QVBoxLayout();
00080   // Right side of screen
00081   QVBoxLayout* right_layout = new QVBoxLayout();
00082 
00083   // Right Image Area ----------------------------------------------
00084   right_image_ = new QImage();
00085   right_image_label_ = new QLabel(this);
00086   std::string image_path = "./resources/MoveIt_Setup_Asst_xSm.png";
00087   if (chdir(config_data_->setup_assistant_path_.c_str()) != 0)
00088   {
00089     ROS_ERROR("FAILED TO CHANGE PACKAGE TO moveit_setup_assistant");
00090   }
00091 
00092   if (right_image_->load(image_path.c_str()))
00093   {
00094     right_image_label_->setPixmap(QPixmap::fromImage(*right_image_));
00095     right_image_label_->setMinimumHeight(384);  // size of right_image_label_
00096     // right_image_label_->setMinimumWidth(450);
00097   }
00098   else
00099   {
00100     ROS_ERROR_STREAM("FAILED TO LOAD " << image_path);
00101   }
00102 
00103   logo_image_ = new QImage();
00104   logo_image_label_ = new QLabel(this);
00105   image_path = "./resources/moveit_logo.png";
00106 
00107   if (logo_image_->load(image_path.c_str()))
00108   {
00109     logo_image_label_->setPixmap(QPixmap::fromImage(logo_image_->scaledToHeight(50)));
00110     logo_image_label_->setMinimumWidth(96);
00111   }
00112   else
00113   {
00114     ROS_ERROR_STREAM("FAILED TO LOAD " << image_path);
00115   }
00116 
00117   // Top Label Area ---------------------------------------------------
00118   HeaderWidget* header = new HeaderWidget(
00119       "MoveIt Setup Assistant", "Welcome to the MoveIt Setup Assistant! These tools will assist you in creating a "
00120                                 "MoveIt configuration package that is required to run MoveIt. This includes generating "
00121                                 "a Semantic Robot Description Format (SRDF) file, kinematics configuration file and "
00122                                 "OMPL planning configuration file. It also involves creating launch files for move "
00123                                 "groups, OMPL planner, planning contexts and the planning warehouse.",
00124       this);
00125   layout->addWidget(header);
00126 
00127   left_layout->addWidget(logo_image_label_);
00128   left_layout->setAlignment(logo_image_label_, Qt::AlignLeft | Qt::AlignTop);
00129 
00130   // Select Mode Area -------------------------------------------------
00131   select_mode_ = new SelectModeWidget(this);
00132   connect(select_mode_->btn_new_, SIGNAL(clicked()), this, SLOT(showNewOptions()));
00133   connect(select_mode_->btn_exist_, SIGNAL(clicked()), this, SLOT(showExistingOptions()));
00134   left_layout->addWidget(select_mode_);
00135 
00136   // Path Box Area ----------------------------------------------------
00137 
00138   // Stack Path Dialog
00139   stack_path_ = new LoadPathWidget("Load MoveIt Configuration Package Path",
00140                                    "Specify the package name or path of an existing MoveIt configuration package to be "
00141                                    "edited for your robot. Example package name: <i>pr2_moveit_config</i>",
00142                                    true, this);  // is directory
00143   stack_path_->hide();                           // user needs to select option before this is shown
00144   left_layout->addWidget(stack_path_);
00145 
00146   // URDF File Dialog
00147   urdf_file_ =
00148       new LoadPathWidget("Load a URDF or COLLADA Robot Model",
00149                          "Specify the location of an existing Universal Robot Description Format or COLLADA file for "
00150                          "your robot. The robot model will be loaded to the parameter server for you.",
00151                          false, true, this);  // no directory, load only
00152   urdf_file_->hide();                         // user needs to select option before this is shown
00153   left_layout->addWidget(urdf_file_);
00154 
00155   // Checkbox to enable Jade+ xacro extensions when loading xacros.
00156   // Add it to the urdf LoadPathWidget's layout instead of to the left_layout,
00157   // as we want this widget to appear on the urdf LoadPathWidget only.
00158   chk_use_jade_xacro_ = new QCheckBox("Enable Jade+ xacro extensions", urdf_file_);
00159   chk_use_jade_xacro_->setToolTip("Enables the use of the xacro extensions that are available on ROS Jade and\n"
00160                                   "newer in ROS Indigo. Enable this if the xacro that will be loaded makes use\n"
00161                                   "of any of those features.");
00162   urdf_file_->layout()->addWidget(chk_use_jade_xacro_);
00163 
00164   // Load settings box ---------------------------------------------
00165   QHBoxLayout* load_files_layout = new QHBoxLayout();
00166 
00167   progress_bar_ = new QProgressBar(this);
00168   progress_bar_->setMaximum(100);
00169   progress_bar_->setMinimum(0);
00170   progress_bar_->hide();
00171   load_files_layout->addWidget(progress_bar_);
00172   // load_files_layout->setContentsMargins( 20, 30, 20, 30 );
00173 
00174   btn_load_ = new QPushButton("&Load Files", this);
00175   btn_load_->setMinimumWidth(180);
00176   btn_load_->setMinimumHeight(40);
00177   btn_load_->hide();
00178   load_files_layout->addWidget(btn_load_);
00179   load_files_layout->setAlignment(btn_load_, Qt::AlignRight);
00180   connect(btn_load_, SIGNAL(clicked()), this, SLOT(loadFilesClick()));
00181 
00182   // Next step instructions
00183   next_label_ = new QLabel(this);
00184   QFont next_label_font("Arial", 11, QFont::Bold);
00185   next_label_->setFont(next_label_font);
00186   // next_label_->setWordWrap(true);
00187   next_label_->setText("Success! Use the left navigation pane to continue.");
00188   //  next_label_->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00189   next_label_->hide();  // only show once the files have been loaded.
00190 
00191   right_layout->addWidget(right_image_label_);
00192   right_layout->setAlignment(right_image_label_, Qt::AlignRight | Qt::AlignTop);
00193 
00194   // Final Layout Setup ---------------------------------------------
00195   // Alignment
00196   layout->setAlignment(Qt::AlignTop);
00197   hlayout->setAlignment(Qt::AlignTop);
00198   left_layout->setAlignment(Qt::AlignTop);
00199   right_layout->setAlignment(Qt::AlignTop);
00200 
00201   // Stretch
00202   left_layout->setSpacing(30);
00203   // hlayout->setContentsMargins( 0, 20, 0, 0);
00204 
00205   // Attach Layouts
00206   hlayout->addLayout(left_layout);
00207   hlayout->addLayout(right_layout);
00208   layout->addLayout(hlayout);
00209 
00210   // Verticle Spacer
00211   QWidget* vspacer = new QWidget(this);
00212   vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00213   layout->addWidget(vspacer);
00214 
00215   // Attach bottom layout
00216   layout->addWidget(next_label_);
00217   layout->setAlignment(next_label_, Qt::AlignRight);
00218   layout->addLayout(load_files_layout);
00219 
00220   this->setLayout(layout);
00221   //  this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00222 
00223   // Debug mode: auto load the configuration file by clicking button after a timeout
00224   if (config_data_->debug_)
00225   {
00226     // select_mode_->btn_exist_->click();
00227 
00228     QTimer* update_timer = new QTimer(this);
00229     update_timer->setSingleShot(true);  // only run once
00230     connect(update_timer, SIGNAL(timeout()), btn_load_, SLOT(click()));
00231     update_timer->start(100);
00232   }
00233 }
00234 
00235 // ******************************************************************************************
00236 // Destructor
00237 // ******************************************************************************************
00238 StartScreenWidget::~StartScreenWidget()
00239 {
00240   delete right_image_;  // does not have a parent passed to it
00241   delete logo_image_;
00242 }
00243 
00244 // ******************************************************************************************
00245 // Show options for creating a new configuration package
00246 // ******************************************************************************************
00247 void StartScreenWidget::showNewOptions()
00248 {
00249   // Do GUI stuff
00250   select_mode_->btn_exist_->setChecked(false);
00251   select_mode_->btn_new_->setChecked(true);
00252   urdf_file_->show();
00253   stack_path_->hide();
00254   btn_load_->show();
00255 
00256   // Remember choice
00257   create_new_package_ = true;
00258 }
00259 
00260 // ******************************************************************************************
00261 // Show options for editing an existing configuration package
00262 // ******************************************************************************************
00263 void StartScreenWidget::showExistingOptions()
00264 {
00265   // Do GUI stuff
00266   select_mode_->btn_exist_->setChecked(true);
00267   select_mode_->btn_new_->setChecked(false);
00268   urdf_file_->hide();
00269   stack_path_->show();
00270   btn_load_->show();
00271 
00272   // Remember choice
00273   create_new_package_ = false;
00274 }
00275 
00276 // ******************************************************************************************
00277 // Load files to parameter server - CLICK
00278 // ******************************************************************************************
00279 void StartScreenWidget::loadFilesClick()
00280 {
00281   // Disable start screen GUI components from being changed
00282   urdf_file_->setDisabled(true);
00283   // srdf_file_->setDisabled(true);
00284   stack_path_->setDisabled(true);
00285   select_mode_->setDisabled(true);
00286   btn_load_->setDisabled(true);
00287   progress_bar_->show();
00288 
00289   bool result;
00290 
00291   // Decide if this is a new config package, or loading an old one
00292   if (create_new_package_)
00293   {
00294     result = loadNewFiles();
00295   }
00296   else
00297   {
00298     result = loadExistingFiles();
00299   }
00300 
00301   // Check if there was a failure loading files
00302   if (!result)
00303   {
00304     // Renable components
00305     urdf_file_->setDisabled(false);
00306     // srdf_file_->setDisabled(false);
00307     stack_path_->setDisabled(false);
00308     select_mode_->setDisabled(false);
00309     btn_load_->setDisabled(false);
00310     progress_bar_->hide();
00311   }
00312   else
00313   {
00314     // Hide the logo image so that other screens can resize the rviz thing properly
00315     right_image_label_->hide();
00316   }
00317 }
00318 
00319 // ******************************************************************************************
00320 // Load exisiting package files
00321 // ******************************************************************************************
00322 bool StartScreenWidget::loadExistingFiles()
00323 {
00324   // Progress Indicator
00325   progress_bar_->setValue(10);
00326   QApplication::processEvents();
00327 
00328   // Get the package path
00329   if (!createFullPackagePath())
00330     return false;  // error occured
00331 
00332   std::string setup_assistant_path;
00333 
00334   // Check if the old package is a setup assistant package. If it is not, quit
00335   if (!config_data_->getSetupAssistantYAMLPath(setup_assistant_path))
00336   {
00337     QMessageBox::warning(
00338         this, "Incorrect Directory/Package",
00339         QString("The chosen package location exists but was not previously created using this MoveIt Setup Assistant. "
00340                 "If this is a mistake, replace the missing file: ")
00341             .append(setup_assistant_path.c_str()));
00342     return false;
00343   }
00344 
00345   // Get setup assistant data
00346   if (!config_data_->inputSetupAssistantYAML(setup_assistant_path))
00347   {
00348     QMessageBox::warning(this, "Setup Assistant File Error",
00349                          QString("Unable to correctly parse the setup assistant configuration file: ")
00350                              .append(setup_assistant_path.c_str()));
00351     return false;
00352   }
00353 
00354   // Progress Indicator
00355   progress_bar_->setValue(30);
00356   QApplication::processEvents();
00357 
00358   // Get the URDF path using the loaded .setup_assistant data and check it
00359   if (!createFullURDFPath())
00360     return false;  // error occured
00361 
00362   // Load the URDF
00363   if (!loadURDFFile(config_data_->urdf_path_, config_data_->urdf_requires_jade_xacro_))
00364     return false;  // error occured
00365 
00366   // Get the SRDF path using the loaded .setup_assistant data and check it
00367   if (!createFullSRDFPath(config_data_->config_pkg_path_))
00368     return false;  // error occured
00369 
00370   // Progress Indicator
00371   progress_bar_->setValue(50);
00372   QApplication::processEvents();
00373 
00374   // Load the SRDF
00375   if (!loadSRDFFile(config_data_->srdf_path_))
00376     return false;  // error occured
00377 
00378   // Progress Indicator
00379   progress_bar_->setValue(60);
00380   QApplication::processEvents();
00381 
00382   // Load the allowed collision matrix
00383   config_data_->loadAllowedCollisionMatrix();
00384 
00385   // Load kinematics yaml file if available --------------------------------------------------
00386   fs::path kinematics_yaml_path = config_data_->config_pkg_path_;
00387   kinematics_yaml_path /= "config/kinematics.yaml";
00388 
00389   if (!config_data_->inputKinematicsYAML(kinematics_yaml_path.make_preferred().native().c_str()))
00390   {
00391     QMessageBox::warning(this, "No Kinematic YAML File",
00392                          QString("Failed to parse kinematics yaml file. This file is not critical but any previous "
00393                                  "kinematic solver settings have been lost. To re-populate this file edit each "
00394                                  "existing planning group and choose a solver, then save each change. \n\nFile error "
00395                                  "at location ")
00396                              .append(kinematics_yaml_path.make_preferred().native().c_str()));
00397   }
00398 
00399   // DONE LOADING --------------------------------------------------------------------------
00400 
00401   // Call a function that enables navigation
00402   Q_EMIT readyToProgress();
00403 
00404   // Progress Indicator
00405   progress_bar_->setValue(70);
00406   QApplication::processEvents();
00407 
00408   // Load Rviz
00409   Q_EMIT loadRviz();
00410 
00411   // Progress Indicator
00412   progress_bar_->setValue(100);
00413   QApplication::processEvents();
00414 
00415   next_label_->show();  // only show once the files have been loaded
00416 
00417   ROS_INFO("Loading Setup Assistant Complete");
00418   return true;  // success!
00419 }
00420 
00421 // ******************************************************************************************
00422 // Load chosen files for creating new package
00423 // ******************************************************************************************
00424 bool StartScreenWidget::loadNewFiles()
00425 {
00426   // Get URDF file path
00427   config_data_->urdf_path_ = urdf_file_->getPath();
00428   // Check whether user wants to enable Jade+ Xacro extensions (only used when actually loading a XACRO)
00429   config_data_->urdf_requires_jade_xacro_ = chk_use_jade_xacro_->isChecked();
00430 
00431   // Check that box is filled out
00432   if (config_data_->urdf_path_.empty())
00433   {
00434     QMessageBox::warning(this, "Error Loading Files", "No robot model file specefied");
00435     return false;
00436   }
00437 
00438   // Check that this file exits
00439   if (!fs::is_regular_file(config_data_->urdf_path_))
00440   {
00441     QMessageBox::warning(this, "Error Loading Files",
00442                          QString("Unable to locate the URDF file: ").append(config_data_->urdf_path_.c_str()));
00443     return false;
00444   }
00445 
00446   // Attempt to get the ROS package from the path
00447   if (!extractPackageNameFromPath())
00448   {
00449     return false;  // An error occurred
00450   }
00451 
00452   // Progress Indicator
00453   progress_bar_->setValue(20);
00454   QApplication::processEvents();
00455 
00456   // Load the URDF to the parameter server and check that it is correct format
00457   if (!loadURDFFile(config_data_->urdf_path_, config_data_->urdf_requires_jade_xacro_))
00458     return false;  // error occurred
00459 
00460   // Progress Indicator
00461   progress_bar_->setValue(50);
00462   QApplication::processEvents();
00463 
00464   // Create blank SRDF file
00465   const std::string blank_srdf = "<?xml version='1.0'?><robot name='" + config_data_->urdf_model_->getName() + "'></"
00466                                                                                                                "robot>";
00467 
00468   // Load a blank SRDF file to the parameter server
00469   if (!setSRDFFile(blank_srdf))
00470   {
00471     QMessageBox::warning(this, "Error Loading Files", "Failure loading blank SRDF file.");
00472     return false;
00473   }
00474 
00475   // Progress Indicator
00476   progress_bar_->setValue(60);
00477   QApplication::processEvents();
00478 
00479   // DONE LOADING --------------------------------------------------------------------------
00480 
00481   // Call a function that enables navigation
00482   Q_EMIT readyToProgress();
00483 
00484   // Progress Indicator
00485   progress_bar_->setValue(70);
00486   QApplication::processEvents();
00487 
00488   // Load Rviz
00489   Q_EMIT loadRviz();
00490 
00491   // Progress Indicator
00492   progress_bar_->setValue(100);
00493   QApplication::processEvents();
00494 
00495   next_label_->show();  // only show once the files have been loaded
00496 
00497   ROS_INFO("Loading Setup Assistant Complete");
00498   return true;  // success!
00499 }
00500 
00501 // ******************************************************************************************
00502 // Load URDF File to Parameter Server
00503 // ******************************************************************************************
00504 bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path, bool use_jade_xacro)
00505 {
00506   // check that URDF can be loaded
00507   std::ifstream urdf_stream(urdf_file_path.c_str());
00508   if (!urdf_stream.good())  // File not found
00509   {
00510     QMessageBox::warning(this, "Error Loading Files",
00511                          QString("URDF/COLLADA file not found: ").append(urdf_file_path.c_str()));
00512     return false;
00513   }
00514   std::string urdf_string;
00515   bool xacro = false;
00516 
00517   if (urdf_file_path.find(".xacro") != std::string::npos)
00518   {
00519     std::string cmd("rosrun xacro xacro.py ");
00520 
00521     // enable Jade+ xacro extensions
00522     if (use_jade_xacro)
00523       cmd += "--inorder ";
00524 
00525     cmd += urdf_file_path;
00526     ROS_INFO("Running '%s'...", cmd.c_str());
00527 
00528     FILE* pipe = popen(cmd.c_str(), "r");
00529     if (!pipe)
00530     {
00531       QMessageBox::warning(this, "Error Loading Files",
00532                            QString("XACRO file or parser not found: ").append(urdf_file_path.c_str()));
00533       return false;
00534     }
00535     char buffer[128] = { 0 };
00536     while (!feof(pipe))
00537     {
00538       if (fgets(buffer, sizeof(buffer), pipe) != NULL)
00539         urdf_string += buffer;
00540     }
00541     pclose(pipe);
00542 
00543     if (urdf_string.empty())
00544     {
00545       QMessageBox::warning(this, "Error Loading Files",
00546                            QString("Unable to parse XACRO file: ").append(urdf_file_path.c_str()));
00547       return false;
00548     }
00549     xacro = true;
00550   }
00551   else
00552   {
00553     // Load the file to a string using an efficient memory allocation technique
00554     urdf_stream.seekg(0, std::ios::end);
00555     urdf_string.reserve(urdf_stream.tellg());
00556     urdf_stream.seekg(0, std::ios::beg);
00557     urdf_string.assign((std::istreambuf_iterator<char>(urdf_stream)), std::istreambuf_iterator<char>());
00558     urdf_stream.close();
00559   }
00560   // Verify that file is in correct format / not an XACRO by loading into robot model
00561   if (!config_data_->urdf_model_->initString(urdf_string))
00562   {
00563     QMessageBox::warning(this, "Error Loading Files", "URDF/COLLADA file is not a valid robot model.");
00564     return false;
00565   }
00566   config_data_->urdf_from_xacro_ = xacro;
00567 
00568   ROS_INFO_STREAM("Loaded " << config_data_->urdf_model_->getName() << " robot model.");
00569 
00570   // Load the robot model to the parameter server
00571   ros::NodeHandle nh;
00572   int steps = 0;
00573   while (!nh.ok() && steps < 4)
00574   {
00575     ROS_WARN("Waiting for node handle");
00576     sleep(1);
00577     steps++;
00578     ros::spinOnce();
00579   }
00580 
00581   ROS_INFO("Setting Param Server with Robot Description");
00582   // ROS_WARN("Ignore the following error message 'Failed to contact master'. This is a known issue.");
00583   nh.setParam("/robot_description", urdf_string);
00584 
00585   return true;
00586 }
00587 
00588 // ******************************************************************************************
00589 // Load SRDF File to Parameter Server
00590 // ******************************************************************************************
00591 bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path)
00592 {
00593   // check that SRDF can be loaded
00594   std::ifstream srdf_stream(srdf_file_path.c_str());
00595   if (!srdf_stream.good())  // File not found
00596   {
00597     QMessageBox::warning(this, "Error Loading Files",
00598                          QString("SRDF file not found: ").append(config_data_->srdf_path_.c_str()));
00599     return false;
00600   }
00601 
00602   // Load the file to a string using an efficient memory allocation technique
00603   std::string srdf_string;
00604   srdf_stream.seekg(0, std::ios::end);
00605   srdf_string.reserve(srdf_stream.tellg());
00606   srdf_stream.seekg(0, std::ios::beg);
00607   srdf_string.assign((std::istreambuf_iterator<char>(srdf_stream)), std::istreambuf_iterator<char>());
00608   srdf_stream.close();
00609 
00610   // Put on param server
00611   return setSRDFFile(srdf_string);
00612 }
00613 
00614 // ******************************************************************************************
00615 // Put SRDF File on Parameter Server
00616 // ******************************************************************************************
00617 bool StartScreenWidget::setSRDFFile(const std::string& srdf_string)
00618 {
00619   // Verify that file is in correct format / not an XACRO by loading into robot model
00620   if (!config_data_->srdf_->initString(*config_data_->urdf_model_, srdf_string))
00621   {
00622     QMessageBox::warning(this, "Error Loading Files", "SRDF file not a valid semantic robot description model.");
00623     return false;
00624   }
00625   ROS_INFO_STREAM("Robot semantic model successfully loaded.");
00626 
00627   // Load to param server
00628   ros::NodeHandle nh;
00629   int steps = 0;
00630   while (!nh.ok() && steps < 4)
00631   {
00632     ROS_WARN("Waiting for node handle");
00633     sleep(1);
00634     steps++;
00635     ros::spinOnce();
00636   }
00637 
00638   ROS_INFO("Setting Param Server with Robot Semantic Description");
00639   nh.setParam("/robot_description_semantic", srdf_string);
00640 
00641   return true;
00642 }
00643 
00644 // ******************************************************************************************
00645 // Extract the package/stack name and relative path to urdf from an absolute path name
00646 // Input:  cofig_data_->urdf_path_
00647 // Output: cofig_data_->urdf_pkg_name_
00648 //         cofig_data_->urdf_pkg_relative_path_
00649 // ******************************************************************************************
00650 bool StartScreenWidget::extractPackageNameFromPath()
00651 {
00652   // Get the path to urdf, save filename
00653   fs::path urdf_path = config_data_->urdf_path_;
00654   fs::path urdf_directory = urdf_path;
00655   urdf_directory.remove_filename();
00656 
00657   fs::path sub_path;         // holds the directory less one folder
00658   fs::path relative_path;    // holds the path after the sub_path
00659   std::string package_name;  // result
00660 
00661   // Paths for testing if files exist
00662   fs::path package_path;
00663 
00664   std::vector<std::string> path_parts;  // holds each folder name in vector
00665 
00666   // Copy path into vector of parts
00667   for (fs::path::iterator it = urdf_directory.begin(); it != urdf_directory.end(); ++it)
00668     path_parts.push_back(it->native());
00669 
00670   bool packageFound = false;
00671 
00672   // reduce the generated directoy path's folder count by 1 each loop
00673   for (int segment_length = path_parts.size(); segment_length > 0; --segment_length)
00674   {
00675     // Reset the sub_path
00676     sub_path.clear();
00677 
00678     // Create a subpath based on the outer loops length
00679     for (int segment_count = 0; segment_count < segment_length; ++segment_count)
00680     {
00681       sub_path /= path_parts[segment_count];
00682 
00683       // decide if we should remember this directory name because it is topmost, in case it is the package/stack name
00684       if (segment_count == segment_length - 1)
00685       {
00686         package_name = path_parts[segment_count];
00687       }
00688     }
00689 
00690     // check if this directory has a package.xml
00691     package_path = sub_path;
00692     package_path /= "package.xml";
00693     ROS_DEBUG_STREAM("Checking for " << package_path.make_preferred().native());
00694 
00695     // Check if the files exist
00696     if (fs::is_regular_file(package_path) || fs::is_regular_file(sub_path / "manifest.xml"))
00697     {
00698       // now generate the relative path
00699       for (size_t relative_count = segment_length; relative_count < path_parts.size(); ++relative_count)
00700         relative_path /= path_parts[relative_count];
00701 
00702       // add the URDF filename at end of relative path
00703       relative_path /= urdf_path.filename();
00704 
00705       // end the search
00706       segment_length = 0;
00707       packageFound = true;
00708       break;
00709     }
00710   }
00711 
00712   // Assign data to moveit_config_data
00713   if (!packageFound)
00714   {
00715     // No package name found, we must be outside ROS
00716     config_data_->urdf_pkg_name_ = "";
00717     config_data_->urdf_pkg_relative_path_ = config_data_->urdf_path_;  // just the absolute path
00718   }
00719   else
00720   {
00721     // Check that ROS can find the package
00722     const std::string robot_desc_pkg_path = ros::package::getPath(config_data_->urdf_pkg_name_) + "/";
00723 
00724     if (robot_desc_pkg_path.empty())
00725     {
00726       QMessageBox::warning(this, "Package Not Found In ROS Workspace",
00727                            QString("ROS was unable to find the package name '")
00728                                .append(config_data_->urdf_pkg_name_.c_str())
00729                                .append("' within the ROS workspace. This may cause issues later."));
00730     }
00731 
00732     // Success
00733     config_data_->urdf_pkg_name_ = package_name;
00734     config_data_->urdf_pkg_relative_path_ = relative_path.make_preferred().native();
00735   }
00736 
00737   ROS_DEBUG_STREAM("URDF Package Name: " << config_data_->urdf_pkg_name_);
00738   ROS_DEBUG_STREAM("URDF Package Path: " << config_data_->urdf_pkg_relative_path_);
00739 
00740   return true;  // success
00741 }
00742 
00743 // ******************************************************************************************
00744 // Make the full URDF path using the loaded .setup_assistant data
00745 // ******************************************************************************************
00746 bool StartScreenWidget::createFullURDFPath()
00747 {
00748   if (!config_data_->createFullURDFPath())
00749   {
00750     if (config_data_->urdf_path_.empty())  // no path could be resolved
00751     {
00752       QMessageBox::warning(this, "Error Loading Files", QString("ROS was unable to find the package name '")
00753                                                             .append(config_data_->urdf_pkg_name_.c_str())
00754                                                             .append("'. Verify this package is inside your ROS "
00755                                                                     "workspace and is a proper ROS package."));
00756     }
00757     else
00758     {
00759       QMessageBox::warning(
00760           this, "Error Loading Files",
00761           QString("Unable to locate the URDF file in package. File: ").append(config_data_->urdf_path_.c_str()));
00762     }
00763     return false;
00764   }
00765   fs::path urdf_path;
00766 
00767   // Check if a package name was provided
00768   if (config_data_->urdf_pkg_name_.empty())
00769   {
00770     ROS_WARN("The URDF path is absolute to the filesystem and not relative to a ROS package/stack");
00771   }
00772 
00773   return true;  // success
00774 }
00775 
00776 // ******************************************************************************************
00777 // Make the full SRDF path using the loaded .setup_assistant data
00778 // ******************************************************************************************
00779 bool StartScreenWidget::createFullSRDFPath(const std::string& package_path)
00780 {
00781   if (!config_data_->createFullSRDFPath(package_path))
00782   {
00783     QMessageBox::warning(this, "Error Loading Files",
00784                          QString("Unable to locate the SRDF file: ").append(config_data_->srdf_path_.c_str()));
00785     return false;
00786   }
00787 
00788   return true;  // success
00789 }
00790 
00791 // ******************************************************************************************
00792 // Get the full package path for editing an existing package
00793 // ******************************************************************************************
00794 bool StartScreenWidget::createFullPackagePath()
00795 {
00796   // Get package path
00797   std::string package_path_input = stack_path_->getPath();
00798   // check that input is provided
00799   if (package_path_input.empty())
00800   {
00801     QMessageBox::warning(this, "Error Loading Files", "Please specify a configuration package path to load.");
00802     return false;
00803   }
00804 
00805   // check that the folder exists
00806   if (!config_data_->setPackagePath(package_path_input))
00807   {
00808     QMessageBox::critical(this, "Error Loading Files", "The specified path is not a directory or is not accessable");
00809     return false;
00810   }
00811   return true;
00812 }
00813 
00814 // ******************************************************************************************
00815 // ******************************************************************************************
00816 // Class for selecting which mode
00817 // ******************************************************************************************
00818 // ******************************************************************************************
00819 
00820 // ******************************************************************************************
00821 // Create the widget
00822 // ******************************************************************************************
00823 SelectModeWidget::SelectModeWidget(QWidget* parent) : QFrame(parent)
00824 {
00825   // Set frame graphics
00826   setFrameShape(QFrame::StyledPanel);
00827   setFrameShadow(QFrame::Raised);
00828   setLineWidth(1);
00829   setMidLineWidth(0);
00830 
00831   // Basic widget container
00832   QVBoxLayout* layout = new QVBoxLayout(this);
00833 
00834   // Horizontal layout splitter
00835   QHBoxLayout* hlayout = new QHBoxLayout();
00836 
00837   // Widget Title
00838   QLabel* widget_title = new QLabel(this);
00839   widget_title->setText("Choose mode:");
00840   QFont widget_title_font("Arial", 12, QFont::Bold);
00841   widget_title->setFont(widget_title_font);
00842   layout->addWidget(widget_title);
00843   layout->setAlignment(widget_title, Qt::AlignTop);
00844 
00845   // Widget Instructions
00846   QTextEdit* widget_instructions = new QTextEdit(this);
00847   widget_instructions->setText("All settings for MoveIt are stored in a Moveit configuration package. Here you have "
00848                                "the option to create a new configuration package, or load an existing one. Note: any "
00849                                "changes to a MoveIt configuration package outside this setup assistant will likely be "
00850                                "overwritten by this tool.");
00851   widget_instructions->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
00852   // widget_instructions->setMinimumWidth(1);
00853   layout->addWidget(widget_instructions);
00854   layout->setAlignment(widget_instructions, Qt::AlignTop);
00855 
00856   // New Button
00857   btn_new_ = new QPushButton(this);
00858   btn_new_->setText("Create &New MoveIt\nConfiguration Package");
00859   hlayout->addWidget(btn_new_);
00860 
00861   // Exist Button
00862   btn_exist_ = new QPushButton(this);
00863   btn_exist_->setText("&Edit Existing MoveIt\nConfiguration Package");
00864   btn_exist_->setCheckable(true);
00865   hlayout->addWidget(btn_exist_);
00866 
00867   // Add horizontal layer to verticle layer
00868   layout->addLayout(hlayout);
00869   setLayout(layout);
00870   btn_new_->setCheckable(true);
00871 }
00872 
00873 }  // namespace


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Wed Jun 19 2019 19:25:13