start_screen_widget.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2012, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of Willow Garage nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *********************************************************************/
34 
35 /* Author: Dave Coleman */
36 
37 // Qt
38 #include <QLabel>
39 #include <QTimer>
40 #include <QVBoxLayout>
41 #include <QHBoxLayout>
42 #include <QMessageBox>
43 #include <QString>
44 #include <QApplication>
45 #include <QFont>
46 #include <QFileDialog>
47 // ROS
48 #include <ros/ros.h>
49 #include <ros/package.h> // for getting file path for loadng images
50 // SA
51 #include "header_widget.h" // title and instructions
52 #include "start_screen_widget.h"
53 // C
54 #include <fstream> // for reading in urdf
55 #include <streambuf>
56 // Boost
57 #include <boost/algorithm/string.hpp> // for trimming whitespace from user input
58 #include <boost/filesystem.hpp> // for reading folders/files
59 #include <boost/algorithm/string.hpp> // for string find and replace in paths
60 // MoveIt
62 
63 namespace moveit_setup_assistant
64 {
65 // Boost file system
66 namespace fs = boost::filesystem;
67 
68 // ******************************************************************************************
69 // Start screen user interface for MoveIt! Configuration Assistant
70 // ******************************************************************************************
71 StartScreenWidget::StartScreenWidget(QWidget* parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
72  : SetupScreenWidget(parent), config_data_(config_data)
73 {
74  // Basic widget container
75  QVBoxLayout* layout = new QVBoxLayout(this);
76 
77  // Horizontal layout splitter
78  QHBoxLayout* hlayout = new QHBoxLayout();
79  // Left side of screen
80  QVBoxLayout* left_layout = new QVBoxLayout();
81  // Right side of screen
82  QVBoxLayout* right_layout = new QVBoxLayout();
83 
84  // Right Image Area ----------------------------------------------
85  right_image_ = new QImage();
86  right_image_label_ = new QLabel(this);
87  std::string image_path = "./resources/MoveIt_Setup_Assistant2.png";
88  if (chdir(config_data_->setup_assistant_path_.c_str()) != 0)
89  {
90  ROS_ERROR("FAILED TO CHANGE PACKAGE TO moveit_setup_assistant");
91  }
92 
93  if (right_image_->load(image_path.c_str()))
94  {
95  right_image_label_->setPixmap(QPixmap::fromImage(*right_image_));
96  right_image_label_->setMinimumHeight(384); // size of right_image_label_
97  }
98  else
99  {
100  ROS_ERROR_STREAM("FAILED TO LOAD " << image_path);
101  }
102 
103  right_layout->addWidget(right_image_label_);
104  right_layout->setAlignment(right_image_label_, Qt::AlignRight | Qt::AlignTop);
105 
106  // Top Label Area ---------------------------------------------------
108  new HeaderWidget("MoveIt! Setup Assistant", "These tools will assist you in creating a Semantic Robot "
109  "Description Format (SRDF) file, various yaml configuration and many "
110  "roslaunch files for utilizing all aspects of MoveIt! functionality.",
111  this);
112  layout->addWidget(header);
113 
114  // Select Mode Area -------------------------------------------------
115  select_mode_ = new SelectModeWidget(this);
116  connect(select_mode_->btn_new_, SIGNAL(clicked()), this, SLOT(showNewOptions()));
117  connect(select_mode_->btn_exist_, SIGNAL(clicked()), this, SLOT(showExistingOptions()));
118  left_layout->addWidget(select_mode_);
119 
120  // Path Box Area ----------------------------------------------------
121 
122  // Stack Path Dialog
123  stack_path_ =
124  new LoadPathArgsWidget("Load MoveIt! Configuration Package",
125  "Specify the package name or path of an existing MoveIt! configuration package to be "
126  "edited for your robot. Example package name: <i>panda_moveit_config</i>",
127  "optional xacro arguments:", this, true); // directory
128  // user needs to select option before this is shown
129  stack_path_->hide();
130  stack_path_->setArgs("--inorder ");
131  connect(stack_path_, SIGNAL(pathChanged(QString)), this, SLOT(onPackagePathChanged(QString)));
132  left_layout->addWidget(stack_path_);
133 
134  // URDF File Dialog
135  urdf_file_ = new LoadPathArgsWidget("Load a URDF or COLLADA Robot Model",
136  "Specify the location of an existing Universal Robot Description Format or "
137  "COLLADA file for your robot",
138  "optional xacro arguments:", this, false, true); // no directory, load only
139  // user needs to select option before this is shown
140  urdf_file_->hide();
141  urdf_file_->setArgs("--inorder ");
142  connect(urdf_file_, SIGNAL(pathChanged(QString)), this, SLOT(onUrdfPathChanged(QString)));
143  left_layout->addWidget(urdf_file_);
144 
145  // Load settings box ---------------------------------------------
146  QHBoxLayout* load_files_layout = new QHBoxLayout();
147 
148  progress_bar_ = new QProgressBar(this);
149  progress_bar_->setMaximum(100);
150  progress_bar_->setMinimum(0);
151  progress_bar_->hide();
152  load_files_layout->addWidget(progress_bar_);
153 
154  btn_load_ = new QPushButton("&Load Files", this);
155  btn_load_->setMinimumWidth(180);
156  btn_load_->setMinimumHeight(40);
157  btn_load_->hide();
158  load_files_layout->addWidget(btn_load_);
159  load_files_layout->setAlignment(btn_load_, Qt::AlignRight);
160  connect(btn_load_, SIGNAL(clicked()), this, SLOT(loadFilesClick()));
161 
162  // Next step instructions
163  next_label_ = new QLabel(this);
164  QFont next_label_font(QFont().defaultFamily(), 11, QFont::Bold);
165  next_label_->setFont(next_label_font);
166  next_label_->setText("Success! Use the left navigation pane to continue.");
167  next_label_->hide(); // only show once the files have been loaded.
168 
169  // Final Layout Setup ---------------------------------------------
170  // Alignment
171  layout->setAlignment(Qt::AlignTop);
172  hlayout->setAlignment(Qt::AlignTop);
173  left_layout->setAlignment(Qt::AlignTop);
174  right_layout->setAlignment(Qt::AlignTop);
175 
176  // Stretch
177  left_layout->setSpacing(10);
178 
179  // Attach Layouts
180  hlayout->addLayout(left_layout);
181  hlayout->addLayout(right_layout);
182  layout->addLayout(hlayout);
183 
184  // Verticle Spacer
185  QWidget* vspacer = new QWidget(this);
186  vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
187  layout->addWidget(vspacer);
188 
189  // Attach bottom layout
190  layout->addWidget(next_label_);
191  layout->setAlignment(next_label_, Qt::AlignRight);
192  layout->addLayout(load_files_layout);
193 
194  this->setLayout(layout);
195 
196  // Debug mode: auto load the configuration file by clicking button after a timeout
197  if (config_data_->debug_)
198  {
199  // select_mode_->btn_exist_->click();
200 
201  QTimer* update_timer = new QTimer(this);
202  update_timer->setSingleShot(true); // only run once
203  connect(update_timer, SIGNAL(timeout()), btn_load_, SLOT(click()));
204  update_timer->start(100);
205  }
206 }
207 
208 // ******************************************************************************************
209 // Destructor
210 // ******************************************************************************************
212 {
213  delete right_image_; // does not have a parent passed to it
214 }
215 
216 // ******************************************************************************************
217 // Show options for creating a new configuration package
218 // ******************************************************************************************
220 {
221  // Do GUI stuff
222  select_mode_->btn_exist_->setChecked(false);
223  select_mode_->btn_new_->setChecked(true);
225  urdf_file_->show();
226  stack_path_->hide();
227  btn_load_->show();
228 
229  // Remember choice
230  create_new_package_ = true;
231 }
232 
233 // ******************************************************************************************
234 // Show options for editing an existing configuration package
235 // ******************************************************************************************
237 {
238  // Do GUI stuff
239  select_mode_->btn_exist_->setChecked(true);
240  select_mode_->btn_new_->setChecked(false);
242  urdf_file_->hide();
243  stack_path_->show();
244  btn_load_->show();
245 
246  // Remember choice
247  create_new_package_ = false;
248 }
249 
250 // ******************************************************************************************
251 // Load files to parameter server - CLICK
252 // ******************************************************************************************
254 {
255  // Disable start screen GUI components from being changed
256  urdf_file_->setDisabled(true);
257  // srdf_file_->setDisabled(true);
258  stack_path_->setDisabled(true);
259  select_mode_->setDisabled(true);
260  btn_load_->setDisabled(true);
261  progress_bar_->show();
262 
263  bool result;
264 
265  // Decide if this is a new config package, or loading an old one
267  {
268  result = loadNewFiles();
269  // Load 3d_sensors config file
271  }
272  else
273  {
274  result = loadExistingFiles();
275  }
276 
277  // Check if there was a failure loading files
278  if (!result)
279  {
280  // Renable components
281  urdf_file_->setDisabled(false);
282  // srdf_file_->setDisabled(false);
283  stack_path_->setDisabled(false);
284  select_mode_->setDisabled(false);
285  btn_load_->setDisabled(false);
286  progress_bar_->hide();
287  }
288  else
289  {
290  // Hide the logo image so that other screens can resize the rviz thing properly
291  right_image_label_->hide();
292  }
293 }
294 
296 {
297  if (!loadPackageSettings(false))
298  return;
299  // set xacro args from loaded settings
300  stack_path_->setArgs(QString::fromStdString(config_data_->xacro_args_));
301 }
302 
303 void StartScreenWidget::onUrdfPathChanged(const QString& path)
304 {
306 }
307 
309 {
310  // Get the package path
311  std::string package_path_input = stack_path_->getPath();
312  // Check that input is provided
313  if (package_path_input.empty())
314  {
315  if (show_warnings)
316  QMessageBox::warning(this, "Error Loading Files", "Please specify a configuration package path to load.");
317  return false;
318  }
319 
320  // check that the folder exists
321  if (!config_data_->setPackagePath(package_path_input))
322  {
323  if (show_warnings)
324  QMessageBox::critical(this, "Error Loading Files", "The specified path is not a directory or is not accessable");
325  return false;
326  }
327 
328  std::string setup_assistant_path;
329 
330  // Check if the old package is a setup assistant package. If it is not, quit
331  if (!config_data_->getSetupAssistantYAMLPath(setup_assistant_path))
332  {
333  if (show_warnings)
334  QMessageBox::warning(
335  this, "Incorrect Directory/Package",
336  QString("The chosen package location exists but was not created using MoveIt! Setup Assistant. "
337  "If this is a mistake, provide the missing file: ")
338  .append(setup_assistant_path.c_str()));
339  return false;
340  }
341 
342  // Get setup assistant data
343  if (!config_data_->inputSetupAssistantYAML(setup_assistant_path))
344  {
345  if (show_warnings)
346  QMessageBox::warning(this, "Setup Assistant File Error",
347  QString("Unable to correctly parse the setup assistant configuration file: ")
348  .append(setup_assistant_path.c_str()));
349  return false;
350  }
351  return true;
352 }
353 
354 // ******************************************************************************************
355 // Load exisiting package files
356 // ******************************************************************************************
358 {
359  // Progress Indicator
360  progress_bar_->setValue(10);
361  QApplication::processEvents();
362 
363  if (!loadPackageSettings(true))
364  return false;
365 
366  // Progress Indicator
367  progress_bar_->setValue(30);
368  QApplication::processEvents();
369 
370  // Get the URDF path using the loaded .setup_assistant data and check it
371  if (!createFullURDFPath())
372  return false; // error occured
373 
374  // use xacro args from GUI
375  config_data_->xacro_args_ = stack_path_->getArgs().toStdString();
376 
377  // Load the URDF
378  if (!loadURDFFile(config_data_->urdf_path_, config_data_->xacro_args_))
379  return false; // error occured
380 
381  // Get the SRDF path using the loaded .setup_assistant data and check it
382  if (!createFullSRDFPath(config_data_->config_pkg_path_))
383  return false; // error occured
384 
385  // Progress Indicator
386  progress_bar_->setValue(50);
387  QApplication::processEvents();
388 
389  // Load the SRDF
390  if (!loadSRDFFile(config_data_->srdf_path_))
391  return false; // error occured
392 
393  // Progress Indicator
394  progress_bar_->setValue(60);
395  QApplication::processEvents();
396 
397  // Load the allowed collision matrix
398  config_data_->loadAllowedCollisionMatrix();
399 
400  // Load kinematics yaml file if available --------------------------------------------------
401  fs::path kinematics_yaml_path = config_data_->config_pkg_path_;
402  kinematics_yaml_path /= "config/kinematics.yaml";
403 
404  if (!config_data_->inputKinematicsYAML(kinematics_yaml_path.make_preferred().native().c_str()))
405  {
406  QMessageBox::warning(this, "No Kinematic YAML File",
407  QString("Failed to parse kinematics yaml file. This file is not critical but any previous "
408  "kinematic solver settings have been lost. To re-populate this file edit each "
409  "existing planning group and choose a solver, then save each change. \n\nFile error "
410  "at location ")
411  .append(kinematics_yaml_path.make_preferred().native().c_str()));
412  }
413 
414  // Load 3d_sensors config file
416 
417  // Load ros controllers yaml file if available-----------------------------------------------
418  fs::path ros_controllers_yaml_path = config_data_->config_pkg_path_;
419  ros_controllers_yaml_path /= "config/ros_controllers.yaml";
420  config_data_->inputROSControllersYAML(ros_controllers_yaml_path.make_preferred().native().c_str());
421 
422  fs::path ompl_yaml_path = config_data_->config_pkg_path_;
423  ompl_yaml_path /= "config/ompl_planning.yaml";
424  config_data_->inputOMPLYAML(ompl_yaml_path.make_preferred().native().c_str());
425 
426  // DONE LOADING --------------------------------------------------------------------------
427 
428  // Call a function that enables navigation
429  Q_EMIT readyToProgress();
430 
431  // Progress Indicator
432  progress_bar_->setValue(70);
433  QApplication::processEvents();
434 
435  // Load Rviz
436  Q_EMIT loadRviz();
437 
438  // Progress Indicator
439  progress_bar_->setValue(100);
440  QApplication::processEvents();
441 
442  next_label_->show(); // only show once the files have been loaded
443 
444  ROS_INFO("Loading Setup Assistant Complete");
445  return true; // success!
446 }
447 
448 // ******************************************************************************************
449 // Load chosen files for creating new package
450 // ******************************************************************************************
452 {
453  // Get URDF file path
454  config_data_->urdf_path_ = urdf_file_->getPath();
455 
456  // Check that box is filled out
457  if (config_data_->urdf_path_.empty())
458  {
459  QMessageBox::warning(this, "Error Loading Files", "No robot model file specefied");
460  return false;
461  }
462 
463  // Check that this file exits
464  if (!fs::is_regular_file(config_data_->urdf_path_))
465  {
466  QMessageBox::warning(this, "Error Loading Files",
467  QString("Unable to locate the URDF file: ").append(config_data_->urdf_path_.c_str()));
468  return false;
469  }
470 
471  // Attempt to get the ROS package from the path
473  {
474  return false; // An error occurred
475  }
476 
477  // Progress Indicator
478  progress_bar_->setValue(20);
479  QApplication::processEvents();
480 
481  // use xacro args from GUI
482  config_data_->xacro_args_ = urdf_file_->getArgs().toStdString();
483 
484  // Load the URDF to the parameter server and check that it is correct format
485  if (!loadURDFFile(config_data_->urdf_path_, config_data_->xacro_args_))
486  return false; // error occurred
487 
488  // Progress Indicator
489  progress_bar_->setValue(50);
490  QApplication::processEvents();
491 
492  // Create blank SRDF file
493  const std::string blank_srdf = "<?xml version='1.0'?><robot name='" + config_data_->urdf_model_->getName() + "'></"
494  "robot>";
495 
496  // Load a blank SRDF file to the parameter server
497  if (!setSRDFFile(blank_srdf))
498  {
499  QMessageBox::warning(this, "Error Loading Files", "Failure loading blank SRDF file.");
500  return false;
501  }
502 
503  // Progress Indicator
504  progress_bar_->setValue(60);
505  QApplication::processEvents();
506 
507  // DONE LOADING --------------------------------------------------------------------------
508 
509  // Call a function that enables navigation
510  Q_EMIT readyToProgress();
511 
512  // Progress Indicator
513  progress_bar_->setValue(70);
514  QApplication::processEvents();
515 
516  // Load Rviz
517  Q_EMIT loadRviz();
518 
519  // Progress Indicator
520  progress_bar_->setValue(100);
521  QApplication::processEvents();
522 
523  next_label_->show(); // only show once the files have been loaded
524 
525  ROS_INFO("Loading Setup Assistant Complete");
526  return true; // success!
527 }
528 
529 // ******************************************************************************************
530 // Load URDF File to Parameter Server
531 // ******************************************************************************************
532 bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path, const std::string& xacro_args)
533 {
534  const std::vector<std::string> xacro_args_ = { xacro_args };
535 
536  if (!rdf_loader::RDFLoader::loadXmlFileToString(config_data_->urdf_string_, urdf_file_path, xacro_args_))
537  {
538  QMessageBox::warning(this, "Error Loading Files",
539  QString("URDF/COLLADA file not found: ").append(urdf_file_path.c_str()));
540  return false;
541  }
542 
543  if (config_data_->urdf_string_.empty() && rdf_loader::RDFLoader::isXacroFile(urdf_file_path))
544  {
545  QMessageBox::warning(this, "Error Loading Files", "Running xacro failed.\nPlease check console for errors.");
546  return false;
547  }
548 
549  // Verify that file is in correct format / not an XACRO by loading into robot model
550  if (!config_data_->urdf_model_->initString(config_data_->urdf_string_))
551  {
552  QMessageBox::warning(this, "Error Loading Files", "URDF/COLLADA file is not a valid robot model.");
553  return false;
554  }
555  config_data_->urdf_from_xacro_ = rdf_loader::RDFLoader::isXacroFile(urdf_file_path);
556 
557  ROS_INFO_STREAM("Loaded " << config_data_->urdf_model_->getName() << " robot model.");
558 
559  // Load the robot model to the parameter server
560  ros::NodeHandle nh;
561  int steps = 0;
562  while (!nh.ok() && steps < 4)
563  {
564  ROS_WARN("Waiting for node handle");
565  sleep(1);
566  steps++;
567  ros::spinOnce();
568  }
569 
570  ROS_INFO("Setting Param Server with Robot Description");
571  // ROS_WARN("Ignore the following error message 'Failed to contact master'. This is a known issue.");
572  nh.setParam("/robot_description", config_data_->urdf_string_);
573 
574  return true;
575 }
576 
577 // ******************************************************************************************
578 // Load SRDF File to Parameter Server
579 // ******************************************************************************************
580 bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path)
581 {
582  const std::vector<std::string> xacro_args;
583 
584  std::string srdf_string;
585  if (!rdf_loader::RDFLoader::loadXmlFileToString(srdf_string, srdf_file_path, xacro_args))
586  {
587  QMessageBox::warning(this, "Error Loading Files", QString("SRDF file not found: ").append(srdf_file_path.c_str()));
588  return false;
589  }
590 
591  // Put on param server
592  return setSRDFFile(srdf_string);
593 }
594 
595 // ******************************************************************************************
596 // Put SRDF File on Parameter Server
597 // ******************************************************************************************
598 bool StartScreenWidget::setSRDFFile(const std::string& srdf_string)
599 {
600  // Verify that file is in correct format / not an XACRO by loading into robot model
601  if (!config_data_->srdf_->initString(*config_data_->urdf_model_, srdf_string))
602  {
603  QMessageBox::warning(this, "Error Loading Files", "SRDF file not a valid semantic robot description model.");
604  return false;
605  }
606  ROS_INFO_STREAM("Robot semantic model successfully loaded.");
607 
608  // Load to param server
609  ros::NodeHandle nh;
610  int steps = 0;
611  while (!nh.ok() && steps < 4)
612  {
613  ROS_WARN("Waiting for node handle");
614  sleep(1);
615  steps++;
616  ros::spinOnce();
617  }
618 
619  ROS_INFO("Setting Param Server with Robot Semantic Description");
620  nh.setParam("/robot_description_semantic", srdf_string);
621 
622  return true;
623 }
624 
625 // ******************************************************************************************
626 // Extract the package/stack name and relative path to urdf from an absolute path name
627 // Input: cofig_data_->urdf_path_
628 // Output: cofig_data_->urdf_pkg_name_
629 // cofig_data_->urdf_pkg_relative_path_
630 // ******************************************************************************************
632 {
633  // Get the path to urdf, save filename
634  fs::path urdf_path = config_data_->urdf_path_;
635  fs::path urdf_directory = urdf_path;
636  urdf_directory.remove_filename();
637 
638  fs::path sub_path; // holds the directory less one folder
639  fs::path relative_path; // holds the path after the sub_path
640  std::string package_name; // result
641 
642  // Paths for testing if files exist
643  fs::path package_path;
644 
645  std::vector<std::string> path_parts; // holds each folder name in vector
646 
647  // Copy path into vector of parts
648  for (fs::path::iterator it = urdf_directory.begin(); it != urdf_directory.end(); ++it)
649  path_parts.push_back(it->native());
650 
651  bool packageFound = false;
652 
653  // reduce the generated directoy path's folder count by 1 each loop
654  for (int segment_length = path_parts.size(); segment_length > 0; --segment_length)
655  {
656  // Reset the sub_path
657  sub_path.clear();
658 
659  // Create a subpath based on the outer loops length
660  for (int segment_count = 0; segment_count < segment_length; ++segment_count)
661  {
662  sub_path /= path_parts[segment_count];
663 
664  // decide if we should remember this directory name because it is topmost, in case it is the package/stack name
665  if (segment_count == segment_length - 1)
666  {
667  package_name = path_parts[segment_count];
668  }
669  }
670 
671  // check if this directory has a package.xml
672  package_path = sub_path;
673  package_path /= "package.xml";
674  ROS_DEBUG_STREAM("Checking for " << package_path.make_preferred().native());
675 
676  // Check if the files exist
677  if (fs::is_regular_file(package_path) || fs::is_regular_file(sub_path / "manifest.xml"))
678  {
679  // now generate the relative path
680  for (std::size_t relative_count = segment_length; relative_count < path_parts.size(); ++relative_count)
681  relative_path /= path_parts[relative_count];
682 
683  // add the URDF filename at end of relative path
684  relative_path /= urdf_path.filename();
685 
686  // end the search
687  segment_length = 0;
688  packageFound = true;
689  break;
690  }
691  }
692 
693  // Assign data to moveit_config_data
694  if (!packageFound)
695  {
696  // No package name found, we must be outside ROS
697  config_data_->urdf_pkg_name_ = "";
698  config_data_->urdf_pkg_relative_path_ = config_data_->urdf_path_; // just the absolute path
699  }
700  else
701  {
702  // Check that ROS can find the package
703  const std::string robot_desc_pkg_path = ros::package::getPath(config_data_->urdf_pkg_name_) + "/";
704 
705  if (robot_desc_pkg_path.empty())
706  {
707  QMessageBox::warning(this, "Package Not Found In ROS Workspace",
708  QString("ROS was unable to find the package name '")
709  .append(config_data_->urdf_pkg_name_.c_str())
710  .append("' within the ROS workspace. This may cause issues later."));
711  }
712 
713  // Success
714  config_data_->urdf_pkg_name_ = package_name;
715  config_data_->urdf_pkg_relative_path_ = relative_path.make_preferred().native();
716  }
717 
718  ROS_DEBUG_STREAM("URDF Package Name: " << config_data_->urdf_pkg_name_);
719  ROS_DEBUG_STREAM("URDF Package Path: " << config_data_->urdf_pkg_relative_path_);
720 
721  return true; // success
722 }
723 
724 // ******************************************************************************************
725 // Make the full URDF path using the loaded .setup_assistant data
726 // ******************************************************************************************
728 {
729  if (!config_data_->createFullURDFPath())
730  {
731  if (config_data_->urdf_path_.empty()) // no path could be resolved
732  {
733  QMessageBox::warning(this, "Error Loading Files", QString("ROS was unable to find the package name '")
734  .append(config_data_->urdf_pkg_name_.c_str())
735  .append("'. Verify this package is inside your ROS "
736  "workspace and is a proper ROS package."));
737  }
738  else
739  {
740  QMessageBox::warning(this, "Error Loading Files",
741  QString("Unable to locate the URDF file in package. Expected File: \n")
742  .append(config_data_->urdf_path_.c_str()));
743  }
744  return false;
745  }
746 
747  // Check if a package name was provided
748  if (config_data_->urdf_pkg_name_.empty())
749  {
750  ROS_WARN("The URDF path is absolute to the filesystem and not relative to a ROS package/stack");
751  }
752 
753  return true; // success
754 }
755 
756 // ******************************************************************************************
757 // Make the full SRDF path using the loaded .setup_assistant data
758 // ******************************************************************************************
759 bool StartScreenWidget::createFullSRDFPath(const std::string& package_path)
760 {
761  if (!config_data_->createFullSRDFPath(package_path))
762  {
763  QMessageBox::warning(this, "Error Loading Files",
764  QString("Unable to locate the SRDF file: ").append(config_data_->srdf_path_.c_str()));
765  return false;
766  }
767 
768  return true; // success
769 }
770 
771 // ******************************************************************************************
772 // Loads sensors_3d yaml file
773 // ******************************************************************************************
775 {
776  // Loads parameters values from sensors_3d yaml file if available
777  fs::path sensors_3d_yaml_path = config_data_->config_pkg_path_;
778  sensors_3d_yaml_path /= "config/sensors_3d.yaml";
779 
780  // Default parameters values are always loaded but overridden by values existing in sensors_3d
781  fs::path default_sensors_3d_yaml_path = "templates/moveit_config_pkg_template/config/sensors_3d.yaml";
782 
783  if (!fs::is_regular_file(sensors_3d_yaml_path))
784  {
785  return config_data_->input3DSensorsYAML(default_sensors_3d_yaml_path.make_preferred().native().c_str());
786  }
787  else
788  {
789  return config_data_->input3DSensorsYAML(default_sensors_3d_yaml_path.make_preferred().native().c_str(),
790  sensors_3d_yaml_path.make_preferred().native().c_str());
791  }
792 }
793 
794 // ******************************************************************************************
795 // ******************************************************************************************
796 // Class for selecting which mode
797 // ******************************************************************************************
798 // ******************************************************************************************
799 
800 // ******************************************************************************************
801 // Create the widget
802 // ******************************************************************************************
803 SelectModeWidget::SelectModeWidget(QWidget* parent) : QFrame(parent)
804 {
805  // Set frame graphics
806  setFrameShape(QFrame::StyledPanel);
807  setFrameShadow(QFrame::Raised);
808  setLineWidth(1);
809  setMidLineWidth(0);
810 
811  // Basic widget container
812  QVBoxLayout* layout = new QVBoxLayout(this);
813 
814  // Horizontal layout splitter
815  QHBoxLayout* hlayout = new QHBoxLayout();
816 
817  // Widget Title
818  QLabel* widget_title = new QLabel(this);
819  widget_title->setText("Create new or edit existing?");
820  QFont widget_title_font(QFont().defaultFamily(), 12, QFont::Bold);
821  widget_title->setFont(widget_title_font);
822  layout->addWidget(widget_title);
823  layout->setAlignment(widget_title, Qt::AlignTop);
824 
825  // Widget Instructions
826  widget_instructions_ = new QTextEdit(this);
827  widget_instructions_->setText(
828  "All settings for MoveIt! are stored in the MoveIt! configuration package. Here you have "
829  "the option to create a new configuration package or load an existing one. Note: "
830  "changes to a MoveIt! configuration package outside this Setup Assistant are likely to be "
831  "overwritten by this tool.");
832 
833  // Change color of TextEdit
834  QPalette p = widget_instructions_->palette();
835  p.setColor(QPalette::Active, QPalette::Base, this->palette().color(QWidget::backgroundRole()));
836  p.setColor(QPalette::Inactive, QPalette::Base, this->palette().color(QWidget::backgroundRole()));
837  widget_instructions_->setPalette(p);
838 
839  // Make TextEdit behave like QLabel
840  widget_instructions_->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
841  widget_instructions_->setReadOnly(true);
842  widget_instructions_->setFrameShape(QFrame::NoFrame);
843  widget_instructions_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
844 
845  layout->addWidget(widget_instructions_);
846  layout->setAlignment(widget_instructions_, Qt::AlignTop);
847 
848  // New Button
849  btn_new_ = new QPushButton(this);
850  btn_new_->setText("Create &New MoveIt\nConfiguration Package");
851  hlayout->addWidget(btn_new_);
852 
853  // Exist Button
854  btn_exist_ = new QPushButton(this);
855  btn_exist_->setText("&Edit Existing MoveIt\nConfiguration Package");
856  btn_exist_->setCheckable(true);
857  hlayout->addWidget(btn_exist_);
858 
859  // Add horizontal layer to verticle layer
860  layout->addLayout(hlayout);
861  setLayout(layout);
862  btn_new_->setCheckable(true);
863 }
864 
865 } // namespace
void loadRviz()
Inform the parent widget to load rviz. This is done so that progress bar can be more accurate...
void onPackagePathChanged(const QString &path)
load package settings
bool loadExistingFiles()
Load exisiting package files.
void showNewOptions()
User has chosen to show new options.
bool loadSRDFFile(const std::string &srdf_file_path)
Load SRDF File.
StartScreenWidget(QWidget *parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
Start screen user interface for MoveIt! Configuration Assistant.
bool setSRDFFile(const std::string &srdf_string)
Put SRDF File on Parameter Server.
bool loadPackageSettings(bool show_warnings)
load package settings from .setup_assistant file
#define ROS_WARN(...)
static bool isXacroFile(const std::string &path)
void loadFilesClick()
Button event for loading user chosen files.
#define ROS_INFO(...)
Extend LoadPathWidget with additional line edit for arguments.
void showExistingOptions()
User has chosen to show edit options.
void onUrdfPathChanged(const QString &path)
enable xacro arguments
bool loadURDFFile(const std::string &urdf_file_path, const std::string &xacro_args)
Load URDF File to Parameter Server.
#define ROS_DEBUG_STREAM(args)
ROSLIB_DECL std::string getPath(const std::string &package_name)
bool createFullURDFPath()
Make the full URDF path using the loaded .setup_assistant data.
bool create_new_package_
Create new config files, or load existing one?
std::string getPath() const
Returns the file path in std::string format.
#define ROS_INFO_STREAM(args)
void readyToProgress()
Event that is fired when the start screen has all its requirements completed and user can move on...
ROSCPP_DECL std::string append(const std::string &left, const std::string &right)
moveit_setup_assistant::MoveItConfigDataPtr config_data_
Contains all the configuration data for the setup assistant.
static bool loadXmlFileToString(std::string &buffer, const std::string &path, const std::vector< std::string > &xacro_args)
bool createFullSRDFPath(const std::string &package_path)
Make the full SRDF path using the loaded .setup_assistant data.
const std::string header
bool ok() const
#define ROS_ERROR_STREAM(args)
ROSCPP_DECL void spinOnce()
#define ROS_ERROR(...)
void setParam(const std::string &key, const XmlRpc::XmlRpcValue &v) const
bool loadNewFiles()
Load chosen files for creating new package.
bool load3DSensorsFile()
Loads sensors_3d yaml file.


moveit_setup_assistant
Author(s): Dave Coleman
autogenerated on Wed Jul 10 2019 04:04:34