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