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 "robot_poses_widget.h"
00039 #include <moveit_msgs/JointLimits.h>
00040
00041 #include <QFormLayout>
00042 #include <QMessageBox>
00043 #include <QDoubleValidator>
00044 #include <QApplication>
00045
00046 #include <moveit/robot_state/conversions.h>
00047 #include <moveit_msgs/DisplayRobotState.h>
00048
00049 namespace moveit_setup_assistant
00050 {
00051
00052
00053
00054
00055 RobotPosesWidget::RobotPosesWidget( QWidget *parent, moveit_setup_assistant::MoveItConfigDataPtr config_data )
00056 : SetupScreenWidget( parent ), config_data_(config_data)
00057 {
00058
00059 joint_list_layout_ = NULL;
00060
00061
00062 QVBoxLayout *layout = new QVBoxLayout( );
00063
00064
00065
00066 HeaderWidget *header = new HeaderWidget( "Robot Poses",
00067 "Create poses for the robot. Poses are defined as sets of joint values for particular planning groups. This is useful for things like <i>folded arms</i>.",
00068 this);
00069 layout->addWidget( header );
00070
00071
00072 pose_list_widget_ = createContentsWidget();
00073 pose_edit_widget_ = createEditWidget();
00074
00075
00076 stacked_layout_ = new QStackedLayout( this );
00077 stacked_layout_->addWidget( pose_list_widget_ );
00078 stacked_layout_->addWidget( pose_edit_widget_ );
00079
00080
00081 QWidget *stacked_layout_widget = new QWidget( this );
00082 stacked_layout_widget->setLayout( stacked_layout_ );
00083
00084 layout->addWidget( stacked_layout_widget );
00085
00086
00087
00088 this->setLayout(layout);
00089
00090
00091
00092 ros::NodeHandle nh;
00093
00094
00095 pub_robot_state_ = nh.advertise<moveit_msgs::DisplayRobotState>( MOVEIT_ROBOT_STATE, 1 );
00096
00097
00098 config_data_->getPlanningScene()->setName("MoveIt Planning Scene");
00099
00100
00101
00102
00103
00104 request.contacts = true;
00105 request.max_contacts = 1;
00106 request.max_contacts_per_pair = 1;
00107 request.verbose = false;
00108
00109 }
00110
00111
00112
00113
00114 QWidget* RobotPosesWidget::createContentsWidget()
00115 {
00116
00117 QWidget *content_widget = new QWidget( this );
00118
00119
00120 QVBoxLayout *layout = new QVBoxLayout( this );
00121
00122
00123
00124 data_table_ = new QTableWidget( this );
00125 data_table_->setColumnCount(2);
00126 data_table_->setSortingEnabled(true);
00127 data_table_->setSelectionBehavior( QAbstractItemView::SelectRows );
00128 connect( data_table_, SIGNAL( cellDoubleClicked( int, int ) ), this, SLOT( editDoubleClicked( int, int ) ) );
00129 connect( data_table_, SIGNAL( cellClicked( int, int ) ), this, SLOT( previewClicked( int, int ) ) );
00130 layout->addWidget( data_table_ );
00131
00132
00133 QStringList header_list;
00134 header_list.append("Pose Name");
00135 header_list.append("Group Name");
00136 data_table_->setHorizontalHeaderLabels(header_list);
00137
00138
00139
00140 QHBoxLayout *controls_layout = new QHBoxLayout();
00141
00142
00143 QPushButton *btn_default = new QPushButton( "&Show Default Pose", this );
00144 btn_default->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
00145 btn_default->setMaximumWidth(300);
00146 connect(btn_default, SIGNAL(clicked()), this, SLOT(showDefaultPose()));
00147 controls_layout->addWidget(btn_default);
00148 controls_layout->setAlignment( btn_default, Qt::AlignLeft );
00149
00150
00151 QPushButton *btn_play = new QPushButton( "&MoveIt!", this );
00152 btn_play->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
00153 btn_play->setMaximumWidth(300);
00154 connect(btn_play, SIGNAL(clicked()), this, SLOT(playPoses()));
00155 controls_layout->addWidget(btn_play);
00156 controls_layout->setAlignment( btn_play, Qt::AlignLeft );
00157
00158
00159 QWidget *spacer = new QWidget( this );
00160 spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00161 controls_layout->addWidget( spacer );
00162
00163
00164 btn_edit_ = new QPushButton( "&Edit Selected", this );
00165 btn_edit_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
00166 btn_edit_->setMaximumWidth(300);
00167 btn_edit_->hide();
00168 connect(btn_edit_, SIGNAL(clicked()), this, SLOT(editSelected()));
00169 controls_layout->addWidget(btn_edit_);
00170 controls_layout->setAlignment( btn_edit_, Qt::AlignRight );
00171
00172
00173 btn_delete_ = new QPushButton( "&Delete Selected", this );
00174 connect( btn_delete_, SIGNAL(clicked()), this, SLOT( deleteSelected() ) );
00175 controls_layout->addWidget( btn_delete_ );
00176 controls_layout->setAlignment(btn_delete_, Qt::AlignRight);
00177
00178
00179 QPushButton *btn_add = new QPushButton( "&Add Pose", this );
00180 btn_add->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred );
00181 btn_add->setMaximumWidth(300);
00182 connect(btn_add, SIGNAL(clicked()), this, SLOT(showNewScreen()));
00183 controls_layout->addWidget(btn_add);
00184 controls_layout->setAlignment( btn_add, Qt::AlignRight );
00185
00186
00187 layout->addLayout( controls_layout );
00188
00189
00190
00191 content_widget->setLayout(layout);
00192
00193 return content_widget;
00194 }
00195
00196
00197
00198
00199 QWidget* RobotPosesWidget::createEditWidget()
00200 {
00201
00202 QWidget *edit_widget = new QWidget( this );
00203
00204 QVBoxLayout *layout = new QVBoxLayout();
00205
00206
00207
00208 QHBoxLayout *columns_layout = new QHBoxLayout();
00209 QVBoxLayout *column1 = new QVBoxLayout();
00210 column2_ = new QVBoxLayout();
00211
00212
00213
00214
00215 QFormLayout *form_layout = new QFormLayout();
00216
00217 form_layout->setRowWrapPolicy( QFormLayout::WrapAllRows );
00218
00219
00220 pose_name_field_ = new QLineEdit( this );
00221
00222 form_layout->addRow( "Pose Name:", pose_name_field_ );
00223
00224
00225 group_name_field_ = new QComboBox( this );
00226 group_name_field_->setEditable( false );
00227
00228 connect( group_name_field_, SIGNAL( currentIndexChanged( const QString & ) ),
00229 this, SLOT( loadJointSliders( const QString & ) ) );
00230
00231 form_layout->addRow( "Planning Group:", group_name_field_ );
00232
00233
00234 collision_warning_ = new QLabel( "<font color='red'><b>Robot in Collision State</b></font>", this );
00235 collision_warning_->setTextFormat( Qt::RichText );
00236 collision_warning_->hide();
00237 form_layout->addRow( " ", collision_warning_ );
00238
00239 column1->addLayout( form_layout );
00240 columns_layout->addLayout( column1 );
00241
00242
00243
00244
00245 joint_list_widget_ = new QWidget( this );
00246
00247
00248 scroll_area_ = new QScrollArea( this );
00249
00250 scroll_area_->setWidget( joint_list_widget_ );
00251
00252 column2_->addWidget( scroll_area_ );
00253
00254 columns_layout->addLayout( column2_ );
00255
00256
00257 layout->addLayout( columns_layout );
00258
00259
00260
00261 QHBoxLayout *controls_layout = new QHBoxLayout();
00262 controls_layout->setContentsMargins( 0, 25, 0, 15 );
00263
00264
00265 QWidget *spacer = new QWidget( this );
00266 spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
00267 controls_layout->addWidget( spacer );
00268
00269
00270 QPushButton *btn_save_ = new QPushButton( "&Save", this );
00271 btn_save_->setMaximumWidth( 200 );
00272 connect( btn_save_, SIGNAL(clicked()), this, SLOT( doneEditing() ) );
00273 controls_layout->addWidget( btn_save_ );
00274 controls_layout->setAlignment(btn_save_, Qt::AlignRight);
00275
00276
00277 QPushButton *btn_cancel_ = new QPushButton( "&Cancel", this );
00278 btn_cancel_->setMaximumWidth( 200 );
00279 connect( btn_cancel_, SIGNAL(clicked()), this, SLOT( cancelEditing() ) );
00280 controls_layout->addWidget( btn_cancel_ );
00281 controls_layout->setAlignment(btn_cancel_, Qt::AlignRight);
00282
00283
00284 layout->addLayout( controls_layout );
00285
00286
00287
00288 edit_widget->setLayout(layout);
00289
00290 return edit_widget;
00291 }
00292
00293
00294
00295
00296 void RobotPosesWidget::showNewScreen()
00297 {
00298
00299 stacked_layout_->setCurrentIndex( 1 );
00300
00301
00302 current_edit_pose_.clear();
00303
00304
00305 if( !group_name_field_->currentText().isEmpty() )
00306 loadJointSliders( group_name_field_->currentText() );
00307
00308
00309 pose_name_field_->setText("");
00310
00311
00312 Q_EMIT isModal( true );
00313 }
00314
00315
00316
00317
00318 void RobotPosesWidget::editDoubleClicked( int row, int column )
00319 {
00320
00321 editSelected();
00322 }
00323
00324
00325
00326
00327 void RobotPosesWidget::previewClicked( int row, int column )
00328 {
00329
00330 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00331
00332
00333 if( !selected.size() )
00334 return;
00335
00336
00337 srdf::Model::GroupState *pose = findPoseByName( selected[0]->text().toStdString() );
00338
00339 showPose( pose );
00340 }
00341
00342
00343
00344
00345 void RobotPosesWidget::showPose( srdf::Model::GroupState *pose )
00346 {
00347
00348 for( std::map<std::string, std::vector<double> >::const_iterator value_it = pose->joint_values_.begin();
00349 value_it != pose->joint_values_.end(); ++value_it )
00350 {
00351
00352 joint_state_map_[ value_it->first ] = value_it->second[0];
00353 }
00354
00355
00356 publishJoints();
00357
00358
00359
00360 Q_EMIT unhighlightAll();
00361
00362
00363 Q_EMIT highlightGroup( pose->group_ );
00364 }
00365
00366
00367
00368
00369 void RobotPosesWidget::showDefaultPose()
00370 {
00371
00372 std::vector<const robot_model::JointModel*> joint_models = config_data_->getRobotModel()->getJointModels();
00373
00374
00375 for( std::vector<const robot_model::JointModel*>::const_iterator joint_it = joint_models.begin();
00376 joint_it < joint_models.end(); ++joint_it )
00377 {
00378
00379
00380 if( (*joint_it)->getVariableCount() == 1 )
00381 {
00382 double init_value;
00383
00384
00385 std::vector<double> default_values;
00386 (*joint_it)->getVariableDefaultValues( default_values );
00387 init_value = default_values[0];
00388
00389
00390 joint_state_map_[ (*joint_it)->getName() ] = init_value;
00391 }
00392 }
00393
00394
00395 publishJoints();
00396
00397
00398 Q_EMIT unhighlightAll();
00399 }
00400
00401
00402
00403
00404 void RobotPosesWidget::playPoses()
00405 {
00406
00407 for( std::vector<srdf::Model::GroupState>::iterator pose_it = config_data_->srdf_->group_states_.begin();
00408 pose_it != config_data_->srdf_->group_states_.end(); ++pose_it )
00409 {
00410 ROS_INFO_STREAM("Showing pose " << pose_it->name_ );
00411 showPose( &(*pose_it) );
00412 ros::Duration(0.05).sleep();
00413 QApplication::processEvents();
00414 ros::Duration(0.45).sleep();
00415 }
00416 }
00417
00418
00419
00420
00421 void RobotPosesWidget::editSelected()
00422 {
00423
00424 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00425
00426
00427 if( !selected.size() )
00428 return;
00429
00430
00431 edit( selected[0]->text().toStdString() );
00432 }
00433
00434
00435
00436
00437 void RobotPosesWidget::edit( const std::string &name )
00438 {
00439
00440 current_edit_pose_ = name;
00441
00442
00443 srdf::Model::GroupState *pose = findPoseByName( name );
00444
00445
00446 pose_name_field_->setText( pose->name_.c_str() );
00447
00448
00449 for( std::map<std::string, std::vector<double> >::const_iterator value_it = pose->joint_values_.begin();
00450 value_it != pose->joint_values_.end(); ++value_it )
00451 {
00452
00453 joint_state_map_[ value_it->first ] = value_it->second[0];
00454 }
00455
00456
00457 publishJoints();
00458
00459
00460 int index = group_name_field_->findText( pose->group_.c_str() );
00461 if( index == -1 )
00462 {
00463 QMessageBox::critical( this, "Error Loading", "Unable to find group name in drop down box" );
00464 return;
00465 }
00466
00467
00468 group_name_field_->setCurrentIndex( index );
00469
00470
00471 stacked_layout_->setCurrentIndex( 1 );
00472
00473
00474 Q_EMIT isModal( true );
00475
00476
00477 loadJointSliders( QString( pose->group_.c_str() ) );
00478
00479 }
00480
00481
00482
00483
00484 void RobotPosesWidget::loadGroupsComboBox()
00485 {
00486
00487 group_name_field_->clear();
00488
00489
00490 for( std::vector<srdf::Model::Group>::iterator group_it = config_data_->srdf_->groups_.begin();
00491 group_it != config_data_->srdf_->groups_.end(); ++group_it )
00492 {
00493 group_name_field_->addItem( group_it->name_.c_str() );
00494 }
00495
00496 }
00497
00498
00499
00500
00501 void RobotPosesWidget::loadJointSliders( const QString &selected )
00502 {
00503
00504
00505 if( !group_name_field_->count() || selected.isEmpty() || stacked_layout_->currentIndex() == 0)
00506 return;
00507
00508
00509 const std::string group_name = selected.toStdString();
00510
00511
00512 if( !config_data_->getRobotModel()->hasJointModelGroup( group_name ) )
00513 {
00514 QMessageBox::critical( this, "Error Loading",
00515 QString("Unable to find joint model group for group: ").append( group_name.c_str()).append(" Are you sure this group has associated joints/links?" ));
00516 return;
00517 }
00518
00519
00520 if( joint_list_layout_ )
00521 {
00522 delete joint_list_layout_;
00523 qDeleteAll( joint_list_widget_->children() );
00524 }
00525
00526
00527 joint_list_layout_ = new QVBoxLayout();
00528 joint_list_widget_->setLayout( joint_list_layout_ );
00529
00530 joint_list_widget_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
00531 joint_list_widget_->setMinimumSize( 50, 50 );
00532
00533
00534 const robot_model::JointModelGroup *joint_model_group =
00535 config_data_->getRobotModel()->getJointModelGroup( group_name );
00536 joint_models_ = joint_model_group->getJointModels();
00537
00538
00539 int num_joints = 0;
00540 for( std::vector<const robot_model::JointModel*>::const_iterator joint_it = joint_models_.begin();
00541 joint_it < joint_models_.end(); ++joint_it )
00542 {
00543
00544
00545 if( (*joint_it)->getVariableCount() == 1 )
00546 {
00547 double init_value;
00548
00549
00550 if( joint_state_map_.find( (*joint_it)->getName() ) == joint_state_map_.end() )
00551 {
00552
00553
00554
00555 std::vector<double> default_values;
00556 (*joint_it)->getVariableDefaultValues( default_values );
00557 init_value = default_values[0];
00558
00559 }
00560 else
00561 {
00562 init_value = joint_state_map_[ (*joint_it)->getName() ];
00563 }
00564
00565
00566 SliderWidget *sw = new SliderWidget( this, *joint_it, init_value );
00567 joint_list_layout_->addWidget( sw );
00568
00569
00570 connect( sw, SIGNAL( jointValueChanged( const std::string &, double ) ),
00571 this, SLOT( updateRobotModel( const std::string &, double ) ) );
00572
00573 ++num_joints;
00574 }
00575 }
00576
00577
00578 joint_list_widget_->resize( 300, num_joints * 70 );
00579
00580
00581 publishJoints();
00582
00583
00584 Q_EMIT unhighlightAll();
00585 Q_EMIT highlightGroup( group_name );
00586 }
00587
00588
00589
00590
00591 srdf::Model::GroupState *RobotPosesWidget::findPoseByName( const std::string &name )
00592 {
00593
00594 srdf::Model::GroupState *searched_group = NULL;
00595
00596 for( std::vector<srdf::Model::GroupState>::iterator pose_it = config_data_->srdf_->group_states_.begin();
00597 pose_it != config_data_->srdf_->group_states_.end(); ++pose_it )
00598 {
00599 if( pose_it->name_ == name )
00600 {
00601 searched_group = &(*pose_it);
00602 break;
00603 }
00604 }
00605
00606
00607 if( searched_group == NULL )
00608 {
00609 QMessageBox::critical( this, "Error Saving", "An internal error has occured while saving. Quitting.");
00610 QApplication::quit();
00611 }
00612
00613 return searched_group;
00614 }
00615
00616
00617
00618
00619 void RobotPosesWidget::deleteSelected()
00620 {
00621
00622 QList<QTableWidgetItem*> selected = data_table_->selectedItems();
00623
00624
00625 if( !selected.size() )
00626 return;
00627
00628
00629 current_edit_pose_ = selected[0]->text().toStdString();
00630
00631
00632 if( QMessageBox::question( this, "Confirm Pose Deletion",
00633 QString("Are you sure you want to delete the pose '")
00634 .append( current_edit_pose_.c_str() )
00635 .append( "'?" ),
00636 QMessageBox::Ok | QMessageBox::Cancel)
00637 == QMessageBox::Cancel )
00638 {
00639 return;
00640 }
00641
00642
00643 for( std::vector<srdf::Model::GroupState>::iterator pose_it = config_data_->srdf_->group_states_.begin();
00644 pose_it != config_data_->srdf_->group_states_.end(); ++pose_it )
00645 {
00646
00647 if( pose_it->name_ == current_edit_pose_ )
00648 {
00649 config_data_->srdf_->group_states_.erase( pose_it );
00650 break;
00651 }
00652 }
00653
00654
00655 loadDataTable();
00656
00657 }
00658
00659
00660
00661
00662 void RobotPosesWidget::doneEditing()
00663 {
00664
00665 const std::string pose_name = pose_name_field_->text().toStdString();
00666
00667
00668 srdf::Model::GroupState *searched_data = NULL;
00669
00670
00671 if( pose_name.empty() )
00672 {
00673 QMessageBox::warning( this, "Error Saving", "A name must be given for the pose!" );
00674 return;
00675 }
00676
00677
00678 if( !current_edit_pose_.empty() )
00679 {
00680
00681 searched_data = findPoseByName( current_edit_pose_ );
00682 }
00683
00684
00685 for( std::vector<srdf::Model::GroupState>::const_iterator data_it = config_data_->srdf_->group_states_.begin();
00686 data_it != config_data_->srdf_->group_states_.end(); ++data_it )
00687 {
00688 if( data_it->name_.compare( pose_name ) == 0 )
00689 {
00690
00691 if( &(*data_it) != searched_data )
00692 {
00693 QMessageBox::warning( this, "Error Saving", "A pose already exists with that name!" );
00694 return;
00695 }
00696 }
00697 }
00698
00699
00700 if( group_name_field_->currentText().isEmpty() )
00701 {
00702 QMessageBox::warning( this, "Error Saving", "A planning group must be chosen!" );
00703 return;
00704 }
00705
00706
00707 bool isNew = false;
00708
00709 if( searched_data == NULL )
00710 {
00711 isNew = true;
00712
00713 searched_data = new srdf::Model::GroupState();
00714 }
00715
00716
00717 searched_data->name_ = pose_name;
00718 searched_data->group_ = group_name_field_->currentText().toStdString();
00719
00720
00721
00722
00723 searched_data->joint_values_.clear();
00724
00725
00726 for( std::vector<const robot_model::JointModel*>::const_iterator joint_it = joint_models_.begin();
00727 joint_it < joint_models_.end(); ++joint_it )
00728 {
00729
00730 if( (*joint_it)->getVariableCount() == 1 )
00731 {
00732
00733 std::vector<double> joint_value;
00734 joint_value.push_back( joint_state_map_[ (*joint_it)->getName() ] );
00735
00736
00737 searched_data->joint_values_[ (*joint_it)->getName() ] = joint_value;
00738 }
00739 }
00740
00741
00742 if( isNew )
00743 {
00744 config_data_->srdf_->group_states_.push_back( *searched_data );
00745 }
00746
00747
00748
00749
00750 loadDataTable();
00751
00752
00753 stacked_layout_->setCurrentIndex( 0 );
00754
00755
00756 Q_EMIT isModal( false );
00757 }
00758
00759
00760
00761
00762 void RobotPosesWidget::cancelEditing()
00763 {
00764
00765 stacked_layout_->setCurrentIndex( 0 );
00766
00767
00768 Q_EMIT isModal( false );
00769 }
00770
00771
00772
00773
00774 void RobotPosesWidget::loadDataTable()
00775 {
00776
00777 data_table_->setUpdatesEnabled(false);
00778 data_table_->setDisabled(true);
00779 data_table_->clearContents();
00780
00781
00782 data_table_->setRowCount( config_data_->srdf_->group_states_.size() );
00783
00784
00785 int row = 0;
00786 for( std::vector<srdf::Model::GroupState>::const_iterator data_it = config_data_->srdf_->group_states_.begin();
00787 data_it != config_data_->srdf_->group_states_.end(); ++data_it )
00788 {
00789
00790 QTableWidgetItem* data_name = new QTableWidgetItem( data_it->name_.c_str() );
00791 data_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00792 QTableWidgetItem* group_name = new QTableWidgetItem( data_it->group_.c_str() );
00793 group_name->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
00794
00795
00796 data_table_->setItem( row, 0, data_name );
00797 data_table_->setItem( row, 1, group_name );
00798
00799
00800 ++row;
00801 }
00802
00803
00804 data_table_->setUpdatesEnabled(true);
00805 data_table_->setDisabled(false);
00806
00807
00808 data_table_->resizeColumnToContents(0);
00809 data_table_->resizeColumnToContents(1);
00810
00811
00812 if( config_data_->srdf_->group_states_.size() )
00813 btn_edit_->show();
00814 }
00815
00816
00817
00818
00819 void RobotPosesWidget::focusGiven()
00820 {
00821
00822 stacked_layout_->setCurrentIndex( 0 );
00823
00824
00825 loadDataTable();
00826
00827
00828 loadGroupsComboBox();
00829
00830 }
00831
00832
00833
00834
00835 void RobotPosesWidget::updateRobotModel( const std::string &name, double value )
00836 {
00837
00838 joint_state_map_[ name ] = value;
00839
00840
00841 publishJoints();
00842 }
00843
00844
00845
00846
00847 void RobotPosesWidget::publishJoints()
00848 {
00849
00850
00851
00852
00853
00854 config_data_->getPlanningScene()->getCurrentStateNonConst().setStateValues( joint_state_map_ );
00855
00856
00857 moveit_msgs::DisplayRobotState msg;
00858 robot_state::robotStateToRobotStateMsg(config_data_->getPlanningScene()->getCurrentState(), msg.state);
00859
00860
00861 pub_robot_state_.publish( msg );
00862
00863
00864 collision_detection::CollisionResult result;
00865 config_data_->getPlanningScene()->checkSelfCollision( request, result,
00866 config_data_->getPlanningScene()->getCurrentState(),
00867 config_data_->allowed_collision_matrix_ );
00868
00869 if( result.contacts.size() )
00870 {
00871 collision_warning_->show();
00872 }
00873 else
00874 {
00875 collision_warning_->hide();
00876 }
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 SliderWidget::SliderWidget( QWidget *parent, const robot_model::JointModel *joint_model,
00890 double init_value )
00891 : QWidget( parent ), joint_model_( joint_model )
00892 {
00893
00894 QVBoxLayout *layout = new QVBoxLayout();
00895 QHBoxLayout *row2 = new QHBoxLayout();
00896
00897
00898 joint_label_ = new QLabel( joint_model_->getName().c_str() , this );
00899 joint_label_->setContentsMargins( 0, 0, 0, 0 );
00900 layout->addWidget( joint_label_ );
00901
00902
00903 joint_slider_ = new QSlider( Qt::Horizontal, this );
00904 joint_slider_->setTickPosition(QSlider::TicksBelow);
00905 joint_slider_->setSingleStep( 10 );
00906 joint_slider_->setPageStep( 500 );
00907 joint_slider_->setTickInterval( 1000 );
00908 joint_slider_->setContentsMargins( 0, 0, 0, 0 );
00909 row2->addWidget( joint_slider_ );
00910
00911
00912 joint_value_ = new QLineEdit( this );
00913 joint_value_->setMaximumWidth( 62 );
00914 joint_value_->setContentsMargins( 0, 0, 0, 0 );
00915 connect( joint_value_, SIGNAL( editingFinished() ), this, SLOT( changeJointSlider() ) );
00916 row2->addWidget( joint_value_ );
00917
00918
00919 const std::vector<moveit_msgs::JointLimits> &limits = joint_model_->getVariableLimits();
00920 if( limits.empty() )
00921 {
00922 QMessageBox::critical( this, "Error Loading", "An internal error has occured while loading the joints" );
00923 return;
00924 }
00925
00926
00927 moveit_msgs::JointLimits joint_limit = limits[0];
00928 max_position_ = joint_limit.max_position;
00929 min_position_ = joint_limit.min_position;
00930
00931
00932 joint_slider_->setMaximum( max_position_*10000 );
00933 joint_slider_->setMinimum( min_position_*10000 );
00934
00935
00936 connect( joint_slider_, SIGNAL(valueChanged(int)), this, SLOT(changeJointValue(int)) );
00937
00938
00939 int value = init_value * 10000;
00940 joint_slider_->setSliderPosition( value );
00941 changeJointValue( value );
00942
00943
00944 layout->addLayout( row2 );
00945
00946 this->setContentsMargins( 0, 0, 0, 0 );
00947
00948 this->setGeometry(QRect(110, 80, 120, 80));
00949 this->setLayout( layout );
00950
00951
00952 qRegisterMetaType<std::string>("std::string");
00953 }
00954
00955
00956
00957
00958 SliderWidget::~SliderWidget()
00959 {
00960 }
00961
00962
00963
00964
00965 void SliderWidget::changeJointValue( int value )
00966 {
00967
00968 const double double_value = double( value ) / 10000;
00969
00970
00971 joint_value_->setText( QString( "%1" ).arg( double_value, 0, 'f', 4 ) );
00972
00973
00974 Q_EMIT jointValueChanged( joint_model_->getName(), double_value );
00975 }
00976
00977
00978
00979
00980 void SliderWidget::changeJointSlider()
00981 {
00982
00983 double value = joint_value_->text().toDouble();
00984
00985 if( min_position_ > value || value > max_position_ ) {
00986 value = (min_position_ > value) ? min_position_ : max_position_;
00987 joint_value_->setText( QString( "%1" ).arg( value, 0, 'f', 4 ) );
00988 }
00989
00990
00991 joint_slider_->setSliderPosition( value * 10000 );
00992
00993
00994 Q_EMIT jointValueChanged( joint_model_->getName(), value );
00995 }
00996
00997
00998
00999
01000
01001
01002 }