00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
00049 #include <ros/ros.h>
00050 #include <ros/package.h>
00051
00052 #include "header_widget.h"
00053 #include "start_screen_widget.h"
00054
00055 #include <fstream>
00056 #include <streambuf>
00057
00058 #include <boost/algorithm/string.hpp>
00059 #include <boost/filesystem.hpp>
00060 #include <boost/algorithm/string.hpp>
00061
00062 namespace moveit_setup_assistant
00063 {
00064
00065 namespace fs = boost::filesystem;
00066
00067
00068
00069
00070 StartScreenWidget::StartScreenWidget(QWidget* parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
00071 : SetupScreenWidget(parent), config_data_(config_data)
00072 {
00073
00074 QVBoxLayout* layout = new QVBoxLayout(this);
00075
00076
00077 QHBoxLayout* hlayout = new QHBoxLayout();
00078
00079 QVBoxLayout* left_layout = new QVBoxLayout();
00080
00081 QVBoxLayout* right_layout = new QVBoxLayout();
00082
00083
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);
00096
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
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
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
00137
00138
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);
00143 stack_path_->hide();
00144 left_layout->addWidget(stack_path_);
00145
00146
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);
00152 urdf_file_->hide();
00153 left_layout->addWidget(urdf_file_);
00154
00155
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
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
00174 next_label_ = new QLabel(this);
00175 QFont next_label_font("Arial", 11, QFont::Bold);
00176 next_label_->setFont(next_label_font);
00177
00178 next_label_->setText("Success! Use the left navigation pane to continue.");
00179
00180 next_label_->hide();
00181
00182 right_layout->addWidget(right_image_label_);
00183 right_layout->setAlignment(right_image_label_, Qt::AlignRight | Qt::AlignTop);
00184
00185
00186
00187 layout->setAlignment(Qt::AlignTop);
00188 hlayout->setAlignment(Qt::AlignTop);
00189 left_layout->setAlignment(Qt::AlignTop);
00190 right_layout->setAlignment(Qt::AlignTop);
00191
00192
00193 left_layout->setSpacing(30);
00194
00195
00196
00197 hlayout->addLayout(left_layout);
00198 hlayout->addLayout(right_layout);
00199 layout->addLayout(hlayout);
00200
00201
00202 QWidget* vspacer = new QWidget(this);
00203 vspacer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
00204 layout->addWidget(vspacer);
00205
00206
00207 layout->addWidget(next_label_);
00208 layout->setAlignment(next_label_, Qt::AlignRight);
00209 layout->addLayout(load_files_layout);
00210
00211 this->setLayout(layout);
00212
00213
00214
00215 if (config_data_->debug_)
00216 {
00217
00218
00219 QTimer* update_timer = new QTimer(this);
00220 update_timer->setSingleShot(true);
00221 connect(update_timer, SIGNAL(timeout()), btn_load_, SLOT(click()));
00222 update_timer->start(100);
00223 }
00224 }
00225
00226
00227
00228
00229 StartScreenWidget::~StartScreenWidget()
00230 {
00231 delete right_image_;
00232 delete logo_image_;
00233 }
00234
00235
00236
00237
00238 void StartScreenWidget::showNewOptions()
00239 {
00240
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
00248 create_new_package_ = true;
00249 }
00250
00251
00252
00253
00254 void StartScreenWidget::showExistingOptions()
00255 {
00256
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
00264 create_new_package_ = false;
00265 }
00266
00267
00268
00269
00270 void StartScreenWidget::loadFilesClick()
00271 {
00272
00273 urdf_file_->setDisabled(true);
00274
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
00283 if (create_new_package_)
00284 {
00285 result = loadNewFiles();
00286 }
00287 else
00288 {
00289 result = loadExistingFiles();
00290 }
00291
00292
00293 if (!result)
00294 {
00295
00296 urdf_file_->setDisabled(false);
00297
00298 stack_path_->setDisabled(false);
00299 select_mode_->setDisabled(false);
00300 btn_load_->setDisabled(false);
00301 progress_bar_->hide();
00302 }
00303 else
00304 {
00305
00306 right_image_label_->hide();
00307 }
00308 }
00309
00310
00311
00312
00313 bool StartScreenWidget::loadExistingFiles()
00314 {
00315
00316 progress_bar_->setValue(10);
00317 QApplication::processEvents();
00318
00319
00320 if (!createFullPackagePath())
00321 return false;
00322
00323 std::string setup_assistant_path;
00324
00325
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
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
00346 progress_bar_->setValue(30);
00347 QApplication::processEvents();
00348
00349
00350 if (!createFullURDFPath())
00351 return false;
00352
00353
00354 if (!loadURDFFile(config_data_->urdf_path_))
00355 return false;
00356
00357
00358 if (!createFullSRDFPath(config_data_->config_pkg_path_))
00359 return false;
00360
00361
00362 progress_bar_->setValue(50);
00363 QApplication::processEvents();
00364
00365
00366 if (!loadSRDFFile(config_data_->srdf_path_))
00367 return false;
00368
00369
00370 progress_bar_->setValue(60);
00371 QApplication::processEvents();
00372
00373
00374 config_data_->loadAllowedCollisionMatrix();
00375
00376
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
00391
00392
00393 Q_EMIT readyToProgress();
00394
00395
00396 progress_bar_->setValue(70);
00397 QApplication::processEvents();
00398
00399
00400 Q_EMIT loadRviz();
00401
00402
00403 progress_bar_->setValue(100);
00404 QApplication::processEvents();
00405
00406 next_label_->show();
00407
00408 ROS_INFO("Loading Setup Assistant Complete");
00409 return true;
00410 }
00411
00412
00413
00414
00415 bool StartScreenWidget::loadNewFiles()
00416 {
00417
00418 config_data_->urdf_path_ = urdf_file_->getPath();
00419
00420
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
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
00436 if (!extractPackageNameFromPath())
00437 {
00438 return false;
00439 }
00440
00441
00442 progress_bar_->setValue(20);
00443 QApplication::processEvents();
00444
00445
00446 if (!loadURDFFile(config_data_->urdf_path_))
00447 return false;
00448
00449
00450 progress_bar_->setValue(50);
00451 QApplication::processEvents();
00452
00453
00454 const std::string blank_srdf = "<?xml version='1.0'?><robot name='" + config_data_->urdf_model_->getName() + "'></"
00455 "robot>";
00456
00457
00458 if (!setSRDFFile(blank_srdf))
00459 {
00460 QMessageBox::warning(this, "Error Loading Files", "Failure loading blank SRDF file.");
00461 return false;
00462 }
00463
00464
00465 progress_bar_->setValue(60);
00466 QApplication::processEvents();
00467
00468
00469
00470
00471 Q_EMIT readyToProgress();
00472
00473
00474 progress_bar_->setValue(70);
00475 QApplication::processEvents();
00476
00477
00478 Q_EMIT loadRviz();
00479
00480
00481 progress_bar_->setValue(100);
00482 QApplication::processEvents();
00483
00484 next_label_->show();
00485
00486 ROS_INFO("Loading Setup Assistant Complete");
00487 return true;
00488 }
00489
00490
00491
00492
00493 bool StartScreenWidget::loadURDFFile(const std::string& urdf_file_path)
00494 {
00495
00496 std::ifstream urdf_stream(urdf_file_path.c_str());
00497 if (!urdf_stream.good())
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
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
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
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
00567 nh.setParam("/robot_description", urdf_string);
00568
00569 return true;
00570 }
00571
00572
00573
00574
00575 bool StartScreenWidget::loadSRDFFile(const std::string& srdf_file_path)
00576 {
00577
00578 std::ifstream srdf_stream(srdf_file_path.c_str());
00579 if (!srdf_stream.good())
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
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
00595 return setSRDFFile(srdf_string);
00596 }
00597
00598
00599
00600
00601 bool StartScreenWidget::setSRDFFile(const std::string& srdf_string)
00602 {
00603
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
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
00630
00631
00632
00633
00634 bool StartScreenWidget::extractPackageNameFromPath()
00635 {
00636
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;
00642 fs::path relative_path;
00643 std::string package_name;
00644
00645
00646 fs::path package_path;
00647
00648 std::vector<std::string> path_parts;
00649
00650
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
00657 for (int segment_length = path_parts.size(); segment_length > 0; --segment_length)
00658 {
00659
00660 sub_path.clear();
00661
00662
00663 for (int segment_count = 0; segment_count < segment_length; ++segment_count)
00664 {
00665 sub_path /= path_parts[segment_count];
00666
00667
00668 if (segment_count == segment_length - 1)
00669 {
00670 package_name = path_parts[segment_count];
00671 }
00672 }
00673
00674
00675 package_path = sub_path;
00676 package_path /= "package.xml";
00677 ROS_DEBUG_STREAM("Checking for " << package_path.make_preferred().native());
00678
00679
00680 if (fs::is_regular_file(package_path) || fs::is_regular_file(sub_path / "manifest.xml"))
00681 {
00682
00683 for (size_t relative_count = segment_length; relative_count < path_parts.size(); ++relative_count)
00684 relative_path /= path_parts[relative_count];
00685
00686
00687 relative_path /= urdf_path.filename();
00688
00689
00690 segment_length = 0;
00691 packageFound = true;
00692 break;
00693 }
00694 }
00695
00696
00697 if (!packageFound)
00698 {
00699
00700 config_data_->urdf_pkg_name_ = "";
00701 config_data_->urdf_pkg_relative_path_ = config_data_->urdf_path_;
00702 }
00703 else
00704 {
00705
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
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;
00725 }
00726
00727
00728
00729
00730 bool StartScreenWidget::createFullURDFPath()
00731 {
00732 if (!config_data_->createFullURDFPath())
00733 {
00734 if (config_data_->urdf_path_.empty())
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
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;
00758 }
00759
00760
00761
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;
00773 }
00774
00775
00776
00777
00778 bool StartScreenWidget::createFullPackagePath()
00779 {
00780
00781 std::string package_path_input = stack_path_->getPath();
00782
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
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
00801
00802
00803
00804
00805
00806
00807 SelectModeWidget::SelectModeWidget(QWidget* parent) : QFrame(parent)
00808 {
00809
00810 setFrameShape(QFrame::StyledPanel);
00811 setFrameShadow(QFrame::Raised);
00812 setLineWidth(1);
00813 setMidLineWidth(0);
00814
00815
00816 QVBoxLayout* layout = new QVBoxLayout(this);
00817
00818
00819 QHBoxLayout* hlayout = new QHBoxLayout();
00820
00821
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
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
00837 layout->addWidget(widget_instructions);
00838 layout->setAlignment(widget_instructions, Qt::AlignTop);
00839
00840
00841 btn_new_ = new QPushButton(this);
00842 btn_new_->setText("Create &New MoveIt\nConfiguration Package");
00843 hlayout->addWidget(btn_new_);
00844
00845
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
00852 layout->addLayout(hlayout);
00853 setLayout(layout);
00854 btn_new_->setCheckable(true);
00855 }
00856
00857 }