39 #include <QApplication> 
   42 #include <QListWidget> 
   43 #include <QMessageBox> 
   44 #include <QProgressBar> 
   45 #include <QPushButton> 
   46 #include <QPushButton> 
   49 #include <QVBoxLayout> 
   54 #include <boost/algorithm/string.hpp>   
   68   has_generated_pkg_ = 
false;
 
   71   QVBoxLayout* layout = 
new QVBoxLayout();
 
   77                        "Create or update the configuration files package needed to run your robot with MoveIt. Uncheck " 
   78                        "files to disable them from being generated - this is useful if you have made custom changes to " 
   79                        "them. Files in orange have been automatically detected as changed.",
 
   81   layout->addWidget(header);
 
   87                                    "Specify the desired directory for the MoveIt configuration package to be " 
   88                                    "generated. Overwriting an existing configuration package directory is acceptable. " 
   89                                    "Example: <i>/u/robot/ros/panda_moveit_config</i>",
 
   92   connect(
stack_path_, SIGNAL(pathChanged(QString)), 
this, SLOT(onPackagePathChanged(QString)));
 
   95   QLabel* generated_list = 
new QLabel(
"Check files you want to be generated:", 
this);
 
   96   layout->addWidget(generated_list);
 
   98   QSplitter* splitter = 
new QSplitter(Qt::Horizontal, 
this);
 
   99   splitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
  103   action_list_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
 
  104   action_list_->setSelectionMode(QAbstractItemView::ExtendedSelection);
 
  105   connect(
action_list_, SIGNAL(currentRowChanged(
int)), 
this, SLOT(changeActionDesc(
int)));
 
  107   action_list_->setContextMenuPolicy(Qt::ActionsContextMenu);
 
  108   QAction* 
action = 
new QAction(
"Check all selected files", 
this);
 
  109   connect(
action, &QAction::triggered, [
this]() { setCheckSelected(
true); });
 
  111   action = 
new QAction(
"Uncheck all selected files", 
this);
 
  112   connect(
action, &QAction::triggered, [
this]() { setCheckSelected(
false); });
 
  122   action_label_->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
 
  132   layout->addWidget(splitter);
 
  135   QHBoxLayout* hlayout1 = 
new QHBoxLayout();
 
  145   btn_save_ = 
new QPushButton(
"&Generate Package", 
this);
 
  148   connect(
btn_save_, SIGNAL(clicked()), 
this, SLOT(savePackage()));
 
  152   layout->addLayout(hlayout1);
 
  156   QHBoxLayout* hlayout3 = 
new QHBoxLayout();
 
  160   QFont success_label_font(QFont().defaultFamily(), 12, QFont::Bold);
 
  163   success_label_->setText(
"Configuration package generated successfully!");
 
  168   QPushButton* btn_exit = 
new QPushButton(
"E&xit Setup Assistant", 
this);
 
  169   btn_exit->setMinimumWidth(180);
 
  170   connect(btn_exit, SIGNAL(clicked()), 
this, SLOT(exitSetupAssistant()));
 
  171   hlayout3->addWidget(btn_exit);
 
  172   hlayout3->setAlignment(btn_exit, Qt::AlignRight);
 
  174   layout->addLayout(hlayout3);
 
  177   this->setLayout(layout);
 
  180 void ConfigurationFilesWidget::setCheckSelected(
bool checked)
 
  182   for (
const QModelIndex& row : 
action_list_->selectionModel()->selectedRows())
 
  183     action_list_->model()->setData(row, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
 
  186 void ConfigurationFilesWidget::onPackagePathChanged(
const QString& path)
 
  188   std::filesystem::path package_path = path.toStdString();
 
  203 bool ConfigurationFilesWidget::checkDependencies()
 
  206   bool required_actions = 
false;
 
  212   if (!dependencies.empty())
 
  216     if (!required_actions)
 
  218       dep_message = 
"Some setup steps have not been completed. None of the steps are required, but here is a reminder " 
  219                     "of what was not filled in, just in case something was forgotten:<br /><ul>";
 
  223       dep_message = 
"Some setup steps have not been completed. Please fix the required steps (printed in bold), " 
  224                     "otherwise the setup cannot be completed:<br /><ul>";
 
  227     for (
const auto& dependency : dependencies)
 
  229       dep_message.append(
"<li>").append(QString::fromStdString(dependency)).append(
"</li>");
 
  232     if (!required_actions)
 
  234       dep_message.append(
"</ul><br/>Press Ok to continue generating files.");
 
  235       if (QMessageBox::question(
this, 
"Incomplete MoveIt Setup Assistant Steps", dep_message,
 
  236                                 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
 
  243       QMessageBox::warning(
this, 
"Incomplete MoveIt Setup Assistant Steps", dep_message);
 
  254 void ConfigurationFilesWidget::updateProgress()
 
  262   QApplication::processEvents();
 
  268 void ConfigurationFilesWidget::changeActionDesc(
int id)
 
  281 void ConfigurationFilesWidget::changeCheckedState(QListWidgetItem* item)
 
  283   std::size_t index = item->data(Qt::UserRole).toUInt();
 
  287   bool generate = (item->checkState() == Qt::Checked);
 
  289   if (!generate && gen_file->hasChanges())
 
  291     QMessageBox::warning(
this, 
"Package Generation",
 
  292                          "You should generate this file to ensure your changes will take " 
  311   disconnect(
action_list_, SIGNAL(itemChanged(QListWidgetItem*)), 
this, SLOT(changeCheckedState(QListWidgetItem*)));
 
  317   connect(
action_list_, SIGNAL(itemChanged(QListWidgetItem*)), 
this, SLOT(changeCheckedState(QListWidgetItem*)));
 
  320   QApplication::processEvents();
 
  326     QString msg(
"Some files have been modified outside of the Setup Assistant (according to timestamp). " 
  327                 "The Setup Assistant will not overwrite these changes by default because often changing configuration " 
  328                 "files manually is necessary, " 
  329                 "but we recommend you check the list and enable the checkbox next to files you would like to " 
  332       msg += 
"<br/><font color='red'>Attention:</font> Some files (<font color='red'>marked red</font>) are changed " 
  333              "both, externally and in Setup Assistant.";
 
  334     QMessageBox::information(
this, 
"Files Modified", msg);
 
  341 void ConfigurationFilesWidget::showGenFiles()
 
  348   for (std::size_t i = 0; i < gen_files.size(); ++i)
 
  350     auto gen_file = gen_files[i];
 
  353     QListWidgetItem* item = 
new QListWidgetItem(QString(gen_file->getRelativePath().string().c_str()), 
action_list_, 0);
 
  356     item->setCheckState(setup_step_.
shouldGenerate(gen_file) ? Qt::Checked : Qt::Unchecked);
 
  358     auto status = gen_file->getStatus();
 
  361       item->setForeground(QBrush(QColor(255, 0, 0)));
 
  365       item->setForeground(QBrush(QColor(255, 135, 0)));
 
  369     item->setData(Qt::UserRole, QVariant(
static_cast<qulonglong
>(i)));
 
  373     action_desc_.append(QString(gen_file->getDescription().c_str()));
 
  383 void ConfigurationFilesWidget::savePackage()
 
  392   if (!generatePackage())
 
  394     RCLCPP_ERROR_STREAM(setup_step_.
getLogger(), 
"Failed to generate entire configuration package");
 
  401   has_generated_pkg_ = 
true;
 
  407 bool ConfigurationFilesWidget::generatePackage()
 
  412   boost::trim(package_path_s);
 
  415   if (package_path_s.empty())
 
  417     QMessageBox::warning(
this, 
"Error Generating",
 
  418                          "No package path provided. Please choose a directory location to " 
  419                          "generate the MoveIt configuration files.");
 
  424   if (!checkDependencies())
 
  428   if (!noGroupsEmpty())
 
  437       QMessageBox::warning(
 
  438           this, 
"Incorrect Folder/Package",
 
  439           QString(
"The chosen package location already exists but was not previously created using this MoveIt Setup " 
  441                   "If this is a mistake, add the missing file: ")
 
  442               .
append(SETUP_ASSISTANT_FILE.c_str()));
 
  447     if (QMessageBox::question(
this, 
"Confirm Package Update",
 
  448                               QString(
"Are you sure you want to overwrite this existing package with updated " 
  449                                       "configurations?<br /><i>")
 
  450                                   .
append(package_path_s.c_str())
 
  452                               QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
 
  461   std::filesystem::path absolute_path;
 
  470     absolute_path = gen_file->getPath();
 
  473     RCLCPP_DEBUG_STREAM(setup_step_.
getLogger(), 
"Creating file " << absolute_path.string());
 
  476     if (!gen_file->write())
 
  479       QMessageBox::critical(
this, 
"Error Generating File",
 
  480                             QString(
"Failed to generate folder or file: '")
 
  481                                 .
append(gen_file->getRelativePath().string().c_str())
 
  482                                 .append(
"' at location:\n")
 
  483                                 .append(absolute_path.c_str()));
 
  495 void ConfigurationFilesWidget::exitSetupAssistant()
 
  497   if (has_generated_pkg_ || QMessageBox::question(
this, 
"Exit Setup Assistant",
 
  498                                                   QString(
"Are you sure you want to exit the MoveIt Setup Assistant?"),
 
  499                                                   QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok)
 
  501     QApplication::quit();
 
  508 bool ConfigurationFilesWidget::noGroupsEmpty()
 
  512   if (!invalid_group.empty())
 
  515     QMessageBox::warning(
 
  517         QString(
"The planning group '")
 
  518             .
append(invalid_group.c_str())
 
  519             .append(
"' is empty and has no subcomponents associated with it (joints/links/chains/subgroups). You must " 
  520                     "edit or remove this planning group before this configuration package can be saved."));
 
  529 #include <pluginlib/class_list_macros.hpp>   
PLUGINLIB_EXPORT_CLASS(cached_ik_kinematics_plugin::CachedIKKinematicsPlugin< kdl_kinematics_plugin::KDLKinematicsPlugin >, kinematics::KinematicsBase)
 
const rclcpp::Logger & getLogger() const
Makes a namespaced logger for this step available to the widget.
 
void loadFiles()
Populate the 'Files to be generated' list.
 
void setShouldGenerate(const std::string &rel_path, bool should_generate)
 
const std::filesystem::path & getPackagePath()
 
std::vector< std::string > getIncompleteWarnings() const
 
bool hasModifiedFiles() const
 
void setPackagePath(const std::filesystem::path &package_path)
 
std::string getInvalidGroupName() const
 
bool shouldGenerate(const GeneratedFilePtr &file) const
 
void setPackageName(const std::string &package_name)
 
unsigned int getNumFiles() const
 
const std::vector< GeneratedFilePtr > getGeneratedFiles() const
 
bool hasConflictingFiles() const
 
bool hasSetupAssistantFile()
 
std::string append(const std::string &left, const std::string &right)