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   // Load settings box ---------------------------------------------
00156   QHBoxLayout* load_files_layout = new QHBoxLayout();
00157 
00158   progress_bar_ = new QProgressBar(this);
00159   progress_bar_->setMaximum(100);
00160   progress_bar_->setMinimum(0);
00161   progress_bar_->hide();
00162   load_files_layout->addWidget(progress_bar_);
00163   // load_files_layout->setContentsMargins( 20, 30, 20, 30 );
00164 
00165   btn_load_ = new QPushButton("&Load Files", this);
00166   btn_load_->setMinimumWidth(180);
00167   btn_load_->setMinimumHeight(40);
00168   btn_load_->hide();
00169   load_files_layout->addWidget(btn_load_);
00170   load_files_layout->setAlignment(btn_load_, Qt::AlignRight);
00171   connect(btn_load_, SIGNAL(clicked()), this, SLOT(loadFilesClick()));
00172 
00173   // Next step instructions
00174   next_label_ = new QLabel(this);
00175   QFont next_label_font("Arial", 11, QFont::Bold);
00176   next_label_->setFont(next_label_font);
00177   // next_label_->setWordWrap(true);
00178   next_label_->setText("Success! Use the left navigation pane to continue.");
00179   //  next_label_->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00180   next_label_->hide();  // only show once the files have been loaded.
00181 
00182   right_layout->addWidget(right_image_label_);
00183   right_layout->setAlignment(right_image_label_, Qt::AlignRight | Qt::AlignTop);
00184 
00185   // Final Layout Setup ---------------------------------------------
00186   // Alignment
00187   layout->setAlignment(Qt::AlignTop);
00188   hlayout->setAlignment(Qt::AlignTop);
00189   left_layout->setAlignment(Qt::AlignTop);
00190   right_layout->setAlignment(Qt::AlignTop);
00191 
00192   // Stretch
00193   left_layout->setSpacing(30);
00194   // hlayout->setContentsMargins( 0, 20, 0, 0);
00195 
00196   // Attach Layouts
00197   hlayout->addLayout(left_layout);
00198   hlayout->addLayout(right_layout);
00199   layout->addLayout(hlayout);
00200 
00201   // Verticle Spacer
00202   QWidget* vspacer = new QWidget(this);
00203   vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00204   layout->addWidget(vspacer);
00205 
00206   // Attach bottom layout
00207   layout->addWidget(next_label_);
00208   layout->setAlignment(next_label_, Qt::AlignRight);
00209   layout->addLayout(load_files_layout);
00210 
00211   this->setLayout(layout);
00212   //  this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00213 
00214   // Debug mode: auto load the configuration file by clicking button after a timeout
00215   if (config_data_->debug_)
00216   {
00217     // select_mode_->btn_exist_->click();
00218 
00219     QTimer* update_timer = new QTimer(this);
00220     update_timer->setSingleShot(true);  // only run once
00221     connect(update_timer, SIGNAL(timeout()), btn_load_, SLOT(click()));
00222     update_timer->start(100);
00223   }
00224 }
00225 
00226 // ******************************************************************************************
00227 // Destructor
00228 // ******************************************************************************************
00229 StartScreenWidget::~StartScreenWidget()
00230 {
00231   delete right_image_;  // does not have a parent passed to it
00232   delete logo_image_;
00233 }
00234 
00235 // ******************************************************************************************
00236 // Show options for creating a new configuration package
00237 // ******************************************************************************************
00238 void StartScreenWidget::showNewOptions()
00239 {
00240   // Do GUI stuff
00241   select_mode_->btn_exist_->setChecked(false);
00242   select_mode_->btn_new_->setChecked(true);
00243   urdf_file_->show();
00244   stack_path_->hide();
00245   btn_load_->show();
00246 
00247   // Remember choice
00248   create_new_package_ = true;
00249 }
00250 
00251 // ******************************************************************************************
00252 // Show options for editing an existing configuration package
00253 // ******************************************************************************************
00254 void StartScreenWidget::showExistingOptions()
00255 {
00256   // Do GUI stuff
00257   select_mode_->btn_exist_->setChecked(true);
00258   select_mode_->btn_new_->setChecked(false);
00259   urdf_file_->hide();
00260   stack_path_->show();
00261   btn_load_->show();
00262 
00263   // Remember choice
00264   create_new_package_ = false;
00265 }
00266 
00267 // ******************************************************************************************
00268 // Load files to parameter server - CLICK
00269 // ******************************************************************************************
00270 void StartScreenWidget::loadFilesClick()
00271 {
00272   // Disable start screen GUI components from being changed
00273   urdf_file_->setDisabled(true);
00274   // srdf_file_->setDisabled(true);
00275   stack_path_->setDisabled(true);
00276   select_mode_->setDisabled(true);
00277   btn_load_->setDisabled(true);
00278   progress_bar_->show();
00279 
00280   bool result;
00281 
00282   // Decide if this is a new config package, or loading an old one
00283   if (create_new_package_)
00284   {
00285     result = loadNewFiles();
00286   }
00287   else
00288   {
00289     result = loadExistingFiles();
00290   }
00291 
00292   // Check if there was a failure loading files
00293   if (!result)
00294   {
00295     // Renable components
00296     urdf_file_->setDisabled(false);
00297     // srdf_file_->setDisabled(false);
00298     stack_path_->setDisabled(false);
00299     select_mode_->setDisabled(false);
00300     btn_load_->setDisabled(false);
00301     progress_bar_->hide();
00302   }
00303   else
00304   {
00305     // Hide the logo image so that other screens can resize the rviz thing properly
00306     right_image_label_->hide();
00307   }
00308 }
00309 
00310 // ******************************************************************************************
00311 // Load exisiting package files
00312 // ******************************************************************************************
00313 bool StartScreenWidget::loadExistingFiles()
00314 {
00315   // Progress Indicator
00316   progress_bar_->setValue(10);
00317   QApplication::processEvents();
00318 
00319   // Get the package path
00320   if (!createFullPackagePath())
00321     return false;  // error occured
00322 
00323   std::string setup_assistant_path;
00324 
00325   // Check if the old package is a setup assistant package. If it is not, quit
00326   if (!config_data_->getSetupAssistantYAMLPath(setup_assistant_path))
00327   {
00328     QMessageBox::warning(
00329         this, "Incorrect Directory/Package",
00330         QString("The chosen package location exists but was not previously created using this MoveIt Setup Assistant. "
00331                 "If this is a mistake, replace the missing file: ")
00332             .append(setup_assistant_path.c_str()));
00333     return false;
00334   }
00335 
00336   // Get setup assistant data
00337   if (!config_data_->inputSetupAssistantYAML(setup_assistant_path))
00338   {
00339     QMessageBox::warning(this, "Setup Assistant File Error",
00340                          QString("Unable to correctly parse the setup assistant configuration file: ")
00341                              .append(setup_assistant_path.c_str()));
00342     return false;
00343   }
00344 
00345   // Progress Indicator
00346   progress_bar_->setValue(30);
00347   QApplication::processEvents();
00348 
00349   // Get the URDF path using the loaded .setup_assistant data and check it
00350   if (!createFullURDFPath())
00351     return false;  // error occured
00352 
00353   // Load the URDF
00354   if (!loadURDFFile(config_data_->urdf_path_))
00355     return false;  // error occured
00356 
00357   // Get the SRDF path using the loaded .setup_assistant data and check it
00358   if (!createFullSRDFPath(config_data_->config_pkg_path_))
00359     return false;  // error occured
00360 
00361   // Progress Indicator
00362   progress_bar_->setValue(50);
00363   QApplication::processEvents();
00364 
00365   // Load the SRDF
00366   if (!loadSRDFFile(config_data_->srdf_path_))
00367     return false;  // error occured
00368 
00369   // Progress Indicator
00370   progress_bar_->setValue(60);
00371   QApplication::processEvents();
00372 
00373   // Load the allowed collision matrix
00374   config_data_->loadAllowedCollisionMatrix();
00375 
00376   // Load kinematics yaml file if available --------------------------------------------------
00377   fs::path kinematics_yaml_path = config_data_->config_pkg_path_;
00378   kinematics_yaml_path /= "config/kinematics.yaml";
00379 
00380   if (!config_data_->inputKinematicsYAML(kinematics_yaml_path.make_preferred().native().c_str()))
00381   {
00382     QMessageBox::warning(this, "No Kinematic YAML File",
00383                          QString("Failed to parse kinematics yaml file. This file is not critical but any previous "
00384                                  "kinematic solver settings have been lost. To re-populate this file edit each "
00385                                  "existing planning group and choose a solver, then save each change. \n\nFile error "
00386                                  "at location ")
00387                              .append(kinematics_yaml_path.make_preferred().native().c_str()));
00388   }
00389 
00390   // DONE LOADING --------------------------------------------------------------------------
00391 
00392   // Call a function that enables navigation
00393   Q_EMIT readyToProgress();
00394 
00395   // Progress Indicator
00396   progress_bar_->setValue(70);
00397   QApplication::processEvents();
00398 
00399   // Load Rviz
00400   Q_EMIT loadRviz();
00401 
00402   // Progress Indicator
00403   progress_bar_->setValue(100);
00404   QApplication::processEvents();
00405 
00406   next_label_->show();  // only show once the files have been loaded
00407 
00408   ROS_INFO("Loading Setup Assistant Complete");
00409   return true;  // success!
00410 }
00411 
00412 // ******************************************************************************************
00413 // Load chosen files for creating new package
00414 // ******************************************************************************************
00415 bool StartScreenWidget::loadNewFiles()
00416 {
00417   // Get URDF file path
00418   config_data_->urdf_path_ = urdf_file_->getPath();
00419 
00420   // Check that box is filled out
00421   if (config_data_->urdf_path_.empty())
00422   {
00423     QMessageBox::warning(this, "Error Loading Files", "No robot model file specefied");
00424     return false;
00425   }
00426 
00427   // Check that this file exits
00428   if (!fs::is_regular_file(config_data_->urdf_path_))
00429   {
00430     QMessageBox::warning(this, "Error Loading Files",
00431                          QString("Unable to locate the URDF file: ").append(config_data_->urdf_path_.c_str()));
00432     return false;
00433   }
00434 
00435   // Attempt to get the ROS package from the path
00436   if (!extractPackageNameFromPath())
00437   {
00438     return false;  // An error occurred
00439   }
00440 
00441   // Progress Indicator
00442   progress_bar_->setValue(20);
00443   QApplication::processEvents();
00444 
00445   // Load the URDF to the parameter server and check that it is correct format
00446   if (!loadURDFFile(config_data_->urdf_path_))
00447     return false;  // error occurred
00448 
00449   // Progress Indicator
00450   progress_bar_->setValue(50);
00451   QApplication::processEvents();
00452 
00453   // Create blank SRDF file
00454   const std::string blank_srdf = "<?xml version='1.0'?><robot name='" + config_data_->urdf_model_->getName() + "'></"
00455                                                                                                                "robot>";
00456 
00457   // Load a blank SRDF file to the parameter server
00458   if (!setSRDFFile(blank_srdf))
00459   {
00460     QMessageBox::warning(this, "Error Loading Files", "Failure loading blank SRDF file.");
00461     return false;
00462   }
00463 
00464   // Progress Indicator
00465   progress_bar_->setValue(60);
00466   QApplication::processEvents();
00467 
00468   // DONE LOADING --------------------------------------------------------------------------
00469 
00470   // Call a function that enables navigation
00471   Q_EMIT readyToProgress();
00472 
00473   // Progress Indicator
00474   progress_bar_->setValue(70);
00475   QApplication::processEvents();
00476 
00477   // Load Rviz
00478   Q_EMIT loadRviz();
00479 
00480   // Progress Indicator
00481   progress_bar_->setValue(100);
00482   QApplication::processEvents();
00483 
00484   next_label_->show();  // only show once the files have been loaded
00485 
00486   ROS_INFO("Loading Setup Assistant Complete");
00487   return true;  // success!
00488 }
00489 
00490 // ******************************************************************************************
00491 // Load URDF File to Parameter Server
00492 // ******************************************************************************************
00493 bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path)
00494 {
00495   // check that URDF can be loaded
00496   std::ifstream urdf_stream(urdf_file_path.c_str());
00497   if (!urdf_stream.good())  // File not found
00498   {
00499     QMessageBox::warning(this, "Error Loading Files",
00500                          QString("URDF/COLLADA file not found: ").append(urdf_file_path.c_str()));
00501     return false;
00502   }
00503   std::string urdf_string;
00504   bool xacro = false;
00505 
00506   if (urdf_file_path.find(".xacro") != std::string::npos)
00507   {
00508     std::string cmd("rosrun xacro xacro.py ");
00509     cmd += urdf_file_path;
00510     ROS_INFO("Running '%s'...", cmd.c_str());
00511 
00512     FILE* pipe = popen(cmd.c_str(), "r");
00513     if (!pipe)
00514     {
00515       QMessageBox::warning(this, "Error Loading Files",
00516                            QString("XACRO file or parser not found: ").append(urdf_file_path.c_str()));
00517       return false;
00518     }
00519     char buffer[128] = { 0 };
00520     while (!feof(pipe))
00521     {
00522       if (fgets(buffer, sizeof(buffer), pipe) != NULL)
00523         urdf_string += buffer;
00524     }
00525     pclose(pipe);
00526 
00527     if (urdf_string.empty())
00528     {
00529       QMessageBox::warning(this, "Error Loading Files",
00530                            QString("Unable to parse XACRO file: ").append(urdf_file_path.c_str()));
00531       return false;
00532     }
00533     xacro = true;
00534   }
00535   else
00536   {
00537     // Load the file to a string using an efficient memory allocation technique
00538     urdf_stream.seekg(0, std::ios::end);
00539     urdf_string.reserve(urdf_stream.tellg());
00540     urdf_stream.seekg(0, std::ios::beg);
00541     urdf_string.assign((std::istreambuf_iterator<char>(urdf_stream)), std::istreambuf_iterator<char>());
00542     urdf_stream.close();
00543   }
00544   // Verify that file is in correct format / not an XACRO by loading into robot model
00545   if (!config_data_->urdf_model_->initString(urdf_string))
00546   {
00547     QMessageBox::warning(this, "Error Loading Files", "URDF/COLLADA file is not a valid robot model.");
00548     return false;
00549   }
00550   config_data_->urdf_from_xacro_ = xacro;
00551 
00552   ROS_INFO_STREAM("Loaded " << config_data_->urdf_model_->getName() << " robot model.");
00553 
00554   // Load the robot model to the parameter server
00555   ros::NodeHandle nh;
00556   int steps = 0;
00557   while (!nh.ok() && steps < 4)
00558   {
00559     ROS_WARN("Waiting for node handle");
00560     sleep(1);
00561     steps++;
00562     ros::spinOnce();
00563   }
00564 
00565   ROS_INFO("Setting Param Server with Robot Description");
00566   // ROS_WARN("Ignore the following error message 'Failed to contact master'. This is a known issue.");
00567   nh.setParam("/robot_description", urdf_string);
00568 
00569   return true;
00570 }
00571 
00572 // ******************************************************************************************
00573 // Load SRDF File to Parameter Server
00574 // ******************************************************************************************
00575 bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path)
00576 {
00577   // check that SRDF can be loaded
00578   std::ifstream srdf_stream(srdf_file_path.c_str());
00579   if (!srdf_stream.good())  // File not found
00580   {
00581     QMessageBox::warning(this, "Error Loading Files",
00582                          QString("SRDF file not found: ").append(config_data_->srdf_path_.c_str()));
00583     return false;
00584   }
00585 
00586   // Load the file to a string using an efficient memory allocation technique
00587   std::string srdf_string;
00588   srdf_stream.seekg(0, std::ios::end);
00589   srdf_string.reserve(srdf_stream.tellg());
00590   srdf_stream.seekg(0, std::ios::beg);
00591   srdf_string.assign((std::istreambuf_iterator<char>(srdf_stream)), std::istreambuf_iterator<char>());
00592   srdf_stream.close();
00593 
00594   // Put on param server
00595   return setSRDFFile(srdf_string);
00596 }
00597 
00598 // ******************************************************************************************
00599 // Put SRDF File on Parameter Server
00600 // ******************************************************************************************
00601 bool StartScreenWidget::setSRDFFile(const std::string& srdf_string)
00602 {
00603   // Verify that file is in correct format / not an XACRO by loading into robot model
00604   if (!config_data_->srdf_->initString(*config_data_->urdf_model_, srdf_string))
00605   {
00606     QMessageBox::warning(this, "Error Loading Files", "SRDF file not a valid semantic robot description model.");
00607     return false;
00608   }
00609   ROS_INFO_STREAM("Robot semantic model successfully loaded.");
00610 
00611   // Load to param server
00612   ros::NodeHandle nh;
00613   int steps = 0;
00614   while (!nh.ok() && steps < 4)
00615   {
00616     ROS_WARN("Waiting for node handle");
00617     sleep(1);
00618     steps++;
00619     ros::spinOnce();
00620   }
00621 
00622   ROS_INFO("Setting Param Server with Robot Semantic Description");
00623   nh.setParam("/robot_description_semantic", srdf_string);
00624 
00625   return true;
00626 }
00627 
00628 // ******************************************************************************************
00629 // Extract the package/stack name and relative path to urdf from an absolute path name
00630 // Input:  cofig_data_->urdf_path_
00631 // Output: cofig_data_->urdf_pkg_name_
00632 //         cofig_data_->urdf_pkg_relative_path_
00633 // ******************************************************************************************
00634 bool StartScreenWidget::extractPackageNameFromPath()
00635 {
00636   // Get the path to urdf, save filename
00637   fs::path urdf_path = config_data_->urdf_path_;
00638   fs::path urdf_directory = urdf_path;
00639   urdf_directory.remove_filename();
00640 
00641   fs::path sub_path;         // holds the directory less one folder
00642   fs::path relative_path;    // holds the path after the sub_path
00643   std::string package_name;  // result
00644 
00645   // Paths for testing if files exist
00646   fs::path package_path;
00647 
00648   std::vector<std::string> path_parts;  // holds each folder name in vector
00649 
00650   // Copy path into vector of parts
00651   for (fs::path::iterator it = urdf_directory.begin(); it != urdf_directory.end(); ++it)
00652     path_parts.push_back(it->native());
00653 
00654   bool packageFound = false;
00655 
00656   // reduce the generated directoy path's folder count by 1 each loop
00657   for (int segment_length = path_parts.size(); segment_length > 0; --segment_length)
00658   {
00659     // Reset the sub_path
00660     sub_path.clear();
00661 
00662     // Create a subpath based on the outer loops length
00663     for (int segment_count = 0; segment_count < segment_length; ++segment_count)
00664     {
00665       sub_path /= path_parts[segment_count];
00666 
00667       // decide if we should remember this directory name because it is topmost, in case it is the package/stack name
00668       if (segment_count == segment_length - 1)
00669       {
00670         package_name = path_parts[segment_count];
00671       }
00672     }
00673 
00674     // check if this directory has a package.xml
00675     package_path = sub_path;
00676     package_path /= "package.xml";
00677     ROS_DEBUG_STREAM("Checking for " << package_path.make_preferred().native());
00678 
00679     // Check if the files exist
00680     if (fs::is_regular_file(package_path) || fs::is_regular_file(sub_path / "manifest.xml"))
00681     {
00682       // now generate the relative path
00683       for (size_t relative_count = segment_length; relative_count < path_parts.size(); ++relative_count)
00684         relative_path /= path_parts[relative_count];
00685 
00686       // add the URDF filename at end of relative path
00687       relative_path /= urdf_path.filename();
00688 
00689       // end the search
00690       segment_length = 0;
00691       packageFound = true;
00692       break;
00693     }
00694   }
00695 
00696   // Assign data to moveit_config_data
00697   if (!packageFound)
00698   {
00699     // No package name found, we must be outside ROS
00700     config_data_->urdf_pkg_name_ = "";
00701     config_data_->urdf_pkg_relative_path_ = config_data_->urdf_path_;  // just the absolute path
00702   }
00703   else
00704   {
00705     // Check that ROS can find the package
00706     const std::string robot_desc_pkg_path = ros::package::getPath(config_data_->urdf_pkg_name_) + "/";
00707 
00708     if (robot_desc_pkg_path.empty())
00709     {
00710       QMessageBox::warning(this, "Package Not Found In ROS Workspace",
00711                            QString("ROS was unable to find the package name '")
00712                                .append(config_data_->urdf_pkg_name_.c_str())
00713                                .append("' within the ROS workspace. This may cause issues later."));
00714     }
00715 
00716     // Success
00717     config_data_->urdf_pkg_name_ = package_name;
00718     config_data_->urdf_pkg_relative_path_ = relative_path.make_preferred().native();
00719   }
00720 
00721   ROS_DEBUG_STREAM("URDF Package Name: " << config_data_->urdf_pkg_name_);
00722   ROS_DEBUG_STREAM("URDF Package Path: " << config_data_->urdf_pkg_relative_path_);
00723 
00724   return true;  // success
00725 }
00726 
00727 // ******************************************************************************************
00728 // Make the full URDF path using the loaded .setup_assistant data
00729 // ******************************************************************************************
00730 bool StartScreenWidget::createFullURDFPath()
00731 {
00732   if (!config_data_->createFullURDFPath())
00733   {
00734     if (config_data_->urdf_path_.empty())  // no path could be resolved
00735     {
00736       QMessageBox::warning(this, "Error Loading Files", QString("ROS was unable to find the package name '")
00737                                                             .append(config_data_->urdf_pkg_name_.c_str())
00738                                                             .append("'. Verify this package is inside your ROS "
00739                                                                     "workspace and is a proper ROS package."));
00740     }
00741     else
00742     {
00743       QMessageBox::warning(
00744           this, "Error Loading Files",
00745           QString("Unable to locate the URDF file in package. File: ").append(config_data_->urdf_path_.c_str()));
00746     }
00747     return false;
00748   }
00749   fs::path urdf_path;
00750 
00751   // Check if a package name was provided
00752   if (config_data_->urdf_pkg_name_.empty())
00753   {
00754     ROS_WARN("The URDF path is absolute to the filesystem and not relative to a ROS package/stack");
00755   }
00756 
00757   return true;  // success
00758 }
00759 
00760 // ******************************************************************************************
00761 // Make the full SRDF path using the loaded .setup_assistant data
00762 // ******************************************************************************************
00763 bool StartScreenWidget::createFullSRDFPath(const std::string& package_path)
00764 {
00765   if (!config_data_->createFullSRDFPath(package_path))
00766   {
00767     QMessageBox::warning(this, "Error Loading Files",
00768                          QString("Unable to locate the SRDF file: ").append(config_data_->srdf_path_.c_str()));
00769     return false;
00770   }
00771 
00772   return true;  // success
00773 }
00774 
00775 // ******************************************************************************************
00776 // Get the full package path for editing an existing package
00777 // ******************************************************************************************
00778 bool StartScreenWidget::createFullPackagePath()
00779 {
00780   // Get package path
00781   std::string package_path_input = stack_path_->getPath();
00782   // check that input is provided
00783   if (package_path_input.empty())
00784   {
00785     QMessageBox::warning(this, "Error Loading Files", "Please specify a configuration package path to load.");
00786     return false;
00787   }
00788 
00789   // check that the folder exists
00790   if (!config_data_->setPackagePath(package_path_input))
00791   {
00792     QMessageBox::critical(this, "Error Loading Files", "The specified path is not a directory or is not accessable");
00793     return false;
00794   }
00795   return true;
00796 }
00797 
00798 // ******************************************************************************************
00799 // ******************************************************************************************
00800 // Class for selecting which mode
00801 // ******************************************************************************************
00802 // ******************************************************************************************
00803 
00804 // ******************************************************************************************
00805 // Create the widget
00806 // ******************************************************************************************
00807 SelectModeWidget::SelectModeWidget(QWidget* parent) : QFrame(parent)
00808 {
00809   // Set frame graphics
00810   setFrameShape(QFrame::StyledPanel);
00811   setFrameShadow(QFrame::Raised);
00812   setLineWidth(1);
00813   setMidLineWidth(0);
00814 
00815   // Basic widget container
00816   QVBoxLayout* layout = new QVBoxLayout(this);
00817 
00818   // Horizontal layout splitter
00819   QHBoxLayout* hlayout = new QHBoxLayout();
00820 
00821   // Widget Title
00822   QLabel* widget_title = new QLabel(this);
00823   widget_title->setText("Choose mode:");
00824   QFont widget_title_font("Arial", 12, QFont::Bold);
00825   widget_title->setFont(widget_title_font);
00826   layout->addWidget(widget_title);
00827   layout->setAlignment(widget_title, Qt::AlignTop);
00828 
00829   // Widget Instructions
00830   QTextEdit* widget_instructions = new QTextEdit(this);
00831   widget_instructions->setText("All settings for MoveIt are stored in a Moveit configuration package. Here you have "
00832                                "the option to create a new configuration package, or load an existing one. Note: any "
00833                                "changes to a MoveIt configuration package outside this setup assistant will likely be "
00834                                "overwritten by this tool.");
00835   widget_instructions->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
00836   // widget_instructions->setMinimumWidth(1);
00837   layout->addWidget(widget_instructions);
00838   layout->setAlignment(widget_instructions, Qt::AlignTop);
00839 
00840   // New Button
00841   btn_new_ = new QPushButton(this);
00842   btn_new_->setText("Create &New MoveIt\nConfiguration Package");
00843   hlayout->addWidget(btn_new_);
00844 
00845   // Exist Button
00846   btn_exist_ = new QPushButton(this);
00847   btn_exist_->setText("&Edit Existing MoveIt\nConfiguration Package");
00848   btn_exist_->setCheckable(true);
00849   hlayout->addWidget(btn_exist_);
00850 
00851   // Add horizontal layer to verticle layer
00852   layout->addLayout(hlayout);
00853   setLayout(layout);
00854   btn_new_->setCheckable(true);
00855 }
00856 
00857 }  // namespace


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Mon Jul 24 2017 02:22:29