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 "end_effectors_widget.h"
00039
00040 #include <QFormLayout>
00041 #include <QMessageBox>
00042 #include <QApplication>
00043
00044 namespace moveit_setup_assistant
00045 {
00046
00047
00048
00049 EndEffectorsWidget::EndEffectorsWidget(QWidget* parent, moveit_setup_assistant::MoveItConfigDataPtr config_data)
00050 : SetupScreenWidget(parent), config_data_(config_data)
00051 {
00052
00053 QVBoxLayout* layout = new QVBoxLayout();
00054
00055
00056
00057 HeaderWidget* header =
00058 new HeaderWidget("End Effectors", "Setup grippers and other end effectors for your robot", this);
00059 layout->addWidget(header);
00060
00061
00062
00063 effector_list_widget_ = createContentsWidget();
00064 effector_edit_widget_ = createEditWidget();
00065
00066
00067 stacked_layout_ = new QStackedLayout(this);
00068 stacked_layout_->addWidget(effector_list_widget_);
00069 stacked_layout_->addWidget(effector_edit_widget_);
00070
00071
00072 QWidget* stacked_layout_widget = new QWidget(this);
00073 stacked_layout_widget->setLayout(stacked_layout_);
00074
00075 layout->addWidget(stacked_layout_widget);
00076
00077
00078 this->setLayout(layout);
00079 }
00080
00081
00082
00083
00084 QWidget* EndEffectorsWidget::createContentsWidget()
00085 {
00086
00087 QWidget* content_widget = new QWidget(this);
00088
00089
00090 QVBoxLayout* layout = new QVBoxLayout(this);
00091
00092
00093
00094 data_table_ = new QTableWidget(this);
00095 data_table_->setColumnCount(4);
00096 data_table_->setSortingEnabled(true);
00097 data_table_->setSelectionBehavior(QAbstractItemView::SelectRows);
00098 connect(data_table_, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(editDoubleClicked(int, int)));
00099 connect(data_table_, SIGNAL(cellClicked(int, int)), this, SLOT(previewClicked(int, int)));
00100 layout->addWidget(data_table_);
00101
00102
00103 QStringList header_list;
00104 header_list.append("End Effector Name");
00105 header_list.append("Group Name");
00106 header_list.append("Parent Link");
00107 header_list.append("Parent Group");
00108 data_table_->setHorizontalHeaderLabels(header_list);
00109
00110
00111
00112 QHBoxLayout* controls_layout = new QHBoxLayout();
00113
00114
00115 QWidget* spacer = new QWidget(this);
00116 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00117 controls_layout->addWidget(spacer);
00118
00119
00120 btn_edit_ = new QPushButton("&Edit Selected", this);
00121 btn_edit_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00122 btn_edit_->setMaximumWidth(300);
00123 btn_edit_->hide();
00124 connect(btn_edit_, SIGNAL(clicked()), this, SLOT(editSelected()));
00125 controls_layout->addWidget(btn_edit_);
00126 controls_layout->setAlignment(btn_edit_, Qt::AlignRight);
00127
00128
00129 btn_delete_ = new QPushButton("&Delete Selected", this);
00130 connect(btn_delete_, SIGNAL(clicked()), this, SLOT(deleteSelected()));
00131 controls_layout->addWidget(btn_delete_);
00132 controls_layout->setAlignment(btn_delete_, Qt::AlignRight);
00133
00134
00135 QPushButton* btn_add = new QPushButton("&Add End Effector", this);
00136 btn_add->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00137 btn_add->setMaximumWidth(300);
00138 connect(btn_add, SIGNAL(clicked()), this, SLOT(showNewScreen()));
00139 controls_layout->addWidget(btn_add);
00140 controls_layout->setAlignment(btn_add, Qt::AlignRight);
00141
00142
00143 layout->addLayout(controls_layout);
00144
00145
00146 content_widget->setLayout(layout);
00147
00148 return content_widget;
00149 }
00150
00151
00152
00153
00154 QWidget* EndEffectorsWidget::createEditWidget()
00155 {
00156
00157 QWidget* edit_widget = new QWidget(this);
00158
00159 QVBoxLayout* layout = new QVBoxLayout();
00160
00161
00162 QFormLayout* form_layout = new QFormLayout();
00163
00164 form_layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
00165
00166
00167 effector_name_field_ = new QLineEdit(this);
00168 form_layout->addRow("End Effector Name:", effector_name_field_);
00169
00170
00171 group_name_field_ = new QComboBox(this);
00172 group_name_field_->setEditable(false);
00173 form_layout->addRow("End Effector Group:", group_name_field_);
00174 connect(group_name_field_, SIGNAL(currentIndexChanged(const QString&)), this,
00175 SLOT(previewClickedString(const QString&)));
00176
00177
00178 parent_name_field_ = new QComboBox(this);
00179 parent_name_field_->setEditable(false);
00180 form_layout->addRow("Parent Link (usually part of the arm):", parent_name_field_);
00181
00182
00183 parent_group_name_field_ = new QComboBox(this);
00184 parent_group_name_field_->setEditable(false);
00185 form_layout->addRow("Parent Group (optional):", parent_group_name_field_);
00186
00187 layout->addLayout(form_layout);
00188
00189
00190
00191 QHBoxLayout* controls_layout = new QHBoxLayout();
00192 controls_layout->setContentsMargins(0, 25, 0, 15);
00193
00194
00195 QWidget* spacer = new QWidget(this);
00196 spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
00197 controls_layout->addWidget(spacer);
00198
00199
00200 QPushButton* btn_save_ = new QPushButton("&Save", this);
00201 btn_save_->setMaximumWidth(200);
00202 connect(btn_save_, SIGNAL(clicked()), this, SLOT(doneEditing()));
00203 controls_layout->addWidget(btn_save_);
00204 controls_layout->setAlignment(btn_save_, Qt::AlignRight);
00205
00206
00207 QPushButton* btn_cancel_ = new QPushButton("&Cancel", this);
00208 btn_cancel_->setMaximumWidth(200);
00209 connect(btn_cancel_, SIGNAL(clicked()), this, SLOT(cancelEditing()));
00210 controls_layout->addWidget(btn_cancel_);
00211 controls_layout->setAlignment(btn_cancel_, Qt::AlignRight);
00212
00213
00214 layout->addLayout(controls_layout);
00215
00216
00217 edit_widget->setLayout(layout);
00218
00219 return edit_widget;
00220 }
00221
00222
00223
00224
00225 void EndEffectorsWidget::showNewScreen()
00226 {
00227
00228 current_edit_effector_.clear();
00229
00230
00231 effector_name_field_->setText("");
00232 parent_name_field_->clearEditText();
00233 group_name_field_->clearEditText();
00234 parent_group_name_field_->clearEditText();
00235
00236
00237 stacked_layout_->setCurrentIndex(1);
00238
00239
00240 Q_EMIT isModal(true);
00241 }
00242
00243
00244
00245
00246 void EndEffectorsWidget::editDoubleClicked(int row, int column)
00247 {
00248 editSelected();
00249 }
00250
00251
00252
00253
00254 void EndEffectorsWidget::previewClicked(int row, int column)
00255 {
00256
00257 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00258
00259
00260 if (!selected.size())
00261 return;
00262
00263
00264 srdf::Model::EndEffector* effector = findEffectorByName(selected[0]->text().toStdString());
00265
00266
00267 Q_EMIT unhighlightAll();
00268
00269
00270 Q_EMIT highlightGroup(effector->component_group_);
00271 }
00272
00273
00274
00275
00276 void EndEffectorsWidget::previewClickedString(const QString& name)
00277 {
00278
00279 if (stacked_layout_->currentIndex() == 0)
00280 return;
00281
00282
00283 Q_EMIT unhighlightAll();
00284
00285
00286 Q_EMIT highlightGroup(name.toStdString());
00287 }
00288
00289
00290
00291
00292 void EndEffectorsWidget::editSelected()
00293 {
00294
00295 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00296
00297
00298 if (!selected.size())
00299 return;
00300
00301
00302 edit(selected[0]->text().toStdString());
00303 }
00304
00305
00306
00307
00308 void EndEffectorsWidget::edit(const std::string& name)
00309 {
00310
00311 current_edit_effector_ = name;
00312
00313
00314 srdf::Model::EndEffector* effector = findEffectorByName(name);
00315
00316
00317 effector_name_field_->setText(effector->name_.c_str());
00318
00319
00320 int index = parent_name_field_->findText(effector->parent_link_.c_str());
00321 if (index == -1)
00322 {
00323 QMessageBox::critical(this, "Error Loading", "Unable to find parent link in drop down box");
00324 return;
00325 }
00326 parent_name_field_->setCurrentIndex(index);
00327
00328
00329 index = group_name_field_->findText(effector->component_group_.c_str());
00330 if (index == -1)
00331 {
00332 QMessageBox::critical(this, "Error Loading", "Unable to find group name in drop down box");
00333 return;
00334 }
00335 group_name_field_->setCurrentIndex(index);
00336
00337
00338 index = parent_group_name_field_->findText(effector->parent_group_.c_str());
00339 if (index == -1)
00340 {
00341 QMessageBox::critical(this, "Error Loading", "Unable to find parent group name in drop down box");
00342 return;
00343 }
00344 parent_group_name_field_->setCurrentIndex(index);
00345
00346
00347 stacked_layout_->setCurrentIndex(1);
00348
00349
00350 Q_EMIT isModal(true);
00351 }
00352
00353
00354
00355
00356 void EndEffectorsWidget::loadGroupsComboBox()
00357 {
00358
00359 group_name_field_->clear();
00360 parent_group_name_field_->clear();
00361 parent_group_name_field_->addItem("");
00362
00363
00364 for (std::vector<srdf::Model::Group>::iterator group_it = config_data_->srdf_->groups_.begin();
00365 group_it != config_data_->srdf_->groups_.end(); ++group_it)
00366 {
00367 group_name_field_->addItem(group_it->name_.c_str());
00368 parent_group_name_field_->addItem(group_it->name_.c_str());
00369 }
00370 }
00371
00372
00373
00374
00375 void EndEffectorsWidget::loadParentComboBox()
00376 {
00377
00378 parent_name_field_->clear();
00379
00380
00381 std::vector<const robot_model::LinkModel*> link_models = config_data_->getRobotModel()->getLinkModels();
00382
00383
00384 for (std::vector<const robot_model::LinkModel*>::const_iterator link_it = link_models.begin();
00385 link_it < link_models.end(); ++link_it)
00386 {
00387 parent_name_field_->addItem((*link_it)->getName().c_str());
00388 }
00389 }
00390
00391
00392
00393
00394 srdf::Model::EndEffector* EndEffectorsWidget::findEffectorByName(const std::string& name)
00395 {
00396
00397 srdf::Model::EndEffector* searched_group = NULL;
00398
00399 for (std::vector<srdf::Model::EndEffector>::iterator effector_it = config_data_->srdf_->end_effectors_.begin();
00400 effector_it != config_data_->srdf_->end_effectors_.end(); ++effector_it)
00401 {
00402 if (effector_it->name_ == name)
00403 {
00404 searched_group = &(*effector_it);
00405 break;
00406 }
00407 }
00408
00409
00410 if (searched_group == NULL)
00411 {
00412 QMessageBox::critical(this, "Error Saving", "An internal error has occured while saving. Quitting.");
00413 QApplication::quit();
00414 }
00415
00416 return searched_group;
00417 }
00418
00419
00420
00421
00422 void EndEffectorsWidget::deleteSelected()
00423 {
00424
00425 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00426
00427
00428 if (!selected.size())
00429 return;
00430
00431
00432 current_edit_effector_ = selected[0]->text().toStdString();
00433
00434
00435 if (QMessageBox::question(this, "Confirm End Effector Deletion",
00436 QString("Are you sure you want to delete the end effector '")
00437 .append(current_edit_effector_.c_str())
00438 .append("'?"),
00439 QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Cancel)
00440 {
00441 return;
00442 }
00443
00444
00445 for (std::vector<srdf::Model::EndEffector>::iterator effector_it = config_data_->srdf_->end_effectors_.begin();
00446 effector_it != config_data_->srdf_->end_effectors_.end(); ++effector_it)
00447 {
00448
00449 if (effector_it->name_ == current_edit_effector_)
00450 {
00451 config_data_->srdf_->end_effectors_.erase(effector_it);
00452 break;
00453 }
00454 }
00455
00456
00457 loadDataTable();
00458 config_data_->changes |= MoveItConfigData::END_EFFECTORS;
00459 }
00460
00461
00462
00463
00464 void EndEffectorsWidget::doneEditing()
00465 {
00466
00467 const std::string effector_name = effector_name_field_->text().toStdString();
00468
00469
00470 srdf::Model::EndEffector* searched_data = NULL;
00471
00472
00473 if (effector_name.empty())
00474 {
00475 QMessageBox::warning(this, "Error Saving", "A name must be specified for the end effector!");
00476 return;
00477 }
00478
00479
00480 if (!current_edit_effector_.empty())
00481 {
00482
00483 searched_data = findEffectorByName(current_edit_effector_);
00484 }
00485
00486
00487 for (std::vector<srdf::Model::EndEffector>::const_iterator data_it = config_data_->srdf_->end_effectors_.begin();
00488 data_it != config_data_->srdf_->end_effectors_.end(); ++data_it)
00489 {
00490 if (data_it->name_.compare(effector_name) == 0)
00491 {
00492
00493 if (&(*data_it) != searched_data)
00494 {
00495 QMessageBox::warning(
00496 this, "Error Saving",
00497 QString("An end-effector named '").append(effector_name.c_str()).append("'already exists!"));
00498 return;
00499 }
00500 }
00501 }
00502
00503
00504 if (group_name_field_->currentText().isEmpty())
00505 {
00506 QMessageBox::warning(this, "Error Saving", "A group that contains the links of the end-effector must be chosen!");
00507 return;
00508 }
00509
00510
00511 if (parent_name_field_->currentText().isEmpty())
00512 {
00513 QMessageBox::warning(this, "Error Saving", "A parent link must be chosen!");
00514 return;
00515 }
00516
00517 const robot_model::JointModelGroup* jmg =
00518 config_data_->getRobotModel()->getJointModelGroup(group_name_field_->currentText().toStdString());
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 if (!parent_group_name_field_->currentText().isEmpty())
00530 {
00531 jmg = config_data_->getRobotModel()->getJointModelGroup(parent_group_name_field_->currentText().toStdString());
00532 if (!jmg->hasLinkModel(parent_name_field_->currentText().toStdString()))
00533 {
00534 QMessageBox::warning(this, "Error Saving",
00535 QString::fromStdString("The specified parent group '" +
00536 parent_group_name_field_->currentText().toStdString() +
00537 "' must contain the specified parent link '" +
00538 parent_name_field_->currentText().toStdString() + "'."));
00539 return;
00540 }
00541 }
00542
00543 config_data_->changes |= MoveItConfigData::END_EFFECTORS;
00544
00545
00546 bool isNew = false;
00547
00548 if (searched_data == NULL)
00549 {
00550 isNew = true;
00551
00552 searched_data = new srdf::Model::EndEffector();
00553 }
00554
00555
00556 searched_data->name_ = effector_name;
00557 searched_data->parent_link_ = parent_name_field_->currentText().toStdString();
00558 searched_data->component_group_ = group_name_field_->currentText().toStdString();
00559 searched_data->parent_group_ = parent_group_name_field_->currentText().toStdString();
00560
00561
00562 if (isNew)
00563 {
00564 config_data_->srdf_->end_effectors_.push_back(*searched_data);
00565 }
00566
00567
00568
00569
00570 loadDataTable();
00571
00572
00573 stacked_layout_->setCurrentIndex(0);
00574
00575
00576 Q_EMIT isModal(false);
00577 }
00578
00579
00580
00581
00582 void EndEffectorsWidget::cancelEditing()
00583 {
00584
00585 stacked_layout_->setCurrentIndex(0);
00586
00587
00588 previewClicked(0, 0);
00589
00590
00591 Q_EMIT isModal(false);
00592 }
00593
00594
00595
00596
00597 void EndEffectorsWidget::loadDataTable()
00598 {
00599
00600 data_table_->setUpdatesEnabled(false);
00601 data_table_->setDisabled(true);
00602 data_table_->clearContents();
00603
00604
00605 data_table_->setRowCount(config_data_->srdf_->end_effectors_.size());
00606
00607
00608 int row = 0;
00609 for (std::vector<srdf::Model::EndEffector>::const_iterator data_it = config_data_->srdf_->end_effectors_.begin();
00610 data_it != config_data_->srdf_->end_effectors_.end(); ++data_it)
00611 {
00612
00613 QTableWidgetItem* data_name = new QTableWidgetItem(data_it->name_.c_str());
00614 data_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00615 QTableWidgetItem* group_name = new QTableWidgetItem(data_it->component_group_.c_str());
00616 group_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00617 QTableWidgetItem* parent_name = new QTableWidgetItem(data_it->parent_link_.c_str());
00618 group_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00619 QTableWidgetItem* parent_group_name = new QTableWidgetItem(data_it->parent_group_.c_str());
00620 parent_group_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00621
00622
00623 data_table_->setItem(row, 0, data_name);
00624 data_table_->setItem(row, 1, group_name);
00625 data_table_->setItem(row, 2, parent_name);
00626 data_table_->setItem(row, 3, parent_group_name);
00627
00628
00629 ++row;
00630 }
00631
00632
00633 data_table_->setUpdatesEnabled(true);
00634 data_table_->setDisabled(false);
00635
00636
00637 data_table_->resizeColumnToContents(0);
00638 data_table_->resizeColumnToContents(1);
00639 data_table_->resizeColumnToContents(2);
00640 data_table_->resizeColumnToContents(3);
00641
00642
00643 if (config_data_->srdf_->end_effectors_.size() > 0)
00644 btn_edit_->show();
00645 }
00646
00647
00648
00649
00650 void EndEffectorsWidget::focusGiven()
00651 {
00652
00653 stacked_layout_->setCurrentIndex(0);
00654
00655
00656 loadDataTable();
00657
00658
00659 loadGroupsComboBox();
00660 loadParentComboBox();
00661 }
00662
00663 }